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

Side by Side 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, 7 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 unified diff | Download patch
« no previous file with comments | « no previous file | 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 <openssl/err.h> 10 #include <openssl/err.h>
(...skipping 16 matching lines...) Expand all
27 #include "net/socket/ssl_session_cache_openssl.h" 27 #include "net/socket/ssl_session_cache_openssl.h"
28 #include "net/ssl/openssl_client_key_store.h" 28 #include "net/ssl/openssl_client_key_store.h"
29 #include "net/ssl/ssl_cert_request_info.h" 29 #include "net/ssl/ssl_cert_request_info.h"
30 #include "net/ssl/ssl_connection_status_flags.h" 30 #include "net/ssl/ssl_connection_status_flags.h"
31 #include "net/ssl/ssl_info.h" 31 #include "net/ssl/ssl_info.h"
32 32
33 namespace net { 33 namespace net {
34 34
35 namespace { 35 namespace {
36 36
37 // This IOBuffer version is to be used with OpenSSL's non-copying interface,
38 // to guarantee that the BIO object remains alive as long as the socket keeps
39 // a reference to it's internal data buffer.
40 //
41 // |bio_buffer| must be retrieved from |bio| using the non-copying interface
42 // BIO_nread0() or BIO_nwrite0(). The reference count of |bio| is increased to
43 // make sure |bio| is not free'd if it is referenced from elsewhere.
44 class WrappedBIOAndIOBuffer : public IOBuffer {
45 public:
46
47 explicit WrappedBIOAndIOBuffer(const char* bio_buffer, BIO* bio)
Ryan Sleevi 2014/04/30 21:33:32 nit: delete newline on 46
48 : IOBuffer(const_cast<char*>(bio_buffer)), bio_(bio) {
49 CHECK(bio);
50
51 CRYPTO_add(&bio_->references, 1, CRYPTO_LOCK_BIO);
52 }
53
54 protected:
55 virtual ~WrappedBIOAndIOBuffer() {
56 data_ = NULL;
57 // Will count down the reference count, and free if the count reaches zero.
58 BIO_free_all(bio_);
59 }
60
61 BIO* bio_;
62 };
63
37 // Enable this to see logging for state machine state transitions. 64 // Enable this to see logging for state machine state transitions.
38 #if 0 65 #if 0
39 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ 66 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
40 " jump to state " << s; \ 67 " jump to state " << s; \
41 next_handshake_state_ = s; } while (0) 68 next_handshake_state_ = s; } while (0)
42 #else 69 #else
43 #define GotoState(s) next_handshake_state_ = s 70 #define GotoState(s) next_handshake_state_ = s
44 #endif 71 #endif
45 72
46 // This constant can be any non-negative/non-zero value (eg: it does not 73 // This constant can be any non-negative/non-zero value (eg: it does not
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1269 } 1296 }
1270 1297
1271 int SSLClientSocketOpenSSL::BufferSend(void) { 1298 int SSLClientSocketOpenSSL::BufferSend(void) {
1272 if (transport_send_busy_) 1299 if (transport_send_busy_)
1273 return ERR_IO_PENDING; 1300 return ERR_IO_PENDING;
1274 1301
1275 if (!send_buffer_.get()) { 1302 if (!send_buffer_.get()) {
1276 // Get a fresh send buffer out of the send BIO. 1303 // Get a fresh send buffer out of the send BIO.
1277 size_t max_read = BIO_ctrl_pending(transport_bio_); 1304 size_t max_read = BIO_ctrl_pending(transport_bio_);
1278 if (!max_read) 1305 if (!max_read)
1279 return 0; // Nothing pending in the OpenSSL write BIO. 1306 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
1280 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); 1307
1281 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); 1308 char* bio_transport_buf;
1282 DCHECK_GT(read_bytes, 0); 1309 // Get the internal buffer and number of bytes available for non-copying
1283 CHECK_EQ(static_cast<int>(max_read), read_bytes); 1310 // read.
1311 // BIO_ctrl_pending() is still called above. Calling BIO_nread0() when
1312 // there is no data triggers a call to BIO_nread() to read one byte. This
1313 // has side effect that the retry flag is set.
1314 int available_read_bytes = BIO_nread0(transport_bio_, &bio_transport_buf);
1315 // BIO_nread0() might report less than BIO_ctrl_pending() due to the buffer
1316 // offset and no ring buffer wrap-around for non-copying interface.
1317 CHECK_GE(static_cast<int>(max_read), available_read_bytes);
1318 if (available_read_bytes <= 0)
1319 return 0;
1320
1321 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
1322 new WrappedBIOAndIOBuffer(bio_transport_buf, transport_bio_),
1323 available_read_bytes);
1284 } 1324 }
1285 1325
1286 int rv = transport_->socket()->Write( 1326 int rv = transport_->socket()->Write(
1287 send_buffer_.get(), 1327 send_buffer_.get(),
1288 send_buffer_->BytesRemaining(), 1328 send_buffer_->BytesRemaining(),
1289 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete, 1329 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete,
1290 base::Unretained(this))); 1330 base::Unretained(this)));
1291 if (rv == ERR_IO_PENDING) { 1331 if (rv == ERR_IO_PENDING) {
1292 transport_send_busy_ = true; 1332 transport_send_busy_ = true;
1293 } else { 1333 } else {
(...skipping 21 matching lines...) Expand all
1315 // One read for the SSL record header (~5 bytes) and one read for the SSL 1355 // One read for the SSL record header (~5 bytes) and one read for the SSL
1316 // record body. Rather than issuing these reads to the underlying socket 1356 // record body. Rather than issuing these reads to the underlying socket
1317 // (and constantly allocating new IOBuffers), a single Read() request to 1357 // (and constantly allocating new IOBuffers), a single Read() request to
1318 // fill |transport_bio_| is issued. As long as an SSL client socket cannot 1358 // fill |transport_bio_| is issued. As long as an SSL client socket cannot
1319 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL 1359 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
1320 // traffic, this over-subscribed Read()ing will not cause issues. 1360 // traffic, this over-subscribed Read()ing will not cause issues.
1321 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); 1361 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
1322 if (!max_write) 1362 if (!max_write)
1323 return ERR_IO_PENDING; 1363 return ERR_IO_PENDING;
1324 1364
1325 recv_buffer_ = new IOBuffer(max_write); 1365 char* bio_transport_buf;
1366 // Get the internal buffer and number of bytes available for non-copying
1367 // write.
1368 int available_write_bytes = BIO_nwrite0(transport_bio_, &bio_transport_buf);
1369 // BIO_nwrite0() might report less than BIO_ctrl_get_write_guarantee() due to
1370 // the buffer offset and no ring buffer wrap-around for non-copying interface.
1371 DCHECK_GE(static_cast<int>(max_write), available_write_bytes);
1372 if (available_write_bytes <= 0)
1373 return ERR_IO_PENDING;
1374
1375 recv_buffer_ = new WrappedBIOAndIOBuffer(bio_transport_buf, transport_bio_);
1326 int rv = transport_->socket()->Read( 1376 int rv = transport_->socket()->Read(
1327 recv_buffer_.get(), 1377 recv_buffer_.get(),
1328 max_write, 1378 available_write_bytes,
1329 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, 1379 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
1330 base::Unretained(this))); 1380 base::Unretained(this)));
1331 if (rv == ERR_IO_PENDING) { 1381 if (rv == ERR_IO_PENDING) {
1332 transport_recv_busy_ = true; 1382 transport_recv_busy_ = true;
1333 } else { 1383 } else {
1334 rv = TransportReadComplete(rv); 1384 rv = TransportReadComplete(rv);
1335 } 1385 }
1336 return rv; 1386 return rv;
1337 } 1387 }
1338 1388
(...skipping 21 matching lines...) Expand all
1360 1410
1361 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads 1411 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads
1362 // from the socket after a write error. 1412 // from the socket after a write error.
1363 // 1413 //
1364 // TODO(davidben): Avoid having read and write ends interact this way. 1414 // TODO(davidben): Avoid having read and write ends interact this way.
1365 transport_write_error_ = result; 1415 transport_write_error_ = result;
1366 (void)BIO_shutdown_wr(transport_bio_); 1416 (void)BIO_shutdown_wr(transport_bio_);
1367 send_buffer_ = NULL; 1417 send_buffer_ = NULL;
1368 } else { 1418 } else {
1369 DCHECK(send_buffer_.get()); 1419 DCHECK(send_buffer_.get());
1420 char* bio_transport_buf;
1421 // Advance the buffer index.
1422 int ret = BIO_nread(transport_bio_, &bio_transport_buf, result);
1423 CHECK_EQ(ret, result);
1424 CHECK_EQ(bio_transport_buf, send_buffer_->data());
1370 send_buffer_->DidConsume(result); 1425 send_buffer_->DidConsume(result);
1371 DCHECK_GE(send_buffer_->BytesRemaining(), 0); 1426 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
1372 if (send_buffer_->BytesRemaining() <= 0) 1427 if (send_buffer_->BytesRemaining() <= 0)
1373 send_buffer_ = NULL; 1428 send_buffer_ = NULL;
1374 } 1429 }
1375 } 1430 }
1376 1431
1377 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { 1432 int SSLClientSocketOpenSSL::TransportReadComplete(int result) {
1378 DCHECK(ERR_IO_PENDING != result); 1433 DCHECK(ERR_IO_PENDING != result);
1379 if (result <= 0) { 1434 if (result <= 0) {
1380 DVLOG(1) << "TransportReadComplete result " << result; 1435 DVLOG(1) << "TransportReadComplete result " << result;
1381 // Received 0 (end of file) or an error. Either way, bubble it up to the 1436 // Received 0 (end of file) or an error. Either way, bubble it up to the
1382 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to 1437 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
1383 // relay up to the SSL socket client (i.e. via DoReadCallback). 1438 // relay up to the SSL socket client (i.e. via DoReadCallback).
1384 if (result == 0) 1439 if (result == 0)
1385 transport_recv_eof_ = true; 1440 transport_recv_eof_ = true;
1386 (void)BIO_shutdown_wr(transport_bio_); 1441 (void)BIO_shutdown_wr(transport_bio_);
1387 } else if (transport_write_error_ < 0) { 1442 } else if (transport_write_error_ < 0) {
1388 // Mirror transport write errors as read failures; transport_bio_ has been 1443 // Mirror transport write errors as read failures; transport_bio_ has been
1389 // shut down by TransportWriteComplete, so the BIO_write will fail, failing 1444 // shut down by TransportWriteComplete, so the BIO_write will fail, failing
1390 // the CHECK. http://crbug.com/335557. 1445 // the CHECK. http://crbug.com/335557.
1391 result = transport_write_error_; 1446 result = transport_write_error_;
1392 } else { 1447 } else {
1393 DCHECK(recv_buffer_.get()); 1448 char* bio_transport_buf;
1394 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); 1449 // Set the amount of data read into buffer.
1450 int ret = BIO_nwrite(transport_bio_, &bio_transport_buf, result);
1451 CHECK_EQ(ret, result);
1452 CHECK_EQ(bio_transport_buf, recv_buffer_->data());
1395 // A write into a memory BIO should always succeed. 1453 // A write into a memory BIO should always succeed.
1396 // Force values on the stack for http://crbug.com/335557 1454 // Force values on the stack for http://crbug.com/335557
1397 base::debug::Alias(&result); 1455 base::debug::Alias(&result);
1398 base::debug::Alias(&ret); 1456 base::debug::Alias(&ret);
1399 CHECK_EQ(result, ret); 1457 CHECK_EQ(result, ret);
1400 } 1458 }
1401 recv_buffer_ = NULL; 1459 recv_buffer_ = NULL;
1402 transport_recv_busy_ = false; 1460 transport_recv_busy_ = false;
1403 return result; 1461 return result;
1404 } 1462 }
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; 1623 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
1566 return SSL_TLSEXT_ERR_OK; 1624 return SSL_TLSEXT_ERR_OK;
1567 } 1625 }
1568 1626
1569 scoped_refptr<X509Certificate> 1627 scoped_refptr<X509Certificate>
1570 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { 1628 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
1571 return server_cert_; 1629 return server_cert_;
1572 } 1630 }
1573 1631
1574 } // namespace net 1632 } // namespace net
OLDNEW
« 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