blob: 4dbb4422c609476db092d6fd3dde2b0349cb3643 [file] [log] [blame]
[email protected]5acdce12011-03-30 13:00:201// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]a796bcec2010-03-22 17:17:262// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/socket/socks_client_socket_pool.h"
6
7#include "base/time.h"
[email protected]ba00b492010-09-08 14:53:388#include "base/values.h"
[email protected]a796bcec2010-03-22 17:17:269#include "googleurl/src/gurl.h"
10#include "net/base/net_errors.h"
11#include "net/socket/client_socket_factory.h"
12#include "net/socket/client_socket_handle.h"
13#include "net/socket/client_socket_pool_base.h"
14#include "net/socket/socks5_client_socket.h"
15#include "net/socket/socks_client_socket.h"
[email protected]ab739042011-04-07 15:22:2816#include "net/socket/transport_client_socket_pool.h"
[email protected]a796bcec2010-03-22 17:17:2617
18namespace net {
19
[email protected]df4b4ef2010-07-12 18:25:2120SOCKSSocketParams::SOCKSSocketParams(
[email protected]ab739042011-04-07 15:22:2821 const scoped_refptr<TransportSocketParams>& proxy_server,
[email protected]df4b4ef2010-07-12 18:25:2122 bool socks_v5,
23 const HostPortPair& host_port_pair,
24 RequestPriority priority,
25 const GURL& referrer)
[email protected]ab739042011-04-07 15:22:2826 : transport_params_(proxy_server),
[email protected]930cc742010-09-15 22:54:1027 destination_(host_port_pair),
[email protected]df4b4ef2010-07-12 18:25:2128 socks_v5_(socks_v5) {
[email protected]ab739042011-04-07 15:22:2829 if (transport_params_)
30 ignore_limits_ = transport_params_->ignore_limits();
[email protected]5acdce12011-03-30 13:00:2031 else
32 ignore_limits_ = false;
[email protected]df4b4ef2010-07-12 18:25:2133 // The referrer is used by the DNS prefetch system to correlate resolutions
34 // with the page that triggered them. It doesn't impact the actual addresses
35 // that we resolve to.
36 destination_.set_referrer(referrer);
37 destination_.set_priority(priority);
38}
39
40SOCKSSocketParams::~SOCKSSocketParams() {}
41
[email protected]a796bcec2010-03-22 17:17:2642// SOCKSConnectJobs will time out after this many seconds. Note this is on
43// top of the timeout for the transport socket.
44static const int kSOCKSConnectJobTimeoutInSeconds = 30;
45
46SOCKSConnectJob::SOCKSConnectJob(
47 const std::string& group_name,
[email protected]df4b4ef2010-07-12 18:25:2148 const scoped_refptr<SOCKSSocketParams>& socks_params,
[email protected]a796bcec2010-03-22 17:17:2649 const base::TimeDelta& timeout_duration,
[email protected]ab739042011-04-07 15:22:2850 TransportClientSocketPool* transport_pool,
[email protected]73c45322010-10-01 23:57:5451 HostResolver* host_resolver,
[email protected]a796bcec2010-03-22 17:17:2652 Delegate* delegate,
[email protected]06650c52010-06-03 00:49:1753 NetLog* net_log)
54 : ConnectJob(group_name, timeout_duration, delegate,
55 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
[email protected]a796bcec2010-03-22 17:17:2656 socks_params_(socks_params),
[email protected]ab739042011-04-07 15:22:2857 transport_pool_(transport_pool),
[email protected]a796bcec2010-03-22 17:17:2658 resolver_(host_resolver),
59 ALLOW_THIS_IN_INITIALIZER_LIST(
[email protected]06650c52010-06-03 00:49:1760 callback_(this, &SOCKSConnectJob::OnIOComplete)) {
61}
[email protected]a796bcec2010-03-22 17:17:2662
63SOCKSConnectJob::~SOCKSConnectJob() {
64 // We don't worry about cancelling the tcp socket since the destructor in
[email protected]ab739042011-04-07 15:22:2865 // scoped_ptr<ClientSocketHandle> transport_socket_handle_ will take care of
66 // it.
[email protected]a796bcec2010-03-22 17:17:2667}
68
69LoadState SOCKSConnectJob::GetLoadState() const {
70 switch (next_state_) {
[email protected]ab739042011-04-07 15:22:2871 case STATE_TRANSPORT_CONNECT:
72 case STATE_TRANSPORT_CONNECT_COMPLETE:
73 return transport_socket_handle_->GetLoadState();
[email protected]81854c42010-09-22 03:39:3674 case STATE_SOCKS_CONNECT:
75 case STATE_SOCKS_CONNECT_COMPLETE:
[email protected]a796bcec2010-03-22 17:17:2676 return LOAD_STATE_CONNECTING;
77 default:
78 NOTREACHED();
79 return LOAD_STATE_IDLE;
80 }
81}
82
[email protected]a796bcec2010-03-22 17:17:2683void SOCKSConnectJob::OnIOComplete(int result) {
84 int rv = DoLoop(result);
85 if (rv != ERR_IO_PENDING)
86 NotifyDelegateOfCompletion(rv); // Deletes |this|
87}
88
89int SOCKSConnectJob::DoLoop(int result) {
[email protected]81854c42010-09-22 03:39:3690 DCHECK_NE(next_state_, STATE_NONE);
[email protected]a796bcec2010-03-22 17:17:2691
92 int rv = result;
93 do {
94 State state = next_state_;
[email protected]81854c42010-09-22 03:39:3695 next_state_ = STATE_NONE;
[email protected]a796bcec2010-03-22 17:17:2696 switch (state) {
[email protected]ab739042011-04-07 15:22:2897 case STATE_TRANSPORT_CONNECT:
[email protected]a796bcec2010-03-22 17:17:2698 DCHECK_EQ(OK, rv);
[email protected]ab739042011-04-07 15:22:2899 rv = DoTransportConnect();
[email protected]a796bcec2010-03-22 17:17:26100 break;
[email protected]ab739042011-04-07 15:22:28101 case STATE_TRANSPORT_CONNECT_COMPLETE:
102 rv = DoTransportConnectComplete(rv);
[email protected]a796bcec2010-03-22 17:17:26103 break;
[email protected]81854c42010-09-22 03:39:36104 case STATE_SOCKS_CONNECT:
[email protected]a796bcec2010-03-22 17:17:26105 DCHECK_EQ(OK, rv);
106 rv = DoSOCKSConnect();
107 break;
[email protected]81854c42010-09-22 03:39:36108 case STATE_SOCKS_CONNECT_COMPLETE:
[email protected]a796bcec2010-03-22 17:17:26109 rv = DoSOCKSConnectComplete(rv);
110 break;
111 default:
112 NOTREACHED() << "bad state";
113 rv = ERR_FAILED;
114 break;
115 }
[email protected]81854c42010-09-22 03:39:36116 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
[email protected]a796bcec2010-03-22 17:17:26117
118 return rv;
119}
120
[email protected]ab739042011-04-07 15:22:28121int SOCKSConnectJob::DoTransportConnect() {
122 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
123 transport_socket_handle_.reset(new ClientSocketHandle());
124 return transport_socket_handle_->Init(group_name(),
125 socks_params_->transport_params(),
126 socks_params_->destination().priority(),
127 &callback_,
128 transport_pool_,
129 net_log());
[email protected]a796bcec2010-03-22 17:17:26130}
131
[email protected]ab739042011-04-07 15:22:28132int SOCKSConnectJob::DoTransportConnectComplete(int result) {
[email protected]a796bcec2010-03-22 17:17:26133 if (result != OK)
[email protected]f7fccee2010-09-16 20:53:01134 return ERR_PROXY_CONNECTION_FAILED;
[email protected]a796bcec2010-03-22 17:17:26135
136 // Reset the timer to just the length of time allowed for SOCKS handshake
137 // so that a fast TCP connection plus a slow SOCKS failure doesn't take
138 // longer to timeout than it should.
139 ResetTimer(base::TimeDelta::FromSeconds(kSOCKSConnectJobTimeoutInSeconds));
[email protected]81854c42010-09-22 03:39:36140 next_state_ = STATE_SOCKS_CONNECT;
[email protected]a796bcec2010-03-22 17:17:26141 return result;
142}
143
144int SOCKSConnectJob::DoSOCKSConnect() {
[email protected]81854c42010-09-22 03:39:36145 next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
[email protected]a796bcec2010-03-22 17:17:26146
147 // Add a SOCKS connection on top of the tcp socket.
[email protected]df4b4ef2010-07-12 18:25:21148 if (socks_params_->is_socks_v5()) {
[email protected]ab739042011-04-07 15:22:28149 socket_.reset(new SOCKS5ClientSocket(transport_socket_handle_.release(),
[email protected]df4b4ef2010-07-12 18:25:21150 socks_params_->destination()));
[email protected]a796bcec2010-03-22 17:17:26151 } else {
[email protected]ab739042011-04-07 15:22:28152 socket_.reset(new SOCKSClientSocket(transport_socket_handle_.release(),
[email protected]df4b4ef2010-07-12 18:25:21153 socks_params_->destination(),
[email protected]a796bcec2010-03-22 17:17:26154 resolver_));
155 }
[email protected]a2006ece2010-04-23 16:44:02156 return socket_->Connect(&callback_);
[email protected]a796bcec2010-03-22 17:17:26157}
158
159int SOCKSConnectJob::DoSOCKSConnectComplete(int result) {
160 if (result != OK) {
161 socket_->Disconnect();
162 return result;
163 }
164
165 set_socket(socket_.release());
166 return result;
167}
168
[email protected]ad74a592011-01-21 18:40:55169int SOCKSConnectJob::ConnectInternal() {
[email protected]ab739042011-04-07 15:22:28170 next_state_ = STATE_TRANSPORT_CONNECT;
[email protected]ad74a592011-01-21 18:40:55171 return DoLoop(OK);
172}
173
[email protected]a796bcec2010-03-22 17:17:26174ConnectJob* SOCKSClientSocketPool::SOCKSConnectJobFactory::NewConnectJob(
175 const std::string& group_name,
176 const PoolBase::Request& request,
[email protected]06650c52010-06-03 00:49:17177 ConnectJob::Delegate* delegate) const {
[email protected]ab739042011-04-07 15:22:28178 return new SOCKSConnectJob(group_name,
179 request.params(),
180 ConnectionTimeout(),
181 transport_pool_,
182 host_resolver_,
183 delegate,
184 net_log_);
[email protected]a796bcec2010-03-22 17:17:26185}
186
187base::TimeDelta
188SOCKSClientSocketPool::SOCKSConnectJobFactory::ConnectionTimeout() const {
[email protected]ab739042011-04-07 15:22:28189 return transport_pool_->ConnectionTimeout() +
[email protected]a796bcec2010-03-22 17:17:26190 base::TimeDelta::FromSeconds(kSOCKSConnectJobTimeoutInSeconds);
191}
192
193SOCKSClientSocketPool::SOCKSClientSocketPool(
194 int max_sockets,
195 int max_sockets_per_group,
[email protected]2431756e2010-09-29 20:26:13196 ClientSocketPoolHistograms* histograms,
[email protected]73c45322010-10-01 23:57:54197 HostResolver* host_resolver,
[email protected]ab739042011-04-07 15:22:28198 TransportClientSocketPool* transport_pool,
[email protected]06650c52010-06-03 00:49:17199 NetLog* net_log)
[email protected]ab739042011-04-07 15:22:28200 : transport_pool_(transport_pool),
[email protected]ba00b492010-09-08 14:53:38201 base_(max_sockets, max_sockets_per_group, histograms,
[email protected]82b8c962011-10-12 09:17:30202 ClientSocketPool::unused_idle_socket_timeout(),
203 ClientSocketPool::used_idle_socket_timeout(),
[email protected]ab739042011-04-07 15:22:28204 new SOCKSConnectJobFactory(transport_pool,
205 host_resolver,
206 net_log)) {
[email protected]66761b952010-06-25 21:30:38207}
[email protected]a796bcec2010-03-22 17:17:26208
209SOCKSClientSocketPool::~SOCKSClientSocketPool() {}
210
[email protected]df4b4ef2010-07-12 18:25:21211int SOCKSClientSocketPool::RequestSocket(const std::string& group_name,
212 const void* socket_params,
213 RequestPriority priority,
214 ClientSocketHandle* handle,
[email protected]f1f3f0f82011-10-01 20:38:10215 OldCompletionCallback* callback,
[email protected]df4b4ef2010-07-12 18:25:21216 const BoundNetLog& net_log) {
217 const scoped_refptr<SOCKSSocketParams>* casted_socket_params =
218 static_cast<const scoped_refptr<SOCKSSocketParams>*>(socket_params);
[email protected]a796bcec2010-03-22 17:17:26219
220 return base_.RequestSocket(group_name, *casted_socket_params, priority,
221 handle, callback, net_log);
222}
223
[email protected]2c2bef152010-10-13 00:55:03224void SOCKSClientSocketPool::RequestSockets(
225 const std::string& group_name,
226 const void* params,
227 int num_sockets,
228 const BoundNetLog& net_log) {
229 const scoped_refptr<SOCKSSocketParams>* casted_params =
230 static_cast<const scoped_refptr<SOCKSSocketParams>*>(params);
231
232 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
233}
234
[email protected]df4b4ef2010-07-12 18:25:21235void SOCKSClientSocketPool::CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21236 ClientSocketHandle* handle) {
[email protected]a796bcec2010-03-22 17:17:26237 base_.CancelRequest(group_name, handle);
238}
239
[email protected]df4b4ef2010-07-12 18:25:21240void SOCKSClientSocketPool::ReleaseSocket(const std::string& group_name,
[email protected]3268023f2011-05-05 00:08:10241 StreamSocket* socket, int id) {
[email protected]a7e38572010-06-07 18:22:24242 base_.ReleaseSocket(group_name, socket, id);
243}
244
245void SOCKSClientSocketPool::Flush() {
246 base_.Flush();
[email protected]a796bcec2010-03-22 17:17:26247}
248
249void SOCKSClientSocketPool::CloseIdleSockets() {
250 base_.CloseIdleSockets();
251}
252
[email protected]7cf40912010-12-09 18:25:03253int SOCKSClientSocketPool::IdleSocketCount() const {
254 return base_.idle_socket_count();
255}
256
[email protected]a796bcec2010-03-22 17:17:26257int SOCKSClientSocketPool::IdleSocketCountInGroup(
258 const std::string& group_name) const {
259 return base_.IdleSocketCountInGroup(group_name);
260}
261
262LoadState SOCKSClientSocketPool::GetLoadState(
263 const std::string& group_name, const ClientSocketHandle* handle) const {
264 return base_.GetLoadState(group_name, handle);
265}
266
[email protected]ba00b492010-09-08 14:53:38267DictionaryValue* SOCKSClientSocketPool::GetInfoAsValue(
268 const std::string& name,
269 const std::string& type,
270 bool include_nested_pools) const {
271 DictionaryValue* dict = base_.GetInfoAsValue(name, type);
272 if (include_nested_pools) {
273 ListValue* list = new ListValue();
[email protected]ab739042011-04-07 15:22:28274 list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool",
275 "transport_socket_pool",
276 false));
[email protected]ba00b492010-09-08 14:53:38277 dict->Set("nested_pools", list);
278 }
279 return dict;
280}
281
[email protected]7cf40912010-12-09 18:25:03282base::TimeDelta SOCKSClientSocketPool::ConnectionTimeout() const {
283 return base_.ConnectionTimeout();
284}
285
286ClientSocketPoolHistograms* SOCKSClientSocketPool::histograms() const {
287 return base_.histograms();
288};
289
[email protected]a796bcec2010-03-22 17:17:26290} // namespace net