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