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

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: Fixed CHECK failure caused by removing setting offset to 0 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
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 size of the internal BoringSSL buffers.
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 // SSLClientSocketOpenSSL retains ownership of the BIO buffers.
742 if (!BIO_new_bio_pair_external_buf(
743 &ssl_bio, send_buffer_->capacity(),
744 reinterpret_cast<uint8_t*>(send_buffer_->data()), &transport_bio_,
745 recv_buffer_->capacity(),
746 reinterpret_cast<uint8_t*>(recv_buffer_->data())))
734 return ERR_UNEXPECTED; 747 return ERR_UNEXPECTED;
735 DCHECK(ssl_bio); 748 DCHECK(ssl_bio);
736 DCHECK(transport_bio_); 749 DCHECK(transport_bio_);
737 750
738 // Install a callback on OpenSSL's end to plumb transport errors through. 751 // Install a callback on OpenSSL's end to plumb transport errors through.
739 BIO_set_callback(ssl_bio, BIOCallback); 752 BIO_set_callback(ssl_bio, BIOCallback);
740 BIO_set_callback_arg(ssl_bio, reinterpret_cast<char*>(this)); 753 BIO_set_callback_arg(ssl_bio, reinterpret_cast<char*>(this));
741 754
742 SSL_set_bio(ssl_, ssl_bio, ssl_bio); 755 SSL_set_bio(ssl_, ssl_bio, ssl_bio);
743 756
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 NetLog::TYPE_SSL_WRITE_ERROR, 1536 NetLog::TYPE_SSL_WRITE_ERROR,
1524 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); 1537 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
1525 } 1538 }
1526 return net_error; 1539 return net_error;
1527 } 1540 }
1528 1541
1529 int SSLClientSocketOpenSSL::BufferSend(void) { 1542 int SSLClientSocketOpenSSL::BufferSend(void) {
1530 if (transport_send_busy_) 1543 if (transport_send_busy_)
1531 return ERR_IO_PENDING; 1544 return ERR_IO_PENDING;
1532 1545
1533 if (!send_buffer_.get()) { 1546 size_t buffer_read_offset;
1534 // Get a fresh send buffer out of the send BIO. 1547 uint8_t* read_buf;
1535 size_t max_read = BIO_pending(transport_bio_); 1548 size_t max_read;
1536 if (!max_read) 1549 int status = BIO_zero_copy_get_read_buf(transport_bio_, &read_buf,
1537 return 0; // Nothing pending in the OpenSSL write BIO. 1550 &buffer_read_offset, &max_read);
1538 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); 1551 DCHECK_EQ(status, 1); // Should never fail.
1539 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); 1552 if (!max_read)
1540 DCHECK_GT(read_bytes, 0); 1553 return 0; // Nothing pending in the OpenSSL write BIO.
1541 CHECK_EQ(static_cast<int>(max_read), read_bytes); 1554 CHECK_EQ(read_buf, reinterpret_cast<uint8_t*>(send_buffer_->StartOfBuffer()));
1542 } 1555 CHECK_LT(buffer_read_offset, static_cast<size_t>(send_buffer_->capacity()));
1556 send_buffer_->set_offset(buffer_read_offset);
1543 1557
1544 int rv = transport_->socket()->Write( 1558 int rv = transport_->socket()->Write(
1545 send_buffer_.get(), 1559 send_buffer_.get(), max_read,
1546 send_buffer_->BytesRemaining(),
1547 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete, 1560 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete,
1548 base::Unretained(this))); 1561 base::Unretained(this)));
1549 if (rv == ERR_IO_PENDING) { 1562 if (rv == ERR_IO_PENDING) {
1550 transport_send_busy_ = true; 1563 transport_send_busy_ = true;
1551 } else { 1564 } else {
1552 TransportWriteComplete(rv); 1565 TransportWriteComplete(rv);
1553 } 1566 }
1554 return rv; 1567 return rv;
1555 } 1568 }
1556 1569
(...skipping 12 matching lines...) Expand all
1569 } 1582 }
1570 1583
1571 // Known Issue: While only reading |requested| data is the more correct 1584 // Known Issue: While only reading |requested| data is the more correct
1572 // implementation, it has the downside of resulting in frequent reads: 1585 // implementation, it has the downside of resulting in frequent reads:
1573 // One read for the SSL record header (~5 bytes) and one read for the SSL 1586 // One read for the SSL record header (~5 bytes) and one read for the SSL
1574 // record body. Rather than issuing these reads to the underlying socket 1587 // record body. Rather than issuing these reads to the underlying socket
1575 // (and constantly allocating new IOBuffers), a single Read() request to 1588 // (and constantly allocating new IOBuffers), a single Read() request to
1576 // fill |transport_bio_| is issued. As long as an SSL client socket cannot 1589 // fill |transport_bio_| is issued. As long as an SSL client socket cannot
1577 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL 1590 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
1578 // traffic, this over-subscribed Read()ing will not cause issues. 1591 // traffic, this over-subscribed Read()ing will not cause issues.
1579 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); 1592
1593 size_t buffer_write_offset;
1594 uint8_t* write_buf;
1595 size_t max_write;
1596 int status = BIO_zero_copy_get_write_buf(transport_bio_, &write_buf,
1597 &buffer_write_offset, &max_write);
1598 DCHECK_EQ(status, 1); // Should never fail.
1580 if (!max_write) 1599 if (!max_write)
1581 return ERR_IO_PENDING; 1600 return ERR_IO_PENDING;
1582 1601
1583 recv_buffer_ = new IOBuffer(max_write); 1602 CHECK_EQ(write_buf,
1603 reinterpret_cast<uint8_t*>(recv_buffer_->StartOfBuffer()));
1604 CHECK_LT(buffer_write_offset, static_cast<size_t>(recv_buffer_->capacity()));
1605
1606 recv_buffer_->set_offset(buffer_write_offset);
1584 int rv = transport_->socket()->Read( 1607 int rv = transport_->socket()->Read(
1585 recv_buffer_.get(), 1608 recv_buffer_.get(),
1586 max_write, 1609 max_write,
1587 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, 1610 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
1588 base::Unretained(this))); 1611 base::Unretained(this)));
1589 if (rv == ERR_IO_PENDING) { 1612 if (rv == ERR_IO_PENDING) {
1590 transport_recv_busy_ = true; 1613 transport_recv_busy_ = true;
1591 } else { 1614 } else {
1592 rv = TransportReadComplete(rv); 1615 rv = TransportReadComplete(rv);
1593 } 1616 }
1594 return rv; 1617 return rv;
1595 } 1618 }
1596 1619
1597 void SSLClientSocketOpenSSL::BufferSendComplete(int result) { 1620 void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
1598 transport_send_busy_ = false;
1599 TransportWriteComplete(result); 1621 TransportWriteComplete(result);
1600 OnSendComplete(result); 1622 OnSendComplete(result);
1601 } 1623 }
1602 1624
1603 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { 1625 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
1604 result = TransportReadComplete(result); 1626 result = TransportReadComplete(result);
1605 OnRecvComplete(result); 1627 OnRecvComplete(result);
1606 } 1628 }
1607 1629
1608 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { 1630 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
1609 DCHECK(ERR_IO_PENDING != result); 1631 DCHECK(ERR_IO_PENDING != result);
1632 int bytes_written = 0;
1610 if (result < 0) { 1633 if (result < 0) {
1611 // Record the error. Save it to be reported in a future read or write on 1634 // Record the error. Save it to be reported in a future read or write on
1612 // transport_bio_'s peer. 1635 // transport_bio_'s peer.
1613 transport_write_error_ = result; 1636 transport_write_error_ = result;
1614 send_buffer_ = NULL;
1615 } else { 1637 } else {
1616 DCHECK(send_buffer_.get()); 1638 bytes_written = result;
1617 send_buffer_->DidConsume(result);
1618 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
1619 if (send_buffer_->BytesRemaining() <= 0)
1620 send_buffer_ = NULL;
1621 } 1639 }
1640 DCHECK_GE(send_buffer_->RemainingCapacity(), bytes_written);
1641 int ret = BIO_zero_copy_get_read_buf_done(transport_bio_, bytes_written);
1642 DCHECK_EQ(1, ret);
1643 transport_send_busy_ = false;
1622 } 1644 }
1623 1645
1624 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { 1646 int SSLClientSocketOpenSSL::TransportReadComplete(int result) {
1625 DCHECK(ERR_IO_PENDING != result); 1647 DCHECK(ERR_IO_PENDING != result);
1626 // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here so MapOpenSSLError 1648 // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here so MapOpenSSLError
1627 // does not report success. 1649 // does not report success.
1628 if (result == 0) 1650 if (result == 0)
1629 result = ERR_CONNECTION_CLOSED; 1651 result = ERR_CONNECTION_CLOSED;
1652 int bytes_read = 0;
1630 if (result < 0) { 1653 if (result < 0) {
1631 DVLOG(1) << "TransportReadComplete result " << result; 1654 DVLOG(1) << "TransportReadComplete result " << result;
1632 // Received an error. Save it to be reported in a future read on 1655 // Received an error. Save it to be reported in a future read on
1633 // transport_bio_'s peer. 1656 // transport_bio_'s peer.
1634 transport_read_error_ = result; 1657 transport_read_error_ = result;
1635 } else { 1658 } else {
1636 DCHECK(recv_buffer_.get()); 1659 bytes_read = result;
1637 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
1638 // A write into a memory BIO should always succeed.
1639 DCHECK_EQ(result, ret);
1640 } 1660 }
1641 recv_buffer_ = NULL; 1661 DCHECK_GE(recv_buffer_->RemainingCapacity(), bytes_read);
1662 int ret = BIO_zero_copy_get_write_buf_done(transport_bio_, bytes_read);
1663 DCHECK_EQ(1, ret);
1642 transport_recv_busy_ = false; 1664 transport_recv_busy_ = false;
1643 return result; 1665 return result;
1644 } 1666 }
1645 1667
1646 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl) { 1668 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl) {
1647 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed. 1669 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
1648 tracked_objects::ScopedTracker tracking_profile( 1670 tracked_objects::ScopedTracker tracking_profile(
1649 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1671 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1650 "424386 SSLClientSocketOpenSSL::ClientCertRequestCallback")); 1672 "424386 SSLClientSocketOpenSSL::ClientCertRequestCallback"));
1651 1673
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 ct::SCT_STATUS_LOG_UNKNOWN)); 1945 ct::SCT_STATUS_LOG_UNKNOWN));
1924 } 1946 }
1925 } 1947 }
1926 1948
1927 scoped_refptr<X509Certificate> 1949 scoped_refptr<X509Certificate>
1928 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { 1950 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
1929 return server_cert_; 1951 return server_cert_;
1930 } 1952 }
1931 1953
1932 } // namespace net 1954 } // namespace net
OLDNEW
« no previous file with comments | « 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