Chromium Code Reviews| 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 |