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 19 matching lines...) Expand all Loading... |
30 const HostPortPair& endpoint, | 30 const HostPortPair& endpoint, |
31 const HostPortPair& proxy_server, | 31 const HostPortPair& proxy_server, |
32 HttpAuthCache* http_auth_cache, | 32 HttpAuthCache* http_auth_cache, |
33 HttpAuthHandlerFactory* http_auth_handler_factory, | 33 HttpAuthHandlerFactory* http_auth_handler_factory, |
34 bool tunnel, | 34 bool tunnel, |
35 bool using_spdy, | 35 bool using_spdy, |
36 bool is_https_proxy) | 36 bool is_https_proxy) |
37 : ALLOW_THIS_IN_INITIALIZER_LIST( | 37 : ALLOW_THIS_IN_INITIALIZER_LIST( |
38 io_callback_(this, &HttpProxyClientSocket::OnIOComplete)), | 38 io_callback_(this, &HttpProxyClientSocket::OnIOComplete)), |
39 next_state_(STATE_NONE), | 39 next_state_(STATE_NONE), |
40 user_callback_(NULL), | 40 old_user_callback_(NULL), |
41 transport_(transport_socket), | 41 transport_(transport_socket), |
42 endpoint_(endpoint), | 42 endpoint_(endpoint), |
43 auth_(tunnel ? | 43 auth_(tunnel ? |
44 new HttpAuthController(HttpAuth::AUTH_PROXY, | 44 new HttpAuthController(HttpAuth::AUTH_PROXY, |
45 GURL((is_https_proxy ? "https://" : "http://") | 45 GURL((is_https_proxy ? "https://" : "http://") |
46 + proxy_server.ToString()), | 46 + proxy_server.ToString()), |
47 http_auth_cache, | 47 http_auth_cache, |
48 http_auth_handler_factory) | 48 http_auth_handler_factory) |
49 : NULL), | 49 : NULL), |
50 tunnel_(tunnel), | 50 tunnel_(tunnel), |
51 using_spdy_(using_spdy), | 51 using_spdy_(using_spdy), |
52 is_https_proxy_(is_https_proxy), | 52 is_https_proxy_(is_https_proxy), |
53 net_log_(transport_socket->socket()->NetLog()) { | 53 net_log_(transport_socket->socket()->NetLog()) { |
54 // Synthesize the bits of a request that we actually use. | 54 // Synthesize the bits of a request that we actually use. |
55 request_.url = request_url; | 55 request_.url = request_url; |
56 request_.method = "GET"; | 56 request_.method = "GET"; |
57 if (!user_agent.empty()) | 57 if (!user_agent.empty()) |
58 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, | 58 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, |
59 user_agent); | 59 user_agent); |
60 } | 60 } |
61 | 61 |
62 HttpProxyClientSocket::~HttpProxyClientSocket() { | 62 HttpProxyClientSocket::~HttpProxyClientSocket() { |
63 Disconnect(); | 63 Disconnect(); |
64 } | 64 } |
65 | 65 |
66 int HttpProxyClientSocket::RestartWithAuth(OldCompletionCallback* callback) { | 66 int HttpProxyClientSocket::RestartWithAuth(OldCompletionCallback* callback) { |
67 DCHECK_EQ(STATE_NONE, next_state_); | 67 DCHECK_EQ(STATE_NONE, next_state_); |
68 DCHECK(!user_callback_); | 68 DCHECK(!old_user_callback_ && user_callback_.is_null()); |
69 | 69 |
70 int rv = PrepareForAuthRestart(); | 70 int rv = PrepareForAuthRestart(); |
71 if (rv != OK || next_state_ == STATE_NONE) | 71 if (rv != OK || next_state_ == STATE_NONE) |
72 return rv; | 72 return rv; |
73 | 73 |
74 rv = DoLoop(OK); | 74 rv = DoLoop(OK); |
75 if (rv == ERR_IO_PENDING) | 75 if (rv == ERR_IO_PENDING) |
76 user_callback_ = callback; | 76 old_user_callback_ = callback; |
77 return rv; | 77 return rv; |
78 } | 78 } |
79 | 79 |
80 const | 80 const |
81 scoped_refptr<HttpAuthController>& HttpProxyClientSocket::auth_controller() { | 81 scoped_refptr<HttpAuthController>& HttpProxyClientSocket::auth_controller() { |
82 return auth_; | 82 return auth_; |
83 } | 83 } |
84 | 84 |
85 const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const { | 85 const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const { |
86 return response_.headers ? &response_ : NULL; | 86 return response_.headers ? &response_ : NULL; |
87 } | 87 } |
88 | 88 |
89 HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { | 89 HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { |
90 return new HttpBasicStream(transport_.release(), | 90 return new HttpBasicStream(transport_.release(), |
91 http_stream_parser_.release(), false); | 91 http_stream_parser_.release(), false); |
92 } | 92 } |
93 | 93 |
94 | 94 |
95 int HttpProxyClientSocket::Connect(OldCompletionCallback* callback) { | 95 int HttpProxyClientSocket::Connect(OldCompletionCallback* callback) { |
96 DCHECK(transport_.get()); | 96 DCHECK(transport_.get()); |
97 DCHECK(transport_->socket()); | 97 DCHECK(transport_->socket()); |
98 DCHECK(!user_callback_); | 98 DCHECK(!old_user_callback_ && user_callback_.is_null()); |
99 | 99 |
100 // TODO(rch): figure out the right way to set up a tunnel with SPDY. | 100 // TODO(rch): figure out the right way to set up a tunnel with SPDY. |
101 // This approach sends the complete HTTPS request to the proxy | 101 // This approach sends the complete HTTPS request to the proxy |
| 102 // which allows the proxy to see "private" data. Instead, we should |
| 103 // create an SSL tunnel to the origin server using the CONNECT method |
| 104 // inside a single SPDY stream. |
| 105 if (using_spdy_ || !tunnel_) |
| 106 next_state_ = STATE_DONE; |
| 107 if (next_state_ == STATE_DONE) |
| 108 return OK; |
| 109 |
| 110 DCHECK_EQ(STATE_NONE, next_state_); |
| 111 next_state_ = STATE_GENERATE_AUTH_TOKEN; |
| 112 |
| 113 int rv = DoLoop(OK); |
| 114 if (rv == ERR_IO_PENDING) |
| 115 old_user_callback_ = callback; |
| 116 return rv; |
| 117 } |
| 118 |
| 119 int HttpProxyClientSocket::Connect(const CompletionCallback& callback) { |
| 120 DCHECK(transport_.get()); |
| 121 DCHECK(transport_->socket()); |
| 122 DCHECK(!old_user_callback_ && user_callback_.is_null()); |
| 123 |
| 124 // TODO(rch): figure out the right way to set up a tunnel with SPDY. |
| 125 // This approach sends the complete HTTPS request to the proxy |
102 // which allows the proxy to see "private" data. Instead, we should | 126 // which allows the proxy to see "private" data. Instead, we should |
103 // create an SSL tunnel to the origin server using the CONNECT method | 127 // create an SSL tunnel to the origin server using the CONNECT method |
104 // inside a single SPDY stream. | 128 // inside a single SPDY stream. |
105 if (using_spdy_ || !tunnel_) | 129 if (using_spdy_ || !tunnel_) |
106 next_state_ = STATE_DONE; | 130 next_state_ = STATE_DONE; |
107 if (next_state_ == STATE_DONE) | 131 if (next_state_ == STATE_DONE) |
108 return OK; | 132 return OK; |
109 | 133 |
110 DCHECK_EQ(STATE_NONE, next_state_); | 134 DCHECK_EQ(STATE_NONE, next_state_); |
111 next_state_ = STATE_GENERATE_AUTH_TOKEN; | 135 next_state_ = STATE_GENERATE_AUTH_TOKEN; |
112 | 136 |
113 int rv = DoLoop(OK); | 137 int rv = DoLoop(OK); |
114 if (rv == ERR_IO_PENDING) | 138 if (rv == ERR_IO_PENDING) |
115 user_callback_ = callback; | 139 user_callback_ = callback; |
116 return rv; | 140 return rv; |
117 } | 141 } |
118 | 142 |
119 void HttpProxyClientSocket::Disconnect() { | 143 void HttpProxyClientSocket::Disconnect() { |
120 if (transport_.get()) | 144 if (transport_.get()) |
121 transport_->socket()->Disconnect(); | 145 transport_->socket()->Disconnect(); |
122 | 146 |
123 // Reset other states to make sure they aren't mistakenly used later. | 147 // Reset other states to make sure they aren't mistakenly used later. |
124 // These are the states initialized by Connect(). | 148 // These are the states initialized by Connect(). |
125 next_state_ = STATE_NONE; | 149 next_state_ = STATE_NONE; |
126 user_callback_ = NULL; | 150 old_user_callback_ = NULL; |
| 151 user_callback_.Reset(); |
127 } | 152 } |
128 | 153 |
129 bool HttpProxyClientSocket::IsConnected() const { | 154 bool HttpProxyClientSocket::IsConnected() const { |
130 return next_state_ == STATE_DONE && transport_->socket()->IsConnected(); | 155 return next_state_ == STATE_DONE && transport_->socket()->IsConnected(); |
131 } | 156 } |
132 | 157 |
133 bool HttpProxyClientSocket::IsConnectedAndIdle() const { | 158 bool HttpProxyClientSocket::IsConnectedAndIdle() const { |
134 return next_state_ == STATE_DONE && | 159 return next_state_ == STATE_DONE && |
135 transport_->socket()->IsConnectedAndIdle(); | 160 transport_->socket()->IsConnectedAndIdle(); |
136 } | 161 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 base::TimeDelta HttpProxyClientSocket::GetConnectTimeMicros() const { | 207 base::TimeDelta HttpProxyClientSocket::GetConnectTimeMicros() const { |
183 if (transport_.get() && transport_->socket()) { | 208 if (transport_.get() && transport_->socket()) { |
184 return transport_->socket()->GetConnectTimeMicros(); | 209 return transport_->socket()->GetConnectTimeMicros(); |
185 } | 210 } |
186 NOTREACHED(); | 211 NOTREACHED(); |
187 return base::TimeDelta::FromMicroseconds(-1); | 212 return base::TimeDelta::FromMicroseconds(-1); |
188 } | 213 } |
189 | 214 |
190 int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len, | 215 int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len, |
191 OldCompletionCallback* callback) { | 216 OldCompletionCallback* callback) { |
192 DCHECK(!user_callback_); | 217 DCHECK(!old_user_callback_); |
193 if (next_state_ != STATE_DONE) { | 218 if (next_state_ != STATE_DONE) { |
194 // We're trying to read the body of the response but we're still trying | 219 // We're trying to read the body of the response but we're still trying |
195 // to establish an SSL tunnel through the proxy. We can't read these | 220 // to establish an SSL tunnel through the proxy. We can't read these |
196 // bytes when establishing a tunnel because they might be controlled by | 221 // bytes when establishing a tunnel because they might be controlled by |
197 // an active network attacker. We don't worry about this for HTTP | 222 // an active network attacker. We don't worry about this for HTTP |
198 // because an active network attacker can already control HTTP sessions. | 223 // because an active network attacker can already control HTTP sessions. |
199 // We reach this case when the user cancels a 407 proxy auth prompt. | 224 // We reach this case when the user cancels a 407 proxy auth prompt. |
200 // See http://crbug.com/8473. | 225 // See http://crbug.com/8473. |
201 DCHECK_EQ(407, response_.headers->response_code()); | 226 DCHECK_EQ(407, response_.headers->response_code()); |
202 LogBlockedTunnelResponse(response_.headers->response_code()); | 227 LogBlockedTunnelResponse(response_.headers->response_code()); |
203 | 228 |
204 return ERR_TUNNEL_CONNECTION_FAILED; | 229 return ERR_TUNNEL_CONNECTION_FAILED; |
205 } | 230 } |
206 | 231 |
207 return transport_->socket()->Read(buf, buf_len, callback); | 232 return transport_->socket()->Read(buf, buf_len, callback); |
208 } | 233 } |
209 | 234 |
210 int HttpProxyClientSocket::Write(IOBuffer* buf, int buf_len, | 235 int HttpProxyClientSocket::Write(IOBuffer* buf, int buf_len, |
211 OldCompletionCallback* callback) { | 236 OldCompletionCallback* callback) { |
212 DCHECK_EQ(STATE_DONE, next_state_); | 237 DCHECK_EQ(STATE_DONE, next_state_); |
213 DCHECK(!user_callback_); | 238 DCHECK(!old_user_callback_); |
214 | 239 |
215 return transport_->socket()->Write(buf, buf_len, callback); | 240 return transport_->socket()->Write(buf, buf_len, callback); |
216 } | 241 } |
217 | 242 |
218 bool HttpProxyClientSocket::SetReceiveBufferSize(int32 size) { | 243 bool HttpProxyClientSocket::SetReceiveBufferSize(int32 size) { |
219 return transport_->socket()->SetReceiveBufferSize(size); | 244 return transport_->socket()->SetReceiveBufferSize(size); |
220 } | 245 } |
221 | 246 |
222 bool HttpProxyClientSocket::SetSendBufferSize(int32 size) { | 247 bool HttpProxyClientSocket::SetSendBufferSize(int32 size) { |
223 return transport_->socket()->SetSendBufferSize(size); | 248 return transport_->socket()->SetSendBufferSize(size); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 } | 295 } |
271 | 296 |
272 void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { | 297 void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { |
273 LOG(WARNING) << "Blocked proxy response with status " << response_code | 298 LOG(WARNING) << "Blocked proxy response with status " << response_code |
274 << " to CONNECT request for " | 299 << " to CONNECT request for " |
275 << GetHostAndPort(request_.url) << "."; | 300 << GetHostAndPort(request_.url) << "."; |
276 } | 301 } |
277 | 302 |
278 void HttpProxyClientSocket::DoCallback(int result) { | 303 void HttpProxyClientSocket::DoCallback(int result) { |
279 DCHECK_NE(ERR_IO_PENDING, result); | 304 DCHECK_NE(ERR_IO_PENDING, result); |
280 DCHECK(user_callback_); | 305 DCHECK(old_user_callback_ || !user_callback_.is_null()); |
281 | 306 |
282 // Since Run() may result in Read being called, | 307 // Since Run() may result in Read being called, |
283 // clear user_callback_ up front. | 308 // clear old_user_callback_ up front. |
284 OldCompletionCallback* c = user_callback_; | 309 if (old_user_callback_) { |
285 user_callback_ = NULL; | 310 OldCompletionCallback* c = old_user_callback_; |
286 c->Run(result); | 311 old_user_callback_ = NULL; |
| 312 c->Run(result); |
| 313 } else { |
| 314 CompletionCallback c = user_callback_; |
| 315 user_callback_.Reset(); |
| 316 c.Run(result); |
| 317 } |
287 } | 318 } |
288 | 319 |
289 void HttpProxyClientSocket::OnIOComplete(int result) { | 320 void HttpProxyClientSocket::OnIOComplete(int result) { |
290 DCHECK_NE(STATE_NONE, next_state_); | 321 DCHECK_NE(STATE_NONE, next_state_); |
291 DCHECK_NE(STATE_DONE, next_state_); | 322 DCHECK_NE(STATE_DONE, next_state_); |
292 int rv = DoLoop(result); | 323 int rv = DoLoop(result); |
293 if (rv != ERR_IO_PENDING) | 324 if (rv != ERR_IO_PENDING) |
294 DoCallback(rv); | 325 DoCallback(rv); |
295 } | 326 } |
296 | 327 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 | 497 |
467 if (http_stream_parser_->IsResponseBodyComplete()) | 498 if (http_stream_parser_->IsResponseBodyComplete()) |
468 return DidDrainBodyForAuthRestart(true); | 499 return DidDrainBodyForAuthRestart(true); |
469 | 500 |
470 // Keep draining. | 501 // Keep draining. |
471 next_state_ = STATE_DRAIN_BODY; | 502 next_state_ = STATE_DRAIN_BODY; |
472 return OK; | 503 return OK; |
473 } | 504 } |
474 | 505 |
475 } // namespace net | 506 } // namespace net |
OLD | NEW |