Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2549)

Unified Diff: net/socket/ssl_client_socket_openssl.cc

Issue 255143002: Implement zero-copy SSL buffers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: New IOBuffer version to reference count BIO objects Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..548c349529621f0cfdd84ff4f83eb011718e4f44 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -34,6 +34,33 @@ namespace net {
namespace {
+// This IOBuffer version is to be used with OpenSSL's non-copying interface,
+// to guarantee that the BIO object remains alive as long as the socket keeps
+// a reference to it's internal data buffer.
+//
+// |bio_buffer| must be retrieved from |bio| using the non-copying interface
+// BIO_nread0() or BIO_nwrite0(). The reference count of |bio| is increased to
+// make sure |bio| is not free'd if it is referenced from elsewhere.
+class WrappedBIOAndIOBuffer : public IOBuffer {
+ public:
+
+ explicit WrappedBIOAndIOBuffer(const char* bio_buffer, BIO* bio)
Ryan Sleevi 2014/04/30 21:33:32 nit: delete newline on 46
+ : IOBuffer(const_cast<char*>(bio_buffer)), bio_(bio) {
+ CHECK(bio);
+
+ CRYPTO_add(&bio_->references, 1, CRYPTO_LOCK_BIO);
+ }
+
+ protected:
+ virtual ~WrappedBIOAndIOBuffer() {
+ data_ = NULL;
+ // Will count down the reference count, and free if the count reaches zero.
+ BIO_free_all(bio_);
+ }
+
+ BIO* bio_;
+};
+
// Enable this to see logging for state machine state transitions.
#if 0
#define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
@@ -1277,10 +1304,23 @@ 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.
Ryan Sleevi 2014/04/30 21:33:32 Is this still necessary, given that BIO_nread0 wit
haavardm 2014/05/01 16:55:19 The problem with letting 0 fall through is that ca
Ryan Sleevi 2014/05/08 22:59:28 Yeah, I suppose the alternative would be to reset
- 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);
+ // 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);
+ if (available_read_bytes <= 0)
+ return 0;
+
+ send_buffer_ = new DrainableIOBuffer(
Ryan Sleevi 2014/04/30 21:33:32 Huh. I'm not really sure why we use a DrainableIOB
haavardm 2014/05/01 16:55:19 I believe the drainable buffer is needed to handle
Ryan Sleevi 2014/05/08 22:59:28 Yeah, but why create a DrainableIOBuffer (and have
haavardm 2014/05/09 07:23:41 Yes, I had a look into NSS yesterday and saw how y
+ new WrappedBIOAndIOBuffer(bio_transport_buf, transport_bio_),
+ available_read_bytes);
}
int rv = transport_->socket()->Write(
@@ -1322,10 +1362,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 WrappedBIOAndIOBuffer(bio_transport_buf, transport_bio_);
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 +1417,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 +1445,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);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698