| 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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 120   DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP); | 120   DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP); | 
| 121 | 121 | 
| 122   // Add the auth entry to the cache before restarting. We don't know whether | 122   // Add the auth entry to the cache before restarting. We don't know whether | 
| 123   // the identity is valid yet, but if it is valid we want other transactions | 123   // the identity is valid yet, but if it is valid we want other transactions | 
| 124   // to know about it. If an entry for (origin, handler->realm()) already | 124   // to know about it. If an entry for (origin, handler->realm()) already | 
| 125   // exists, we update it. | 125   // exists, we update it. | 
| 126   session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], | 126   session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], | 
| 127       auth_identity_[target].username, auth_identity_[target].password, | 127       auth_identity_[target].username, auth_identity_[target].password, | 
| 128       AuthPath(target)); | 128       AuthPath(target)); | 
| 129 | 129 | 
| 130   next_state_ = STATE_INIT_CONNECTION; | 130   bool keep_alive = false; | 
| 131   connection_.set_socket(NULL); | 131   if (response_.headers->IsKeepAlive()) { | 
| 132   connection_.Reset(); | 132     // If there is a response body of known length, we need to drain it first. | 
|  | 133     if (content_length_ > 0 || chunked_decoder_.get()) { | 
|  | 134       next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 
|  | 135       read_buf_ = new IOBuffer(kDrainBodyBufferSize);  // A bit bucket | 
|  | 136       read_buf_len_ = kDrainBodyBufferSize; | 
|  | 137       return; | 
|  | 138     } | 
|  | 139     if (content_length_ == 0)  // No response body to drain. | 
|  | 140       keep_alive = true; | 
|  | 141     // content_length_ is -1 and we're not using chunked encoding.  We don't | 
|  | 142     // know the length of the response body, so we can't reuse this connection | 
|  | 143     // even though the server says it's keep-alive. | 
|  | 144   } | 
|  | 145 | 
|  | 146   // We don't need to drain the response body, so we act as if we had drained | 
|  | 147   // the response body. | 
|  | 148   DidDrainBodyForAuthRestart(keep_alive); | 
|  | 149 } | 
|  | 150 | 
|  | 151 void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) { | 
|  | 152   if (keep_alive) { | 
|  | 153     next_state_ = STATE_WRITE_HEADERS; | 
|  | 154     reused_socket_ = true; | 
|  | 155   } else { | 
|  | 156     next_state_ = STATE_INIT_CONNECTION; | 
|  | 157     connection_.set_socket(NULL); | 
|  | 158     connection_.Reset(); | 
|  | 159   } | 
| 133 | 160 | 
| 134   // Reset the other member variables. | 161   // Reset the other member variables. | 
| 135   ResetStateForRestart(); | 162   ResetStateForRestart(); | 
| 136 } | 163 } | 
| 137 | 164 | 
| 138 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len, | 165 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len, | 
| 139                                  CompletionCallback* callback) { | 166                                  CompletionCallback* callback) { | 
| 140   DCHECK(response_.headers); | 167   DCHECK(response_.headers); | 
| 141   DCHECK(buf); | 168   DCHECK(buf); | 
| 142   DCHECK(buf_len > 0); | 169   DCHECK(buf_len > 0); | 
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 372         break; | 399         break; | 
| 373       case STATE_READ_BODY: | 400       case STATE_READ_BODY: | 
| 374         DCHECK(rv == OK); | 401         DCHECK(rv == OK); | 
| 375         TRACE_EVENT_BEGIN("http.read_body", request_, request_->url.spec()); | 402         TRACE_EVENT_BEGIN("http.read_body", request_, request_->url.spec()); | 
| 376         rv = DoReadBody(); | 403         rv = DoReadBody(); | 
| 377         break; | 404         break; | 
| 378       case STATE_READ_BODY_COMPLETE: | 405       case STATE_READ_BODY_COMPLETE: | 
| 379         rv = DoReadBodyComplete(rv); | 406         rv = DoReadBodyComplete(rv); | 
| 380         TRACE_EVENT_END("http.read_body", request_, request_->url.spec()); | 407         TRACE_EVENT_END("http.read_body", request_, request_->url.spec()); | 
| 381         break; | 408         break; | 
|  | 409       case STATE_DRAIN_BODY_FOR_AUTH_RESTART: | 
|  | 410         DCHECK(rv == OK); | 
|  | 411         TRACE_EVENT_BEGIN("http.drain_body_for_auth_restart", | 
|  | 412                           request_, request_->url.spec()); | 
|  | 413         rv = DoDrainBodyForAuthRestart(); | 
|  | 414         break; | 
|  | 415       case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE: | 
|  | 416         rv = DoDrainBodyForAuthRestartComplete(rv); | 
|  | 417         TRACE_EVENT_END("http.drain_body_for_auth_restart", | 
|  | 418                         request_, request_->url.spec()); | 
|  | 419         break; | 
| 382       default: | 420       default: | 
| 383         NOTREACHED() << "bad state"; | 421         NOTREACHED() << "bad state"; | 
| 384         rv = ERR_FAILED; | 422         rv = ERR_FAILED; | 
| 385         break; | 423         break; | 
| 386     } | 424     } | 
| 387   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 425   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 
| 388 | 426 | 
| 389   return rv; | 427   return rv; | 
| 390 } | 428 } | 
| 391 | 429 | 
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 771       keep_alive = response_.headers->IsKeepAlive(); | 809       keep_alive = response_.headers->IsKeepAlive(); | 
| 772       // We can't reuse the connection if we read more than the advertised | 810       // We can't reuse the connection if we read more than the advertised | 
| 773       // content length, or if the tunnel was not established successfully. | 811       // content length, or if the tunnel was not established successfully. | 
| 774       if (unfiltered_eof || | 812       if (unfiltered_eof || | 
| 775           (content_length_ != -1 && content_read_ > content_length_) || | 813           (content_length_ != -1 && content_read_ > content_length_) || | 
| 776           establishing_tunnel_) | 814           establishing_tunnel_) | 
| 777         keep_alive = false; | 815         keep_alive = false; | 
| 778     } | 816     } | 
| 779   } | 817   } | 
| 780 | 818 | 
| 781   // Clean up the HttpConnection if we are done. | 819   // Clean up connection_ if we are done. | 
| 782   if (done) { | 820   if (done) { | 
| 783     LogTransactionMetrics(); | 821     LogTransactionMetrics(); | 
| 784     if (!keep_alive) | 822     if (!keep_alive) | 
| 785       connection_.set_socket(NULL); | 823       connection_.set_socket(NULL); | 
| 786     connection_.Reset(); | 824     connection_.Reset(); | 
| 787     // The next Read call will return 0 (EOF). | 825     // The next Read call will return 0 (EOF). | 
| 788   } | 826   } | 
| 789 | 827 | 
| 790   // Clear these to avoid leaving around old state. | 828   // Clear these to avoid leaving around old state. | 
| 791   read_buf_ = NULL; | 829   read_buf_ = NULL; | 
| 792   read_buf_len_ = 0; | 830   read_buf_len_ = 0; | 
| 793 | 831 | 
| 794   return result; | 832   return result; | 
| 795 } | 833 } | 
| 796 | 834 | 
|  | 835 int HttpNetworkTransaction::DoDrainBodyForAuthRestart() { | 
|  | 836   // This method differs from DoReadBody only in the next_state_.  So we just | 
|  | 837   // call DoReadBody and override the next_state_.  Perhaps there is a more | 
|  | 838   // elegant way for these two methods to share code. | 
|  | 839   int rv = DoReadBody(); | 
|  | 840   DCHECK(next_state_ == STATE_READ_BODY_COMPLETE); | 
|  | 841   next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE; | 
|  | 842   return rv; | 
|  | 843 } | 
|  | 844 | 
|  | 845 // TODO(wtc): The first two thirds of this method and the DoReadBodyComplete | 
|  | 846 // method are almost the same.  Figure out a good way for these two methods | 
|  | 847 // to share code. | 
|  | 848 int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) { | 
|  | 849   bool unfiltered_eof = (result == 0); | 
|  | 850 | 
|  | 851   // Filter incoming data if appropriate.  FilterBuf may return an error. | 
|  | 852   if (result > 0 && chunked_decoder_.get()) { | 
|  | 853     result = chunked_decoder_->FilterBuf(read_buf_->data(), result); | 
|  | 854     if (result == 0 && !chunked_decoder_->reached_eof()) { | 
|  | 855       // Don't signal completion of the Read call yet or else it'll look like | 
|  | 856       // we received end-of-file.  Wait for more data. | 
|  | 857       next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 
|  | 858       return OK; | 
|  | 859     } | 
|  | 860   } | 
|  | 861 | 
|  | 862   bool done = false, keep_alive = false; | 
|  | 863   if (result < 0) { | 
|  | 864     // Error while reading the socket. | 
|  | 865     done = true; | 
|  | 866   } else { | 
|  | 867     content_read_ += result; | 
|  | 868     if (unfiltered_eof || | 
|  | 869         (content_length_ != -1 && content_read_ >= content_length_) || | 
|  | 870         (chunked_decoder_.get() && chunked_decoder_->reached_eof())) { | 
|  | 871       done = true; | 
|  | 872       keep_alive = response_.headers->IsKeepAlive(); | 
|  | 873       // We can't reuse the connection if we read more than the advertised | 
|  | 874       // content length. | 
|  | 875       if (unfiltered_eof || | 
|  | 876           (content_length_ != -1 && content_read_ > content_length_)) | 
|  | 877         keep_alive = false; | 
|  | 878     } | 
|  | 879   } | 
|  | 880 | 
|  | 881   if (done) { | 
|  | 882     DidDrainBodyForAuthRestart(keep_alive); | 
|  | 883   } else { | 
|  | 884     // Keep draining. | 
|  | 885     next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 
|  | 886   } | 
|  | 887 | 
|  | 888   return OK; | 
|  | 889 } | 
|  | 890 | 
| 797 void HttpNetworkTransaction::LogTransactionMetrics() const { | 891 void HttpNetworkTransaction::LogTransactionMetrics() const { | 
| 798   base::TimeDelta duration = base::Time::Now() - response_.request_time; | 892   base::TimeDelta duration = base::Time::Now() - response_.request_time; | 
| 799   if (60 < duration.InMinutes()) | 893   if (60 < duration.InMinutes()) | 
| 800     return; | 894     return; | 
| 801   UMA_HISTOGRAM_LONG_TIMES(L"Net.Transaction_Latency", duration); | 895   UMA_HISTOGRAM_LONG_TIMES(L"Net.Transaction_Latency", duration); | 
| 802   if (!duration.InMilliseconds()) | 896   if (!duration.InMilliseconds()) | 
| 803     return; | 897     return; | 
| 804   UMA_HISTOGRAM_COUNTS(L"Net.Transaction_Bandwidth", | 898   UMA_HISTOGRAM_COUNTS(L"Net.Transaction_Bandwidth", | 
| 805       static_cast<int> (content_read_ / duration.InMilliseconds())); | 899       static_cast<int> (content_read_ / duration.InMilliseconds())); | 
| 806 } | 900 } | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 862               header_buf_len_); | 956               header_buf_len_); | 
| 863     } | 957     } | 
| 864     header_buf_body_offset_ = -1; | 958     header_buf_body_offset_ = -1; | 
| 865     next_state_ = STATE_READ_HEADERS; | 959     next_state_ = STATE_READ_HEADERS; | 
| 866     return OK; | 960     return OK; | 
| 867   } | 961   } | 
| 868 | 962 | 
| 869   response_.headers = headers; | 963   response_.headers = headers; | 
| 870   response_.vary_data.Init(*request_, *response_.headers); | 964   response_.vary_data.Init(*request_, *response_.headers); | 
| 871 | 965 | 
| 872   int rv = HandleAuthChallenge(); |  | 
| 873   if (rv == WILL_RESTART_TRANSACTION) { |  | 
| 874     DCHECK(next_state_ == STATE_INIT_CONNECTION); |  | 
| 875     return OK; |  | 
| 876   } |  | 
| 877   if (rv != OK) |  | 
| 878     return rv; |  | 
| 879 |  | 
| 880   // Figure how to determine EOF: | 966   // Figure how to determine EOF: | 
| 881 | 967 | 
| 882   // For certain responses, we know the content length is always 0. | 968   // For certain responses, we know the content length is always 0. | 
| 883   switch (response_.headers->response_code()) { | 969   switch (response_.headers->response_code()) { | 
| 884     case 204:  // No Content | 970     case 204:  // No Content | 
| 885     case 205:  // Reset Content | 971     case 205:  // Reset Content | 
| 886     case 304:  // Not Modified | 972     case 304:  // Not Modified | 
| 887       content_length_ = 0; | 973       content_length_ = 0; | 
| 888       break; | 974       break; | 
| 889   } | 975   } | 
| 890 | 976 | 
| 891   if (content_length_ == -1) { | 977   if (content_length_ == -1) { | 
| 892     // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 978     // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 
| 893     // Otherwise "Transfer-Encoding: chunked" trumps "Content-Length: N" | 979     // Otherwise "Transfer-Encoding: chunked" trumps "Content-Length: N" | 
| 894     if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1) && | 980     if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1) && | 
| 895         response_.headers->HasHeaderValue("Transfer-Encoding", "chunked")) { | 981         response_.headers->HasHeaderValue("Transfer-Encoding", "chunked")) { | 
| 896       chunked_decoder_.reset(new HttpChunkedDecoder()); | 982       chunked_decoder_.reset(new HttpChunkedDecoder()); | 
| 897     } else { | 983     } else { | 
| 898       content_length_ = response_.headers->GetContentLength(); | 984       content_length_ = response_.headers->GetContentLength(); | 
| 899       // If content_length_ is still -1, then we have to wait for the server to | 985       // If content_length_ is still -1, then we have to wait for the server to | 
| 900       // close the connection. | 986       // close the connection. | 
| 901     } | 987     } | 
| 902   } | 988   } | 
| 903 | 989 | 
|  | 990   int rv = HandleAuthChallenge(); | 
|  | 991   if (rv == WILL_RESTART_TRANSACTION) | 
|  | 992     return OK; | 
|  | 993   if (rv != OK) | 
|  | 994     return rv; | 
|  | 995 | 
| 904   if (using_ssl_ && !establishing_tunnel_) { | 996   if (using_ssl_ && !establishing_tunnel_) { | 
| 905     SSLClientSocket* ssl_socket = | 997     SSLClientSocket* ssl_socket = | 
| 906         reinterpret_cast<SSLClientSocket*>(connection_.socket()); | 998         reinterpret_cast<SSLClientSocket*>(connection_.socket()); | 
| 907     ssl_socket->GetSSLInfo(&response_.ssl_info); | 999     ssl_socket->GetSSLInfo(&response_.ssl_info); | 
| 908   } | 1000   } | 
| 909 | 1001 | 
| 910   return OK; | 1002   return OK; | 
| 911 } | 1003 } | 
| 912 | 1004 | 
| 913 int HttpNetworkTransaction::HandleCertificateError(int error) { | 1005 int HttpNetworkTransaction::HandleCertificateError(int error) { | 
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1273   if (target == HttpAuth::AUTH_PROXY) { | 1365   if (target == HttpAuth::AUTH_PROXY) { | 
| 1274     auth_info->host = ASCIIToWide(proxy_info_.proxy_server()); | 1366     auth_info->host = ASCIIToWide(proxy_info_.proxy_server()); | 
| 1275   } else { | 1367   } else { | 
| 1276     DCHECK(target == HttpAuth::AUTH_SERVER); | 1368     DCHECK(target == HttpAuth::AUTH_SERVER); | 
| 1277     auth_info->host = ASCIIToWide(request_->url.host()); | 1369     auth_info->host = ASCIIToWide(request_->url.host()); | 
| 1278   } | 1370   } | 
| 1279   response_.auth_challenge = auth_info; | 1371   response_.auth_challenge = auth_info; | 
| 1280 } | 1372 } | 
| 1281 | 1373 | 
| 1282 }  // namespace net | 1374 }  // namespace net | 
| OLD | NEW | 
|---|