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 | |
| 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 |