OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // TODO(ukai): code is similar with http_network_transaction.cc. We should | 5 // TODO(ukai): code is similar with http_network_transaction.cc. We should |
6 // think about ways to share code, if possible. | 6 // think about ways to share code, if possible. |
7 | 7 |
8 #include "net/socket_stream/socket_stream.h" | 8 #include "net/socket_stream/socket_stream.h" |
9 | 9 |
10 #include <set> | 10 #include <set> |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
297 Delegate* delegate = delegate_; | 297 Delegate* delegate = delegate_; |
298 delegate_ = NULL; | 298 delegate_ = NULL; |
299 if (delegate) { | 299 if (delegate) { |
300 delegate->OnError(this, result); | 300 delegate->OnError(this, result); |
301 if (result != ERR_PROTOCOL_SWITCHED) | 301 if (result != ERR_PROTOCOL_SWITCHED) |
302 delegate->OnClose(this); | 302 delegate->OnClose(this); |
303 } | 303 } |
304 Release(); | 304 Release(); |
305 } | 305 } |
306 | 306 |
307 int SocketStream::DidEstablishSSL(int result) { | |
308 if (IsCertificateError(result)) { | |
309 if (socket_->IsConnectedAndIdle()) { | |
310 result = HandleCertificateError(result); | |
311 } else { | |
312 // SSLClientSocket for Mac will report socket is not connected, | |
313 // if it returns cert verification error. It didn't perform | |
314 // SSLHandshake yet. | |
315 // So, we should restart establishing connection with the | |
316 // certificate in allowed bad certificates in |ssl_config_|. | |
317 // See also net/http/http_network_transaction.cc | |
318 // HandleCertificateError() and RestartIgnoringLastError(). | |
319 SSLClientSocket* ssl_socket = | |
320 reinterpret_cast<SSLClientSocket*>(socket_.get()); | |
321 SSLInfo ssl_info; | |
322 ssl_socket->GetSSLInfo(&ssl_info); | |
323 if (ssl_info.cert == NULL || | |
324 ssl_config_.IsAllowedBadCert(ssl_info.cert, NULL)) { | |
325 // If we already have the certificate in the set of allowed bad | |
326 // certificates, we did try it and failed again, so we should not | |
327 // retry again: the connection should fail at last. | |
328 next_state_ = STATE_CLOSE; | |
329 return result; | |
330 } | |
331 // Add the bad certificate to the set of allowed certificates in the | |
332 // SSL config object. | |
333 SSLConfig::CertAndStatus bad_cert; | |
334 if (!ssl_info.cert->GetDEREncoded(&bad_cert.der_cert)) { | |
335 next_state_ = STATE_CLOSE; | |
336 return result; | |
337 } | |
338 bad_cert.cert_status = ssl_info.cert_status; | |
339 ssl_config_.allowed_bad_certs.push_back(bad_cert); | |
340 // Restart connection ignoring the bad certificate. | |
341 socket_->Disconnect(); | |
342 socket_.reset(); | |
343 next_state_ = STATE_TCP_CONNECT; | |
344 return OK; | |
345 } | |
346 } | |
347 return result; | |
348 } | |
349 | |
307 int SocketStream::DidEstablishConnection() { | 350 int SocketStream::DidEstablishConnection() { |
308 if (!socket_.get() || !socket_->IsConnected()) { | 351 if (!socket_.get() || !socket_->IsConnected()) { |
309 next_state_ = STATE_CLOSE; | 352 next_state_ = STATE_CLOSE; |
310 return ERR_CONNECTION_FAILED; | 353 return ERR_CONNECTION_FAILED; |
311 } | 354 } |
312 next_state_ = STATE_READ_WRITE; | 355 next_state_ = STATE_READ_WRITE; |
313 metrics_->OnConnected(); | 356 metrics_->OnConnected(); |
314 | 357 |
315 net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT, NULL); | 358 net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT, NULL); |
316 if (delegate_) | 359 if (delegate_) |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
433 case STATE_READ_TUNNEL_HEADERS_COMPLETE: | 476 case STATE_READ_TUNNEL_HEADERS_COMPLETE: |
434 result = DoReadTunnelHeadersComplete(result); | 477 result = DoReadTunnelHeadersComplete(result); |
435 break; | 478 break; |
436 case STATE_SOCKS_CONNECT: | 479 case STATE_SOCKS_CONNECT: |
437 DCHECK_EQ(OK, result); | 480 DCHECK_EQ(OK, result); |
438 result = DoSOCKSConnect(); | 481 result = DoSOCKSConnect(); |
439 break; | 482 break; |
440 case STATE_SOCKS_CONNECT_COMPLETE: | 483 case STATE_SOCKS_CONNECT_COMPLETE: |
441 result = DoSOCKSConnectComplete(result); | 484 result = DoSOCKSConnectComplete(result); |
442 break; | 485 break; |
486 case STATE_SECURE_PROXY_CONNECT: | |
487 DCHECK_EQ(OK, result); | |
488 result = DoSecureProxyConnect(); | |
489 break; | |
490 case STATE_SECURE_PROXY_CONNECT_COMPLETE: | |
491 result = DoSecureProxyConnectComplete(result); | |
492 break; | |
443 case STATE_SSL_CONNECT: | 493 case STATE_SSL_CONNECT: |
444 DCHECK_EQ(OK, result); | 494 DCHECK_EQ(OK, result); |
445 result = DoSSLConnect(); | 495 result = DoSSLConnect(); |
446 break; | 496 break; |
447 case STATE_SSL_CONNECT_COMPLETE: | 497 case STATE_SSL_CONNECT_COMPLETE: |
448 result = DoSSLConnectComplete(result); | 498 result = DoSSLConnectComplete(result); |
449 break; | 499 break; |
450 case STATE_READ_WRITE: | 500 case STATE_READ_WRITE: |
451 result = DoReadWrite(result); | 501 result = DoReadWrite(result); |
452 break; | 502 break; |
453 case STATE_AUTH_REQUIRED: | 503 case STATE_AUTH_REQUIRED: |
454 // It might be called when DoClose is called while waiting in | 504 // It might be called when DoClose is called while waiting in |
455 // STATE_AUTH_REQUIRED. | 505 // STATE_AUTH_REQUIRED. |
456 Finish(result); | 506 Finish(result); |
457 return; | 507 return; |
458 case STATE_CLOSE: | 508 case STATE_CLOSE: |
459 DCHECK_LE(result, OK); | 509 DCHECK_LE(result, OK); |
460 Finish(result); | 510 Finish(result); |
461 return; | 511 return; |
462 default: | 512 default: |
463 NOTREACHED() << "bad state " << state; | 513 NOTREACHED() << "bad state " << state; |
464 Finish(result); | 514 Finish(result); |
465 return; | 515 return; |
466 } | 516 } |
467 if (state == STATE_RESOLVE_PROTOCOL && result == ERR_PROTOCOL_SWITCHED) | 517 if (state == STATE_RESOLVE_PROTOCOL && result == ERR_PROTOCOL_SWITCHED) |
468 continue; | 518 continue; |
469 // If the connection is not established yet and had actual errors, | 519 // If the connection is not established yet and had actual errors, |
470 // close the connection. | 520 // close the connection. |
471 if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) { | 521 if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) { |
472 DCHECK_EQ(next_state_, STATE_CLOSE); | 522 next_state_ = STATE_CLOSE; |
ukai
2011/07/25 12:33:14
hmm, we might not need this.
If Do* method returns
Yuta Kitamura
2011/07/25 12:39:47
I think that's better.
| |
473 net_log_.EndEventWithNetErrorCode( | 523 net_log_.EndEventWithNetErrorCode( |
474 NetLog::TYPE_SOCKET_STREAM_CONNECT, result); | 524 NetLog::TYPE_SOCKET_STREAM_CONNECT, result); |
475 } | 525 } |
476 } while (result != ERR_IO_PENDING); | 526 } while (result != ERR_IO_PENDING); |
477 } | 527 } |
478 | 528 |
479 int SocketStream::DoResolveProxy() { | 529 int SocketStream::DoResolveProxy() { |
480 DCHECK(!pac_request_); | 530 DCHECK(!pac_request_); |
481 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | 531 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; |
482 | 532 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
609 return socket_->Connect(&io_callback_); | 659 return socket_->Connect(&io_callback_); |
610 } | 660 } |
611 | 661 |
612 int SocketStream::DoTcpConnectComplete(int result) { | 662 int SocketStream::DoTcpConnectComplete(int result) { |
613 // TODO(ukai): if error occured, reconsider proxy after error. | 663 // TODO(ukai): if error occured, reconsider proxy after error. |
614 if (result != OK) { | 664 if (result != OK) { |
615 next_state_ = STATE_CLOSE; | 665 next_state_ = STATE_CLOSE; |
616 return result; | 666 return result; |
617 } | 667 } |
618 | 668 |
619 if (proxy_mode_ == kTunnelProxy) | 669 if (proxy_mode_ == kTunnelProxy) { |
620 next_state_ = STATE_WRITE_TUNNEL_HEADERS; | 670 if (proxy_info_.is_https()) |
621 else if (proxy_mode_ == kSOCKSProxy) | 671 next_state_ = STATE_SECURE_PROXY_CONNECT; |
672 else | |
673 next_state_ = STATE_WRITE_TUNNEL_HEADERS; | |
674 } else if (proxy_mode_ == kSOCKSProxy) { | |
622 next_state_ = STATE_SOCKS_CONNECT; | 675 next_state_ = STATE_SOCKS_CONNECT; |
623 else if (is_secure()) { | 676 } else if (is_secure()) { |
624 next_state_ = STATE_SSL_CONNECT; | 677 next_state_ = STATE_SSL_CONNECT; |
625 } else { | 678 } else { |
626 result = DidEstablishConnection(); | 679 result = DidEstablishConnection(); |
627 } | 680 } |
628 return result; | 681 return result; |
629 } | 682 } |
630 | 683 |
631 int SocketStream::DoWriteTunnelHeaders() { | 684 int SocketStream::DoWriteTunnelHeaders() { |
632 DCHECK_EQ(kTunnelProxy, proxy_mode_); | 685 DCHECK_EQ(kTunnelProxy, proxy_mode_); |
633 | 686 |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
843 if (is_secure()) | 896 if (is_secure()) |
844 next_state_ = STATE_SSL_CONNECT; | 897 next_state_ = STATE_SSL_CONNECT; |
845 else | 898 else |
846 result = DidEstablishConnection(); | 899 result = DidEstablishConnection(); |
847 } else { | 900 } else { |
848 next_state_ = STATE_CLOSE; | 901 next_state_ = STATE_CLOSE; |
849 } | 902 } |
850 return result; | 903 return result; |
851 } | 904 } |
852 | 905 |
906 int SocketStream::DoSecureProxyConnect() { | |
907 DCHECK(factory_); | |
908 SSLClientSocketContext ssl_context; | |
909 ssl_context.cert_verifier = cert_verifier_; | |
910 ssl_context.origin_bound_cert_service = origin_bound_cert_service_; | |
911 // TODO(agl): look into plumbing SSLHostInfo here. | |
912 socket_.reset(factory_->CreateSSLClientSocket( | |
913 socket_.release(), | |
914 proxy_info_.proxy_server().host_port_pair(), | |
915 ssl_config_, | |
916 NULL /* ssl_host_info */, | |
917 ssl_context)); | |
918 next_state_ = STATE_SECURE_PROXY_CONNECT_COMPLETE; | |
919 metrics_->OnCountConnectionType(SocketStreamMetrics::SECURE_PROXY_CONNECTION); | |
920 return socket_->Connect(&io_callback_); | |
Yuta Kitamura
2011/07/25 10:24:44
Can't you set STATE_CLOSE to next_state_ if Connec
ukai
2011/07/25 10:29:59
It's possible, but other methods (Read, Write, ...
Yuta Kitamura
2011/07/25 10:44:48
Um... if I read DoReadWrite() correctly, it always
ukai
2011/07/25 11:49:04
not only DoReadWrite().
We had a potential bug whe
| |
921 } | |
922 | |
923 int SocketStream::DoSecureProxyConnectComplete(int result) { | |
924 DCHECK_EQ(STATE_NONE, next_state_); | |
925 result = DidEstablishSSL(result); | |
926 if (next_state_ != STATE_NONE) | |
927 return result; | |
928 if (result == OK) | |
929 next_state_ = STATE_WRITE_TUNNEL_HEADERS; | |
930 else | |
931 next_state_ = STATE_CLOSE; | |
932 return result; | |
933 } | |
934 | |
853 int SocketStream::DoSSLConnect() { | 935 int SocketStream::DoSSLConnect() { |
854 DCHECK(factory_); | 936 DCHECK(factory_); |
855 SSLClientSocketContext ssl_context; | 937 SSLClientSocketContext ssl_context; |
856 ssl_context.cert_verifier = cert_verifier_; | 938 ssl_context.cert_verifier = cert_verifier_; |
857 ssl_context.origin_bound_cert_service = origin_bound_cert_service_; | 939 ssl_context.origin_bound_cert_service = origin_bound_cert_service_; |
858 // TODO(agl): look into plumbing SSLHostInfo here. | 940 // TODO(agl): look into plumbing SSLHostInfo here. |
859 socket_.reset(factory_->CreateSSLClientSocket(socket_.release(), | 941 socket_.reset(factory_->CreateSSLClientSocket(socket_.release(), |
860 HostPortPair::FromURL(url_), | 942 HostPortPair::FromURL(url_), |
861 ssl_config_, | 943 ssl_config_, |
862 NULL /* ssl_host_info */, | 944 NULL /* ssl_host_info */, |
863 ssl_context)); | 945 ssl_context)); |
864 next_state_ = STATE_SSL_CONNECT_COMPLETE; | 946 next_state_ = STATE_SSL_CONNECT_COMPLETE; |
865 metrics_->OnCountConnectionType(SocketStreamMetrics::SSL_CONNECTION); | 947 metrics_->OnCountConnectionType(SocketStreamMetrics::SSL_CONNECTION); |
866 return socket_->Connect(&io_callback_); | 948 return socket_->Connect(&io_callback_); |
867 } | 949 } |
868 | 950 |
869 int SocketStream::DoSSLConnectComplete(int result) { | 951 int SocketStream::DoSSLConnectComplete(int result) { |
870 if (IsCertificateError(result)) { | 952 DCHECK_EQ(STATE_NONE, next_state_); |
871 if (socket_->IsConnectedAndIdle()) { | 953 result = DidEstablishSSL(result); |
872 result = HandleCertificateError(result); | 954 if (next_state_ != STATE_NONE) |
873 } else { | 955 return result; |
874 // SSLClientSocket for Mac will report socket is not connected, | |
875 // if it returns cert verification error. It didn't perform | |
876 // SSLHandshake yet. | |
877 // So, we should restart establishing connection with the | |
878 // certificate in allowed bad certificates in |ssl_config_|. | |
879 // See also net/http/http_network_transaction.cc | |
880 // HandleCertificateError() and RestartIgnoringLastError(). | |
881 SSLClientSocket* ssl_socket = | |
882 reinterpret_cast<SSLClientSocket*>(socket_.get()); | |
883 SSLInfo ssl_info; | |
884 ssl_socket->GetSSLInfo(&ssl_info); | |
885 if (ssl_info.cert == NULL || | |
886 ssl_config_.IsAllowedBadCert(ssl_info.cert, NULL)) { | |
887 // If we already have the certificate in the set of allowed bad | |
888 // certificates, we did try it and failed again, so we should not | |
889 // retry again: the connection should fail at last. | |
890 next_state_ = STATE_CLOSE; | |
891 return result; | |
892 } | |
893 // Add the bad certificate to the set of allowed certificates in the | |
894 // SSL config object. | |
895 SSLConfig::CertAndStatus bad_cert; | |
896 if (!ssl_info.cert->GetDEREncoded(&bad_cert.der_cert)) { | |
897 next_state_ = STATE_CLOSE; | |
898 return result; | |
899 } | |
900 bad_cert.cert_status = ssl_info.cert_status; | |
901 ssl_config_.allowed_bad_certs.push_back(bad_cert); | |
902 // Restart connection ignoring the bad certificate. | |
903 socket_->Disconnect(); | |
904 socket_.reset(); | |
905 next_state_ = STATE_TCP_CONNECT; | |
906 return OK; | |
907 } | |
908 } | |
909 | |
910 // TODO(toyoshim): Upgrade to SPDY through TLS NPN extension if possible. | 956 // TODO(toyoshim): Upgrade to SPDY through TLS NPN extension if possible. |
911 // If we use HTTPS and this is the first connection to the SPDY server, | 957 // If we use HTTPS and this is the first connection to the SPDY server, |
912 // we should take care of TLS NPN extension here. | 958 // we should take care of TLS NPN extension here. |
913 | 959 |
914 if (result == OK) | 960 if (result == OK) |
915 result = DidEstablishConnection(); | 961 result = DidEstablishConnection(); |
916 else | 962 else |
917 next_state_ = STATE_CLOSE; | 963 next_state_ = STATE_CLOSE; |
918 return result; | 964 return result; |
919 } | 965 } |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1087 | 1133 |
1088 SSLConfigService* SocketStream::ssl_config_service() const { | 1134 SSLConfigService* SocketStream::ssl_config_service() const { |
1089 return context_->ssl_config_service(); | 1135 return context_->ssl_config_service(); |
1090 } | 1136 } |
1091 | 1137 |
1092 ProxyService* SocketStream::proxy_service() const { | 1138 ProxyService* SocketStream::proxy_service() const { |
1093 return context_->proxy_service(); | 1139 return context_->proxy_service(); |
1094 } | 1140 } |
1095 | 1141 |
1096 } // namespace net | 1142 } // namespace net |
OLD | NEW |