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

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: Add a unit test. 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
« no previous file with comments | « jingle/glue/pseudotcp_adapter.h ('k') | jingle/glue/pseudotcp_adapter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 int Read(net::IOBuffer* buffer, int buffer_size,
32 net::CompletionCallback* callback);
33 int Write(net::IOBuffer* buffer, int buffer_size,
34 net::CompletionCallback* callback);
35 int Connect(net::CompletionCallback* callback);
36 void Disconnect();
37 bool IsConnected() const;
38
39 // cricket::IPseudoTcpNotify interface.
40 // These notifications are triggered from NotifyPacket.
41 virtual void OnTcpOpen(cricket::PseudoTcp* tcp) OVERRIDE;
42 virtual void OnTcpReadable(cricket::PseudoTcp* tcp) OVERRIDE;
43 virtual void OnTcpWriteable(cricket::PseudoTcp* tcp) OVERRIDE;
44 // This is triggered by NotifyClock or NotifyPacket.
45 virtual void OnTcpClosed(cricket::PseudoTcp* tcp, uint32 error) OVERRIDE;
46 // This is triggered by NotifyClock, NotifyPacket, Recv and Send.
47 virtual WriteResult TcpWritePacket(cricket::PseudoTcp* tcp,
48 const char* buffer, size_t len) OVERRIDE;
49 private:
50 // These are invoked by the underlying Socket, and may trigger callbacks.
51 // They hold a reference to |this| while running, to protect from deletion.
52 void OnRead(int result);
53 void OnWritten(int result);
54
55 // These may trigger callbacks, so the holder must hold a reference on
56 // the stack while calling them.
57 void DoReadFromSocket();
58 void HandleReadResults(int result);
59 void HandleTcpClock();
60
61 // This re-sets |timer| without triggering callbacks.
62 void AdjustClock();
63
64 net::CompletionCallback* connect_callback_;
65 net::CompletionCallback* read_callback_;
66 net::CompletionCallback* write_callback_;
67
68 cricket::PseudoTcp pseudo_tcp_;
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 the Core in case a callback deletes the adapter.
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 the Core in case a callback deletes the adapter.
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
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 the Core in case a callback deletes the adapter.
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::Disconnect() {
134 DCHECK(CalledOnValidThread()); 192 // Don't dispatch outstanding callbacks, as mandated by net::StreamSocket.
135 pseudotcp_.Close(false); 193 read_callback_ = NULL;
194 read_buffer_ = NULL;
195 write_callback_ = NULL;
196 write_buffer_ = NULL;
197 connect_callback_ = NULL;
198
199 // TODO(wez): Connect should succeed if called after Disconnect, which
200 // PseudoTcp doesn't support, so we need to teardown the internal PseudoTcp
201 // and create a new one in Connect.
202 // TODO(wez): Close sets a shutdown flag inside PseudoTcp but has no other
203 // effect. This should be addressed in PseudoTcp, really.
204 // In the meantime we can fake OnTcpClosed notification and tear down the
205 // PseudoTcp.
206 // TODO(wez): The "force" parameter to Close() should be true, since the
Sergey Ulanov 2011/05/24 00:37:34 Can we change it to true now? If not, explain why.
Wez 2011/05/24 00:57:09 Done.
207 // behaviour of disconnect is to dump any pending reads & writes.
208 pseudo_tcp_.Close(false);
136 } 209 }
137 210
138 bool PseudoTcpAdapter::IsConnected() const { 211 bool PseudoTcpAdapter::Core::IsConnected() const {
139 DCHECK(CalledOnValidThread()); 212 return pseudo_tcp_.State() == PseudoTcp::TCP_ESTABLISHED;
140 return pseudotcp_.State() == PseudoTcp::TCP_ESTABLISHED;
141 } 213 }
142 214
143 bool PseudoTcpAdapter::IsConnectedAndIdle() const { 215 void PseudoTcpAdapter::Core::OnTcpOpen(PseudoTcp* tcp) {
144 DCHECK(CalledOnValidThread()); 216 DCHECK(tcp == &pseudo_tcp_);
145 NOTIMPLEMENTED();
146 return false;
147 }
148 217
149 int PseudoTcpAdapter::GetPeerAddress(net::AddressList* address) const { 218 if (connect_callback_) {
150 DCHECK(CalledOnValidThread()); 219 net::CompletionCallback* callback = connect_callback_;
151 220 connect_callback_ = NULL;
152 // We actually don't know the peer address. Returning so the upper layers 221 callback->Run(net::OK);
153 // won't complain. 222 }
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 223
197 OnTcpReadable(tcp); 224 OnTcpReadable(tcp);
198 OnTcpWriteable(tcp); 225 OnTcpWriteable(tcp);
199 } 226 }
200 227
201 void PseudoTcpAdapter::OnTcpReadable(PseudoTcp* tcp) { 228 void PseudoTcpAdapter::Core::OnTcpReadable(PseudoTcp* tcp) {
202 DCHECK(CalledOnValidThread()); 229 DCHECK_EQ(tcp, &pseudo_tcp_);
203 230 if (!read_callback_)
204 if (!read_buffer_)
205 return; 231 return;
206 232
207 // Try to send the data we have pending. 233 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) { 234 if (result < 0) {
210 result = net::MapSystemError(pseudotcp_.GetError()); 235 result = net::MapSystemError(pseudo_tcp_.GetError());
211 DCHECK(result < 0); 236 DCHECK(result < 0);
212 if (result == net::ERR_IO_PENDING) 237 if (result == net::ERR_IO_PENDING)
213 return; 238 return;
214 } 239 }
215 240
216 AdjustClock(); 241 AdjustClock();
217 242
218 net::CompletionCallback* cb = read_callback_; 243 net::CompletionCallback* callback = read_callback_;
219 read_callback_ = NULL; 244 read_callback_ = NULL;
220 read_buffer_ = NULL; 245 read_buffer_ = NULL;
221 cb->Run(result); 246 callback->Run(result);
222 } 247 }
223 248
224 void PseudoTcpAdapter::OnTcpWriteable(PseudoTcp* tcp) { 249 void PseudoTcpAdapter::Core::OnTcpWriteable(PseudoTcp* tcp) {
225 DCHECK(CalledOnValidThread()); 250 DCHECK_EQ(tcp, &pseudo_tcp_);
226 251 if (!write_callback_)
227 if (!write_buffer_)
228 return; 252 return;
229 253
230 // Try to send the data we have pending. 254 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) { 255 if (result < 0) {
233 result = net::MapSystemError(pseudotcp_.GetError()); 256 result = net::MapSystemError(pseudo_tcp_.GetError());
234 DCHECK(result < 0); 257 DCHECK(result < 0);
235 if (result == net::ERR_IO_PENDING) 258 if (result == net::ERR_IO_PENDING)
236 return; 259 return;
237 } 260 }
238 261
239 AdjustClock(); 262 AdjustClock();
240 263
241 net::CompletionCallback* cb = write_callback_; 264 net::CompletionCallback* callback = write_callback_;
242 write_callback_ = NULL; 265 write_callback_ = NULL;
243 write_buffer_ = NULL; 266 write_buffer_ = NULL;
244 cb->Run(result); 267 callback->Run(result);
245 } 268 }
246 269
247 void PseudoTcpAdapter::OnTcpClosed(PseudoTcp* tcp, uint32 error) { 270 void PseudoTcpAdapter::Core::OnTcpClosed(PseudoTcp* tcp, uint32 error) {
248 DCHECK(CalledOnValidThread()); 271 DCHECK_EQ(tcp, &pseudo_tcp_);
249 272
250 if (connect_callback_) { 273 if (connect_callback_) {
251 connect_callback_->Run(net::MapSystemError(error)); 274 net::CompletionCallback* callback = connect_callback_;
252 connect_callback_ = NULL; 275 connect_callback_ = NULL;
276 callback->Run(net::MapSystemError(error));
253 } 277 }
254 278
255 if (read_callback_) { 279 if (read_callback_) {
256 read_callback_->Run(net::MapSystemError(error)); 280 net::CompletionCallback* callback = read_callback_;
257 read_callback_ = NULL; 281 read_callback_ = NULL;
282 callback->Run(net::MapSystemError(error));
258 } 283 }
259 284
260 if (write_callback_) { 285 if (write_callback_) {
261 write_callback_->Run(net::MapSystemError(error)); 286 net::CompletionCallback* callback = write_callback_;
262 write_callback_ = NULL; 287 write_callback_ = NULL;
288 callback->Run(net::MapSystemError(error));
263 } 289 }
264 } 290 }
265 291
266 cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::TcpWritePacket( 292 cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::Core::TcpWritePacket(
267 PseudoTcp* tcp, 293 PseudoTcp* tcp,
268 const char* buffer, 294 const char* buffer,
269 size_t len) { 295 size_t len) {
270 DCHECK(CalledOnValidThread()); 296 DCHECK_EQ(tcp, &pseudo_tcp_);
271 297
272 if (socket_write_pending_) 298 if (socket_write_pending_)
273 return IPseudoTcpNotify::WR_SUCCESS; 299 return IPseudoTcpNotify::WR_SUCCESS;
274 300
275 scoped_refptr<net::IOBuffer> write_buffer = new net::IOBuffer(len); 301 scoped_refptr<net::IOBuffer> write_buffer = new net::IOBuffer(len);
276 memcpy(write_buffer->data(), buffer, len); 302 memcpy(write_buffer->data(), buffer, len);
277 303
278 int result = socket_->Write(write_buffer, len, &socket_write_callback_); 304 int result = socket_->Write(write_buffer, len, &socket_write_callback_);
279 if (result == net::ERR_IO_PENDING) { 305 if (result == net::ERR_IO_PENDING) {
280 socket_write_pending_ = true; 306 socket_write_pending_ = true;
281 return IPseudoTcpNotify::WR_SUCCESS; 307 return IPseudoTcpNotify::WR_SUCCESS;
282 } if (result == net::ERR_MSG_TOO_BIG) { 308 } if (result == net::ERR_MSG_TOO_BIG) {
283 return IPseudoTcpNotify::WR_TOO_LARGE; 309 return IPseudoTcpNotify::WR_TOO_LARGE;
284 } else if (result < 0) { 310 } else if (result < 0) {
285 return IPseudoTcpNotify::WR_FAIL; 311 return IPseudoTcpNotify::WR_FAIL;
286 } else { 312 } else {
287 return IPseudoTcpNotify::WR_SUCCESS; 313 return IPseudoTcpNotify::WR_SUCCESS;
288 } 314 }
289 } 315 }
290 316
291 void PseudoTcpAdapter::DoReadFromSocket() { 317 void PseudoTcpAdapter::Core::DoReadFromSocket() {
292 if (!socket_read_buffer_) { 318 if (!socket_read_buffer_)
293 socket_read_buffer_ = new net::IOBuffer(kReadBufferSize); 319 socket_read_buffer_ = new net::IOBuffer(kReadBufferSize);
294 }
295 320
296 while (true) { 321 while (true) {
297 int result = socket_->Read(socket_read_buffer_, kReadBufferSize, 322 int result = socket_->Read(socket_read_buffer_, kReadBufferSize,
298 &socket_read_callback_); 323 &socket_read_callback_);
299 if (result == net::ERR_IO_PENDING) 324 if (result == net::ERR_IO_PENDING)
300 break; 325 break;
301 326
302 HandleReadResults(result); 327 HandleReadResults(result);
303 } 328 }
304 } 329 }
305 330
306 void PseudoTcpAdapter::HandleReadResults(int result) { 331 void PseudoTcpAdapter::Core::HandleReadResults(int result) {
307 if (result <= 0) { 332 if (result <= 0) {
308 LOG(ERROR) << "Read returned " << result; 333 LOG(ERROR) << "Read returned " << result;
309 return; 334 return;
310 } 335 }
311 336
312 pseudotcp_.NotifyPacket(socket_read_buffer_->data(), result); 337 // TODO(wez): Disconnect on failure of NotifyPacket?
338 pseudo_tcp_.NotifyPacket(socket_read_buffer_->data(), result);
313 AdjustClock(); 339 AdjustClock();
314 } 340 }
315 341
316 void PseudoTcpAdapter::OnRead(int result) { 342 void PseudoTcpAdapter::Core::OnRead(int result) {
343 // Reference the Core in case a callback deletes the adapter.
344 scoped_refptr<Core> core(this);
345
317 HandleReadResults(result); 346 HandleReadResults(result);
318 if (result >= 0) 347 if (result >= 0)
319 DoReadFromSocket(); 348 DoReadFromSocket();
320 } 349 }
321 350
322 void PseudoTcpAdapter::OnWritten(int result) { 351 void PseudoTcpAdapter::Core::OnWritten(int result) {
352 // Reference the Core in case a callback deletes the adapter.
353 scoped_refptr<Core> core(this);
354
323 socket_write_pending_ = false; 355 socket_write_pending_ = false;
324 if (result < 0) { 356 if (result < 0) {
325 LOG(WARNING) << "Write failed. Error code: " << result; 357 LOG(WARNING) << "Write failed. Error code: " << result;
326 } 358 }
327 } 359 }
328 360
329 void PseudoTcpAdapter::AdjustClock() { 361 void PseudoTcpAdapter::Core::AdjustClock() {
330 long timeout = 0; 362 long timeout = 0;
331 if (pseudotcp_.GetNextClock(PseudoTcp::Now(), timeout)) { 363 if (pseudo_tcp_.GetNextClock(PseudoTcp::Now(), timeout)) {
332 timer_.Stop(); 364 timer_.Stop();
333 timer_.Start(base::TimeDelta::FromMilliseconds(std::max(timeout, 0L)), this, 365 timer_.Start(base::TimeDelta::FromMilliseconds(std::max(timeout, 0L)), this,
334 &PseudoTcpAdapter::HandleTcpClock); 366 &PseudoTcpAdapter::Core::HandleTcpClock);
335 } 367 }
336 } 368 }
337 369
338 void PseudoTcpAdapter::HandleTcpClock() { 370 void PseudoTcpAdapter::Core::HandleTcpClock() {
339 pseudotcp_.NotifyClock(PseudoTcp::Now()); 371 // Reference the Core in case a callback deletes the adapter.
372 scoped_refptr<Core> core(this);
373
374 pseudo_tcp_.NotifyClock(PseudoTcp::Now());
340 AdjustClock(); 375 AdjustClock();
341 } 376 }
342 377
378 // Public interface implemention.
379
380 PseudoTcpAdapter::PseudoTcpAdapter(net::Socket* socket)
381 : core_(new Core(socket)) {
382 }
383
384 PseudoTcpAdapter::~PseudoTcpAdapter() {
385 Disconnect();
386 }
387
388 int PseudoTcpAdapter::Read(net::IOBuffer* buffer, int buffer_size,
389 net::CompletionCallback* callback) {
390 DCHECK(CalledOnValidThread());
391 return core_->Read(buffer, buffer_size, callback);
392 }
393
394 int PseudoTcpAdapter::Write(net::IOBuffer* buffer, int buffer_size,
395 net::CompletionCallback* callback) {
396 DCHECK(CalledOnValidThread());
397 return core_->Write(buffer, buffer_size, callback);
398 }
399
400 bool PseudoTcpAdapter::SetReceiveBufferSize(int32 size) {
401 DCHECK(CalledOnValidThread());
402 // TODO(sergeyu): Implement support for adjustable buffer size and
403 // used it here.
404 return false;
405 }
406
407 bool PseudoTcpAdapter::SetSendBufferSize(int32 size) {
408 DCHECK(CalledOnValidThread());
409 // TODO(sergeyu): Implement support for adjustable buffer size and
410 // used it here.
411 return false;
412 }
413
414 int PseudoTcpAdapter::Connect(net::CompletionCallback* callback) {
415 DCHECK(CalledOnValidThread());
416
417 // net::StreamSocket requires that Connect return OK if already connected.
418 if (IsConnected())
419 return net::OK;
420
421 return core_->Connect(callback);
422 }
423
424 void PseudoTcpAdapter::Disconnect() {
425 DCHECK(CalledOnValidThread());
426 core_->Disconnect();
427 }
428
429 bool PseudoTcpAdapter::IsConnected() const {
430 return core_->IsConnected();
431 }
432
433 bool PseudoTcpAdapter::IsConnectedAndIdle() const {
434 DCHECK(CalledOnValidThread());
435 NOTIMPLEMENTED();
436 return false;
437 }
438
439 int PseudoTcpAdapter::GetPeerAddress(net::AddressList* address) const {
440 DCHECK(CalledOnValidThread());
441
442 // We actually don't know the peer address. Returning so the upper layers
443 // won't complain.
444 net::IPAddressNumber ip_address(4);
445 *address = net::AddressList::CreateFromIPAddress(ip_address, 0);
446 return net::OK;
447 }
448
449 int PseudoTcpAdapter::GetLocalAddress(net::IPEndPoint* address) const {
450 DCHECK(CalledOnValidThread());
451 NOTIMPLEMENTED();
452 return net::ERR_FAILED;
453 }
454
455 const net::BoundNetLog& PseudoTcpAdapter::NetLog() const {
456 DCHECK(CalledOnValidThread());
457 return net_log_;
458 }
459
460 void PseudoTcpAdapter::SetSubresourceSpeculation() {
461 DCHECK(CalledOnValidThread());
462 NOTIMPLEMENTED();
463 }
464
465 void PseudoTcpAdapter::SetOmniboxSpeculation() {
466 DCHECK(CalledOnValidThread());
467 NOTIMPLEMENTED();
468 }
469
470 bool PseudoTcpAdapter::WasEverUsed() const {
471 DCHECK(CalledOnValidThread());
472 NOTIMPLEMENTED();
473 return true;
474 }
475
476 bool PseudoTcpAdapter::UsingTCPFastOpen() const {
477 DCHECK(CalledOnValidThread());
478 return false;
479 }
480
343 } // namespace jingle_glue 481 } // namespace jingle_glue
OLDNEW
« no previous file with comments | « jingle/glue/pseudotcp_adapter.h ('k') | jingle/glue/pseudotcp_adapter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698