| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/socket/socket_bio_adapter.h" |
| 6 |
| 7 #include <openssl/bio.h> |
| 8 #include <string.h> |
| 9 |
| 10 #include <algorithm> |
| 11 |
| 12 #include "base/bind.h" |
| 13 #include "base/location.h" |
| 14 #include "base/logging.h" |
| 15 #include "base/threading/thread_task_runner_handle.h" |
| 16 #include "net/base/io_buffer.h" |
| 17 #include "net/base/net_errors.h" |
| 18 #include "net/socket/stream_socket.h" |
| 19 #include "net/ssl/openssl_ssl_util.h" |
| 20 |
| 21 namespace net { |
| 22 |
| 23 SocketBIOAdapter::SocketBIOAdapter(StreamSocket* socket, |
| 24 int read_buffer_capacity, |
| 25 int write_buffer_capacity, |
| 26 Delegate* delegate) |
| 27 : socket_(socket), |
| 28 read_buffer_capacity_(read_buffer_capacity), |
| 29 read_offset_(0), |
| 30 read_result_(0), |
| 31 write_buffer_capacity_(write_buffer_capacity), |
| 32 write_buffer_used_(0), |
| 33 write_error_(OK), |
| 34 delegate_(delegate), |
| 35 weak_factory_(this) { |
| 36 bio_.reset(BIO_new(&kBIOMethod)); |
| 37 bio_->ptr = this; |
| 38 bio_->init = 1; |
| 39 |
| 40 read_callback_ = base::Bind(&SocketBIOAdapter::OnSocketReadComplete, |
| 41 weak_factory_.GetWeakPtr()); |
| 42 write_callback_ = base::Bind(&SocketBIOAdapter::OnSocketWriteComplete, |
| 43 weak_factory_.GetWeakPtr()); |
| 44 } |
| 45 |
| 46 SocketBIOAdapter::~SocketBIOAdapter() { |
| 47 // BIOs are reference-counted and may outlive the adapter. Clear the pointer |
| 48 // so future operations fail. |
| 49 bio_->ptr = nullptr; |
| 50 } |
| 51 |
| 52 bool SocketBIOAdapter::HasPendingReadData() { |
| 53 return read_result_ > 0; |
| 54 } |
| 55 |
| 56 int SocketBIOAdapter::BIORead(char* out, int len) { |
| 57 if (len <= 0) |
| 58 return len; |
| 59 |
| 60 // If there is no result available synchronously, report any Write() errors |
| 61 // that were observed. Otherwise the application may have encountered a socket |
| 62 // error while writing that would otherwise not be reported until the |
| 63 // application attempted to write again - which it may never do. See |
| 64 // https://crbug.com/249848. |
| 65 if (write_error_ != OK && write_error_ != ERR_IO_PENDING && |
| 66 (read_result_ == 0 || read_result_ == ERR_IO_PENDING)) { |
| 67 OpenSSLPutNetError(FROM_HERE, write_error_); |
| 68 return -1; |
| 69 } |
| 70 |
| 71 if (read_result_ == 0) { |
| 72 // Instantiate the read buffer and read from the socket. Although only |len| |
| 73 // bytes were requested, intentionally read to the full buffer size. The SSL |
| 74 // layer reads the record header and body in separate reads to avoid |
| 75 // overreading, but issuing one is more efficient. SSL sockets are not |
| 76 // reused after shutdown for non-SSL traffic, so overreading is fine. |
| 77 DCHECK(!read_buffer_); |
| 78 DCHECK_EQ(0, read_offset_); |
| 79 read_buffer_ = new IOBuffer(read_buffer_capacity_); |
| 80 int result = socket_->Read(read_buffer_.get(), read_buffer_capacity_, |
| 81 read_callback_); |
| 82 if (result == ERR_IO_PENDING) { |
| 83 read_result_ = ERR_IO_PENDING; |
| 84 } else { |
| 85 HandleSocketReadResult(result); |
| 86 } |
| 87 } |
| 88 |
| 89 // There is a pending Read(). Inform the caller to retry when it completes. |
| 90 if (read_result_ == ERR_IO_PENDING) { |
| 91 BIO_set_retry_read(bio()); |
| 92 return -1; |
| 93 } |
| 94 |
| 95 // If the last Read() failed, report the error. |
| 96 if (read_result_ < 0) { |
| 97 OpenSSLPutNetError(FROM_HERE, read_result_); |
| 98 return -1; |
| 99 } |
| 100 |
| 101 // Report the result of the last Read() if non-empty. |
| 102 CHECK_LT(read_offset_, read_result_); |
| 103 len = std::min(len, read_result_ - read_offset_); |
| 104 memcpy(out, read_buffer_->data() + read_offset_, len); |
| 105 read_offset_ += len; |
| 106 |
| 107 // Release the buffer when empty. |
| 108 if (read_offset_ == read_result_) { |
| 109 read_buffer_ = nullptr; |
| 110 read_offset_ = 0; |
| 111 read_result_ = 0; |
| 112 } |
| 113 |
| 114 return len; |
| 115 } |
| 116 |
| 117 void SocketBIOAdapter::HandleSocketReadResult(int result) { |
| 118 DCHECK_NE(ERR_IO_PENDING, result); |
| 119 |
| 120 // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here, so that higher |
| 121 // levels don't report success. |
| 122 if (result == 0) |
| 123 result = ERR_CONNECTION_CLOSED; |
| 124 |
| 125 read_result_ = result; |
| 126 |
| 127 // The read buffer is no longer needed. |
| 128 if (read_result_ <= 0) |
| 129 read_buffer_ = nullptr; |
| 130 } |
| 131 |
| 132 void SocketBIOAdapter::OnSocketReadComplete(int result) { |
| 133 DCHECK_EQ(ERR_IO_PENDING, read_result_); |
| 134 |
| 135 HandleSocketReadResult(result); |
| 136 delegate_->OnReadReady(); |
| 137 } |
| 138 |
| 139 int SocketBIOAdapter::BIOWrite(const char* in, int len) { |
| 140 if (len <= 0) |
| 141 return len; |
| 142 |
| 143 // If the write buffer is not empty, there must be a pending Write() to flush |
| 144 // it. |
| 145 DCHECK(write_buffer_used_ == 0 || write_error_ == ERR_IO_PENDING); |
| 146 |
| 147 // If a previous Write() failed, report the error. |
| 148 if (write_error_ != OK && write_error_ != ERR_IO_PENDING) { |
| 149 OpenSSLPutNetError(FROM_HERE, write_error_); |
| 150 return -1; |
| 151 } |
| 152 |
| 153 // Instantiate the write buffer if needed. |
| 154 if (!write_buffer_) { |
| 155 DCHECK_EQ(0, write_buffer_used_); |
| 156 write_buffer_ = new GrowableIOBuffer; |
| 157 write_buffer_->SetCapacity(write_buffer_capacity_); |
| 158 } |
| 159 |
| 160 // If the ring buffer is full, inform the caller to try again later. |
| 161 if (write_buffer_used_ == write_buffer_->capacity()) { |
| 162 BIO_set_retry_write(bio()); |
| 163 return -1; |
| 164 } |
| 165 |
| 166 int bytes_copied = 0; |
| 167 |
| 168 // If there is space after the offset, fill it. |
| 169 if (write_buffer_used_ < write_buffer_->RemainingCapacity()) { |
| 170 int chunk = |
| 171 std::min(write_buffer_->RemainingCapacity() - write_buffer_used_, len); |
| 172 memcpy(write_buffer_->data() + write_buffer_used_, in, chunk); |
| 173 in += chunk; |
| 174 len -= chunk; |
| 175 bytes_copied += chunk; |
| 176 write_buffer_used_ += chunk; |
| 177 } |
| 178 |
| 179 // If there is still space for remaining data, try to wrap around. |
| 180 if (len > 0 && write_buffer_used_ < write_buffer_->capacity()) { |
| 181 // If there were any room after the offset, the previous branch would have |
| 182 // filled it. |
| 183 CHECK_LE(write_buffer_->RemainingCapacity(), write_buffer_used_); |
| 184 int write_offset = write_buffer_used_ - write_buffer_->RemainingCapacity(); |
| 185 int chunk = std::min(len, write_buffer_->capacity() - write_buffer_used_); |
| 186 memcpy(write_buffer_->StartOfBuffer() + write_offset, in, chunk); |
| 187 in += chunk; |
| 188 len -= chunk; |
| 189 bytes_copied += chunk; |
| 190 write_buffer_used_ += chunk; |
| 191 } |
| 192 |
| 193 // Either the buffer is now full or there is no more input. |
| 194 DCHECK(len == 0 || write_buffer_used_ == write_buffer_->capacity()); |
| 195 |
| 196 // Schedule a socket Write() if necessary. (The ring buffer may previously |
| 197 // have been empty.) |
| 198 SocketWrite(); |
| 199 |
| 200 // If a read-interrupting write error was synchronously discovered, |
| 201 // asynchronously notify OnReadReady. See https://crbug.com/249848. Avoid |
| 202 // reentrancy by deferring it to a later event loop iteration. |
| 203 if (write_error_ != OK && write_error_ != ERR_IO_PENDING && |
| 204 read_result_ == ERR_IO_PENDING) { |
| 205 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 206 FROM_HERE, base::Bind(&SocketBIOAdapter::CallOnReadReady, |
| 207 weak_factory_.GetWeakPtr())); |
| 208 } |
| 209 |
| 210 return bytes_copied; |
| 211 } |
| 212 |
| 213 void SocketBIOAdapter::SocketWrite() { |
| 214 while (write_error_ == OK && write_buffer_used_ > 0) { |
| 215 int write_size = |
| 216 std::min(write_buffer_used_, write_buffer_->RemainingCapacity()); |
| 217 int result = |
| 218 socket_->Write(write_buffer_.get(), write_size, write_callback_); |
| 219 if (result == ERR_IO_PENDING) { |
| 220 write_error_ = ERR_IO_PENDING; |
| 221 return; |
| 222 } |
| 223 |
| 224 HandleSocketWriteResult(result); |
| 225 } |
| 226 } |
| 227 |
| 228 void SocketBIOAdapter::HandleSocketWriteResult(int result) { |
| 229 DCHECK_NE(ERR_IO_PENDING, result); |
| 230 |
| 231 if (result < 0) { |
| 232 write_error_ = result; |
| 233 |
| 234 // The write buffer is no longer needed. |
| 235 write_buffer_ = nullptr; |
| 236 write_buffer_used_ = 0; |
| 237 return; |
| 238 } |
| 239 |
| 240 // Advance the ring buffer. |
| 241 write_buffer_->set_offset(write_buffer_->offset() + result); |
| 242 write_buffer_used_ -= result; |
| 243 if (write_buffer_->RemainingCapacity() == 0) |
| 244 write_buffer_->set_offset(0); |
| 245 write_error_ = OK; |
| 246 |
| 247 // Release the write buffer if empty. |
| 248 if (write_buffer_used_ == 0) |
| 249 write_buffer_ = nullptr; |
| 250 } |
| 251 |
| 252 void SocketBIOAdapter::OnSocketWriteComplete(int result) { |
| 253 DCHECK_EQ(ERR_IO_PENDING, write_error_); |
| 254 |
| 255 bool was_full = write_buffer_used_ == write_buffer_->capacity(); |
| 256 |
| 257 HandleSocketWriteResult(result); |
| 258 SocketWrite(); |
| 259 |
| 260 // If transitioning from being unable to accept data to being able to, signal |
| 261 // OnWriteReady. |
| 262 if (was_full) { |
| 263 base::WeakPtr<SocketBIOAdapter> guard(weak_factory_.GetWeakPtr()); |
| 264 delegate_->OnWriteReady(); |
| 265 // OnWriteReady may delete the adapter. |
| 266 if (!guard) |
| 267 return; |
| 268 } |
| 269 |
| 270 // Write errors are fed back into BIO_read once the read buffer is empty. If |
| 271 // BIO_read is currently blocked, signal early that a read result is ready. |
| 272 if (result < 0 && read_result_ == ERR_IO_PENDING) |
| 273 delegate_->OnReadReady(); |
| 274 } |
| 275 |
| 276 void SocketBIOAdapter::CallOnReadReady() { |
| 277 if (read_result_ == ERR_IO_PENDING) |
| 278 delegate_->OnReadReady(); |
| 279 } |
| 280 |
| 281 SocketBIOAdapter* SocketBIOAdapter::GetAdapter(BIO* bio) { |
| 282 DCHECK_EQ(&kBIOMethod, bio->method); |
| 283 SocketBIOAdapter* adapter = reinterpret_cast<SocketBIOAdapter*>(bio->ptr); |
| 284 if (adapter) |
| 285 DCHECK_EQ(bio, adapter->bio()); |
| 286 return adapter; |
| 287 } |
| 288 |
| 289 int SocketBIOAdapter::BIOWriteWrapper(BIO* bio, const char* in, int len) { |
| 290 BIO_clear_retry_flags(bio); |
| 291 |
| 292 SocketBIOAdapter* adapter = GetAdapter(bio); |
| 293 if (!adapter) { |
| 294 OpenSSLPutNetError(FROM_HERE, ERR_UNEXPECTED); |
| 295 return -1; |
| 296 } |
| 297 |
| 298 return adapter->BIOWrite(in, len); |
| 299 } |
| 300 |
| 301 int SocketBIOAdapter::BIOReadWrapper(BIO* bio, char* out, int len) { |
| 302 BIO_clear_retry_flags(bio); |
| 303 |
| 304 SocketBIOAdapter* adapter = GetAdapter(bio); |
| 305 if (!adapter) { |
| 306 OpenSSLPutNetError(FROM_HERE, ERR_UNEXPECTED); |
| 307 return -1; |
| 308 } |
| 309 |
| 310 return adapter->BIORead(out, len); |
| 311 } |
| 312 |
| 313 long SocketBIOAdapter::BIOCtrlWrapper(BIO* bio, |
| 314 int cmd, |
| 315 long larg, |
| 316 void* parg) { |
| 317 switch (cmd) { |
| 318 case BIO_CTRL_FLUSH: |
| 319 // The SSL stack requires BIOs handle BIO_flush. |
| 320 return 1; |
| 321 } |
| 322 |
| 323 NOTIMPLEMENTED(); |
| 324 return 0; |
| 325 } |
| 326 |
| 327 const BIO_METHOD SocketBIOAdapter::kBIOMethod = { |
| 328 0, // type (unused) |
| 329 nullptr, // name (unused) |
| 330 SocketBIOAdapter::BIOWriteWrapper, |
| 331 SocketBIOAdapter::BIOReadWrapper, |
| 332 nullptr, // puts |
| 333 nullptr, // gets |
| 334 SocketBIOAdapter::BIOCtrlWrapper, |
| 335 nullptr, // create |
| 336 nullptr, // destroy |
| 337 nullptr, // callback_ctrl |
| 338 }; |
| 339 |
| 340 } // namespace net |
| OLD | NEW |