| 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 |