OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_pool.h" | 5 #include "net/http/http_proxy_client_socket_pool.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 |
7 #include "base/time.h" | 9 #include "base/time.h" |
8 #include "googleurl/src/gurl.h" | 10 #include "googleurl/src/gurl.h" |
9 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
10 #include "net/http/http_network_session.h" | 12 #include "net/http/http_network_session.h" |
11 #include "net/http/http_proxy_client_socket.h" | 13 #include "net/http/http_proxy_client_socket.h" |
12 #include "net/socket/client_socket_factory.h" | 14 #include "net/socket/client_socket_factory.h" |
13 #include "net/socket/client_socket_handle.h" | 15 #include "net/socket/client_socket_handle.h" |
14 #include "net/socket/client_socket_pool_base.h" | 16 #include "net/socket/client_socket_pool_base.h" |
15 #include "net/socket/tcp_client_socket_pool.h" | 17 #include "net/socket/tcp_client_socket_pool.h" |
16 | 18 |
17 namespace net { | 19 namespace net { |
18 | 20 |
19 HttpProxySocketParams::HttpProxySocketParams( | 21 HttpProxySocketParams::HttpProxySocketParams( |
20 const scoped_refptr<TCPSocketParams>& proxy_server, | 22 const scoped_refptr<TCPSocketParams>& tcp_params, |
| 23 const scoped_refptr<SSLSocketParams>& ssl_params, |
21 const GURL& request_url, | 24 const GURL& request_url, |
22 const std::string& user_agent, | 25 const std::string& user_agent, |
23 HostPortPair endpoint, | 26 HostPortPair endpoint, |
24 scoped_refptr<HttpNetworkSession> session, | 27 scoped_refptr<HttpNetworkSession> session, |
25 bool tunnel) | 28 bool tunnel) |
26 : tcp_params_(proxy_server), | 29 : tcp_params_(tcp_params), |
| 30 ssl_params_(ssl_params), |
27 request_url_(request_url), | 31 request_url_(request_url), |
28 user_agent_(user_agent), | 32 user_agent_(user_agent), |
29 endpoint_(endpoint), | 33 endpoint_(endpoint), |
30 session_(tunnel ? session : NULL), | 34 session_(tunnel ? session : NULL), |
31 tunnel_(tunnel) { | 35 tunnel_(tunnel) { |
| 36 DCHECK((tcp_params == NULL && ssl_params != NULL) || |
| 37 (tcp_params != NULL && ssl_params == NULL)); |
| 38 } |
| 39 |
| 40 const HostResolver::RequestInfo& HttpProxySocketParams::destination() const { |
| 41 if (tcp_params_ == NULL) |
| 42 return ssl_params_->tcp_params()->destination(); |
| 43 else |
| 44 return tcp_params_->destination(); |
32 } | 45 } |
33 | 46 |
34 HttpProxySocketParams::~HttpProxySocketParams() {} | 47 HttpProxySocketParams::~HttpProxySocketParams() {} |
35 | 48 |
36 // HttpProxyConnectJobs will time out after this many seconds. Note this is on | 49 // HttpProxyConnectJobs will time out after this many seconds. Note this is on |
37 // top of the timeout for the transport socket. | 50 // top of the timeout for the transport socket. |
38 static const int kHttpProxyConnectJobTimeoutInSeconds = 30; | 51 static const int kHttpProxyConnectJobTimeoutInSeconds = 30; |
39 | 52 |
40 HttpProxyConnectJob::HttpProxyConnectJob( | 53 HttpProxyConnectJob::HttpProxyConnectJob( |
41 const std::string& group_name, | 54 const std::string& group_name, |
42 const scoped_refptr<HttpProxySocketParams>& params, | 55 const scoped_refptr<HttpProxySocketParams>& params, |
43 const base::TimeDelta& timeout_duration, | 56 const base::TimeDelta& timeout_duration, |
44 const scoped_refptr<TCPClientSocketPool>& tcp_pool, | 57 const scoped_refptr<TCPClientSocketPool>& tcp_pool, |
| 58 const scoped_refptr<SSLClientSocketPool>& ssl_pool, |
45 const scoped_refptr<HostResolver>& host_resolver, | 59 const scoped_refptr<HostResolver>& host_resolver, |
46 Delegate* delegate, | 60 Delegate* delegate, |
47 NetLog* net_log) | 61 NetLog* net_log) |
48 : ConnectJob(group_name, timeout_duration, delegate, | 62 : ConnectJob(group_name, timeout_duration, delegate, |
49 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), | 63 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), |
50 params_(params), | 64 params_(params), |
51 tcp_pool_(tcp_pool), | 65 tcp_pool_(tcp_pool), |
| 66 ssl_pool_(ssl_pool), |
52 resolver_(host_resolver), | 67 resolver_(host_resolver), |
53 ALLOW_THIS_IN_INITIALIZER_LIST( | 68 ALLOW_THIS_IN_INITIALIZER_LIST( |
54 callback_(this, &HttpProxyConnectJob::OnIOComplete)) { | 69 callback_(this, &HttpProxyConnectJob::OnIOComplete)) { |
55 } | 70 } |
56 | 71 |
57 HttpProxyConnectJob::~HttpProxyConnectJob() {} | 72 HttpProxyConnectJob::~HttpProxyConnectJob() {} |
58 | 73 |
59 LoadState HttpProxyConnectJob::GetLoadState() const { | 74 LoadState HttpProxyConnectJob::GetLoadState() const { |
60 switch (next_state_) { | 75 switch (next_state_) { |
61 case kStateTCPConnect: | 76 case kStateTCPConnect: |
62 case kStateTCPConnectComplete: | 77 case kStateTCPConnectComplete: |
63 return tcp_socket_handle_->GetLoadState(); | 78 case kStateSSLConnect: |
| 79 case kStateSSLConnectComplete: |
| 80 return transport_socket_handle_->GetLoadState(); |
64 case kStateHttpProxyConnect: | 81 case kStateHttpProxyConnect: |
65 case kStateHttpProxyConnectComplete: | 82 case kStateHttpProxyConnectComplete: |
66 return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL; | 83 return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL; |
67 default: | 84 default: |
68 NOTREACHED(); | 85 NOTREACHED(); |
69 return LOAD_STATE_IDLE; | 86 return LOAD_STATE_IDLE; |
70 } | 87 } |
71 } | 88 } |
72 | 89 |
73 int HttpProxyConnectJob::ConnectInternal() { | 90 int HttpProxyConnectJob::ConnectInternal() { |
74 next_state_ = kStateTCPConnect; | 91 if (params_->tcp_params()) |
| 92 next_state_ = kStateTCPConnect; |
| 93 else |
| 94 next_state_ = kStateSSLConnect; |
75 return DoLoop(OK); | 95 return DoLoop(OK); |
76 } | 96 } |
77 | 97 |
78 void HttpProxyConnectJob::OnIOComplete(int result) { | 98 void HttpProxyConnectJob::OnIOComplete(int result) { |
79 int rv = DoLoop(result); | 99 int rv = DoLoop(result); |
80 if (rv != ERR_IO_PENDING) | 100 if (rv != ERR_IO_PENDING) |
81 NotifyDelegateOfCompletion(rv); // Deletes |this| | 101 NotifyDelegateOfCompletion(rv); // Deletes |this| |
82 } | 102 } |
83 | 103 |
84 int HttpProxyConnectJob::DoLoop(int result) { | 104 int HttpProxyConnectJob::DoLoop(int result) { |
85 DCHECK_NE(next_state_, kStateNone); | 105 DCHECK_NE(next_state_, kStateNone); |
86 | 106 |
87 int rv = result; | 107 int rv = result; |
88 do { | 108 do { |
89 State state = next_state_; | 109 State state = next_state_; |
90 next_state_ = kStateNone; | 110 next_state_ = kStateNone; |
91 switch (state) { | 111 switch (state) { |
92 case kStateTCPConnect: | 112 case kStateTCPConnect: |
93 DCHECK_EQ(OK, rv); | 113 DCHECK_EQ(OK, rv); |
94 rv = DoTCPConnect(); | 114 rv = DoTCPConnect(); |
95 break; | 115 break; |
96 case kStateTCPConnectComplete: | 116 case kStateTCPConnectComplete: |
97 rv = DoTCPConnectComplete(rv); | 117 rv = DoTCPConnectComplete(rv); |
98 break; | 118 break; |
| 119 case kStateSSLConnect: |
| 120 DCHECK_EQ(OK, rv); |
| 121 rv = DoSSLConnect(); |
| 122 break; |
| 123 case kStateSSLConnectComplete: |
| 124 rv = DoSSLConnectComplete(rv); |
| 125 break; |
99 case kStateHttpProxyConnect: | 126 case kStateHttpProxyConnect: |
100 DCHECK_EQ(OK, rv); | 127 DCHECK_EQ(OK, rv); |
101 rv = DoHttpProxyConnect(); | 128 rv = DoHttpProxyConnect(); |
102 break; | 129 break; |
103 case kStateHttpProxyConnectComplete: | 130 case kStateHttpProxyConnectComplete: |
104 rv = DoHttpProxyConnectComplete(rv); | 131 rv = DoHttpProxyConnectComplete(rv); |
105 break; | 132 break; |
106 default: | 133 default: |
107 NOTREACHED() << "bad state"; | 134 NOTREACHED() << "bad state"; |
108 rv = ERR_FAILED; | 135 rv = ERR_FAILED; |
109 break; | 136 break; |
110 } | 137 } |
111 } while (rv != ERR_IO_PENDING && next_state_ != kStateNone); | 138 } while (rv != ERR_IO_PENDING && next_state_ != kStateNone); |
112 | 139 |
113 return rv; | 140 return rv; |
114 } | 141 } |
115 | 142 |
116 int HttpProxyConnectJob::DoTCPConnect() { | 143 int HttpProxyConnectJob::DoTCPConnect() { |
117 next_state_ = kStateTCPConnectComplete; | 144 next_state_ = kStateTCPConnectComplete; |
118 tcp_socket_handle_.reset(new ClientSocketHandle()); | 145 transport_socket_handle_.reset(new ClientSocketHandle()); |
119 return tcp_socket_handle_->Init( | 146 return transport_socket_handle_->Init( |
120 group_name(), params_->tcp_params(), | 147 group_name(), params_->tcp_params(), |
121 params_->tcp_params()->destination().priority(), &callback_, tcp_pool_, | 148 params_->tcp_params()->destination().priority(), &callback_, tcp_pool_, |
122 net_log()); | 149 net_log()); |
123 } | 150 } |
124 | 151 |
125 int HttpProxyConnectJob::DoTCPConnectComplete(int result) { | 152 int HttpProxyConnectJob::DoTCPConnectComplete(int result) { |
126 if (result != OK) | 153 if (result != OK) |
127 return result; | 154 return result; |
128 | 155 |
129 // Reset the timer to just the length of time allowed for HttpProxy handshake | 156 // Reset the timer to just the length of time allowed for HttpProxy handshake |
130 // so that a fast TCP connection plus a slow HttpProxy failure doesn't take | 157 // so that a fast TCP connection plus a slow HttpProxy failure doesn't take |
131 // longer to timeout than it should. | 158 // longer to timeout than it should. |
132 ResetTimer(base::TimeDelta::FromSeconds( | 159 ResetTimer(base::TimeDelta::FromSeconds( |
133 kHttpProxyConnectJobTimeoutInSeconds)); | 160 kHttpProxyConnectJobTimeoutInSeconds)); |
134 next_state_ = kStateHttpProxyConnect; | 161 next_state_ = kStateHttpProxyConnect; |
135 return result; | 162 return result; |
136 } | 163 } |
137 | 164 |
| 165 int HttpProxyConnectJob::DoSSLConnect() { |
| 166 next_state_ = kStateSSLConnectComplete; |
| 167 transport_socket_handle_.reset(new ClientSocketHandle()); |
| 168 return transport_socket_handle_->Init( |
| 169 group_name(), params_->ssl_params(), |
| 170 params_->ssl_params()->tcp_params()->destination().priority(), |
| 171 &callback_, ssl_pool_, net_log()); |
| 172 } |
| 173 |
| 174 int HttpProxyConnectJob::DoSSLConnectComplete(int result) { |
| 175 if (result < 0) { |
| 176 if (transport_socket_handle_->socket()) |
| 177 transport_socket_handle_->socket()->Disconnect(); |
| 178 return result; |
| 179 } |
| 180 |
| 181 // Reset the timer to just the length of time allowed for HttpProxy handshake |
| 182 // so that a fast SSL connection plus a slow HttpProxy failure doesn't take |
| 183 // longer to timeout than it should. |
| 184 ResetTimer(base::TimeDelta::FromSeconds( |
| 185 kHttpProxyConnectJobTimeoutInSeconds)); |
| 186 next_state_ = kStateHttpProxyConnect; |
| 187 return result; |
| 188 } |
| 189 |
138 int HttpProxyConnectJob::DoHttpProxyConnect() { | 190 int HttpProxyConnectJob::DoHttpProxyConnect() { |
139 next_state_ = kStateHttpProxyConnectComplete; | 191 next_state_ = kStateHttpProxyConnectComplete; |
140 const HostResolver::RequestInfo& tcp_destination = | 192 const HostResolver::RequestInfo& tcp_destination = params_->destination(); |
141 params_->tcp_params()->destination(); | |
142 HostPortPair proxy_server(tcp_destination.hostname(), | 193 HostPortPair proxy_server(tcp_destination.hostname(), |
143 tcp_destination.port()); | 194 tcp_destination.port()); |
144 | 195 |
145 // Add a HttpProxy connection on top of the tcp socket. | 196 // Add a HttpProxy connection on top of the tcp socket. |
146 socket_.reset(new HttpProxyClientSocket(tcp_socket_handle_.release(), | 197 transport_socket_.reset( |
147 params_->request_url(), | 198 new HttpProxyClientSocket(transport_socket_handle_.release(), |
148 params_->user_agent(), | 199 params_->request_url(), |
149 params_->endpoint(), | 200 params_->user_agent(), |
150 proxy_server, | 201 params_->endpoint(), |
151 params_->session(), | 202 proxy_server, params_->session(), |
152 params_->tunnel())); | 203 params_->tunnel())); |
153 int result = socket_->Connect(&callback_); | 204 int result = transport_socket_->Connect(&callback_); |
154 | 205 |
155 // Clear the circular reference to HttpNetworkSession (|params_| reference | 206 // Clear the circular reference to HttpNetworkSession (|params_| reference |
156 // HttpNetworkSession, which reference HttpProxyClientSocketPool, which | 207 // HttpNetworkSession, which reference HttpProxyClientSocketPool, which |
157 // references |this|) here because it is safe to do so now but not at other | 208 // references |this|) here because it is safe to do so now but not at other |
158 // points. This may cancel this ConnectJob. | 209 // points. This may cancel this ConnectJob. |
159 params_ = NULL; | 210 params_ = NULL; |
160 return result; | 211 return result; |
161 } | 212 } |
162 | 213 |
163 int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) { | 214 int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) { |
164 if (result == OK || result == ERR_PROXY_AUTH_REQUESTED) | 215 if (result == OK || result == ERR_PROXY_AUTH_REQUESTED) |
165 set_socket(socket_.release()); | 216 set_socket(transport_socket_.release()); |
166 | 217 |
167 return result; | 218 return result; |
168 } | 219 } |
169 | 220 |
| 221 HttpProxyClientSocketPool:: |
| 222 HttpProxyConnectJobFactory::HttpProxyConnectJobFactory( |
| 223 const scoped_refptr<TCPClientSocketPool>& tcp_pool, |
| 224 const scoped_refptr<SSLClientSocketPool>& ssl_pool, |
| 225 HostResolver* host_resolver, |
| 226 NetLog* net_log) |
| 227 : tcp_pool_(tcp_pool), |
| 228 ssl_pool_(ssl_pool), |
| 229 host_resolver_(host_resolver), |
| 230 net_log_(net_log) { |
| 231 base::TimeDelta max_pool_timeout = base::TimeDelta(); |
| 232 if (tcp_pool_) |
| 233 max_pool_timeout = tcp_pool_->ConnectionTimeout(); |
| 234 if (ssl_pool_) |
| 235 max_pool_timeout = std::max(max_pool_timeout, |
| 236 ssl_pool_->ConnectionTimeout()); |
| 237 timeout_ = max_pool_timeout + |
| 238 base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds); |
| 239 } |
| 240 |
| 241 |
170 ConnectJob* | 242 ConnectJob* |
171 HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob( | 243 HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob( |
172 const std::string& group_name, | 244 const std::string& group_name, |
173 const PoolBase::Request& request, | 245 const PoolBase::Request& request, |
174 ConnectJob::Delegate* delegate) const { | 246 ConnectJob::Delegate* delegate) const { |
175 return new HttpProxyConnectJob(group_name, request.params(), | 247 return new HttpProxyConnectJob(group_name, request.params(), |
176 ConnectionTimeout(), tcp_pool_, host_resolver_, | 248 ConnectionTimeout(), tcp_pool_, ssl_pool_, |
177 delegate, net_log_); | 249 host_resolver_, delegate, net_log_); |
178 } | |
179 | |
180 base::TimeDelta | |
181 HttpProxyClientSocketPool::HttpProxyConnectJobFactory::ConnectionTimeout() | |
182 const { | |
183 return tcp_pool_->ConnectionTimeout() + | |
184 base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds); | |
185 } | 250 } |
186 | 251 |
187 HttpProxyClientSocketPool::HttpProxyClientSocketPool( | 252 HttpProxyClientSocketPool::HttpProxyClientSocketPool( |
188 int max_sockets, | 253 int max_sockets, |
189 int max_sockets_per_group, | 254 int max_sockets_per_group, |
190 const scoped_refptr<ClientSocketPoolHistograms>& histograms, | 255 const scoped_refptr<ClientSocketPoolHistograms>& histograms, |
191 const scoped_refptr<HostResolver>& host_resolver, | 256 const scoped_refptr<HostResolver>& host_resolver, |
192 const scoped_refptr<TCPClientSocketPool>& tcp_pool, | 257 const scoped_refptr<TCPClientSocketPool>& tcp_pool, |
| 258 const scoped_refptr<SSLClientSocketPool>& ssl_pool, |
193 NetLog* net_log) | 259 NetLog* net_log) |
194 : base_(max_sockets, max_sockets_per_group, histograms, | 260 : base_(max_sockets, max_sockets_per_group, histograms, |
195 base::TimeDelta::FromSeconds( | 261 base::TimeDelta::FromSeconds( |
196 ClientSocketPool::unused_idle_socket_timeout()), | 262 ClientSocketPool::unused_idle_socket_timeout()), |
197 base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout), | 263 base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout), |
198 new HttpProxyConnectJobFactory(tcp_pool, host_resolver, net_log)) {} | 264 new HttpProxyConnectJobFactory(tcp_pool, ssl_pool, host_resolver, |
| 265 net_log)) {} |
199 | 266 |
200 HttpProxyClientSocketPool::~HttpProxyClientSocketPool() {} | 267 HttpProxyClientSocketPool::~HttpProxyClientSocketPool() {} |
201 | 268 |
202 int HttpProxyClientSocketPool::RequestSocket(const std::string& group_name, | 269 int HttpProxyClientSocketPool::RequestSocket(const std::string& group_name, |
203 const void* socket_params, | 270 const void* socket_params, |
204 RequestPriority priority, | 271 RequestPriority priority, |
205 ClientSocketHandle* handle, | 272 ClientSocketHandle* handle, |
206 CompletionCallback* callback, | 273 CompletionCallback* callback, |
207 const BoundNetLog& net_log) { | 274 const BoundNetLog& net_log) { |
208 const scoped_refptr<HttpProxySocketParams>* casted_socket_params = | 275 const scoped_refptr<HttpProxySocketParams>* casted_socket_params = |
(...skipping 26 matching lines...) Expand all Loading... |
235 const std::string& group_name) const { | 302 const std::string& group_name) const { |
236 return base_.IdleSocketCountInGroup(group_name); | 303 return base_.IdleSocketCountInGroup(group_name); |
237 } | 304 } |
238 | 305 |
239 LoadState HttpProxyClientSocketPool::GetLoadState( | 306 LoadState HttpProxyClientSocketPool::GetLoadState( |
240 const std::string& group_name, const ClientSocketHandle* handle) const { | 307 const std::string& group_name, const ClientSocketHandle* handle) const { |
241 return base_.GetLoadState(group_name, handle); | 308 return base_.GetLoadState(group_name, handle); |
242 } | 309 } |
243 | 310 |
244 } // namespace net | 311 } // namespace net |
OLD | NEW |