OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_proxy_client_socket.h" | 5 #include "net/http/http_proxy_client_socket.h" |
6 | 6 |
7 #include "base/string_util.h" | 7 #include "base/string_util.h" |
8 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
9 #include "googleurl/src/gurl.h" | 9 #include "googleurl/src/gurl.h" |
10 #include "net/base/auth.h" | 10 #include "net/base/auth.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 | 60 |
61 HttpProxyClientSocket::~HttpProxyClientSocket() { | 61 HttpProxyClientSocket::~HttpProxyClientSocket() { |
62 Disconnect(); | 62 Disconnect(); |
63 } | 63 } |
64 | 64 |
65 int HttpProxyClientSocket::RestartWithAuth(OldCompletionCallback* callback) { | 65 int HttpProxyClientSocket::RestartWithAuth(OldCompletionCallback* callback) { |
66 DCHECK_EQ(STATE_NONE, next_state_); | 66 DCHECK_EQ(STATE_NONE, next_state_); |
67 DCHECK(user_callback_.is_null()); | 67 DCHECK(user_callback_.is_null()); |
68 | 68 |
69 int rv = PrepareForAuthRestart(); | 69 int rv = PrepareForAuthRestart(); |
70 if (rv != OK || next_state_ == STATE_NONE) | 70 if (rv != OK) |
71 return rv; | 71 return rv; |
72 | 72 |
73 rv = DoLoop(OK); | 73 rv = DoLoop(OK); |
74 if (rv == ERR_IO_PENDING) | 74 if (rv == ERR_IO_PENDING) |
75 if (callback) { | 75 if (callback) { |
76 user_callback_ = base::Bind(&OldCompletionCallback::Run<int>, | 76 user_callback_ = base::Bind(&OldCompletionCallback::Run<int>, |
77 base::Unretained(callback)); | 77 base::Unretained(callback)); |
78 } | 78 } |
79 return rv; | 79 return rv; |
80 } | 80 } |
81 | 81 |
82 const | |
83 scoped_refptr<HttpAuthController>& HttpProxyClientSocket::auth_controller() { | |
84 return auth_; | |
85 } | |
86 | |
87 const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const { | 82 const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const { |
88 return response_.headers ? &response_ : NULL; | 83 return response_.headers ? &response_ : NULL; |
89 } | 84 } |
90 | 85 |
91 HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { | 86 HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { |
92 return new HttpBasicStream(transport_.release(), | 87 return new HttpBasicStream(transport_.release(), |
93 http_stream_parser_.release(), false); | 88 http_stream_parser_.release(), false); |
94 } | 89 } |
95 | 90 |
96 | 91 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 // We don't need to drain the response body, so we act as if we had drained | 246 // We don't need to drain the response body, so we act as if we had drained |
252 // the response body. | 247 // the response body. |
253 return DidDrainBodyForAuthRestart(keep_alive); | 248 return DidDrainBodyForAuthRestart(keep_alive); |
254 } | 249 } |
255 | 250 |
256 int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) { | 251 int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) { |
257 if (keep_alive && transport_->socket()->IsConnectedAndIdle()) { | 252 if (keep_alive && transport_->socket()->IsConnectedAndIdle()) { |
258 next_state_ = STATE_GENERATE_AUTH_TOKEN; | 253 next_state_ = STATE_GENERATE_AUTH_TOKEN; |
259 transport_->set_is_reused(true); | 254 transport_->set_is_reused(true); |
260 } else { | 255 } else { |
261 next_state_ = STATE_NONE; | 256 // This assumes that the underlying transport socket is a TCP socket, |
| 257 // since only TCP sockets are restartable. |
| 258 next_state_ = STATE_TCP_RESTART; |
| 259 transport_->socket()->Disconnect(); |
262 } | 260 } |
263 | 261 |
264 // Reset the other member variables. | 262 // Reset the other member variables. |
265 drain_buf_ = NULL; | 263 drain_buf_ = NULL; |
266 parser_buf_ = NULL; | 264 parser_buf_ = NULL; |
267 http_stream_parser_.reset(); | 265 http_stream_parser_.reset(); |
268 request_line_.clear(); | 266 request_line_.clear(); |
269 request_headers_.Clear(); | 267 request_headers_.Clear(); |
270 response_ = HttpResponseInfo(); | 268 response_ = HttpResponseInfo(); |
271 return OK; | 269 return OK; |
272 } | 270 } |
273 | 271 |
| 272 int HttpProxyClientSocket::HandleAuthChallenge() { |
| 273 DCHECK(response_.headers); |
| 274 |
| 275 int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_); |
| 276 response_.auth_challenge = auth_->auth_info(); |
| 277 if (rv == OK) |
| 278 return ERR_PROXY_AUTH_REQUESTED; |
| 279 |
| 280 return rv; |
| 281 } |
| 282 |
274 void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { | 283 void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { |
275 LOG(WARNING) << "Blocked proxy response with status " << response_code | 284 LOG(WARNING) << "Blocked proxy response with status " << response_code |
276 << " to CONNECT request for " | 285 << " to CONNECT request for " |
277 << GetHostAndPort(request_.url) << "."; | 286 << GetHostAndPort(request_.url) << "."; |
278 } | 287 } |
279 | 288 |
280 void HttpProxyClientSocket::DoCallback(int result) { | 289 void HttpProxyClientSocket::DoCallback(int result) { |
281 DCHECK_NE(ERR_IO_PENDING, result); | 290 DCHECK_NE(ERR_IO_PENDING, result); |
282 DCHECK(!user_callback_.is_null()); | 291 DCHECK(!user_callback_.is_null()); |
283 | 292 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 net_log_.EndEventWithNetErrorCode( | 342 net_log_.EndEventWithNetErrorCode( |
334 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv); | 343 NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv); |
335 break; | 344 break; |
336 case STATE_DRAIN_BODY: | 345 case STATE_DRAIN_BODY: |
337 DCHECK_EQ(OK, rv); | 346 DCHECK_EQ(OK, rv); |
338 rv = DoDrainBody(); | 347 rv = DoDrainBody(); |
339 break; | 348 break; |
340 case STATE_DRAIN_BODY_COMPLETE: | 349 case STATE_DRAIN_BODY_COMPLETE: |
341 rv = DoDrainBodyComplete(rv); | 350 rv = DoDrainBodyComplete(rv); |
342 break; | 351 break; |
| 352 case STATE_TCP_RESTART: |
| 353 DCHECK_EQ(OK, rv); |
| 354 rv = DoTCPRestart(); |
| 355 break; |
| 356 case STATE_TCP_RESTART_COMPLETE: |
| 357 rv = DoTCPRestartComplete(rv); |
| 358 break; |
343 case STATE_DONE: | 359 case STATE_DONE: |
344 break; | 360 break; |
345 default: | 361 default: |
346 NOTREACHED() << "bad state"; | 362 NOTREACHED() << "bad state"; |
347 rv = ERR_UNEXPECTED; | 363 rv = ERR_UNEXPECTED; |
348 break; | 364 break; |
349 } | 365 } |
350 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE && | 366 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE && |
351 next_state_ != STATE_DONE); | 367 next_state_ != STATE_DONE); |
352 return rv; | 368 return rv; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 // need to be very suspicious about the response because an active network | 447 // need to be very suspicious about the response because an active network |
432 // attacker can force us into this state by masquerading as the proxy. | 448 // attacker can force us into this state by masquerading as the proxy. |
433 // The only safe thing to do here is to fail the connection because our | 449 // The only safe thing to do here is to fail the connection because our |
434 // client is expecting an SSL protected response. | 450 // client is expecting an SSL protected response. |
435 // See http://crbug.com/7338. | 451 // See http://crbug.com/7338. |
436 case 407: // Proxy Authentication Required | 452 case 407: // Proxy Authentication Required |
437 // We need this status code to allow proxy authentication. Our | 453 // We need this status code to allow proxy authentication. Our |
438 // authentication code is smart enough to avoid being tricked by an | 454 // authentication code is smart enough to avoid being tricked by an |
439 // active network attacker. | 455 // active network attacker. |
440 // The next state is intentionally not set as it should be STATE_NONE; | 456 // The next state is intentionally not set as it should be STATE_NONE; |
441 return HandleAuthChallenge(auth_, &response_, net_log_); | 457 return HandleAuthChallenge(); |
442 | 458 |
443 default: | 459 default: |
444 if (is_https_proxy_) | 460 if (is_https_proxy_) |
445 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; | 461 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; |
446 // For all other status codes, we conservatively fail the CONNECT | 462 // For all other status codes, we conservatively fail the CONNECT |
447 // request. | 463 // request. |
448 // We lose something by doing this. We have seen proxy 403, 404, and | 464 // We lose something by doing this. We have seen proxy 403, 404, and |
449 // 501 response bodies that contain a useful error message. For | 465 // 501 response bodies that contain a useful error message. For |
450 // example, Squid uses a 404 response to report the DNS error: "The | 466 // example, Squid uses a 404 response to report the DNS error: "The |
451 // domain name does not exist." | 467 // domain name does not exist." |
(...skipping 15 matching lines...) Expand all Loading... |
467 return result; | 483 return result; |
468 | 484 |
469 if (http_stream_parser_->IsResponseBodyComplete()) | 485 if (http_stream_parser_->IsResponseBodyComplete()) |
470 return DidDrainBodyForAuthRestart(true); | 486 return DidDrainBodyForAuthRestart(true); |
471 | 487 |
472 // Keep draining. | 488 // Keep draining. |
473 next_state_ = STATE_DRAIN_BODY; | 489 next_state_ = STATE_DRAIN_BODY; |
474 return OK; | 490 return OK; |
475 } | 491 } |
476 | 492 |
| 493 int HttpProxyClientSocket::DoTCPRestart() { |
| 494 next_state_ = STATE_TCP_RESTART_COMPLETE; |
| 495 return transport_->socket()->Connect( |
| 496 base::Bind(&HttpProxyClientSocket::OnIOComplete, base::Unretained(this))); |
| 497 } |
| 498 |
| 499 int HttpProxyClientSocket::DoTCPRestartComplete(int result) { |
| 500 if (result != OK) |
| 501 return result; |
| 502 |
| 503 next_state_ = STATE_GENERATE_AUTH_TOKEN; |
| 504 return result; |
| 505 } |
| 506 |
477 } // namespace net | 507 } // namespace net |
OLD | NEW |