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

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

Issue 12025040: When reading from an SSL socket, attempt to fully fill the caller's buffer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review feedback Created 7 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | 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/ssl.h> 10 #include <openssl/ssl.h>
(...skipping 25 matching lines...) Expand all
36 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ 36 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
37 " jump to state " << s; \ 37 " jump to state " << s; \
38 next_handshake_state_ = s; } while (0) 38 next_handshake_state_ = s; } while (0)
39 #else 39 #else
40 #define GotoState(s) next_handshake_state_ = s 40 #define GotoState(s) next_handshake_state_ = s
41 #endif 41 #endif
42 42
43 const int kSessionCacheTimeoutSeconds = 60 * 60; 43 const int kSessionCacheTimeoutSeconds = 60 * 60;
44 const size_t kSessionCacheMaxEntires = 1024; 44 const size_t kSessionCacheMaxEntires = 1024;
45 45
46 // This constant can be any non-negative/non-zero value (eg: it does not
47 // overlap with any value of the net::Error range, including net::OK).
48 const int kNoPendingReadResult = 1;
49
46 // If a client doesn't have a list of protocols that it supports, but 50 // If a client doesn't have a list of protocols that it supports, but
47 // the server supports NPN, choosing "http/1.1" is the best answer. 51 // the server supports NPN, choosing "http/1.1" is the best answer.
48 const char kDefaultSupportedNPNProtocol[] = "http/1.1"; 52 const char kDefaultSupportedNPNProtocol[] = "http/1.1";
49 53
50 #if OPENSSL_VERSION_NUMBER < 0x1000103fL 54 #if OPENSSL_VERSION_NUMBER < 0x1000103fL
51 // This method doesn't seem to have made it into the OpenSSL headers. 55 // This method doesn't seem to have made it into the OpenSSL headers.
52 unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; } 56 unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; }
53 #endif 57 #endif
54 58
55 // Used for encoding the |connection_status| field of an SSLInfo object. 59 // Used for encoding the |connection_status| field of an SSLInfo object.
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 } 422 }
419 423
420 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( 424 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
421 ClientSocketHandle* transport_socket, 425 ClientSocketHandle* transport_socket,
422 const HostPortPair& host_and_port, 426 const HostPortPair& host_and_port,
423 const SSLConfig& ssl_config, 427 const SSLConfig& ssl_config,
424 const SSLClientSocketContext& context) 428 const SSLClientSocketContext& context)
425 : transport_send_busy_(false), 429 : transport_send_busy_(false),
426 transport_recv_busy_(false), 430 transport_recv_busy_(false),
427 transport_recv_eof_(false), 431 transport_recv_eof_(false),
432 pending_read_error_(kNoPendingReadResult),
428 completed_handshake_(false), 433 completed_handshake_(false),
429 client_auth_cert_needed_(false), 434 client_auth_cert_needed_(false),
430 cert_verifier_(context.cert_verifier), 435 cert_verifier_(context.cert_verifier),
431 ssl_(NULL), 436 ssl_(NULL),
432 transport_bio_(NULL), 437 transport_bio_(NULL),
433 transport_(transport_socket), 438 transport_(transport_socket),
434 host_and_port_(host_and_port), 439 host_and_port_(host_and_port),
435 ssl_config_(ssl_config), 440 ssl_config_(ssl_config),
436 ssl_session_cache_shard_(context.ssl_session_cache_shard), 441 ssl_session_cache_shard_(context.ssl_session_cache_shard),
437 trying_cached_session_(false), 442 trying_cached_session_(false),
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after
1333 bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { 1338 bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
1334 return transport_->socket()->SetReceiveBufferSize(size); 1339 return transport_->socket()->SetReceiveBufferSize(size);
1335 } 1340 }
1336 1341
1337 bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { 1342 bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
1338 return transport_->socket()->SetSendBufferSize(size); 1343 return transport_->socket()->SetSendBufferSize(size);
1339 } 1344 }
1340 1345
1341 int SSLClientSocketOpenSSL::DoPayloadRead() { 1346 int SSLClientSocketOpenSSL::DoPayloadRead() {
1342 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 1347 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
1343 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_); 1348
1344 // We don't need to invalidate the non-client-authenticated SSL session 1349 int rv;
1345 // because the server will renegotiate anyway. 1350 if (pending_read_error_ != kNoPendingReadResult) {
1346 if (client_auth_cert_needed_) 1351 rv = pending_read_error_;
1347 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 1352 pending_read_error_ = kNoPendingReadResult;
1353 if (rv == 0) {
1354 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED,
1355 rv, user_read_buf_->data());
1356 }
1357 return rv;
1358 }
1359
1360 int total_bytes_read = 0;
1361 do {
1362 rv = SSL_read(ssl_, user_read_buf_->data() + total_bytes_read,
1363 user_read_buf_len_ - total_bytes_read);
1364 if (rv > 0)
1365 total_bytes_read += rv;
1366 } while (total_bytes_read < user_read_buf_len_ && rv > 0);
1367
1368 if (total_bytes_read == user_read_buf_len_) {
1369 rv = total_bytes_read;
1370 } else {
1371 // Otherwise, an error occurred (rv <= 0). The error needs to be handled
1372 // immediately, while the OpenSSL errors are still available in
1373 // thread-local storage. However, the handled/remapped error code should
1374 // only be returned if no application data was already read; if it was, the
1375 // error code should be deferred until the next call of DoPayloadRead.
1376 //
1377 // If no data was read, |*next_result| will point to the return value of
1378 // this function. If at least some data was read, |*next_result| will point
1379 // to |pending_read_error_|, to be returned in a future call to
1380 // DoPayloadRead() (e.g.: after the current data is handled).
1381 int *next_result = &rv;
1382 if (total_bytes_read > 0) {
1383 pending_read_error_ = rv;
1384 rv = total_bytes_read;
1385 next_result = &pending_read_error_;
1386 }
1387
1388 if (client_auth_cert_needed_) {
1389 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1390 } else if (*next_result < 0) {
1391 int err = SSL_get_error(ssl_, *next_result);
1392 *next_result = MapOpenSSLError(err, err_tracer);
1393 if (rv > 0 && *next_result == ERR_IO_PENDING) {
1394 // If at least some data was read from SSL_read(), do not treat
1395 // insufficient data as an error to return in the next call to
1396 // DoPayloadRead() - instead, let the call fall through to check
1397 // SSL_read() again. This is because DoTransportIO() may complete
1398 // in between the next call to DoPayloadRead(), and thus it is
1399 // important to check SSL_read() on subsequent invocations to see
1400 // if a complete record may now be read.
1401 *next_result = kNoPendingReadResult;
1402 }
1403 }
1404 }
1348 1405
1349 if (rv >= 0) { 1406 if (rv >= 0) {
1350 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, 1407 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
1351 user_read_buf_->data()); 1408 user_read_buf_->data());
1352 return rv;
1353 } 1409 }
1354 1410 return rv;
1355 int err = SSL_get_error(ssl_, rv);
1356 return MapOpenSSLError(err, err_tracer);
1357 } 1411 }
1358 1412
1359 int SSLClientSocketOpenSSL::DoPayloadWrite() { 1413 int SSLClientSocketOpenSSL::DoPayloadWrite() {
1360 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 1414 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
1361 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); 1415 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
1362 1416
1363 if (rv >= 0) { 1417 if (rv >= 0) {
1364 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv, 1418 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
1365 user_write_buf_->data()); 1419 user_write_buf_->data());
1366 return rv; 1420 return rv;
1367 } 1421 }
1368 1422
1369 int err = SSL_get_error(ssl_, rv); 1423 int err = SSL_get_error(ssl_, rv);
1370 return MapOpenSSLError(err, err_tracer); 1424 return MapOpenSSLError(err, err_tracer);
1371 } 1425 }
1372 1426
1373 } // namespace net 1427 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698