OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/string_util.h" | 9 #include "base/string_util.h" |
10 #include "base/trace_event.h" | 10 #include "base/trace_event.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 reused_socket_(false), | 45 reused_socket_(false), |
46 using_ssl_(false), | 46 using_ssl_(false), |
47 using_proxy_(false), | 47 using_proxy_(false), |
48 using_tunnel_(false), | 48 using_tunnel_(false), |
49 establishing_tunnel_(false), | 49 establishing_tunnel_(false), |
50 request_headers_bytes_sent_(0), | 50 request_headers_bytes_sent_(0), |
51 header_buf_capacity_(0), | 51 header_buf_capacity_(0), |
52 header_buf_len_(0), | 52 header_buf_len_(0), |
53 header_buf_body_offset_(-1), | 53 header_buf_body_offset_(-1), |
54 header_buf_http_offset_(-1), | 54 header_buf_http_offset_(-1), |
55 content_length_(-1), // -1 means unspecified. | 55 response_body_length_(-1), // -1 means unspecified. |
56 content_read_(0), | 56 response_body_read_(0), |
57 read_buf_len_(0), | 57 read_buf_len_(0), |
58 next_state_(STATE_NONE) { | 58 next_state_(STATE_NONE) { |
59 #if defined(OS_WIN) | 59 #if defined(OS_WIN) |
60 // TODO(port): Port the SSLConfigService class to Linux and Mac OS X. | 60 // TODO(port): Port the SSLConfigService class to Linux and Mac OS X. |
61 session->ssl_config_service()->GetSSLConfig(&ssl_config_); | 61 session->ssl_config_service()->GetSSLConfig(&ssl_config_); |
62 #endif | 62 #endif |
63 } | 63 } |
64 | 64 |
65 int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info, | 65 int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info, |
66 CompletionCallback* callback) { | 66 CompletionCallback* callback) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 // required yet. | 129 // required yet. |
130 if (auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) { | 130 if (auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) { |
131 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], | 131 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], |
132 auth_identity_[target].username, auth_identity_[target].password, | 132 auth_identity_[target].username, auth_identity_[target].password, |
133 AuthPath(target)); | 133 AuthPath(target)); |
134 } | 134 } |
135 | 135 |
136 bool keep_alive = false; | 136 bool keep_alive = false; |
137 if (response_.headers->IsKeepAlive()) { | 137 if (response_.headers->IsKeepAlive()) { |
138 // If there is a response body of known length, we need to drain it first. | 138 // If there is a response body of known length, we need to drain it first. |
139 if (content_length_ > 0 || chunked_decoder_.get()) { | 139 if (response_body_length_ > 0 || chunked_decoder_.get()) { |
140 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 140 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; |
141 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket | 141 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket |
142 read_buf_len_ = kDrainBodyBufferSize; | 142 read_buf_len_ = kDrainBodyBufferSize; |
143 return; | 143 return; |
144 } | 144 } |
145 if (content_length_ == 0) // No response body to drain. | 145 if (response_body_length_ == 0) // No response body to drain. |
146 keep_alive = true; | 146 keep_alive = true; |
147 // content_length_ is -1 and we're not using chunked encoding. We don't | 147 // response_body_length_ is -1 and we're not using chunked encoding. We |
148 // know the length of the response body, so we can't reuse this connection | 148 // don't know the length of the response body, so we can't reuse this |
149 // even though the server says it's keep-alive. | 149 // connection even though the server says it's keep-alive. |
150 } | 150 } |
151 | 151 |
152 // If the auth scheme is connection-based but the proxy/server mistakenly | 152 // If the auth scheme is connection-based but the proxy/server mistakenly |
153 // marks the connection as not keep-alive, the auth is going to fail, so log | 153 // marks the connection as not keep-alive, the auth is going to fail, so log |
154 // an error message. | 154 // an error message. |
155 if (!keep_alive && auth_handler_[target]->is_connection_based() && | 155 if (!keep_alive && auth_handler_[target]->is_connection_based() && |
156 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) { | 156 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) { |
157 std::string auth_target(target == HttpAuth::AUTH_PROXY ? | 157 std::string auth_target(target == HttpAuth::AUTH_PROXY ? |
158 "proxy" : "server"); | 158 "proxy" : "server"); |
159 LOG(ERROR) << "Can't perform " << auth_handler_[target]->scheme() | 159 LOG(ERROR) << "Can't perform " << auth_handler_[target]->scheme() |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 } | 789 } |
790 | 790 |
791 int HttpNetworkTransaction::DoReadBody() { | 791 int HttpNetworkTransaction::DoReadBody() { |
792 DCHECK(read_buf_); | 792 DCHECK(read_buf_); |
793 DCHECK(read_buf_len_ > 0); | 793 DCHECK(read_buf_len_ > 0); |
794 DCHECK(connection_.is_initialized()); | 794 DCHECK(connection_.is_initialized()); |
795 | 795 |
796 next_state_ = STATE_READ_BODY_COMPLETE; | 796 next_state_ = STATE_READ_BODY_COMPLETE; |
797 | 797 |
798 // We may have already consumed the indicated content length. | 798 // We may have already consumed the indicated content length. |
799 if (content_length_ != -1 && content_read_ >= content_length_) | 799 if (response_body_length_ != -1 && |
| 800 response_body_read_ >= response_body_length_) |
800 return 0; | 801 return 0; |
801 | 802 |
802 // We may have some data remaining in the header buffer. | 803 // We may have some data remaining in the header buffer. |
803 if (header_buf_.get() && header_buf_body_offset_ < header_buf_len_) { | 804 if (header_buf_.get() && header_buf_body_offset_ < header_buf_len_) { |
804 int n = std::min(read_buf_len_, header_buf_len_ - header_buf_body_offset_); | 805 int n = std::min(read_buf_len_, header_buf_len_ - header_buf_body_offset_); |
805 memcpy(read_buf_->data(), header_buf_.get() + header_buf_body_offset_, n); | 806 memcpy(read_buf_->data(), header_buf_.get() + header_buf_body_offset_, n); |
806 header_buf_body_offset_ += n; | 807 header_buf_body_offset_ += n; |
807 if (header_buf_body_offset_ == header_buf_len_) { | 808 if (header_buf_body_offset_ == header_buf_len_) { |
808 header_buf_.reset(); | 809 header_buf_.reset(); |
809 header_buf_capacity_ = 0; | 810 header_buf_capacity_ = 0; |
(...skipping 23 matching lines...) Expand all Loading... |
833 next_state_ = STATE_READ_BODY; | 834 next_state_ = STATE_READ_BODY; |
834 return OK; | 835 return OK; |
835 } | 836 } |
836 } | 837 } |
837 | 838 |
838 bool done = false, keep_alive = false; | 839 bool done = false, keep_alive = false; |
839 if (result < 0) { | 840 if (result < 0) { |
840 // Error while reading the socket. | 841 // Error while reading the socket. |
841 done = true; | 842 done = true; |
842 } else { | 843 } else { |
843 content_read_ += result; | 844 response_body_read_ += result; |
844 if (unfiltered_eof || | 845 if (unfiltered_eof || |
845 (content_length_ != -1 && content_read_ >= content_length_) || | 846 (response_body_length_ != -1 && |
| 847 response_body_read_ >= response_body_length_) || |
846 (chunked_decoder_.get() && chunked_decoder_->reached_eof())) { | 848 (chunked_decoder_.get() && chunked_decoder_->reached_eof())) { |
847 done = true; | 849 done = true; |
848 keep_alive = response_.headers->IsKeepAlive(); | 850 keep_alive = response_.headers->IsKeepAlive(); |
849 // We can't reuse the connection if we read more than the advertised | 851 // We can't reuse the connection if we read more than the advertised |
850 // content length. | 852 // content length. |
851 if (unfiltered_eof || | 853 if (unfiltered_eof || |
852 (content_length_ != -1 && content_read_ > content_length_)) | 854 (response_body_length_ != -1 && |
| 855 response_body_read_ > response_body_length_)) |
853 keep_alive = false; | 856 keep_alive = false; |
854 } | 857 } |
855 } | 858 } |
856 | 859 |
857 // Clean up connection_ if we are done. | 860 // Clean up connection_ if we are done. |
858 if (done) { | 861 if (done) { |
859 LogTransactionMetrics(); | 862 LogTransactionMetrics(); |
860 if (!keep_alive) | 863 if (!keep_alive) |
861 connection_.set_socket(NULL); | 864 connection_.set_socket(NULL); |
862 connection_.Reset(); | 865 connection_.Reset(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 898 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; |
896 return OK; | 899 return OK; |
897 } | 900 } |
898 } | 901 } |
899 | 902 |
900 bool done = false, keep_alive = false; | 903 bool done = false, keep_alive = false; |
901 if (result < 0) { | 904 if (result < 0) { |
902 // Error while reading the socket. | 905 // Error while reading the socket. |
903 done = true; | 906 done = true; |
904 } else { | 907 } else { |
905 content_read_ += result; | 908 response_body_read_ += result; |
906 if (unfiltered_eof || | 909 if (unfiltered_eof || |
907 (content_length_ != -1 && content_read_ >= content_length_) || | 910 (response_body_length_ != -1 && |
| 911 response_body_read_ >= response_body_length_) || |
908 (chunked_decoder_.get() && chunked_decoder_->reached_eof())) { | 912 (chunked_decoder_.get() && chunked_decoder_->reached_eof())) { |
909 done = true; | 913 done = true; |
910 keep_alive = response_.headers->IsKeepAlive(); | 914 keep_alive = response_.headers->IsKeepAlive(); |
911 // We can't reuse the connection if we read more than the advertised | 915 // We can't reuse the connection if we read more than the advertised |
912 // content length. | 916 // content length. |
913 if (unfiltered_eof || | 917 if (unfiltered_eof || |
914 (content_length_ != -1 && content_read_ > content_length_)) | 918 (response_body_length_ != -1 && |
| 919 response_body_read_ > response_body_length_)) |
915 keep_alive = false; | 920 keep_alive = false; |
916 } | 921 } |
917 } | 922 } |
918 | 923 |
919 if (done) { | 924 if (done) { |
920 DidDrainBodyForAuthRestart(keep_alive); | 925 DidDrainBodyForAuthRestart(keep_alive); |
921 } else { | 926 } else { |
922 // Keep draining. | 927 // Keep draining. |
923 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 928 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; |
924 } | 929 } |
925 | 930 |
926 return OK; | 931 return OK; |
927 } | 932 } |
928 | 933 |
929 void HttpNetworkTransaction::LogTransactionMetrics() const { | 934 void HttpNetworkTransaction::LogTransactionMetrics() const { |
930 base::TimeDelta duration = base::Time::Now() - response_.request_time; | 935 base::TimeDelta duration = base::Time::Now() - response_.request_time; |
931 if (60 < duration.InMinutes()) | 936 if (60 < duration.InMinutes()) |
932 return; | 937 return; |
933 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration); | 938 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration); |
934 if (!duration.InMilliseconds()) | 939 if (!duration.InMilliseconds()) |
935 return; | 940 return; |
936 UMA_HISTOGRAM_COUNTS("Net.Transaction_Bandwidth", | 941 UMA_HISTOGRAM_COUNTS("Net.Transaction_Bandwidth", |
937 static_cast<int> (content_read_ / duration.InMilliseconds())); | 942 static_cast<int> (response_body_read_ / duration.InMilliseconds())); |
938 } | 943 } |
939 | 944 |
940 int HttpNetworkTransaction::DidReadResponseHeaders() { | 945 int HttpNetworkTransaction::DidReadResponseHeaders() { |
941 scoped_refptr<HttpResponseHeaders> headers; | 946 scoped_refptr<HttpResponseHeaders> headers; |
942 if (has_found_status_line_start()) { | 947 if (has_found_status_line_start()) { |
943 headers = new HttpResponseHeaders( | 948 headers = new HttpResponseHeaders( |
944 HttpUtil::AssembleRawHeaders( | 949 HttpUtil::AssembleRawHeaders( |
945 header_buf_.get(), header_buf_body_offset_)); | 950 header_buf_.get(), header_buf_body_offset_)); |
946 } else { | 951 } else { |
947 // Fabricate a status line to to preserve the HTTP/0.9 version. | 952 // Fabricate a status line to to preserve the HTTP/0.9 version. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 header_buf_body_offset_ = -1; | 1021 header_buf_body_offset_ = -1; |
1017 next_state_ = STATE_READ_HEADERS; | 1022 next_state_ = STATE_READ_HEADERS; |
1018 return OK; | 1023 return OK; |
1019 } | 1024 } |
1020 | 1025 |
1021 response_.headers = headers; | 1026 response_.headers = headers; |
1022 response_.vary_data.Init(*request_, *response_.headers); | 1027 response_.vary_data.Init(*request_, *response_.headers); |
1023 | 1028 |
1024 // Figure how to determine EOF: | 1029 // Figure how to determine EOF: |
1025 | 1030 |
1026 // For certain responses, we know the content length is always 0. | 1031 // For certain responses, we know the content length is always 0. From |
| 1032 // RFC 2616 Section 4.3 Message Body: |
| 1033 // |
| 1034 // For response messages, whether or not a message-body is included with |
| 1035 // a message is dependent on both the request method and the response |
| 1036 // status code (section 6.1.1). All responses to the HEAD request method |
| 1037 // MUST NOT include a message-body, even though the presence of entity- |
| 1038 // header fields might lead one to believe they do. All 1xx |
| 1039 // (informational), 204 (no content), and 304 (not modified) responses |
| 1040 // MUST NOT include a message-body. All other responses do include a |
| 1041 // message-body, although it MAY be of zero length. |
1027 switch (response_.headers->response_code()) { | 1042 switch (response_.headers->response_code()) { |
1028 case 204: // No Content | 1043 case 204: // No Content |
1029 case 205: // Reset Content | 1044 case 205: // Reset Content |
1030 case 304: // Not Modified | 1045 case 304: // Not Modified |
1031 content_length_ = 0; | 1046 response_body_length_ = 0; |
1032 break; | 1047 break; |
1033 } | 1048 } |
| 1049 if (request_->method == "HEAD") |
| 1050 response_body_length_ = 0; |
1034 | 1051 |
1035 if (content_length_ == -1) { | 1052 if (response_body_length_ == -1) { |
1036 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1053 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
1037 // Otherwise "Transfer-Encoding: chunked" trumps "Content-Length: N" | 1054 // Otherwise "Transfer-Encoding: chunked" trumps "Content-Length: N" |
1038 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1) && | 1055 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1) && |
1039 response_.headers->HasHeaderValue("Transfer-Encoding", "chunked")) { | 1056 response_.headers->HasHeaderValue("Transfer-Encoding", "chunked")) { |
1040 chunked_decoder_.reset(new HttpChunkedDecoder()); | 1057 chunked_decoder_.reset(new HttpChunkedDecoder()); |
1041 } else { | 1058 } else { |
1042 content_length_ = response_.headers->GetContentLength(); | 1059 response_body_length_ = response_.headers->GetContentLength(); |
1043 // If content_length_ is still -1, then we have to wait for the server to | 1060 // If response_body_length_ is still -1, then we have to wait for the |
1044 // close the connection. | 1061 // server to close the connection. |
1045 } | 1062 } |
1046 } | 1063 } |
1047 | 1064 |
1048 int rv = HandleAuthChallenge(); | 1065 int rv = HandleAuthChallenge(); |
1049 if (rv == WILL_RESTART_TRANSACTION) | 1066 if (rv == WILL_RESTART_TRANSACTION) |
1050 return OK; | 1067 return OK; |
1051 if (rv != OK) | 1068 if (rv != OK) |
1052 return rv; | 1069 return rv; |
1053 | 1070 |
1054 if (using_ssl_ && !establishing_tunnel_) { | 1071 if (using_ssl_ && !establishing_tunnel_) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 } | 1146 } |
1130 return error; | 1147 return error; |
1131 } | 1148 } |
1132 | 1149 |
1133 void HttpNetworkTransaction::ResetStateForRestart() { | 1150 void HttpNetworkTransaction::ResetStateForRestart() { |
1134 header_buf_.reset(); | 1151 header_buf_.reset(); |
1135 header_buf_capacity_ = 0; | 1152 header_buf_capacity_ = 0; |
1136 header_buf_len_ = 0; | 1153 header_buf_len_ = 0; |
1137 header_buf_body_offset_ = -1; | 1154 header_buf_body_offset_ = -1; |
1138 header_buf_http_offset_ = -1; | 1155 header_buf_http_offset_ = -1; |
1139 content_length_ = -1; | 1156 response_body_length_ = -1; |
1140 content_read_ = 0; | 1157 response_body_read_ = 0; |
1141 read_buf_ = NULL; | 1158 read_buf_ = NULL; |
1142 read_buf_len_ = 0; | 1159 read_buf_len_ = 0; |
1143 request_headers_.clear(); | 1160 request_headers_.clear(); |
1144 request_headers_bytes_sent_ = 0; | 1161 request_headers_bytes_sent_ = 0; |
1145 chunked_decoder_.reset(); | 1162 chunked_decoder_.reset(); |
1146 // Reset the scoped_refptr | 1163 // Reset the scoped_refptr |
1147 response_.headers = NULL; | 1164 response_.headers = NULL; |
1148 response_.auth_challenge = NULL; | 1165 response_.auth_challenge = NULL; |
1149 } | 1166 } |
1150 | 1167 |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 if (target == HttpAuth::AUTH_PROXY) { | 1461 if (target == HttpAuth::AUTH_PROXY) { |
1445 auth_info->host = ASCIIToWide(proxy_info_.proxy_server().host_and_port()); | 1462 auth_info->host = ASCIIToWide(proxy_info_.proxy_server().host_and_port()); |
1446 } else { | 1463 } else { |
1447 DCHECK(target == HttpAuth::AUTH_SERVER); | 1464 DCHECK(target == HttpAuth::AUTH_SERVER); |
1448 auth_info->host = ASCIIToWide(request_->url.host()); | 1465 auth_info->host = ASCIIToWide(request_->url.host()); |
1449 } | 1466 } |
1450 response_.auth_challenge = auth_info; | 1467 response_.auth_challenge = auth_info; |
1451 } | 1468 } |
1452 | 1469 |
1453 } // namespace net | 1470 } // namespace net |
OLD | NEW |