Chromium Code Reviews| Index: net/socket/ssl_client_socket_openssl.cc |
| diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc |
| index d6345f71501d2acc3e20384943045d90ebdfa846..f30715d3577088092683bb0025724c7d2fc71a03 100644 |
| --- a/net/socket/ssl_client_socket_openssl.cc |
| +++ b/net/socket/ssl_client_socket_openssl.cc |
| @@ -1277,10 +1277,22 @@ int SSLClientSocketOpenSSL::BufferSend(void) { |
| size_t max_read = BIO_ctrl_pending(transport_bio_); |
| if (!max_read) |
| return 0; // Nothing pending in the OpenSSL write BIO. |
| - send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); |
| - int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); |
| - DCHECK_GT(read_bytes, 0); |
| - CHECK_EQ(static_cast<int>(max_read), read_bytes); |
| + |
| + char* bio_transport_buf; |
| + // Get the internal buffer and number of bytes available for non-copying |
| + // read. |
| + // BIO_ctrl_pending() is still called above. Calling BIO_nread0() when |
| + // there is no data triggers a call to BIO_nread() to read one byte. This |
| + // has side effect that the retry flag is set. |
| + int available_read_bytes = BIO_nread0(transport_bio_, &bio_transport_buf); |
|
Ryan Sleevi
2014/04/29 18:57:02
Note the comments in bss_bio.c
WARNING: The non-c
haavardm
2014/04/29 20:52:56
Yes I saw that too and agree it's a bit risky, esp
|
| + // BIO_nread0() might report less than BIO_ctrl_pending() due to the buffer |
| + // offset and no ring buffer wrap-around for non-copying interface. |
| + CHECK_GE(static_cast<int>(max_read), available_read_bytes); |
|
Ryan Sleevi
2014/04/29 18:57:02
Two things:
1) I'm a little nervous about this CHE
haavardm
2014/04/29 20:52:56
Normally, if the read/write index is in the middle
|
| + if (available_read_bytes <= 0) |
| + return 0; |
| + |
| + send_buffer_ = new DrainableIOBuffer(new WrappedIOBuffer(bio_transport_buf), |
| + available_read_bytes); |
|
Ryan Sleevi
2014/04/29 18:57:02
BUG: So, the contract of IOBuffer is that, althoug
haavardm
2014/04/29 20:52:56
Ah, right. I knew about the contract for IOBuffer
|
| } |
| int rv = transport_->socket()->Write( |
| @@ -1322,10 +1334,20 @@ int SSLClientSocketOpenSSL::BufferRecv(void) { |
| if (!max_write) |
| return ERR_IO_PENDING; |
| - recv_buffer_ = new IOBuffer(max_write); |
| + char* bio_transport_buf; |
| + // Get the internal buffer and number of bytes available for non-copying |
| + // write. |
| + int available_write_bytes = BIO_nwrite0(transport_bio_, &bio_transport_buf); |
| + // BIO_nwrite0() might report less than BIO_ctrl_get_write_guarantee() due to |
| + // the buffer offset and no ring buffer wrap-around for non-copying interface. |
| + DCHECK_GE(static_cast<int>(max_write), available_write_bytes); |
| + if (available_write_bytes <= 0) |
| + return ERR_IO_PENDING; |
| + |
| + recv_buffer_ = new WrappedIOBuffer(bio_transport_buf); |
| int rv = transport_->socket()->Read( |
| recv_buffer_.get(), |
| - max_write, |
| + available_write_bytes, |
| base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, |
| base::Unretained(this))); |
| if (rv == ERR_IO_PENDING) { |
| @@ -1367,6 +1389,11 @@ void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { |
| send_buffer_ = NULL; |
| } else { |
| DCHECK(send_buffer_.get()); |
| + char* bio_transport_buf; |
| + // Advance the buffer index. |
| + int ret = BIO_nread(transport_bio_, &bio_transport_buf, result); |
| + CHECK_EQ(ret, result); |
| + CHECK_EQ(bio_transport_buf, send_buffer_->data()); |
| send_buffer_->DidConsume(result); |
| DCHECK_GE(send_buffer_->BytesRemaining(), 0); |
| if (send_buffer_->BytesRemaining() <= 0) |
| @@ -1390,8 +1417,11 @@ int SSLClientSocketOpenSSL::TransportReadComplete(int result) { |
| // the CHECK. http://crbug.com/335557. |
| result = transport_write_error_; |
| } else { |
| - DCHECK(recv_buffer_.get()); |
| - int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); |
| + char* bio_transport_buf; |
| + // Set the amount of data read into buffer. |
| + int ret = BIO_nwrite(transport_bio_, &bio_transport_buf, result); |
| + CHECK_EQ(ret, result); |
| + CHECK_EQ(bio_transport_buf, recv_buffer_->data()); |
| // A write into a memory BIO should always succeed. |
| // Force values on the stack for http://crbug.com/335557 |
| base::debug::Alias(&result); |