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 | |
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_; | |
Sergey Ulanov
2011/05/23 20:09:05
Can we make them private, and make Core class a fr
Wez
2011/05/23 21:27:02
The only use for them was to support Disconnect()
| |
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 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::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 | 206 if (!read_callback_) |
204 if (!read_buffer_) | |
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 net::CompletionCallback* callback = read_callback_; |
219 read_callback_ = NULL; | 220 read_callback_ = NULL; |
220 read_buffer_ = NULL; | 221 read_buffer_ = NULL; |
221 cb->Run(result); | 222 callback->Run(result); |
222 } | 223 } |
223 | 224 |
224 void PseudoTcpAdapter::OnTcpWriteable(PseudoTcp* tcp) { | 225 void PseudoTcpAdapter::Core::OnTcpWriteable(PseudoTcp* tcp) { |
225 DCHECK(CalledOnValidThread()); | 226 DCHECK_EQ(tcp, &pseudo_tcp_); |
226 | 227 if (!write_callback_) |
227 if (!write_buffer_) | |
228 return; | 228 return; |
229 | 229 |
230 // Try to send the data we have pending. | 230 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) { | 231 if (result < 0) { |
233 result = net::MapSystemError(pseudotcp_.GetError()); | 232 result = net::MapSystemError(pseudo_tcp_.GetError()); |
234 DCHECK(result < 0); | 233 DCHECK(result < 0); |
235 if (result == net::ERR_IO_PENDING) | 234 if (result == net::ERR_IO_PENDING) |
236 return; | 235 return; |
237 } | 236 } |
238 | 237 |
239 AdjustClock(); | 238 AdjustClock(); |
240 | 239 |
241 net::CompletionCallback* cb = write_callback_; | 240 net::CompletionCallback* callback = write_callback_; |
242 write_callback_ = NULL; | 241 write_callback_ = NULL; |
243 write_buffer_ = NULL; | 242 write_buffer_ = NULL; |
244 cb->Run(result); | 243 callback->Run(result); |
245 } | 244 } |
246 | 245 |
247 void PseudoTcpAdapter::OnTcpClosed(PseudoTcp* tcp, uint32 error) { | 246 void PseudoTcpAdapter::Core::OnTcpClosed(PseudoTcp* tcp, uint32 error) { |
248 DCHECK(CalledOnValidThread()); | 247 DCHECK_EQ(tcp, &pseudo_tcp_); |
249 | 248 |
250 if (connect_callback_) { | 249 if (connect_callback_) { |
251 connect_callback_->Run(net::MapSystemError(error)); | 250 net::CompletionCallback* callback = connect_callback_; |
252 connect_callback_ = NULL; | 251 connect_callback_ = NULL; |
252 callback->Run(net::MapSystemError(error)); | |
253 } | 253 } |
254 | 254 |
255 if (read_callback_) { | 255 if (read_callback_) { |
256 read_callback_->Run(net::MapSystemError(error)); | 256 net::CompletionCallback* callback = read_callback_; |
257 read_callback_ = NULL; | 257 read_callback_ = NULL; |
258 callback->Run(net::MapSystemError(error)); | |
258 } | 259 } |
259 | 260 |
260 if (write_callback_) { | 261 if (write_callback_) { |
261 write_callback_->Run(net::MapSystemError(error)); | 262 net::CompletionCallback* callback = write_callback_; |
262 write_callback_ = NULL; | 263 write_callback_ = NULL; |
264 callback->Run(net::MapSystemError(error)); | |
263 } | 265 } |
264 } | 266 } |
265 | 267 |
266 cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::TcpWritePacket( | 268 cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::Core::TcpWritePacket( |
267 PseudoTcp* tcp, | 269 PseudoTcp* tcp, |
268 const char* buffer, | 270 const char* buffer, |
269 size_t len) { | 271 size_t len) { |
270 DCHECK(CalledOnValidThread()); | 272 DCHECK_EQ(tcp, &pseudo_tcp_); |
271 | 273 |
272 if (socket_write_pending_) | 274 if (socket_write_pending_) |
273 return IPseudoTcpNotify::WR_SUCCESS; | 275 return IPseudoTcpNotify::WR_SUCCESS; |
274 | 276 |
275 scoped_refptr<net::IOBuffer> write_buffer = new net::IOBuffer(len); | 277 scoped_refptr<net::IOBuffer> write_buffer = new net::IOBuffer(len); |
276 memcpy(write_buffer->data(), buffer, len); | 278 memcpy(write_buffer->data(), buffer, len); |
277 | 279 |
278 int result = socket_->Write(write_buffer, len, &socket_write_callback_); | 280 int result = socket_->Write(write_buffer, len, &socket_write_callback_); |
279 if (result == net::ERR_IO_PENDING) { | 281 if (result == net::ERR_IO_PENDING) { |
280 socket_write_pending_ = true; | 282 socket_write_pending_ = true; |
281 return IPseudoTcpNotify::WR_SUCCESS; | 283 return IPseudoTcpNotify::WR_SUCCESS; |
282 } if (result == net::ERR_MSG_TOO_BIG) { | 284 } if (result == net::ERR_MSG_TOO_BIG) { |
283 return IPseudoTcpNotify::WR_TOO_LARGE; | 285 return IPseudoTcpNotify::WR_TOO_LARGE; |
284 } else if (result < 0) { | 286 } else if (result < 0) { |
285 return IPseudoTcpNotify::WR_FAIL; | 287 return IPseudoTcpNotify::WR_FAIL; |
286 } else { | 288 } else { |
287 return IPseudoTcpNotify::WR_SUCCESS; | 289 return IPseudoTcpNotify::WR_SUCCESS; |
288 } | 290 } |
289 } | 291 } |
290 | 292 |
291 void PseudoTcpAdapter::DoReadFromSocket() { | 293 void PseudoTcpAdapter::Core::DoReadFromSocket() { |
292 if (!socket_read_buffer_) { | 294 if (!socket_read_buffer_) |
293 socket_read_buffer_ = new net::IOBuffer(kReadBufferSize); | 295 socket_read_buffer_ = new net::IOBuffer(kReadBufferSize); |
294 } | |
295 | 296 |
296 while (true) { | 297 while (true) { |
297 int result = socket_->Read(socket_read_buffer_, kReadBufferSize, | 298 int result = socket_->Read(socket_read_buffer_, kReadBufferSize, |
298 &socket_read_callback_); | 299 &socket_read_callback_); |
299 if (result == net::ERR_IO_PENDING) | 300 if (result == net::ERR_IO_PENDING) |
300 break; | 301 break; |
301 | 302 |
302 HandleReadResults(result); | 303 HandleReadResults(result); |
303 } | 304 } |
304 } | 305 } |
305 | 306 |
306 void PseudoTcpAdapter::HandleReadResults(int result) { | 307 void PseudoTcpAdapter::Core::HandleReadResults(int result) { |
307 if (result <= 0) { | 308 if (result <= 0) { |
308 LOG(ERROR) << "Read returned " << result; | 309 LOG(ERROR) << "Read returned " << result; |
309 return; | 310 return; |
310 } | 311 } |
311 | 312 |
312 pseudotcp_.NotifyPacket(socket_read_buffer_->data(), result); | 313 // TODO(wez): Disconnect on failure of NotifyPacket? |
314 pseudo_tcp_.NotifyPacket(socket_read_buffer_->data(), result); | |
313 AdjustClock(); | 315 AdjustClock(); |
314 } | 316 } |
315 | 317 |
316 void PseudoTcpAdapter::OnRead(int result) { | 318 void PseudoTcpAdapter::Core::OnRead(int result) { |
319 // Reference the Core in case a callback deletes the adapter. | |
320 scoped_refptr<Core> core(this); | |
321 | |
317 HandleReadResults(result); | 322 HandleReadResults(result); |
318 if (result >= 0) | 323 if (result >= 0) |
319 DoReadFromSocket(); | 324 DoReadFromSocket(); |
320 } | 325 } |
321 | 326 |
322 void PseudoTcpAdapter::OnWritten(int result) { | 327 void PseudoTcpAdapter::Core::OnWritten(int result) { |
328 // Reference the Core in case a callback deletes the adapter. | |
329 scoped_refptr<Core> core(this); | |
330 | |
323 socket_write_pending_ = false; | 331 socket_write_pending_ = false; |
324 if (result < 0) { | 332 if (result < 0) { |
325 LOG(WARNING) << "Write failed. Error code: " << result; | 333 LOG(WARNING) << "Write failed. Error code: " << result; |
326 } | 334 } |
327 } | 335 } |
328 | 336 |
329 void PseudoTcpAdapter::AdjustClock() { | 337 void PseudoTcpAdapter::Core::AdjustClock() { |
330 long timeout = 0; | 338 long timeout = 0; |
331 if (pseudotcp_.GetNextClock(PseudoTcp::Now(), timeout)) { | 339 if (pseudo_tcp_.GetNextClock(PseudoTcp::Now(), timeout)) { |
332 timer_.Stop(); | 340 timer_.Stop(); |
333 timer_.Start(base::TimeDelta::FromMilliseconds(std::max(timeout, 0L)), this, | 341 timer_.Start(base::TimeDelta::FromMilliseconds(std::max(timeout, 0L)), this, |
334 &PseudoTcpAdapter::HandleTcpClock); | 342 &PseudoTcpAdapter::Core::HandleTcpClock); |
335 } | 343 } |
336 } | 344 } |
337 | 345 |
338 void PseudoTcpAdapter::HandleTcpClock() { | 346 void PseudoTcpAdapter::Core::HandleTcpClock() { |
339 pseudotcp_.NotifyClock(PseudoTcp::Now()); | 347 // Reference the Core in case a callback deletes the adapter. |
348 scoped_refptr<Core> core(this); | |
349 | |
350 pseudo_tcp_.NotifyClock(PseudoTcp::Now()); | |
340 AdjustClock(); | 351 AdjustClock(); |
341 } | 352 } |
342 | 353 |
354 // Public interface implemention. | |
355 | |
356 PseudoTcpAdapter::PseudoTcpAdapter(net::Socket* socket) | |
357 : core_(new Core(socket)) { | |
358 } | |
359 | |
360 PseudoTcpAdapter::~PseudoTcpAdapter() { | |
361 core_->connect_callback_ = NULL; | |
Sergey Ulanov
2011/05/23 20:09:05
Do we also need to reset read/write buffers? Maybe
Wez
2011/05/23 21:27:02
I've moved clearing of the callbacks and PseudoTcp
| |
362 core_->read_callback_ = NULL; | |
363 core_->write_callback_ = NULL; | |
364 } | |
365 | |
366 int PseudoTcpAdapter::Read(net::IOBuffer* buffer, int buffer_size, | |
367 net::CompletionCallback* callback) { | |
368 DCHECK(CalledOnValidThread()); | |
369 return core_->Read(buffer, buffer_size, callback); | |
370 } | |
371 | |
372 int PseudoTcpAdapter::Write(net::IOBuffer* buffer, int buffer_size, | |
373 net::CompletionCallback* callback) { | |
374 DCHECK(CalledOnValidThread()); | |
375 return core_->Write(buffer, buffer_size, callback); | |
376 } | |
377 | |
378 bool PseudoTcpAdapter::SetReceiveBufferSize(int32 size) { | |
379 DCHECK(CalledOnValidThread()); | |
380 // TODO(sergeyu): Implement support for adjustable buffer size and | |
381 // used it here. | |
382 return false; | |
383 } | |
384 | |
385 bool PseudoTcpAdapter::SetSendBufferSize(int32 size) { | |
386 DCHECK(CalledOnValidThread()); | |
387 // TODO(sergeyu): Implement support for adjustable buffer size and | |
388 // used it here. | |
389 return false; | |
390 } | |
391 | |
392 int PseudoTcpAdapter::Connect(net::CompletionCallback* callback) { | |
393 DCHECK(CalledOnValidThread()); | |
394 | |
395 // net::StreamSocket requires that Connect return OK if already connected. | |
396 if (IsConnected()) | |
397 return net::OK; | |
398 | |
399 return core_->Connect(callback); | |
400 } | |
401 | |
402 void PseudoTcpAdapter::Disconnect() { | |
403 DCHECK(CalledOnValidThread()); | |
404 | |
405 // Don't dispatch outstanding callbacks, as mandated by net::StreamSocket. | |
406 core_->read_callback_ = NULL; | |
407 core_->write_callback_ = NULL; | |
408 core_->connect_callback_ = NULL; | |
409 | |
410 // TODO(wez): Connect should succeed if called after Disconnect, which | |
411 // PseudoTcp doesn't support, so we need to teardown the internal PseudoTcp | |
412 // and create a new one in Connect. | |
413 // TODO(wez): Close sets a shutdown flag inside PseudoTcp but has no other | |
414 // effect. This should be addressed in PseudoTcp, really. | |
415 // In the meantime we can fake OnTcpClosed notification and tear down the | |
416 // PseudoTcp. | |
417 // TODO(wez): The "force" parameter to Close() should be true, since the | |
418 // behaviour of disconnect is to dump any pending reads & writes. | |
419 core_->pseudo_tcp_.Close(false); | |
420 } | |
421 | |
422 bool PseudoTcpAdapter::IsConnected() const { | |
423 return core_->pseudo_tcp_.State() == PseudoTcp::TCP_ESTABLISHED; | |
424 } | |
425 | |
426 bool PseudoTcpAdapter::IsConnectedAndIdle() const { | |
427 DCHECK(CalledOnValidThread()); | |
428 NOTIMPLEMENTED(); | |
429 return false; | |
430 } | |
431 | |
432 int PseudoTcpAdapter::GetPeerAddress(net::AddressList* address) const { | |
433 DCHECK(CalledOnValidThread()); | |
434 | |
435 // We actually don't know the peer address. Returning so the upper layers | |
436 // won't complain. | |
437 net::IPAddressNumber ip_address(4); | |
438 *address = net::AddressList::CreateFromIPAddress(ip_address, 0); | |
439 return net::OK; | |
440 } | |
441 | |
442 int PseudoTcpAdapter::GetLocalAddress(net::IPEndPoint* address) const { | |
443 DCHECK(CalledOnValidThread()); | |
444 NOTIMPLEMENTED(); | |
445 return net::ERR_FAILED; | |
446 } | |
447 | |
448 const net::BoundNetLog& PseudoTcpAdapter::NetLog() const { | |
449 DCHECK(CalledOnValidThread()); | |
450 return net_log_; | |
451 } | |
452 | |
453 void PseudoTcpAdapter::SetSubresourceSpeculation() { | |
454 DCHECK(CalledOnValidThread()); | |
455 NOTIMPLEMENTED(); | |
456 } | |
457 | |
458 void PseudoTcpAdapter::SetOmniboxSpeculation() { | |
459 DCHECK(CalledOnValidThread()); | |
460 NOTIMPLEMENTED(); | |
461 } | |
462 | |
463 bool PseudoTcpAdapter::WasEverUsed() const { | |
464 DCHECK(CalledOnValidThread()); | |
465 NOTIMPLEMENTED(); | |
466 return true; | |
467 } | |
468 | |
469 bool PseudoTcpAdapter::UsingTCPFastOpen() const { | |
470 DCHECK(CalledOnValidThread()); | |
471 return false; | |
472 } | |
473 | |
343 } // namespace jingle_glue | 474 } // namespace jingle_glue |
OLD | NEW |