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 4e86c055932ed7517600625db0179d13ee720029..d7b028ccba0f7789ed056a37d3de489f252cc9d3 100644 |
| --- a/net/socket/ssl_client_socket_openssl.cc |
| +++ b/net/socket/ssl_client_socket_openssl.cc |
| @@ -68,6 +68,9 @@ const int kNoPendingReadResult = 1; |
| // the server supports NPN, choosing "http/1.1" is the best answer. |
| const char kDefaultSupportedNPNProtocol[] = "http/1.1"; |
| +// Default sizes of the internal BoringSSL buffers. |
|
agl
2014/12/17 19:12:22
// Default size of the internal BoringSSL buffers.
haavardm
2014/12/18 12:18:07
Done.
|
| +const int KDefaultOpenSSLBufferSize = 17 * 1024; |
| + |
| void FreeX509Stack(STACK_OF(X509)* ptr) { |
| sk_X509_pop_free(ptr, X509_free); |
| } |
| @@ -728,9 +731,20 @@ int SSLClientSocketOpenSSL::Init() { |
| trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( |
| ssl_, GetSessionCacheKey()); |
| + send_buffer_ = new GrowableIOBuffer(); |
| + send_buffer_->SetCapacity(KDefaultOpenSSLBufferSize); |
| + recv_buffer_ = new GrowableIOBuffer(); |
| + recv_buffer_->SetCapacity(KDefaultOpenSSLBufferSize); |
| + |
| BIO* ssl_bio = NULL; |
| - // 0 => use default buffer sizes. |
| - if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
| + |
| + // Let |SSLClientSocketOpenSSL| have ownership over the bio buffers to keep |
|
agl
2014/12/17 19:12:22
// SSLClientSocketOpenSSL retains ownership of the
haavardm
2014/12/18 12:18:07
Done.
|
| + // the IOBuffers user contract. |
| + if (!BIO_new_bio_pair_external_buf( |
| + &ssl_bio, send_buffer_->capacity(), |
| + reinterpret_cast<uint8_t*>(send_buffer_->data()), &transport_bio_, |
| + recv_buffer_->capacity(), |
| + reinterpret_cast<uint8_t*>(recv_buffer_->data()))) |
| return ERR_UNEXPECTED; |
| DCHECK(ssl_bio); |
| DCHECK(transport_bio_); |
| @@ -1509,20 +1523,20 @@ int SSLClientSocketOpenSSL::BufferSend(void) { |
| if (transport_send_busy_) |
| return ERR_IO_PENDING; |
| - if (!send_buffer_.get()) { |
| - // Get a fresh send buffer out of the send BIO. |
| - size_t max_read = BIO_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); |
| - } |
| + size_t buffer_read_offset; |
| + uint8_t* read_buf; |
| + size_t max_read; |
| + int status = BIO_zero_copy_get_read_buf(transport_bio_, &read_buf, |
| + &buffer_read_offset, &max_read); |
| + DCHECK(status == 1); // Should never fail. |
|
agl
2014/12/17 22:29:56
DCHECK_EQ
haavardm
2014/12/18 12:18:07
Done.
|
| + if (!max_read) |
| + return 0; // Nothing pending in the OpenSSL write BIO. |
| + CHECK(read_buf == reinterpret_cast<uint8_t*>(send_buffer_->data())); |
|
agl
2014/12/17 22:29:56
CHECK_EQ
haavardm
2014/12/18 12:18:07
Done.
|
| + CHECK(buffer_read_offset < static_cast<size_t>(send_buffer_->capacity())); |
|
agl
2014/12/17 22:29:56
CHECK_LT
haavardm
2014/12/18 12:18:07
Done.
|
| + send_buffer_->set_offset(buffer_read_offset); |
| int rv = transport_->socket()->Write( |
| - send_buffer_.get(), |
| - send_buffer_->BytesRemaining(), |
| + send_buffer_.get(), max_read, |
| base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete, |
| base::Unretained(this))); |
| if (rv == ERR_IO_PENDING) { |
| @@ -1555,11 +1569,20 @@ int SSLClientSocketOpenSSL::BufferRecv(void) { |
| // fill |transport_bio_| is issued. As long as an SSL client socket cannot |
| // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL |
| // traffic, this over-subscribed Read()ing will not cause issues. |
|
Ryan Sleevi
2014/12/17 22:57:10
Is this comment still applicable/accurate? Does th
haavardm
2014/12/18 12:18:07
I've done no changes to that logic, so max_write i
|
| - size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); |
| + |
| + size_t buffer_write_offset; |
| + uint8_t* write_buf; |
| + size_t max_write; |
| + int status = BIO_zero_copy_get_write_buf(transport_bio_, &write_buf, |
| + &buffer_write_offset, &max_write); |
| + DCHECK(status == 1); // Should never fail. |
|
agl
2014/12/17 22:29:56
DCHECK_EQ
|
| if (!max_write) |
| return ERR_IO_PENDING; |
| - recv_buffer_ = new IOBuffer(max_write); |
| + CHECK(write_buf == reinterpret_cast<uint8_t*>(recv_buffer_->data())); |
|
agl
2014/12/17 22:29:56
CHECK_EQ
|
| + CHECK(buffer_write_offset < static_cast<size_t>(recv_buffer_->capacity())); |
|
agl
2014/12/17 22:29:56
CHECK_LT
|
| + |
| + recv_buffer_->set_offset(buffer_write_offset); |
| int rv = transport_->socket()->Read( |
| recv_buffer_.get(), |
| max_write, |
| @@ -1574,7 +1597,6 @@ int SSLClientSocketOpenSSL::BufferRecv(void) { |
| } |
| void SSLClientSocketOpenSSL::BufferSendComplete(int result) { |
| - transport_send_busy_ = false; |
| TransportWriteComplete(result); |
| OnSendComplete(result); |
| } |
| @@ -1586,18 +1608,19 @@ void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { |
| void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { |
| DCHECK(ERR_IO_PENDING != result); |
| + int bytes_written = 0; |
| if (result < 0) { |
| // Record the error. Save it to be reported in a future read or write on |
| // transport_bio_'s peer. |
| transport_write_error_ = result; |
| - send_buffer_ = NULL; |
| } else { |
| - DCHECK(send_buffer_.get()); |
| - send_buffer_->DidConsume(result); |
| - DCHECK_GE(send_buffer_->BytesRemaining(), 0); |
| - if (send_buffer_->BytesRemaining() <= 0) |
| - send_buffer_ = NULL; |
| + bytes_written = result; |
| } |
| + DCHECK_GE(send_buffer_->RemainingCapacity(), bytes_written); |
| + int ret = BIO_zero_copy_get_read_buf_done(transport_bio_, bytes_written); |
|
Ryan Sleevi
2014/12/17 22:57:10
What's the contract from BoringSSL if the zero-cop
haavardm
2014/12/18 12:18:07
Yes, BoringSSL will handle this case. BIO_zero_cop
|
| + DCHECK_EQ(1, ret); |
| + send_buffer_->set_offset(0); |
|
agl
2014/12/17 22:29:56
Is this set_offset needed? It seems that it would
haavardm
2014/12/18 12:18:07
It is not really needed since the offset is always
haavardm
2014/12/18 12:18:07
Done.
|
| + transport_send_busy_ = false; |
| } |
| int SSLClientSocketOpenSSL::TransportReadComplete(int result) { |
| @@ -1606,18 +1629,19 @@ int SSLClientSocketOpenSSL::TransportReadComplete(int result) { |
| // does not report success. |
| if (result == 0) |
| result = ERR_CONNECTION_CLOSED; |
| + int bytes_read = 0; |
| if (result < 0) { |
| DVLOG(1) << "TransportReadComplete result " << result; |
| // Received an error. Save it to be reported in a future read on |
| // transport_bio_'s peer. |
| transport_read_error_ = result; |
| } else { |
| - DCHECK(recv_buffer_.get()); |
| - int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); |
| - // A write into a memory BIO should always succeed. |
| - DCHECK_EQ(result, ret); |
| + bytes_read = result; |
| } |
| - recv_buffer_ = NULL; |
| + DCHECK_GE(recv_buffer_->RemainingCapacity(), bytes_read); |
| + int ret = BIO_zero_copy_get_write_buf_done(transport_bio_, bytes_read); |
| + DCHECK_EQ(1, ret); |
| + recv_buffer_->set_offset(0); |
|
agl
2014/12/17 22:29:56
Ditto.
haavardm
2014/12/18 12:18:07
Done.
|
| transport_recv_busy_ = false; |
| return result; |
| } |