| 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/field_trial.h" | 9 #include "base/field_trial.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP); | 225 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP); |
| 226 | 226 |
| 227 // Add the auth entry to the cache before restarting. We don't know whether | 227 // Add the auth entry to the cache before restarting. We don't know whether |
| 228 // the identity is valid yet, but if it is valid we want other transactions | 228 // the identity is valid yet, but if it is valid we want other transactions |
| 229 // to know about it. If an entry for (origin, handler->realm()) already | 229 // to know about it. If an entry for (origin, handler->realm()) already |
| 230 // exists, we update it. | 230 // exists, we update it. |
| 231 // | 231 // |
| 232 // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE, | 232 // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE, |
| 233 // auth_identity_[target] contains no identity because identity is not | 233 // auth_identity_[target] contains no identity because identity is not |
| 234 // required yet. | 234 // required yet. |
| 235 if (auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) { | 235 bool has_auth_identity = |
| 236 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE; |
| 237 if (has_auth_identity) { |
| 236 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], | 238 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], |
| 237 auth_identity_[target].username, auth_identity_[target].password, | 239 auth_identity_[target].username, auth_identity_[target].password, |
| 238 AuthPath(target)); | 240 AuthPath(target)); |
| 239 } | 241 } |
| 240 | 242 |
| 241 bool keep_alive = false; | 243 bool keep_alive = false; |
| 242 if (response_.headers->IsKeepAlive()) { | 244 // If the auth scheme is connection-based but the proxy/server mistakenly |
| 245 // marks the connection as non-keep-alive, we still keep it alive. |
| 246 if (response_.headers->IsKeepAlive() || |
| 247 (auth_handler_[target]->is_connection_based() && has_auth_identity)) { |
| 243 // If there is a response body of known length, we need to drain it first. | 248 // If there is a response body of known length, we need to drain it first. |
| 244 if (response_body_length_ > 0 || chunked_decoder_.get()) { | 249 if (response_body_length_ > 0 || chunked_decoder_.get()) { |
| 245 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 250 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; |
| 246 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket | 251 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket |
| 247 read_buf_len_ = kDrainBodyBufferSize; | 252 read_buf_len_ = kDrainBodyBufferSize; |
| 248 return; | 253 return; |
| 249 } | 254 } |
| 250 if (response_body_length_ == 0) // No response body to drain. | 255 if (response_body_length_ == 0) // No response body to drain. |
| 251 keep_alive = true; | 256 keep_alive = true; |
| 252 // response_body_length_ is -1 and we're not using chunked encoding. We | 257 // response_body_length_ is -1 and we're not using chunked encoding. We |
| 253 // don't know the length of the response body, so we can't reuse this | 258 // don't know the length of the response body, so we can't reuse this |
| 254 // connection even though the server says it's keep-alive. | 259 // connection even though the server says it's keep-alive or we need to |
| 255 } | 260 // keep it alive for authentication. |
| 256 | |
| 257 // If the auth scheme is connection-based but the proxy/server mistakenly | |
| 258 // marks the connection as not keep-alive, the auth is going to fail, so log | |
| 259 // an error message. | |
| 260 if (!keep_alive && auth_handler_[target]->is_connection_based() && | |
| 261 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) { | |
| 262 LOG(ERROR) << "Can't perform " << auth_handler_[target]->scheme() | |
| 263 << " auth to the " << AuthTargetString(target) << " " | |
| 264 << AuthOrigin(target) << " over a non-keep-alive connection"; | |
| 265 | |
| 266 HttpVersion http_version = response_.headers->GetHttpVersion(); | |
| 267 LOG(ERROR) << " HTTP version is " << http_version.major_value() << "." | |
| 268 << http_version.minor_value(); | |
| 269 | |
| 270 std::string header_val; | |
| 271 void* iter = NULL; | |
| 272 while (response_.headers->EnumerateHeader(&iter, "connection", | |
| 273 &header_val)) { | |
| 274 LOG(ERROR) << " Has header Connection: " << header_val; | |
| 275 } | |
| 276 | |
| 277 iter = NULL; | |
| 278 while (response_.headers->EnumerateHeader(&iter, "proxy-connection", | |
| 279 &header_val)) { | |
| 280 LOG(ERROR) << " Has header Proxy-Connection: " << header_val; | |
| 281 } | |
| 282 | |
| 283 // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate | |
| 284 // authentication with a "Proxy-Support: Session-Based-Authentication" | |
| 285 // response header. | |
| 286 iter = NULL; | |
| 287 while (response_.headers->EnumerateHeader(&iter, "proxy-support", | |
| 288 &header_val)) { | |
| 289 LOG(ERROR) << " Has header Proxy-Support: " << header_val; | |
| 290 } | |
| 291 } | 261 } |
| 292 | 262 |
| 293 // We don't need to drain the response body, so we act as if we had drained | 263 // We don't need to drain the response body, so we act as if we had drained |
| 294 // the response body. | 264 // the response body. |
| 295 DidDrainBodyForAuthRestart(keep_alive); | 265 DidDrainBodyForAuthRestart(keep_alive); |
| 296 } | 266 } |
| 297 | 267 |
| 298 void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) { | 268 void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) { |
| 299 if (keep_alive) { | 269 if (keep_alive) { |
| 300 next_state_ = STATE_WRITE_HEADERS; | 270 next_state_ = STATE_WRITE_HEADERS; |
| (...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 912 if (result > 0 && chunked_decoder_.get()) { | 882 if (result > 0 && chunked_decoder_.get()) { |
| 913 result = chunked_decoder_->FilterBuf(read_buf_->data(), result); | 883 result = chunked_decoder_->FilterBuf(read_buf_->data(), result); |
| 914 if (result == 0 && !chunked_decoder_->reached_eof()) { | 884 if (result == 0 && !chunked_decoder_->reached_eof()) { |
| 915 // Don't signal completion of the Read call yet or else it'll look like | 885 // Don't signal completion of the Read call yet or else it'll look like |
| 916 // we received end-of-file. Wait for more data. | 886 // we received end-of-file. Wait for more data. |
| 917 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 887 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; |
| 918 return OK; | 888 return OK; |
| 919 } | 889 } |
| 920 } | 890 } |
| 921 | 891 |
| 922 bool done = false, keep_alive = false; | 892 // keep_alive defaults to true because the very reason we're draining the |
| 893 // response body is to reuse the connection for auth restart. |
| 894 bool done = false, keep_alive = true; |
| 923 if (result < 0) { | 895 if (result < 0) { |
| 924 // Error while reading the socket. | 896 // Error while reading the socket. |
| 925 done = true; | 897 done = true; |
| 898 keep_alive = false; |
| 926 } else { | 899 } else { |
| 927 response_body_read_ += result; | 900 response_body_read_ += result; |
| 928 if (unfiltered_eof || | 901 if (unfiltered_eof || |
| 929 (response_body_length_ != -1 && | 902 (response_body_length_ != -1 && |
| 930 response_body_read_ >= response_body_length_) || | 903 response_body_read_ >= response_body_length_) || |
| 931 (chunked_decoder_.get() && chunked_decoder_->reached_eof())) { | 904 (chunked_decoder_.get() && chunked_decoder_->reached_eof())) { |
| 932 done = true; | 905 done = true; |
| 933 keep_alive = response_.headers->IsKeepAlive(); | |
| 934 // We can't reuse the connection if we read more than the advertised | 906 // We can't reuse the connection if we read more than the advertised |
| 935 // content length. | 907 // content length. |
| 936 if (unfiltered_eof || | 908 if (unfiltered_eof || |
| 937 (response_body_length_ != -1 && | 909 (response_body_length_ != -1 && |
| 938 response_body_read_ > response_body_length_)) | 910 response_body_read_ > response_body_length_)) |
| 939 keep_alive = false; | 911 keep_alive = false; |
| 940 } | 912 } |
| 941 } | 913 } |
| 942 | 914 |
| 943 if (done) { | 915 if (done) { |
| (...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1607 host_and_port = proxy_info_.proxy_server().host_and_port(); | 1579 host_and_port = proxy_info_.proxy_server().host_and_port(); |
| 1608 } else { | 1580 } else { |
| 1609 DCHECK(target == HttpAuth::AUTH_SERVER); | 1581 DCHECK(target == HttpAuth::AUTH_SERVER); |
| 1610 host_and_port = GetHostAndPort(request_->url); | 1582 host_and_port = GetHostAndPort(request_->url); |
| 1611 } | 1583 } |
| 1612 auth_info->host_and_port = ASCIIToWide(host_and_port); | 1584 auth_info->host_and_port = ASCIIToWide(host_and_port); |
| 1613 response_.auth_challenge = auth_info; | 1585 response_.auth_challenge = auth_info; |
| 1614 } | 1586 } |
| 1615 | 1587 |
| 1616 } // namespace net | 1588 } // namespace net |
| OLD | NEW |