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

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: 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 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 1270
1271 int SSLClientSocketOpenSSL::BufferSend(void) { 1271 int SSLClientSocketOpenSSL::BufferSend(void) {
1272 if (transport_send_busy_) 1272 if (transport_send_busy_)
1273 return ERR_IO_PENDING; 1273 return ERR_IO_PENDING;
1274 1274
1275 if (!send_buffer_.get()) { 1275 if (!send_buffer_.get()) {
1276 // Get a fresh send buffer out of the send BIO. 1276 // Get a fresh send buffer out of the send BIO.
1277 size_t max_read = BIO_ctrl_pending(transport_bio_); 1277 size_t max_read = BIO_ctrl_pending(transport_bio_);
1278 if (!max_read) 1278 if (!max_read)
1279 return 0; // Nothing pending in the OpenSSL write BIO. 1279 return 0; // Nothing pending in the OpenSSL write BIO.
1280 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); 1280
1281 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); 1281 char* bio_transport_buf;
1282 DCHECK_GT(read_bytes, 0); 1282 // Get the internal buffer and number of bytes available for non-copying
1283 CHECK_EQ(static_cast<int>(max_read), read_bytes); 1283 // read.
1284 // BIO_ctrl_pending() is still called above. Calling BIO_nread0() when
1285 // there is no data triggers a call to BIO_nread() to read one byte. This
1286 // has side effect that the retry flag is set.
1287 int available_read_bytes = BIO_nread0(transport_bio_, &bio_transport_buf);
Ryan Sleevi 2014/04/29 18:57:02 Note the comments in bss_bio.c WARNING: The non-c
haavardm 2014/04/29 20:52:56 Yes I saw that too and agree it's a bit risky, esp
1288 // BIO_nread0() might report less than BIO_ctrl_pending() due to the buffer
1289 // offset and no ring buffer wrap-around for non-copying interface.
1290 CHECK_GE(static_cast<int>(max_read), available_read_bytes);
Ryan Sleevi 2014/04/29 18:57:02 Two things: 1) I'm a little nervous about this CHE
haavardm 2014/04/29 20:52:56 Normally, if the read/write index is in the middle
1291 if (available_read_bytes <= 0)
1292 return 0;
1293
1294 send_buffer_ = new DrainableIOBuffer(new WrappedIOBuffer(bio_transport_buf),
1295 available_read_bytes);
Ryan Sleevi 2014/04/29 18:57:02 BUG: So, the contract of IOBuffer is that, althoug
haavardm 2014/04/29 20:52:56 Ah, right. I knew about the contract for IOBuffer
1284 } 1296 }
1285 1297
1286 int rv = transport_->socket()->Write( 1298 int rv = transport_->socket()->Write(
1287 send_buffer_.get(), 1299 send_buffer_.get(),
1288 send_buffer_->BytesRemaining(), 1300 send_buffer_->BytesRemaining(),
1289 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete, 1301 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete,
1290 base::Unretained(this))); 1302 base::Unretained(this)));
1291 if (rv == ERR_IO_PENDING) { 1303 if (rv == ERR_IO_PENDING) {
1292 transport_send_busy_ = true; 1304 transport_send_busy_ = true;
1293 } else { 1305 } else {
(...skipping 21 matching lines...) Expand all
1315 // One read for the SSL record header (~5 bytes) and one read for the SSL 1327 // 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 1328 // record body. Rather than issuing these reads to the underlying socket
1317 // (and constantly allocating new IOBuffers), a single Read() request to 1329 // (and constantly allocating new IOBuffers), a single Read() request to
1318 // fill |transport_bio_| is issued. As long as an SSL client socket cannot 1330 // 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 1331 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
1320 // traffic, this over-subscribed Read()ing will not cause issues. 1332 // traffic, this over-subscribed Read()ing will not cause issues.
1321 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); 1333 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
1322 if (!max_write) 1334 if (!max_write)
1323 return ERR_IO_PENDING; 1335 return ERR_IO_PENDING;
1324 1336
1325 recv_buffer_ = new IOBuffer(max_write); 1337 char* bio_transport_buf;
1338 // Get the internal buffer and number of bytes available for non-copying
1339 // write.
1340 int available_write_bytes = BIO_nwrite0(transport_bio_, &bio_transport_buf);
1341 // BIO_nwrite0() might report less than BIO_ctrl_get_write_guarantee() due to
1342 // the buffer offset and no ring buffer wrap-around for non-copying interface.
1343 DCHECK_GE(static_cast<int>(max_write), available_write_bytes);
1344 if (available_write_bytes <= 0)
1345 return ERR_IO_PENDING;
1346
1347 recv_buffer_ = new WrappedIOBuffer(bio_transport_buf);
1326 int rv = transport_->socket()->Read( 1348 int rv = transport_->socket()->Read(
1327 recv_buffer_.get(), 1349 recv_buffer_.get(),
1328 max_write, 1350 available_write_bytes,
1329 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, 1351 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
1330 base::Unretained(this))); 1352 base::Unretained(this)));
1331 if (rv == ERR_IO_PENDING) { 1353 if (rv == ERR_IO_PENDING) {
1332 transport_recv_busy_ = true; 1354 transport_recv_busy_ = true;
1333 } else { 1355 } else {
1334 rv = TransportReadComplete(rv); 1356 rv = TransportReadComplete(rv);
1335 } 1357 }
1336 return rv; 1358 return rv;
1337 } 1359 }
1338 1360
(...skipping 21 matching lines...) Expand all
1360 1382
1361 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads 1383 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads
1362 // from the socket after a write error. 1384 // from the socket after a write error.
1363 // 1385 //
1364 // TODO(davidben): Avoid having read and write ends interact this way. 1386 // TODO(davidben): Avoid having read and write ends interact this way.
1365 transport_write_error_ = result; 1387 transport_write_error_ = result;
1366 (void)BIO_shutdown_wr(transport_bio_); 1388 (void)BIO_shutdown_wr(transport_bio_);
1367 send_buffer_ = NULL; 1389 send_buffer_ = NULL;
1368 } else { 1390 } else {
1369 DCHECK(send_buffer_.get()); 1391 DCHECK(send_buffer_.get());
1392 char* bio_transport_buf;
1393 // Advance the buffer index.
1394 int ret = BIO_nread(transport_bio_, &bio_transport_buf, result);
1395 CHECK_EQ(ret, result);
1396 CHECK_EQ(bio_transport_buf, send_buffer_->data());
1370 send_buffer_->DidConsume(result); 1397 send_buffer_->DidConsume(result);
1371 DCHECK_GE(send_buffer_->BytesRemaining(), 0); 1398 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
1372 if (send_buffer_->BytesRemaining() <= 0) 1399 if (send_buffer_->BytesRemaining() <= 0)
1373 send_buffer_ = NULL; 1400 send_buffer_ = NULL;
1374 } 1401 }
1375 } 1402 }
1376 1403
1377 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { 1404 int SSLClientSocketOpenSSL::TransportReadComplete(int result) {
1378 DCHECK(ERR_IO_PENDING != result); 1405 DCHECK(ERR_IO_PENDING != result);
1379 if (result <= 0) { 1406 if (result <= 0) {
1380 DVLOG(1) << "TransportReadComplete result " << result; 1407 DVLOG(1) << "TransportReadComplete result " << result;
1381 // Received 0 (end of file) or an error. Either way, bubble it up to the 1408 // 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 1409 // 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). 1410 // relay up to the SSL socket client (i.e. via DoReadCallback).
1384 if (result == 0) 1411 if (result == 0)
1385 transport_recv_eof_ = true; 1412 transport_recv_eof_ = true;
1386 (void)BIO_shutdown_wr(transport_bio_); 1413 (void)BIO_shutdown_wr(transport_bio_);
1387 } else if (transport_write_error_ < 0) { 1414 } else if (transport_write_error_ < 0) {
1388 // Mirror transport write errors as read failures; transport_bio_ has been 1415 // Mirror transport write errors as read failures; transport_bio_ has been
1389 // shut down by TransportWriteComplete, so the BIO_write will fail, failing 1416 // shut down by TransportWriteComplete, so the BIO_write will fail, failing
1390 // the CHECK. http://crbug.com/335557. 1417 // the CHECK. http://crbug.com/335557.
1391 result = transport_write_error_; 1418 result = transport_write_error_;
1392 } else { 1419 } else {
1393 DCHECK(recv_buffer_.get()); 1420 char* bio_transport_buf;
1394 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); 1421 // Set the amount of data read into buffer.
1422 int ret = BIO_nwrite(transport_bio_, &bio_transport_buf, result);
1423 CHECK_EQ(ret, result);
1424 CHECK_EQ(bio_transport_buf, recv_buffer_->data());
1395 // A write into a memory BIO should always succeed. 1425 // A write into a memory BIO should always succeed.
1396 // Force values on the stack for http://crbug.com/335557 1426 // Force values on the stack for http://crbug.com/335557
1397 base::debug::Alias(&result); 1427 base::debug::Alias(&result);
1398 base::debug::Alias(&ret); 1428 base::debug::Alias(&ret);
1399 CHECK_EQ(result, ret); 1429 CHECK_EQ(result, ret);
1400 } 1430 }
1401 recv_buffer_ = NULL; 1431 recv_buffer_ = NULL;
1402 transport_recv_busy_ = false; 1432 transport_recv_busy_ = false;
1403 return result; 1433 return result;
1404 } 1434 }
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; 1595 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
1566 return SSL_TLSEXT_ERR_OK; 1596 return SSL_TLSEXT_ERR_OK;
1567 } 1597 }
1568 1598
1569 scoped_refptr<X509Certificate> 1599 scoped_refptr<X509Certificate>
1570 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { 1600 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
1571 return server_cert_; 1601 return server_cert_;
1572 } 1602 }
1573 1603
1574 } // namespace net 1604 } // 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