OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 #include "net/http/http_network_transaction.h" | 5 #include "net/http/http_network_transaction.h" |
6 | 6 |
7 #include "base/scoped_ptr.h" | 7 #include "base/scoped_ptr.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/field_trial.h" | 9 #include "base/field_trial.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "base/trace_event.h" | 11 #include "base/trace_event.h" |
12 #include "build/build_config.h" | 12 #include "build/build_config.h" |
13 #include "net/base/connection_type_histograms.h" | 13 #include "net/base/connection_type_histograms.h" |
14 #include "net/base/io_buffer.h" | 14 #include "net/base/io_buffer.h" |
15 #include "net/base/load_flags.h" | 15 #include "net/base/load_flags.h" |
16 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
17 #include "net/base/net_util.h" | 17 #include "net/base/net_util.h" |
18 #include "net/base/ssl_cert_request_info.h" | 18 #include "net/base/ssl_cert_request_info.h" |
19 #include "net/base/upload_data_stream.h" | 19 #include "net/base/upload_data_stream.h" |
20 #include "net/http/http_auth.h" | 20 #include "net/http/http_auth.h" |
21 #include "net/http/http_auth_handler.h" | 21 #include "net/http/http_auth_handler.h" |
22 #include "net/http/http_basic_stream.h" | 22 #include "net/http/http_basic_stream.h" |
23 #include "net/http/http_chunked_decoder.h" | 23 #include "net/http/http_chunked_decoder.h" |
24 #include "net/http/http_network_session.h" | 24 #include "net/http/http_network_session.h" |
25 #include "net/http/http_request_info.h" | 25 #include "net/http/http_request_info.h" |
26 #include "net/http/http_response_headers.h" | 26 #include "net/http/http_response_headers.h" |
27 #include "net/http/http_util.h" | 27 #include "net/http/http_util.h" |
28 #include "net/socket/client_socket_factory.h" | 28 #include "net/socket/client_socket_factory.h" |
| 29 #include "net/socket/socks_client_socket.h" |
29 #include "net/socket/ssl_client_socket.h" | 30 #include "net/socket/ssl_client_socket.h" |
30 | 31 |
31 using base::Time; | 32 using base::Time; |
32 | 33 |
33 namespace net { | 34 namespace net { |
34 | 35 |
35 void HttpNetworkTransaction::ResponseHeaders::Realloc(size_t new_size) { | 36 void HttpNetworkTransaction::ResponseHeaders::Realloc(size_t new_size) { |
36 headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size))); | 37 headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size))); |
37 } | 38 } |
38 | 39 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 user_callback_(NULL), | 135 user_callback_(NULL), |
135 session_(session), | 136 session_(session), |
136 request_(NULL), | 137 request_(NULL), |
137 pac_request_(NULL), | 138 pac_request_(NULL), |
138 socket_factory_(csf), | 139 socket_factory_(csf), |
139 connection_(session->connection_pool()), | 140 connection_(session->connection_pool()), |
140 reused_socket_(false), | 141 reused_socket_(false), |
141 using_ssl_(false), | 142 using_ssl_(false), |
142 using_proxy_(false), | 143 using_proxy_(false), |
143 using_tunnel_(false), | 144 using_tunnel_(false), |
| 145 using_socks_proxy_(false), |
144 establishing_tunnel_(false), | 146 establishing_tunnel_(false), |
145 reading_body_from_socket_(false), | 147 reading_body_from_socket_(false), |
146 request_headers_(new RequestHeaders()), | 148 request_headers_(new RequestHeaders()), |
147 request_headers_bytes_sent_(0), | 149 request_headers_bytes_sent_(0), |
148 header_buf_(new ResponseHeaders()), | 150 header_buf_(new ResponseHeaders()), |
149 header_buf_capacity_(0), | 151 header_buf_capacity_(0), |
150 header_buf_len_(0), | 152 header_buf_len_(0), |
151 header_buf_body_offset_(-1), | 153 header_buf_body_offset_(-1), |
152 header_buf_http_offset_(-1), | 154 header_buf_http_offset_(-1), |
153 response_body_length_(-1), // -1 means unspecified. | 155 response_body_length_(-1), // -1 means unspecified. |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 break; | 443 break; |
442 case STATE_INIT_CONNECTION: | 444 case STATE_INIT_CONNECTION: |
443 DCHECK_EQ(OK, rv); | 445 DCHECK_EQ(OK, rv); |
444 TRACE_EVENT_BEGIN("http.init_conn", request_, request_->url.spec()); | 446 TRACE_EVENT_BEGIN("http.init_conn", request_, request_->url.spec()); |
445 rv = DoInitConnection(); | 447 rv = DoInitConnection(); |
446 break; | 448 break; |
447 case STATE_INIT_CONNECTION_COMPLETE: | 449 case STATE_INIT_CONNECTION_COMPLETE: |
448 rv = DoInitConnectionComplete(rv); | 450 rv = DoInitConnectionComplete(rv); |
449 TRACE_EVENT_END("http.init_conn", request_, request_->url.spec()); | 451 TRACE_EVENT_END("http.init_conn", request_, request_->url.spec()); |
450 break; | 452 break; |
| 453 case STATE_SOCKS_CONNECT: |
| 454 DCHECK_EQ(OK, rv); |
| 455 TRACE_EVENT_BEGIN("http.socks_connect", request_, request_->url.spec()); |
| 456 rv = DoSOCKSConnect(); |
| 457 break; |
| 458 case STATE_SOCKS_CONNECT_COMPLETE: |
| 459 rv = DoSOCKSConnectComplete(rv); |
| 460 TRACE_EVENT_END("http.socks_connect", request_, request_->url.spec()); |
| 461 break; |
451 case STATE_SSL_CONNECT: | 462 case STATE_SSL_CONNECT: |
452 DCHECK_EQ(OK, rv); | 463 DCHECK_EQ(OK, rv); |
453 TRACE_EVENT_BEGIN("http.ssl_connect", request_, request_->url.spec()); | 464 TRACE_EVENT_BEGIN("http.ssl_connect", request_, request_->url.spec()); |
454 rv = DoSSLConnect(); | 465 rv = DoSSLConnect(); |
455 break; | 466 break; |
456 case STATE_SSL_CONNECT_COMPLETE: | 467 case STATE_SSL_CONNECT_COMPLETE: |
457 rv = DoSSLConnectComplete(rv); | 468 rv = DoSSLConnectComplete(rv); |
458 TRACE_EVENT_END("http.ssl_connect", request_, request_->url.spec()); | 469 TRACE_EVENT_END("http.ssl_connect", request_, request_->url.spec()); |
459 break; | 470 break; |
460 case STATE_WRITE_HEADERS: | 471 case STATE_WRITE_HEADERS: |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 return OK; | 535 return OK; |
525 } | 536 } |
526 | 537 |
527 return session_->proxy_service()->ResolveProxy( | 538 return session_->proxy_service()->ResolveProxy( |
528 request_->url, &proxy_info_, &io_callback_, &pac_request_); | 539 request_->url, &proxy_info_, &io_callback_, &pac_request_); |
529 } | 540 } |
530 | 541 |
531 int HttpNetworkTransaction::DoResolveProxyComplete(int result) { | 542 int HttpNetworkTransaction::DoResolveProxyComplete(int result) { |
532 next_state_ = STATE_INIT_CONNECTION; | 543 next_state_ = STATE_INIT_CONNECTION; |
533 | 544 |
534 // Since we only support HTTP proxies or DIRECT connections, remove | 545 // Remove unsupported proxies (like SOCKS5) from the list. |
535 // any other type of proxy from the list (i.e. SOCKS). | |
536 // Supporting SOCKS is issue http://crbug.com/469. | |
537 proxy_info_.RemoveProxiesWithoutScheme( | 546 proxy_info_.RemoveProxiesWithoutScheme( |
538 ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP); | 547 ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP | |
| 548 ProxyServer::SCHEME_SOCKS4); |
539 | 549 |
540 pac_request_ = NULL; | 550 pac_request_ = NULL; |
541 | 551 |
542 if (result != OK) { | 552 if (result != OK) { |
543 DLOG(ERROR) << "Failed to resolve proxy: " << result; | 553 DLOG(ERROR) << "Failed to resolve proxy: " << result; |
544 proxy_info_.UseDirect(); | 554 proxy_info_.UseDirect(); |
545 } | 555 } |
546 return OK; | 556 return OK; |
547 } | 557 } |
548 | 558 |
549 int HttpNetworkTransaction::DoInitConnection() { | 559 int HttpNetworkTransaction::DoInitConnection() { |
550 DCHECK(!connection_.is_initialized()); | 560 DCHECK(!connection_.is_initialized()); |
551 | 561 |
552 next_state_ = STATE_INIT_CONNECTION_COMPLETE; | 562 next_state_ = STATE_INIT_CONNECTION_COMPLETE; |
553 | 563 |
554 using_ssl_ = request_->url.SchemeIs("https"); | 564 using_ssl_ = request_->url.SchemeIs("https"); |
555 using_proxy_ = !proxy_info_.is_direct() && !using_ssl_; | 565 using_socks_proxy_ = !proxy_info_.is_direct() && |
556 using_tunnel_ = !proxy_info_.is_direct() && using_ssl_; | 566 proxy_info_.proxy_server().is_socks(); |
| 567 using_proxy_ = !proxy_info_.is_direct() && !using_ssl_ && !using_socks_proxy_; |
| 568 using_tunnel_ = !proxy_info_.is_direct() && using_ssl_ && !using_socks_proxy_; |
557 | 569 |
558 // Build the string used to uniquely identify connections of this type. | 570 // Build the string used to uniquely identify connections of this type. |
559 // Determine the host and port to connect to. | 571 // Determine the host and port to connect to. |
560 std::string connection_group; | 572 std::string connection_group; |
561 std::string host; | 573 std::string host; |
562 int port; | 574 int port; |
563 if (using_proxy_ || using_tunnel_) { | 575 if (using_proxy_ || using_tunnel_ || using_socks_proxy_) { |
564 ProxyServer proxy_server = proxy_info_.proxy_server(); | 576 ProxyServer proxy_server = proxy_info_.proxy_server(); |
565 connection_group = "proxy/" + proxy_server.ToURI() + "/"; | 577 connection_group = "proxy/" + proxy_server.ToURI() + "/"; |
566 host = proxy_server.HostNoBrackets(); | 578 host = proxy_server.HostNoBrackets(); |
567 port = proxy_server.port(); | 579 port = proxy_server.port(); |
568 } else { | 580 } else { |
569 host = request_->url.HostNoBrackets(); | 581 host = request_->url.HostNoBrackets(); |
570 port = request_->url.EffectiveIntPort(); | 582 port = request_->url.EffectiveIntPort(); |
571 } | 583 } |
572 if (!using_proxy_) | 584 if (!using_proxy_ && !using_socks_proxy_) |
573 connection_group.append(request_->url.GetOrigin().spec()); | 585 connection_group.append(request_->url.GetOrigin().spec()); |
574 | 586 |
575 DCHECK(!connection_group.empty()); | 587 DCHECK(!connection_group.empty()); |
576 | 588 |
577 HostResolver::RequestInfo resolve_info(host, port); | 589 HostResolver::RequestInfo resolve_info(host, port); |
578 | 590 |
579 // The referrer is used by the DNS prefetch system to corellate resolutions | 591 // The referrer is used by the DNS prefetch system to corellate resolutions |
580 // with the page that triggered them. It doesn't impact the actual addresses | 592 // with the page that triggered them. It doesn't impact the actual addresses |
581 // that we resolve to. | 593 // that we resolve to. |
582 resolve_info.set_referrer(request_->referrer); | 594 resolve_info.set_referrer(request_->referrer); |
(...skipping 18 matching lines...) Expand all Loading... |
601 // Set the reused_socket_ flag to indicate that we are using a keep-alive | 613 // Set the reused_socket_ flag to indicate that we are using a keep-alive |
602 // connection. This flag is used to handle errors that occur while we are | 614 // connection. This flag is used to handle errors that occur while we are |
603 // trying to reuse a keep-alive connection. | 615 // trying to reuse a keep-alive connection. |
604 reused_socket_ = connection_.is_reused(); | 616 reused_socket_ = connection_.is_reused(); |
605 if (reused_socket_) { | 617 if (reused_socket_) { |
606 next_state_ = STATE_WRITE_HEADERS; | 618 next_state_ = STATE_WRITE_HEADERS; |
607 } else { | 619 } else { |
608 // Now we have a TCP connected socket. Perform other connection setup as | 620 // Now we have a TCP connected socket. Perform other connection setup as |
609 // needed. | 621 // needed. |
610 LogTCPConnectedMetrics(); | 622 LogTCPConnectedMetrics(); |
611 if (using_ssl_ && !using_tunnel_) { | 623 if (using_socks_proxy_) |
| 624 next_state_ = STATE_SOCKS_CONNECT; |
| 625 else if (using_ssl_ && !using_tunnel_) { |
612 next_state_ = STATE_SSL_CONNECT; | 626 next_state_ = STATE_SSL_CONNECT; |
613 } else { | 627 } else { |
614 next_state_ = STATE_WRITE_HEADERS; | 628 next_state_ = STATE_WRITE_HEADERS; |
615 if (using_tunnel_) | 629 if (using_tunnel_) |
616 establishing_tunnel_ = true; | 630 establishing_tunnel_ = true; |
617 } | 631 } |
618 } | 632 } |
619 http_stream_.reset(new HttpBasicStream(&connection_)); | 633 http_stream_.reset(new HttpBasicStream(&connection_)); |
620 return OK; | 634 return OK; |
621 } | 635 } |
622 | 636 |
| 637 int HttpNetworkTransaction::DoSOCKSConnect() { |
| 638 DCHECK(using_socks_proxy_); |
| 639 DCHECK(!using_proxy_); |
| 640 DCHECK(!using_tunnel_); |
| 641 |
| 642 next_state_ = STATE_SOCKS_CONNECT_COMPLETE; |
| 643 |
| 644 // Add a SOCKS connection on top of our existing transport socket. |
| 645 ClientSocket* s = connection_.release_socket(); |
| 646 HostResolver::RequestInfo req_info(request_->url.HostNoBrackets(), |
| 647 request_->url.EffectiveIntPort()); |
| 648 req_info.set_referrer(request_->referrer); |
| 649 |
| 650 s = new SOCKSClientSocket(s, req_info, session_->host_resolver()); |
| 651 connection_.set_socket(s); |
| 652 return connection_.socket()->Connect(&io_callback_); |
| 653 } |
| 654 |
| 655 int HttpNetworkTransaction::DoSOCKSConnectComplete(int result) { |
| 656 DCHECK(using_socks_proxy_); |
| 657 DCHECK(!using_proxy_); |
| 658 DCHECK(!using_tunnel_); |
| 659 |
| 660 if (result == OK) { |
| 661 if (using_ssl_) { |
| 662 next_state_ = STATE_SSL_CONNECT; |
| 663 } else { |
| 664 next_state_ = STATE_WRITE_HEADERS; |
| 665 } |
| 666 } else { |
| 667 result = ReconsiderProxyAfterError(result); |
| 668 } |
| 669 return result; |
| 670 } |
| 671 |
623 int HttpNetworkTransaction::DoSSLConnect() { | 672 int HttpNetworkTransaction::DoSSLConnect() { |
624 next_state_ = STATE_SSL_CONNECT_COMPLETE; | 673 next_state_ = STATE_SSL_CONNECT_COMPLETE; |
625 | 674 |
626 // Add a SSL socket on top of our existing transport socket. | 675 // Add a SSL socket on top of our existing transport socket. |
627 ClientSocket* s = connection_.release_socket(); | 676 ClientSocket* s = connection_.release_socket(); |
628 s = socket_factory_->CreateSSLClientSocket( | 677 s = socket_factory_->CreateSSLClientSocket( |
629 s, request_->url.HostNoBrackets(), ssl_config_); | 678 s, request_->url.HostNoBrackets(), ssl_config_); |
630 connection_.set_socket(s); | 679 connection_.set_socket(s); |
631 return connection_.socket()->Connect(&io_callback_); | 680 return connection_.socket()->Connect(&io_callback_); |
632 } | 681 } |
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1707 host_and_port = proxy_info_.proxy_server().host_and_port(); | 1756 host_and_port = proxy_info_.proxy_server().host_and_port(); |
1708 } else { | 1757 } else { |
1709 DCHECK(target == HttpAuth::AUTH_SERVER); | 1758 DCHECK(target == HttpAuth::AUTH_SERVER); |
1710 host_and_port = GetHostAndPort(request_->url); | 1759 host_and_port = GetHostAndPort(request_->url); |
1711 } | 1760 } |
1712 auth_info->host_and_port = ASCIIToWide(host_and_port); | 1761 auth_info->host_and_port = ASCIIToWide(host_and_port); |
1713 response_.auth_challenge = auth_info; | 1762 response_.auth_challenge = auth_info; |
1714 } | 1763 } |
1715 | 1764 |
1716 } // namespace net | 1765 } // namespace net |
OLD | NEW |