OLD | NEW |
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 pseudo_tcp_.Close(true); |
136 } | 207 } |
137 | 208 |
138 bool PseudoTcpAdapter::IsConnected() const { | 209 bool PseudoTcpAdapter::Core::IsConnected() const { |
139 DCHECK(CalledOnValidThread()); | 210 return pseudo_tcp_.State() == PseudoTcp::TCP_ESTABLISHED; |
140 return pseudotcp_.State() == PseudoTcp::TCP_ESTABLISHED; | |
141 } | 211 } |
142 | 212 |
143 bool PseudoTcpAdapter::IsConnectedAndIdle() const { | 213 void PseudoTcpAdapter::Core::OnTcpOpen(PseudoTcp* tcp) { |
144 DCHECK(CalledOnValidThread()); | 214 DCHECK(tcp == &pseudo_tcp_); |
145 NOTIMPLEMENTED(); | |
146 return false; | |
147 } | |
148 | 215 |
149 int PseudoTcpAdapter::GetPeerAddress(net::AddressList* address) const { | 216 if (connect_callback_) { |
150 DCHECK(CalledOnValidThread()); | 217 net::CompletionCallback* callback = connect_callback_; |
151 | 218 connect_callback_ = NULL; |
152 // We actually don't know the peer address. Returning so the upper layers | 219 callback->Run(net::OK); |
153 // won't complain. | 220 } |
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 | 221 |
197 OnTcpReadable(tcp); | 222 OnTcpReadable(tcp); |
198 OnTcpWriteable(tcp); | 223 OnTcpWriteable(tcp); |
199 } | 224 } |
200 | 225 |
201 void PseudoTcpAdapter::OnTcpReadable(PseudoTcp* tcp) { | 226 void PseudoTcpAdapter::Core::OnTcpReadable(PseudoTcp* tcp) { |
202 DCHECK(CalledOnValidThread()); | 227 DCHECK_EQ(tcp, &pseudo_tcp_); |
203 | 228 if (!read_callback_) |
204 if (!read_buffer_) | |
205 return; | 229 return; |
206 | 230 |
207 // Try to send the data we have pending. | 231 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) { | 232 if (result < 0) { |
210 result = net::MapSystemError(pseudotcp_.GetError()); | 233 result = net::MapSystemError(pseudo_tcp_.GetError()); |
211 DCHECK(result < 0); | 234 DCHECK(result < 0); |
212 if (result == net::ERR_IO_PENDING) | 235 if (result == net::ERR_IO_PENDING) |
213 return; | 236 return; |
214 } | 237 } |
215 | 238 |
216 AdjustClock(); | 239 AdjustClock(); |
217 | 240 |
218 net::CompletionCallback* cb = read_callback_; | 241 net::CompletionCallback* callback = read_callback_; |
219 read_callback_ = NULL; | 242 read_callback_ = NULL; |
220 read_buffer_ = NULL; | 243 read_buffer_ = NULL; |
221 cb->Run(result); | 244 callback->Run(result); |
222 } | 245 } |
223 | 246 |
224 void PseudoTcpAdapter::OnTcpWriteable(PseudoTcp* tcp) { | 247 void PseudoTcpAdapter::Core::OnTcpWriteable(PseudoTcp* tcp) { |
225 DCHECK(CalledOnValidThread()); | 248 DCHECK_EQ(tcp, &pseudo_tcp_); |
226 | 249 if (!write_callback_) |
227 if (!write_buffer_) | |
228 return; | 250 return; |
229 | 251 |
230 // Try to send the data we have pending. | 252 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) { | 253 if (result < 0) { |
233 result = net::MapSystemError(pseudotcp_.GetError()); | 254 result = net::MapSystemError(pseudo_tcp_.GetError()); |
234 DCHECK(result < 0); | 255 DCHECK(result < 0); |
235 if (result == net::ERR_IO_PENDING) | 256 if (result == net::ERR_IO_PENDING) |
236 return; | 257 return; |
237 } | 258 } |
238 | 259 |
239 AdjustClock(); | 260 AdjustClock(); |
240 | 261 |
241 net::CompletionCallback* cb = write_callback_; | 262 net::CompletionCallback* callback = write_callback_; |
242 write_callback_ = NULL; | 263 write_callback_ = NULL; |
243 write_buffer_ = NULL; | 264 write_buffer_ = NULL; |
244 cb->Run(result); | 265 callback->Run(result); |
245 } | 266 } |
246 | 267 |
247 void PseudoTcpAdapter::OnTcpClosed(PseudoTcp* tcp, uint32 error) { | 268 void PseudoTcpAdapter::Core::OnTcpClosed(PseudoTcp* tcp, uint32 error) { |
248 DCHECK(CalledOnValidThread()); | 269 DCHECK_EQ(tcp, &pseudo_tcp_); |
249 | 270 |
250 if (connect_callback_) { | 271 if (connect_callback_) { |
251 connect_callback_->Run(net::MapSystemError(error)); | 272 net::CompletionCallback* callback = connect_callback_; |
252 connect_callback_ = NULL; | 273 connect_callback_ = NULL; |
| 274 callback->Run(net::MapSystemError(error)); |
253 } | 275 } |
254 | 276 |
255 if (read_callback_) { | 277 if (read_callback_) { |
256 read_callback_->Run(net::MapSystemError(error)); | 278 net::CompletionCallback* callback = read_callback_; |
257 read_callback_ = NULL; | 279 read_callback_ = NULL; |
| 280 callback->Run(net::MapSystemError(error)); |
258 } | 281 } |
259 | 282 |
260 if (write_callback_) { | 283 if (write_callback_) { |
261 write_callback_->Run(net::MapSystemError(error)); | 284 net::CompletionCallback* callback = write_callback_; |
262 write_callback_ = NULL; | 285 write_callback_ = NULL; |
| 286 callback->Run(net::MapSystemError(error)); |
263 } | 287 } |
264 } | 288 } |
265 | 289 |
266 cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::TcpWritePacket( | 290 cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::Core::TcpWritePacket( |
267 PseudoTcp* tcp, | 291 PseudoTcp* tcp, |
268 const char* buffer, | 292 const char* buffer, |
269 size_t len) { | 293 size_t len) { |
270 DCHECK(CalledOnValidThread()); | 294 DCHECK_EQ(tcp, &pseudo_tcp_); |
271 | 295 |
272 if (socket_write_pending_) | 296 if (socket_write_pending_) |
273 return IPseudoTcpNotify::WR_SUCCESS; | 297 return IPseudoTcpNotify::WR_SUCCESS; |
274 | 298 |
275 scoped_refptr<net::IOBuffer> write_buffer = new net::IOBuffer(len); | 299 scoped_refptr<net::IOBuffer> write_buffer = new net::IOBuffer(len); |
276 memcpy(write_buffer->data(), buffer, len); | 300 memcpy(write_buffer->data(), buffer, len); |
277 | 301 |
278 int result = socket_->Write(write_buffer, len, &socket_write_callback_); | 302 int result = socket_->Write(write_buffer, len, &socket_write_callback_); |
279 if (result == net::ERR_IO_PENDING) { | 303 if (result == net::ERR_IO_PENDING) { |
280 socket_write_pending_ = true; | 304 socket_write_pending_ = true; |
281 return IPseudoTcpNotify::WR_SUCCESS; | 305 return IPseudoTcpNotify::WR_SUCCESS; |
282 } if (result == net::ERR_MSG_TOO_BIG) { | 306 } if (result == net::ERR_MSG_TOO_BIG) { |
283 return IPseudoTcpNotify::WR_TOO_LARGE; | 307 return IPseudoTcpNotify::WR_TOO_LARGE; |
284 } else if (result < 0) { | 308 } else if (result < 0) { |
285 return IPseudoTcpNotify::WR_FAIL; | 309 return IPseudoTcpNotify::WR_FAIL; |
286 } else { | 310 } else { |
287 return IPseudoTcpNotify::WR_SUCCESS; | 311 return IPseudoTcpNotify::WR_SUCCESS; |
288 } | 312 } |
289 } | 313 } |
290 | 314 |
291 void PseudoTcpAdapter::DoReadFromSocket() { | 315 void PseudoTcpAdapter::Core::DoReadFromSocket() { |
292 if (!socket_read_buffer_) { | 316 if (!socket_read_buffer_) |
293 socket_read_buffer_ = new net::IOBuffer(kReadBufferSize); | 317 socket_read_buffer_ = new net::IOBuffer(kReadBufferSize); |
294 } | |
295 | 318 |
296 while (true) { | 319 while (true) { |
297 int result = socket_->Read(socket_read_buffer_, kReadBufferSize, | 320 int result = socket_->Read(socket_read_buffer_, kReadBufferSize, |
298 &socket_read_callback_); | 321 &socket_read_callback_); |
299 if (result == net::ERR_IO_PENDING) | 322 if (result == net::ERR_IO_PENDING) |
300 break; | 323 break; |
301 | 324 |
302 HandleReadResults(result); | 325 HandleReadResults(result); |
303 } | 326 } |
304 } | 327 } |
305 | 328 |
306 void PseudoTcpAdapter::HandleReadResults(int result) { | 329 void PseudoTcpAdapter::Core::HandleReadResults(int result) { |
307 if (result <= 0) { | 330 if (result <= 0) { |
308 LOG(ERROR) << "Read returned " << result; | 331 LOG(ERROR) << "Read returned " << result; |
309 return; | 332 return; |
310 } | 333 } |
311 | 334 |
312 pseudotcp_.NotifyPacket(socket_read_buffer_->data(), result); | 335 // TODO(wez): Disconnect on failure of NotifyPacket? |
| 336 pseudo_tcp_.NotifyPacket(socket_read_buffer_->data(), result); |
313 AdjustClock(); | 337 AdjustClock(); |
314 } | 338 } |
315 | 339 |
316 void PseudoTcpAdapter::OnRead(int result) { | 340 void PseudoTcpAdapter::Core::OnRead(int result) { |
| 341 // Reference the Core in case a callback deletes the adapter. |
| 342 scoped_refptr<Core> core(this); |
| 343 |
317 HandleReadResults(result); | 344 HandleReadResults(result); |
318 if (result >= 0) | 345 if (result >= 0) |
319 DoReadFromSocket(); | 346 DoReadFromSocket(); |
320 } | 347 } |
321 | 348 |
322 void PseudoTcpAdapter::OnWritten(int result) { | 349 void PseudoTcpAdapter::Core::OnWritten(int result) { |
| 350 // Reference the Core in case a callback deletes the adapter. |
| 351 scoped_refptr<Core> core(this); |
| 352 |
323 socket_write_pending_ = false; | 353 socket_write_pending_ = false; |
324 if (result < 0) { | 354 if (result < 0) { |
325 LOG(WARNING) << "Write failed. Error code: " << result; | 355 LOG(WARNING) << "Write failed. Error code: " << result; |
326 } | 356 } |
327 } | 357 } |
328 | 358 |
329 void PseudoTcpAdapter::AdjustClock() { | 359 void PseudoTcpAdapter::Core::AdjustClock() { |
330 long timeout = 0; | 360 long timeout = 0; |
331 if (pseudotcp_.GetNextClock(PseudoTcp::Now(), timeout)) { | 361 if (pseudo_tcp_.GetNextClock(PseudoTcp::Now(), timeout)) { |
332 timer_.Stop(); | 362 timer_.Stop(); |
333 timer_.Start(base::TimeDelta::FromMilliseconds(std::max(timeout, 0L)), this, | 363 timer_.Start(base::TimeDelta::FromMilliseconds(std::max(timeout, 0L)), this, |
334 &PseudoTcpAdapter::HandleTcpClock); | 364 &PseudoTcpAdapter::Core::HandleTcpClock); |
335 } | 365 } |
336 } | 366 } |
337 | 367 |
338 void PseudoTcpAdapter::HandleTcpClock() { | 368 void PseudoTcpAdapter::Core::HandleTcpClock() { |
339 pseudotcp_.NotifyClock(PseudoTcp::Now()); | 369 // Reference the Core in case a callback deletes the adapter. |
| 370 scoped_refptr<Core> core(this); |
| 371 |
| 372 pseudo_tcp_.NotifyClock(PseudoTcp::Now()); |
340 AdjustClock(); | 373 AdjustClock(); |
341 } | 374 } |
342 | 375 |
| 376 // Public interface implemention. |
| 377 |
| 378 PseudoTcpAdapter::PseudoTcpAdapter(net::Socket* socket) |
| 379 : core_(new Core(socket)) { |
| 380 } |
| 381 |
| 382 PseudoTcpAdapter::~PseudoTcpAdapter() { |
| 383 Disconnect(); |
| 384 } |
| 385 |
| 386 int PseudoTcpAdapter::Read(net::IOBuffer* buffer, int buffer_size, |
| 387 net::CompletionCallback* callback) { |
| 388 DCHECK(CalledOnValidThread()); |
| 389 return core_->Read(buffer, buffer_size, callback); |
| 390 } |
| 391 |
| 392 int PseudoTcpAdapter::Write(net::IOBuffer* buffer, int buffer_size, |
| 393 net::CompletionCallback* callback) { |
| 394 DCHECK(CalledOnValidThread()); |
| 395 return core_->Write(buffer, buffer_size, callback); |
| 396 } |
| 397 |
| 398 bool PseudoTcpAdapter::SetReceiveBufferSize(int32 size) { |
| 399 DCHECK(CalledOnValidThread()); |
| 400 // TODO(sergeyu): Implement support for adjustable buffer size and |
| 401 // used it here. |
| 402 return false; |
| 403 } |
| 404 |
| 405 bool PseudoTcpAdapter::SetSendBufferSize(int32 size) { |
| 406 DCHECK(CalledOnValidThread()); |
| 407 // TODO(sergeyu): Implement support for adjustable buffer size and |
| 408 // used it here. |
| 409 return false; |
| 410 } |
| 411 |
| 412 int PseudoTcpAdapter::Connect(net::CompletionCallback* callback) { |
| 413 DCHECK(CalledOnValidThread()); |
| 414 |
| 415 // net::StreamSocket requires that Connect return OK if already connected. |
| 416 if (IsConnected()) |
| 417 return net::OK; |
| 418 |
| 419 return core_->Connect(callback); |
| 420 } |
| 421 |
| 422 void PseudoTcpAdapter::Disconnect() { |
| 423 DCHECK(CalledOnValidThread()); |
| 424 core_->Disconnect(); |
| 425 } |
| 426 |
| 427 bool PseudoTcpAdapter::IsConnected() const { |
| 428 return core_->IsConnected(); |
| 429 } |
| 430 |
| 431 bool PseudoTcpAdapter::IsConnectedAndIdle() const { |
| 432 DCHECK(CalledOnValidThread()); |
| 433 NOTIMPLEMENTED(); |
| 434 return false; |
| 435 } |
| 436 |
| 437 int PseudoTcpAdapter::GetPeerAddress(net::AddressList* address) const { |
| 438 DCHECK(CalledOnValidThread()); |
| 439 |
| 440 // We actually don't know the peer address. Returning so the upper layers |
| 441 // won't complain. |
| 442 net::IPAddressNumber ip_address(4); |
| 443 *address = net::AddressList::CreateFromIPAddress(ip_address, 0); |
| 444 return net::OK; |
| 445 } |
| 446 |
| 447 int PseudoTcpAdapter::GetLocalAddress(net::IPEndPoint* address) const { |
| 448 DCHECK(CalledOnValidThread()); |
| 449 NOTIMPLEMENTED(); |
| 450 return net::ERR_FAILED; |
| 451 } |
| 452 |
| 453 const net::BoundNetLog& PseudoTcpAdapter::NetLog() const { |
| 454 DCHECK(CalledOnValidThread()); |
| 455 return net_log_; |
| 456 } |
| 457 |
| 458 void PseudoTcpAdapter::SetSubresourceSpeculation() { |
| 459 DCHECK(CalledOnValidThread()); |
| 460 NOTIMPLEMENTED(); |
| 461 } |
| 462 |
| 463 void PseudoTcpAdapter::SetOmniboxSpeculation() { |
| 464 DCHECK(CalledOnValidThread()); |
| 465 NOTIMPLEMENTED(); |
| 466 } |
| 467 |
| 468 bool PseudoTcpAdapter::WasEverUsed() const { |
| 469 DCHECK(CalledOnValidThread()); |
| 470 NOTIMPLEMENTED(); |
| 471 return true; |
| 472 } |
| 473 |
| 474 bool PseudoTcpAdapter::UsingTCPFastOpen() const { |
| 475 DCHECK(CalledOnValidThread()); |
| 476 return false; |
| 477 } |
| 478 |
343 } // namespace jingle_glue | 479 } // namespace jingle_glue |
OLD | NEW |