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

Side by Side Diff: net/socket/ssl_client_socket_openssl.cc

Issue 795573002: Implement zero-copy SSL buffers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // OpenSSL binding for SSLClientSocket. The class layout and general principle 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle
6 // of operation is derived from SSLClientSocketNSS. 6 // of operation is derived from SSLClientSocketNSS.
7 7
8 #include "net/socket/ssl_client_socket_openssl.h" 8 #include "net/socket/ssl_client_socket_openssl.h"
9 9
10 #include <errno.h> 10 #include <errno.h>
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 #endif 61 #endif
62 62
63 // This constant can be any non-negative/non-zero value (eg: it does not 63 // This constant can be any non-negative/non-zero value (eg: it does not
64 // overlap with any value of the net::Error range, including net::OK). 64 // overlap with any value of the net::Error range, including net::OK).
65 const int kNoPendingReadResult = 1; 65 const int kNoPendingReadResult = 1;
66 66
67 // If a client doesn't have a list of protocols that it supports, but 67 // If a client doesn't have a list of protocols that it supports, but
68 // the server supports NPN, choosing "http/1.1" is the best answer. 68 // the server supports NPN, choosing "http/1.1" is the best answer.
69 const char kDefaultSupportedNPNProtocol[] = "http/1.1"; 69 const char kDefaultSupportedNPNProtocol[] = "http/1.1";
70 70
71 // 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.
72 const int KDefaultOpenSSLBufferSize = 17 * 1024;
73
71 void FreeX509Stack(STACK_OF(X509)* ptr) { 74 void FreeX509Stack(STACK_OF(X509)* ptr) {
72 sk_X509_pop_free(ptr, X509_free); 75 sk_X509_pop_free(ptr, X509_free);
73 } 76 }
74 77
75 typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509; 78 typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509;
76 typedef crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>::Type 79 typedef crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>::Type
77 ScopedX509Stack; 80 ScopedX509Stack;
78 81
79 #if OPENSSL_VERSION_NUMBER < 0x1000103fL 82 #if OPENSSL_VERSION_NUMBER < 0x1000103fL
80 // This method doesn't seem to have made it into the OpenSSL headers. 83 // This method doesn't seem to have made it into the OpenSSL headers.
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 724
722 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) 725 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str()))
723 return ERR_UNEXPECTED; 726 return ERR_UNEXPECTED;
724 727
725 // Set an OpenSSL callback to monitor this SSL*'s connection. 728 // Set an OpenSSL callback to monitor this SSL*'s connection.
726 SSL_set_info_callback(ssl_, &InfoCallback); 729 SSL_set_info_callback(ssl_, &InfoCallback);
727 730
728 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( 731 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey(
729 ssl_, GetSessionCacheKey()); 732 ssl_, GetSessionCacheKey());
730 733
734 send_buffer_ = new GrowableIOBuffer();
735 send_buffer_->SetCapacity(KDefaultOpenSSLBufferSize);
736 recv_buffer_ = new GrowableIOBuffer();
737 recv_buffer_->SetCapacity(KDefaultOpenSSLBufferSize);
738
731 BIO* ssl_bio = NULL; 739 BIO* ssl_bio = NULL;
732 // 0 => use default buffer sizes. 740
733 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) 741 // 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.
742 // the IOBuffers user contract.
743 if (!BIO_new_bio_pair_external_buf(
744 &ssl_bio, send_buffer_->capacity(),
745 reinterpret_cast<uint8_t*>(send_buffer_->data()), &transport_bio_,
746 recv_buffer_->capacity(),
747 reinterpret_cast<uint8_t*>(recv_buffer_->data())))
734 return ERR_UNEXPECTED; 748 return ERR_UNEXPECTED;
735 DCHECK(ssl_bio); 749 DCHECK(ssl_bio);
736 DCHECK(transport_bio_); 750 DCHECK(transport_bio_);
737 751
738 // Install a callback on OpenSSL's end to plumb transport errors through. 752 // Install a callback on OpenSSL's end to plumb transport errors through.
739 BIO_set_callback(ssl_bio, BIOCallback); 753 BIO_set_callback(ssl_bio, BIOCallback);
740 BIO_set_callback_arg(ssl_bio, reinterpret_cast<char*>(this)); 754 BIO_set_callback_arg(ssl_bio, reinterpret_cast<char*>(this));
741 755
742 SSL_set_bio(ssl_, ssl_bio, ssl_bio); 756 SSL_set_bio(ssl_, ssl_bio, ssl_bio);
743 757
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after
1502 NetLog::TYPE_SSL_WRITE_ERROR, 1516 NetLog::TYPE_SSL_WRITE_ERROR,
1503 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); 1517 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
1504 } 1518 }
1505 return net_error; 1519 return net_error;
1506 } 1520 }
1507 1521
1508 int SSLClientSocketOpenSSL::BufferSend(void) { 1522 int SSLClientSocketOpenSSL::BufferSend(void) {
1509 if (transport_send_busy_) 1523 if (transport_send_busy_)
1510 return ERR_IO_PENDING; 1524 return ERR_IO_PENDING;
1511 1525
1512 if (!send_buffer_.get()) { 1526 size_t buffer_read_offset;
1513 // Get a fresh send buffer out of the send BIO. 1527 uint8_t* read_buf;
1514 size_t max_read = BIO_pending(transport_bio_); 1528 size_t max_read;
1515 if (!max_read) 1529 int status = BIO_zero_copy_get_read_buf(transport_bio_, &read_buf,
1516 return 0; // Nothing pending in the OpenSSL write BIO. 1530 &buffer_read_offset, &max_read);
1517 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); 1531 DCHECK(status == 1); // Should never fail.
agl 2014/12/17 22:29:56 DCHECK_EQ
haavardm 2014/12/18 12:18:07 Done.
1518 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); 1532 if (!max_read)
1519 DCHECK_GT(read_bytes, 0); 1533 return 0; // Nothing pending in the OpenSSL write BIO.
1520 CHECK_EQ(static_cast<int>(max_read), read_bytes); 1534 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.
1521 } 1535 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.
1536 send_buffer_->set_offset(buffer_read_offset);
1522 1537
1523 int rv = transport_->socket()->Write( 1538 int rv = transport_->socket()->Write(
1524 send_buffer_.get(), 1539 send_buffer_.get(), max_read,
1525 send_buffer_->BytesRemaining(),
1526 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete, 1540 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete,
1527 base::Unretained(this))); 1541 base::Unretained(this)));
1528 if (rv == ERR_IO_PENDING) { 1542 if (rv == ERR_IO_PENDING) {
1529 transport_send_busy_ = true; 1543 transport_send_busy_ = true;
1530 } else { 1544 } else {
1531 TransportWriteComplete(rv); 1545 TransportWriteComplete(rv);
1532 } 1546 }
1533 return rv; 1547 return rv;
1534 } 1548 }
1535 1549
(...skipping 11 matching lines...) Expand all
1547 return ERR_IO_PENDING; 1561 return ERR_IO_PENDING;
1548 } 1562 }
1549 1563
1550 // Known Issue: While only reading |requested| data is the more correct 1564 // Known Issue: While only reading |requested| data is the more correct
1551 // implementation, it has the downside of resulting in frequent reads: 1565 // implementation, it has the downside of resulting in frequent reads:
1552 // One read for the SSL record header (~5 bytes) and one read for the SSL 1566 // One read for the SSL record header (~5 bytes) and one read for the SSL
1553 // record body. Rather than issuing these reads to the underlying socket 1567 // record body. Rather than issuing these reads to the underlying socket
1554 // (and constantly allocating new IOBuffers), a single Read() request to 1568 // (and constantly allocating new IOBuffers), a single Read() request to
1555 // fill |transport_bio_| is issued. As long as an SSL client socket cannot 1569 // fill |transport_bio_| is issued. As long as an SSL client socket cannot
1556 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL 1570 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
1557 // traffic, this over-subscribed Read()ing will not cause issues. 1571 // 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
1558 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); 1572
1573 size_t buffer_write_offset;
1574 uint8_t* write_buf;
1575 size_t max_write;
1576 int status = BIO_zero_copy_get_write_buf(transport_bio_, &write_buf,
1577 &buffer_write_offset, &max_write);
1578 DCHECK(status == 1); // Should never fail.
agl 2014/12/17 22:29:56 DCHECK_EQ
1559 if (!max_write) 1579 if (!max_write)
1560 return ERR_IO_PENDING; 1580 return ERR_IO_PENDING;
1561 1581
1562 recv_buffer_ = new IOBuffer(max_write); 1582 CHECK(write_buf == reinterpret_cast<uint8_t*>(recv_buffer_->data()));
agl 2014/12/17 22:29:56 CHECK_EQ
1583 CHECK(buffer_write_offset < static_cast<size_t>(recv_buffer_->capacity()));
agl 2014/12/17 22:29:56 CHECK_LT
1584
1585 recv_buffer_->set_offset(buffer_write_offset);
1563 int rv = transport_->socket()->Read( 1586 int rv = transport_->socket()->Read(
1564 recv_buffer_.get(), 1587 recv_buffer_.get(),
1565 max_write, 1588 max_write,
1566 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, 1589 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
1567 base::Unretained(this))); 1590 base::Unretained(this)));
1568 if (rv == ERR_IO_PENDING) { 1591 if (rv == ERR_IO_PENDING) {
1569 transport_recv_busy_ = true; 1592 transport_recv_busy_ = true;
1570 } else { 1593 } else {
1571 rv = TransportReadComplete(rv); 1594 rv = TransportReadComplete(rv);
1572 } 1595 }
1573 return rv; 1596 return rv;
1574 } 1597 }
1575 1598
1576 void SSLClientSocketOpenSSL::BufferSendComplete(int result) { 1599 void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
1577 transport_send_busy_ = false;
1578 TransportWriteComplete(result); 1600 TransportWriteComplete(result);
1579 OnSendComplete(result); 1601 OnSendComplete(result);
1580 } 1602 }
1581 1603
1582 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { 1604 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
1583 result = TransportReadComplete(result); 1605 result = TransportReadComplete(result);
1584 OnRecvComplete(result); 1606 OnRecvComplete(result);
1585 } 1607 }
1586 1608
1587 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { 1609 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
1588 DCHECK(ERR_IO_PENDING != result); 1610 DCHECK(ERR_IO_PENDING != result);
1611 int bytes_written = 0;
1589 if (result < 0) { 1612 if (result < 0) {
1590 // Record the error. Save it to be reported in a future read or write on 1613 // Record the error. Save it to be reported in a future read or write on
1591 // transport_bio_'s peer. 1614 // transport_bio_'s peer.
1592 transport_write_error_ = result; 1615 transport_write_error_ = result;
1593 send_buffer_ = NULL;
1594 } else { 1616 } else {
1595 DCHECK(send_buffer_.get()); 1617 bytes_written = result;
1596 send_buffer_->DidConsume(result);
1597 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
1598 if (send_buffer_->BytesRemaining() <= 0)
1599 send_buffer_ = NULL;
1600 } 1618 }
1619 DCHECK_GE(send_buffer_->RemainingCapacity(), bytes_written);
1620 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
1621 DCHECK_EQ(1, ret);
1622 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.
1623 transport_send_busy_ = false;
1601 } 1624 }
1602 1625
1603 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { 1626 int SSLClientSocketOpenSSL::TransportReadComplete(int result) {
1604 DCHECK(ERR_IO_PENDING != result); 1627 DCHECK(ERR_IO_PENDING != result);
1605 // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here so MapOpenSSLError 1628 // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here so MapOpenSSLError
1606 // does not report success. 1629 // does not report success.
1607 if (result == 0) 1630 if (result == 0)
1608 result = ERR_CONNECTION_CLOSED; 1631 result = ERR_CONNECTION_CLOSED;
1632 int bytes_read = 0;
1609 if (result < 0) { 1633 if (result < 0) {
1610 DVLOG(1) << "TransportReadComplete result " << result; 1634 DVLOG(1) << "TransportReadComplete result " << result;
1611 // Received an error. Save it to be reported in a future read on 1635 // Received an error. Save it to be reported in a future read on
1612 // transport_bio_'s peer. 1636 // transport_bio_'s peer.
1613 transport_read_error_ = result; 1637 transport_read_error_ = result;
1614 } else { 1638 } else {
1615 DCHECK(recv_buffer_.get()); 1639 bytes_read = result;
1616 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
1617 // A write into a memory BIO should always succeed.
1618 DCHECK_EQ(result, ret);
1619 } 1640 }
1620 recv_buffer_ = NULL; 1641 DCHECK_GE(recv_buffer_->RemainingCapacity(), bytes_read);
1642 int ret = BIO_zero_copy_get_write_buf_done(transport_bio_, bytes_read);
1643 DCHECK_EQ(1, ret);
1644 recv_buffer_->set_offset(0);
agl 2014/12/17 22:29:56 Ditto.
haavardm 2014/12/18 12:18:07 Done.
1621 transport_recv_busy_ = false; 1645 transport_recv_busy_ = false;
1622 return result; 1646 return result;
1623 } 1647 }
1624 1648
1625 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl) { 1649 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl) {
1626 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed. 1650 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
1627 tracked_objects::ScopedTracker tracking_profile( 1651 tracked_objects::ScopedTracker tracking_profile(
1628 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1652 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1629 "424386 SSLClientSocketOpenSSL::ClientCertRequestCallback")); 1653 "424386 SSLClientSocketOpenSSL::ClientCertRequestCallback"));
1630 1654
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
1903 ct::SCT_STATUS_LOG_UNKNOWN)); 1927 ct::SCT_STATUS_LOG_UNKNOWN));
1904 } 1928 }
1905 } 1929 }
1906 1930
1907 scoped_refptr<X509Certificate> 1931 scoped_refptr<X509Certificate>
1908 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { 1932 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
1909 return server_cert_; 1933 return server_cert_;
1910 } 1934 }
1911 1935
1912 } // namespace net 1936 } // namespace net
OLDNEW
« net/socket/ssl_client_socket_openssl.h ('K') | « net/socket/ssl_client_socket_openssl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698