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 // 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 |
OLD | NEW |