Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: jingle/glue/pseudotcp_adapter.cc

Issue 7040021: Fix crash condition if caller deletes PseudoTcpAdaptor from within a callback. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make it safe to delete PseudoTcpAdapter from callbacks. Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "jingle/glue/pseudotcp_adapter.h" 5 #include "jingle/glue/pseudotcp_adapter.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/time.h" 8 #include "base/time.h"
9 #include "net/base/address_list.h" 9 #include "net/base/address_list.h"
10 #include "net/base/completion_callback.h" 10 #include "net/base/completion_callback.h"
11 #include "net/base/io_buffer.h" 11 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h" 12 #include "net/base/net_errors.h"
13 #include "net/base/net_util.h" 13 #include "net/base/net_util.h"
14 14
15 using cricket::PseudoTcp; 15 using cricket::PseudoTcp;
16 16
17 namespace { 17 namespace {
18 const int kReadBufferSize = 65536; // Maximum size of a packet. 18 const int kReadBufferSize = 65536; // Maximum size of a packet.
19 const uint16 kDefaultMtu = 1280; 19 const uint16 kDefaultMtu = 1280;
20 } // namespace 20 } // namespace
21 21
22 namespace jingle_glue { 22 namespace jingle_glue {
23 23
24 PseudoTcpAdapter::PseudoTcpAdapter(net::Socket* socket) 24 class PseudoTcpAdapter::Core : public cricket::IPseudoTcpNotify,
25 : socket_(socket), 25 public base::RefCounted<Core> {
26 ALLOW_THIS_IN_INITIALIZER_LIST(pseudotcp_(this, 0)), 26 public:
27 connect_callback_(NULL), 27 Core(net::Socket* socket);
28 virtual ~Core();
29
30 // Functions used to implement net::StreamSocket.
31 virtual int Read(net::IOBuffer* buffer, int buffer_size,
Sergey Ulanov 2011/05/20 22:01:40 Do these methods need to be virtual?
Wez 2011/05/21 08:10:55 Done.
32 net::CompletionCallback* callback);
33 virtual int Write(net::IOBuffer* buffer, int buffer_size,
34 net::CompletionCallback* callback);
35 virtual int Connect(net::CompletionCallback* callback);
36
37 // cricket::IPseudoTcpNotify interface.
38 // These notifications are triggered from NotifyPacket.
39 virtual void OnTcpOpen(cricket::PseudoTcp* tcp) OVERRIDE;
40 virtual void OnTcpReadable(cricket::PseudoTcp* tcp) OVERRIDE;
41 virtual void OnTcpWriteable(cricket::PseudoTcp* tcp) OVERRIDE;
42 // This is triggered by NotifyClock or NotifyPacket.
43 virtual void OnTcpClosed(cricket::PseudoTcp* tcp, uint32 error) OVERRIDE;
44 // This is triggered by NotifyClock, NotifyPacket, Recv and Send.
45 virtual WriteResult TcpWritePacket(cricket::PseudoTcp* tcp,
46 const char* buffer, size_t len) OVERRIDE;
47
48 // "public" to avoid excessive boilerplate in PseudoTcpAdapter.
49 net::CompletionCallback* connect_callback_;
50 net::CompletionCallback* read_callback_;
51 net::CompletionCallback* write_callback_;
52
53 cricket::PseudoTcp pseudo_tcp_;
54 private:
55 // These are invoked by the underlying Socket, and may trigger callbacks.
56 // They hold a reference to |this| while running, to protect from deletion.
57 void OnRead(int result);
58 void OnWritten(int result);
59
60 // These may trigger callbacks, so the holder must hold a reference on
61 // the stack while calling them.
62 void DoReadFromSocket();
63 void HandleReadResults(int result);
64 void HandleTcpClock();
65
66 // This re-sets |timer| without triggering callbacks.
67 void AdjustClock();
68
69 scoped_ptr<net::Socket> socket_;
70
71 scoped_refptr<net::IOBuffer> read_buffer_;
72 int read_buffer_size_;
73 scoped_refptr<net::IOBuffer> write_buffer_;
74 int write_buffer_size_;
75
76 bool socket_write_pending_;
77 scoped_refptr<net::IOBuffer> socket_read_buffer_;
78
79 net::CompletionCallbackImpl<Core> socket_read_callback_;
80 net::CompletionCallbackImpl<Core> socket_write_callback_;
81
82 base::OneShotTimer<Core> timer_;
83
84 DISALLOW_COPY_AND_ASSIGN(Core);
85 };
86
87
88 PseudoTcpAdapter::Core::Core(net::Socket* socket)
89 : connect_callback_(NULL),
28 read_callback_(NULL), 90 read_callback_(NULL),
29 write_callback_(NULL), 91 write_callback_(NULL),
92 ALLOW_THIS_IN_INITIALIZER_LIST(pseudo_tcp_(this, 0)),
93 socket_(socket),
30 socket_write_pending_(false), 94 socket_write_pending_(false),
31 ALLOW_THIS_IN_INITIALIZER_LIST( 95 ALLOW_THIS_IN_INITIALIZER_LIST(
32 socket_read_callback_(this, &PseudoTcpAdapter::OnRead)), 96 socket_read_callback_(this, &PseudoTcpAdapter::Core::OnRead)),
33 ALLOW_THIS_IN_INITIALIZER_LIST( 97 ALLOW_THIS_IN_INITIALIZER_LIST(
34 socket_write_callback_(this, &PseudoTcpAdapter::OnWritten)) { 98 socket_write_callback_(this, &PseudoTcpAdapter::Core::OnWritten)) {
35 pseudotcp_.NotifyMTU(kDefaultMtu); 99 // Doesn't trigger callbacks.
100 pseudo_tcp_.NotifyMTU(kDefaultMtu);
36 } 101 }
37 102
38 PseudoTcpAdapter::~PseudoTcpAdapter() { 103 PseudoTcpAdapter::Core::~Core() {
39 } 104 }
40 105
41 int PseudoTcpAdapter::Read(net::IOBuffer* buffer, int buffer_size, 106 int PseudoTcpAdapter::Core::Read(net::IOBuffer* buffer, int buffer_size,
42 net::CompletionCallback* callback) { 107 net::CompletionCallback* callback) {
43 DCHECK(CalledOnValidThread()); 108 DCHECK(!read_callback_);
44 109
45 // Verify that there is no other pending read. 110 // Reference ourself in case callbacks result.
46 DCHECK(read_callback_ == NULL); 111 scoped_refptr<Core> core(this);
47 112
48 PseudoTcp::TcpState state = pseudotcp_.State(); 113 // TODO(wez): This is a hack for remoting. See JingleSession.
114 PseudoTcp::TcpState state = pseudo_tcp_.State();
49 int result; 115 int result;
50 if (state == PseudoTcp::TCP_SYN_SENT || 116 if (state == PseudoTcp::TCP_SYN_SENT ||
51 state == PseudoTcp::TCP_SYN_RECEIVED) { 117 state == PseudoTcp::TCP_SYN_RECEIVED) {
52 result = net::ERR_IO_PENDING; 118 result = net::ERR_IO_PENDING;
119
53 } else { 120 } else {
54 result = pseudotcp_.Recv(buffer->data(), buffer_size); 121 result = pseudo_tcp_.Recv(buffer->data(), buffer_size);
55 if (result < 0) { 122 if (result < 0) {
56 result = net::MapSystemError(pseudotcp_.GetError()); 123 result = net::MapSystemError(pseudo_tcp_.GetError());
57 DCHECK(result < 0); 124 DCHECK(result < 0);
58 } 125 }
59 } 126 }
60 127
61 if (result == net::ERR_IO_PENDING) { 128 if (result == net::ERR_IO_PENDING) {
62 read_buffer_ = buffer; 129 read_buffer_ = buffer;
63 read_buffer_size_ = buffer_size; 130 read_buffer_size_ = buffer_size;
64 read_callback_ = callback; 131 read_callback_ = callback;
65 } 132 }
66 133
67 AdjustClock(); 134 AdjustClock();
68 135
69 return result; 136 return result;
70 } 137 }
71 138
72 int PseudoTcpAdapter::Write(net::IOBuffer* buffer, int buffer_size, 139 int PseudoTcpAdapter::Core::Write(net::IOBuffer* buffer, int buffer_size,
73 net::CompletionCallback* callback) { 140 net::CompletionCallback* callback) {
74 DCHECK(CalledOnValidThread()); 141 DCHECK(!write_callback_);
75 142
76 // Verify that there is no other pending write. 143 // Reference ourself in case callbacks result.
Sergey Ulanov 2011/05/20 22:01:40 The comments doesn't seem to be complete.
Wez 2011/05/21 08:10:55 Done.
77 DCHECK(write_callback_ == NULL); 144 scoped_refptr<Core> core(this);
78 145
79 PseudoTcp::TcpState state = pseudotcp_.State(); 146 // TODO(wez): This is a hack for remoting. See JingleSession.
147 PseudoTcp::TcpState state = pseudo_tcp_.State();
80 int result; 148 int result;
81 if (state == PseudoTcp::TCP_SYN_SENT || 149 if (state == PseudoTcp::TCP_SYN_SENT ||
82 state == PseudoTcp::TCP_SYN_RECEIVED) { 150 state == PseudoTcp::TCP_SYN_RECEIVED) {
83 result = net::ERR_IO_PENDING; 151 result = net::ERR_IO_PENDING;
152
Sergey Ulanov 2011/05/20 22:01:40 Don't need this empty line
Wez 2011/05/21 08:10:55 It's there to mark the end of the block of code im
84 } else { 153 } else {
85 result = pseudotcp_.Send(buffer->data(), buffer_size); 154 result = pseudo_tcp_.Send(buffer->data(), buffer_size);
86 if (result < 0) { 155 if (result < 0) {
87 result = net::MapSystemError(pseudotcp_.GetError()); 156 result = net::MapSystemError(pseudo_tcp_.GetError());
88 DCHECK(result < 0); 157 DCHECK(result < 0);
89 } 158 }
90 } 159 }
91 160
92 if (result == net::ERR_IO_PENDING) { 161 if (result == net::ERR_IO_PENDING) {
93 write_buffer_ = buffer; 162 write_buffer_ = buffer;
94 write_buffer_size_ = buffer_size; 163 write_buffer_size_ = buffer_size;
95 write_callback_ = callback; 164 write_callback_ = callback;
96 } 165 }
97 166
98 AdjustClock(); 167 AdjustClock();
99 168
100 return result; 169 return result;
101 } 170 }
102 171
103 bool PseudoTcpAdapter::SetReceiveBufferSize(int32 size) { 172 int PseudoTcpAdapter::Core::Connect(net::CompletionCallback* callback) {
104 DCHECK(CalledOnValidThread()); 173 DCHECK_EQ(pseudo_tcp_.State(), cricket::PseudoTcp::TCP_LISTEN);
105 // TODO(sergeyu): Implement support for adjustable buffer size and
106 // used it here.
107 return false;
108 }
109 174
110 bool PseudoTcpAdapter::SetSendBufferSize(int32 size) { 175 // Reference ourself in case callbacks result.
Sergey Ulanov 2011/05/20 22:01:40 The comments doesn't seem to be complete
Wez 2011/05/21 08:10:55 Done.
111 DCHECK(CalledOnValidThread()); 176 scoped_refptr<Core> core(this);
112 // TODO(sergeyu): Implement support for adjustable buffer size and
113 // used it here.
114 return false;
115 }
116 177
117 int PseudoTcpAdapter::Connect(net::CompletionCallback* callback) { 178 // Start the connection attempt.
118 DCHECK(CalledOnValidThread()); 179 int result = pseudo_tcp_.Connect();
119
120 // Start reading from the socket.
121 DoReadFromSocket();
122
123 int result = pseudotcp_.Connect();
124 if (result < 0) 180 if (result < 0)
125 return net::ERR_FAILED; 181 return net::ERR_FAILED;
126 182
127 AdjustClock(); 183 AdjustClock();
128 184
129 connect_callback_ = callback; 185 connect_callback_ = callback;
186 DoReadFromSocket();
187
130 return net::ERR_IO_PENDING; 188 return net::ERR_IO_PENDING;
131 } 189 }
132 190
133 void PseudoTcpAdapter::Disconnect() { 191 void PseudoTcpAdapter::Core::OnTcpOpen(PseudoTcp* tcp) {
134 DCHECK(CalledOnValidThread()); 192 DCHECK(tcp == &pseudo_tcp_);
135 pseudotcp_.Close(false);
136 }
137 193
138 bool PseudoTcpAdapter::IsConnected() const { 194 if (connect_callback_) {
139 DCHECK(CalledOnValidThread()); 195 net::CompletionCallback* callback = connect_callback_;
140 return pseudotcp_.State() == PseudoTcp::TCP_ESTABLISHED; 196 connect_callback_ = NULL;
141 } 197 callback->Run(net::OK);
142 198 }
143 bool PseudoTcpAdapter::IsConnectedAndIdle() const {
144 DCHECK(CalledOnValidThread());
145 NOTIMPLEMENTED();
146 return false;
147 }
148
149 int PseudoTcpAdapter::GetPeerAddress(net::AddressList* address) const {
150 DCHECK(CalledOnValidThread());
151
152 // We actually don't know the peer address. Returning so the upper layers
153 // won't complain.
154 net::IPAddressNumber ip_address(4);
155 *address = net::AddressList::CreateFromIPAddress(ip_address, 0);
156 return net::OK;
157 }
158
159 int PseudoTcpAdapter::GetLocalAddress(net::IPEndPoint* address) const {
160 DCHECK(CalledOnValidThread());
161 NOTIMPLEMENTED();
162 return net::ERR_FAILED;
163 }
164
165 const net::BoundNetLog& PseudoTcpAdapter::NetLog() const {
166 DCHECK(CalledOnValidThread());
167 return net_log_;
168 }
169
170 void PseudoTcpAdapter::SetSubresourceSpeculation() {
171 DCHECK(CalledOnValidThread());
172 NOTIMPLEMENTED();
173 }
174
175 void PseudoTcpAdapter::SetOmniboxSpeculation() {
176 DCHECK(CalledOnValidThread());
177 NOTIMPLEMENTED();
178 }
179
180 bool PseudoTcpAdapter::WasEverUsed() const {
181 DCHECK(CalledOnValidThread());
182 NOTIMPLEMENTED();
183 return true;
184 }
185
186 bool PseudoTcpAdapter::UsingTCPFastOpen() const {
187 DCHECK(CalledOnValidThread());
188 return false;
189 }
190
191 void PseudoTcpAdapter::OnTcpOpen(PseudoTcp* tcp) {
192 DCHECK(CalledOnValidThread());
193 DCHECK(connect_callback_);
194 connect_callback_->Run(net::OK);
195 connect_callback_ = NULL;
196 199
197 OnTcpReadable(tcp); 200 OnTcpReadable(tcp);
198 OnTcpWriteable(tcp); 201 OnTcpWriteable(tcp);
199 } 202 }
200 203
201 void PseudoTcpAdapter::OnTcpReadable(PseudoTcp* tcp) { 204 void PseudoTcpAdapter::Core::OnTcpReadable(PseudoTcp* tcp) {
202 DCHECK(CalledOnValidThread()); 205 DCHECK_EQ(tcp, &pseudo_tcp_);
203
204 if (!read_buffer_) 206 if (!read_buffer_)
Sergey Ulanov 2011/05/20 22:01:40 It's better to check for read_callback here and DC
Wez 2011/05/21 08:10:55 Done.
205 return; 207 return;
206 208
207 // Try to send the data we have pending. 209 int result = pseudo_tcp_.Recv(read_buffer_->data(), read_buffer_size_);
208 int result = pseudotcp_.Recv(read_buffer_->data(), read_buffer_size_);
209 if (result < 0) { 210 if (result < 0) {
210 result = net::MapSystemError(pseudotcp_.GetError()); 211 result = net::MapSystemError(pseudo_tcp_.GetError());
211 DCHECK(result < 0); 212 DCHECK(result < 0);
212 if (result == net::ERR_IO_PENDING) 213 if (result == net::ERR_IO_PENDING)
213 return; 214 return;
214 } 215 }
215 216
216 AdjustClock(); 217 AdjustClock();
217 218
218 net::CompletionCallback* cb = read_callback_;
219 read_callback_ = NULL;
220 read_buffer_ = NULL; 219 read_buffer_ = NULL;
221 cb->Run(result); 220 if (read_callback_) {
Sergey Ulanov 2011/05/20 22:01:40 Don't think we need this if. if read_buffer_ is se
Wez 2011/05/21 08:10:55 Done.
221 net::CompletionCallback* callback = read_callback_;
222 read_callback_ = NULL;
223 callback->Run(result);
224 }
222 } 225 }
223 226
224 void PseudoTcpAdapter::OnTcpWriteable(PseudoTcp* tcp) { 227 void PseudoTcpAdapter::Core::OnTcpWriteable(PseudoTcp* tcp) {
225 DCHECK(CalledOnValidThread()); 228 DCHECK_EQ(tcp, &pseudo_tcp_);
226
227 if (!write_buffer_) 229 if (!write_buffer_)
228 return; 230 return;
229 231
230 // Try to send the data we have pending. 232 int result = pseudo_tcp_.Send(write_buffer_->data(), write_buffer_size_);
231 int result = pseudotcp_.Send(write_buffer_->data(), write_buffer_size_);
232 if (result < 0) { 233 if (result < 0) {
233 result = net::MapSystemError(pseudotcp_.GetError()); 234 result = net::MapSystemError(pseudo_tcp_.GetError());
234 DCHECK(result < 0); 235 DCHECK(result < 0);
235 if (result == net::ERR_IO_PENDING) 236 if (result == net::ERR_IO_PENDING)
236 return; 237 return;
237 } 238 }
238 239
239 AdjustClock(); 240 AdjustClock();
240 241
241 net::CompletionCallback* cb = write_callback_;
242 write_callback_ = NULL;
243 write_buffer_ = NULL; 242 write_buffer_ = NULL;
244 cb->Run(result); 243 if (write_callback_) {
Sergey Ulanov 2011/05/20 22:01:40 Same comment as for Read(): if there is data to wr
Wez 2011/05/21 08:10:55 Done.
244 net::CompletionCallback* callback = write_callback_;
245 write_callback_ = NULL;
246 callback->Run(result);
247 }
245 } 248 }
246 249
247 void PseudoTcpAdapter::OnTcpClosed(PseudoTcp* tcp, uint32 error) { 250 void PseudoTcpAdapter::Core::OnTcpClosed(PseudoTcp* tcp, uint32 error) {
248 DCHECK(CalledOnValidThread()); 251 DCHECK_EQ(tcp, &pseudo_tcp_);
249 252
250 if (connect_callback_) { 253 if (connect_callback_) {
251 connect_callback_->Run(net::MapSystemError(error)); 254 net::CompletionCallback* callback = connect_callback_;
252 connect_callback_ = NULL; 255 connect_callback_ = NULL;
256 callback->Run(net::MapSystemError(error));
253 } 257 }
254 258
255 if (read_callback_) { 259 if (read_callback_) {
256 read_callback_->Run(net::MapSystemError(error)); 260 net::CompletionCallback* callback = read_callback_;
257 read_callback_ = NULL; 261 read_callback_ = NULL;
262 callback->Run(net::MapSystemError(error));
258 } 263 }
259 264
260 if (write_callback_) { 265 if (write_callback_) {
261 write_callback_->Run(net::MapSystemError(error)); 266 net::CompletionCallback* callback = write_callback_;
262 write_callback_ = NULL; 267 write_callback_ = NULL;
268 callback->Run(net::MapSystemError(error));
263 } 269 }
264 } 270 }
265 271
266 cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::TcpWritePacket( 272 cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::Core::TcpWritePacket(
267 PseudoTcp* tcp, 273 PseudoTcp* tcp,
268 const char* buffer, 274 const char* buffer,
269 size_t len) { 275 size_t len) {
270 DCHECK(CalledOnValidThread()); 276 DCHECK_EQ(tcp, &pseudo_tcp_);
271 277
272 if (socket_write_pending_) 278 if (socket_write_pending_)
273 return IPseudoTcpNotify::WR_SUCCESS; 279 return IPseudoTcpNotify::WR_SUCCESS;
274 280
275 scoped_refptr<net::IOBuffer> write_buffer = new net::IOBuffer(len); 281 scoped_refptr<net::IOBuffer> write_buffer = new net::IOBuffer(len);
276 memcpy(write_buffer->data(), buffer, len); 282 memcpy(write_buffer->data(), buffer, len);
277 283
278 int result = socket_->Write(write_buffer, len, &socket_write_callback_); 284 int result = socket_->Write(write_buffer, len, &socket_write_callback_);
279 if (result == net::ERR_IO_PENDING) { 285 if (result == net::ERR_IO_PENDING) {
280 socket_write_pending_ = true; 286 socket_write_pending_ = true;
281 return IPseudoTcpNotify::WR_SUCCESS; 287 return IPseudoTcpNotify::WR_SUCCESS;
282 } if (result == net::ERR_MSG_TOO_BIG) { 288 } if (result == net::ERR_MSG_TOO_BIG) {
283 return IPseudoTcpNotify::WR_TOO_LARGE; 289 return IPseudoTcpNotify::WR_TOO_LARGE;
284 } else if (result < 0) { 290 } else if (result < 0) {
285 return IPseudoTcpNotify::WR_FAIL; 291 return IPseudoTcpNotify::WR_FAIL;
286 } else { 292 } else {
287 return IPseudoTcpNotify::WR_SUCCESS; 293 return IPseudoTcpNotify::WR_SUCCESS;
288 } 294 }
289 } 295 }
290 296
291 void PseudoTcpAdapter::DoReadFromSocket() { 297 void PseudoTcpAdapter::Core::DoReadFromSocket() {
292 if (!socket_read_buffer_) { 298 if (!socket_read_buffer_)
293 socket_read_buffer_ = new net::IOBuffer(kReadBufferSize); 299 socket_read_buffer_ = new net::IOBuffer(kReadBufferSize);
294 }
295 300
296 while (true) { 301 while (true) {
297 int result = socket_->Read(socket_read_buffer_, kReadBufferSize, 302 int result = socket_->Read(socket_read_buffer_, kReadBufferSize,
298 &socket_read_callback_); 303 &socket_read_callback_);
299 if (result == net::ERR_IO_PENDING) 304 if (result == net::ERR_IO_PENDING)
300 break; 305 break;
301 306
302 HandleReadResults(result); 307 HandleReadResults(result);
303 } 308 }
304 } 309 }
305 310
306 void PseudoTcpAdapter::HandleReadResults(int result) { 311 void PseudoTcpAdapter::Core::HandleReadResults(int result) {
307 if (result <= 0) { 312 if (result <= 0) {
308 LOG(ERROR) << "Read returned " << result; 313 LOG(ERROR) << "Read returned " << result;
309 return; 314 return;
310 } 315 }
311 316
312 pseudotcp_.NotifyPacket(socket_read_buffer_->data(), result); 317 // TODO(wez): Disconnect on failure of NotifyPacket?
318 pseudo_tcp_.NotifyPacket(socket_read_buffer_->data(), result);
313 AdjustClock(); 319 AdjustClock();
314 } 320 }
315 321
316 void PseudoTcpAdapter::OnRead(int result) { 322 void PseudoTcpAdapter::Core::OnRead(int result) {
323 // Reference ourself in case callbacks result.
324 scoped_refptr<Core> core(this);
325
317 HandleReadResults(result); 326 HandleReadResults(result);
318 if (result >= 0) 327 if (result >= 0)
319 DoReadFromSocket(); 328 DoReadFromSocket();
320 } 329 }
321 330
322 void PseudoTcpAdapter::OnWritten(int result) { 331 void PseudoTcpAdapter::Core::OnWritten(int result) {
332 // Reference ourself in case callbacks result.
333 scoped_refptr<Core> core(this);
334
323 socket_write_pending_ = false; 335 socket_write_pending_ = false;
324 if (result < 0) { 336 if (result < 0) {
325 LOG(WARNING) << "Write failed. Error code: " << result; 337 LOG(WARNING) << "Write failed. Error code: " << result;
326 } 338 }
327 } 339 }
328 340
329 void PseudoTcpAdapter::AdjustClock() { 341 void PseudoTcpAdapter::Core::AdjustClock() {
330 long timeout = 0; 342 long timeout = 0;
331 if (pseudotcp_.GetNextClock(PseudoTcp::Now(), timeout)) { 343 if (pseudo_tcp_.GetNextClock(PseudoTcp::Now(), timeout)) {
332 timer_.Stop(); 344 timer_.Stop();
333 timer_.Start(base::TimeDelta::FromMilliseconds(std::max(timeout, 0L)), this, 345 timer_.Start(base::TimeDelta::FromMilliseconds(std::max(timeout, 0L)), this,
334 &PseudoTcpAdapter::HandleTcpClock); 346 &PseudoTcpAdapter::Core::HandleTcpClock);
335 } 347 }
336 } 348 }
337 349
338 void PseudoTcpAdapter::HandleTcpClock() { 350 void PseudoTcpAdapter::Core::HandleTcpClock() {
339 pseudotcp_.NotifyClock(PseudoTcp::Now()); 351 // Reference ourself in case callbacks result.
352 scoped_refptr<Core> core(this);
353
354 pseudo_tcp_.NotifyClock(PseudoTcp::Now());
340 AdjustClock(); 355 AdjustClock();
341 } 356 }
342 357
358 // Public interface implemention.
359
360 PseudoTcpAdapter::PseudoTcpAdapter(net::Socket* socket)
361 : core_(new Core(socket)) {
362 }
363
364 PseudoTcpAdapter::~PseudoTcpAdapter() {
365 core_->connect_callback_ = NULL;
366 core_->read_callback_ = NULL;
367 core_->write_callback_ = NULL;
368 }
369
370 int PseudoTcpAdapter::Read(net::IOBuffer* buffer, int buffer_size,
371 net::CompletionCallback* callback) {
372 DCHECK(CalledOnValidThread());
373 return core_->Read(buffer, buffer_size, callback);
374 }
375
376 int PseudoTcpAdapter::Write(net::IOBuffer* buffer, int buffer_size,
377 net::CompletionCallback* callback) {
378 DCHECK(CalledOnValidThread());
379 return core_->Write(buffer, buffer_size, callback);
380 }
381
382 bool PseudoTcpAdapter::SetReceiveBufferSize(int32 size) {
383 DCHECK(CalledOnValidThread());
384 // TODO(sergeyu): Implement support for adjustable buffer size and
385 // used it here.
386 return false;
387 }
388
389 bool PseudoTcpAdapter::SetSendBufferSize(int32 size) {
390 DCHECK(CalledOnValidThread());
391 // TODO(sergeyu): Implement support for adjustable buffer size and
392 // used it here.
393 return false;
394 }
395
396 int PseudoTcpAdapter::Connect(net::CompletionCallback* callback) {
397 DCHECK(CalledOnValidThread());
398
399 // net::StreamSocket requires that Connect return OK if already connected.
400 if (IsConnected())
401 return net::OK;
402
403 return core_->Connect(callback);
404 }
405
406 void PseudoTcpAdapter::Disconnect() {
407 DCHECK(CalledOnValidThread());
408
409 // Don't dispatch outstanding callbacks, as mandated by net::StreamSocket.
410 core_->read_callback_ = NULL;
411 core_->write_callback_ = NULL;
412 core_->connect_callback_ = NULL;
413
414 // TODO(wez): Connect should succeed if called after Disconnect, which
415 // PseudoTcp doesn't support, so we need to teardown the internal PseudoTcp
416 // and create a new one in Connect.
417 // TODO(wez): Close sets a shutdown flag inside PseudoTcp but has no other
418 // effect. This should be addressed in PseudoTcp, really.
419 // In the meantime we can fake OnTcpClosed notification and tear down the
420 // PseudoTcp.
421 // TODO(wez): The "force" parameter to Close() should be true, since the
422 // behaviour of disconnect is to dump any pending reads & writes.
423 core_->pseudo_tcp_.Close(false);
424 }
425
426 bool PseudoTcpAdapter::IsConnected() const {
427 return core_->pseudo_tcp_.State() == PseudoTcp::TCP_ESTABLISHED;
428 }
429
430 bool PseudoTcpAdapter::IsConnectedAndIdle() const {
431 DCHECK(CalledOnValidThread());
432 NOTIMPLEMENTED();
433 return false;
434 }
435
436 int PseudoTcpAdapter::GetPeerAddress(net::AddressList* address) const {
437 DCHECK(CalledOnValidThread());
438
439 // We actually don't know the peer address. Returning so the upper layers
440 // won't complain.
441 net::IPAddressNumber ip_address(4);
442 *address = net::AddressList::CreateFromIPAddress(ip_address, 0);
443 return net::OK;
444 }
445
446 int PseudoTcpAdapter::GetLocalAddress(net::IPEndPoint* address) const {
447 DCHECK(CalledOnValidThread());
448 NOTIMPLEMENTED();
449 return net::ERR_FAILED;
450 }
451
452 const net::BoundNetLog& PseudoTcpAdapter::NetLog() const {
453 DCHECK(CalledOnValidThread());
454 return net_log_;
455 }
456
457 void PseudoTcpAdapter::SetSubresourceSpeculation() {
458 DCHECK(CalledOnValidThread());
459 NOTIMPLEMENTED();
460 }
461
462 void PseudoTcpAdapter::SetOmniboxSpeculation() {
463 DCHECK(CalledOnValidThread());
464 NOTIMPLEMENTED();
465 }
466
467 bool PseudoTcpAdapter::WasEverUsed() const {
468 DCHECK(CalledOnValidThread());
469 NOTIMPLEMENTED();
470 return true;
471 }
472
473 bool PseudoTcpAdapter::UsingTCPFastOpen() const {
474 DCHECK(CalledOnValidThread());
475 return false;
476 }
477
343 } // namespace jingle_glue 478 } // namespace jingle_glue
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698