blob: 543c2c4ad72103612348315af0255806c1c88697 [file] [log] [blame]
[email protected]e34400c32012-01-24 02:49:331// Copyright (c) 2012 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
dchengc7eeda422015-12-26 03:56:487#include <utility>
8
[email protected]6ecf2b92011-12-15 01:14:529#include "base/bind.h"
10#include "base/bind_helpers.h"
[email protected]f002abb2013-06-28 02:30:2111#include "base/time/time.h"
[email protected]ba00b492010-09-08 14:53:3812#include "base/values.h"
[email protected]a796bcec2010-03-22 17:17:2613#include "net/base/net_errors.h"
14#include "net/socket/client_socket_factory.h"
15#include "net/socket/client_socket_handle.h"
16#include "net/socket/client_socket_pool_base.h"
17#include "net/socket/socks5_client_socket.h"
18#include "net/socket/socks_client_socket.h"
[email protected]ab739042011-04-07 15:22:2819#include "net/socket/transport_client_socket_pool.h"
[email protected]a796bcec2010-03-22 17:17:2620
21namespace net {
22
[email protected]df4b4ef2010-07-12 18:25:2123SOCKSSocketParams::SOCKSSocketParams(
[email protected]ab739042011-04-07 15:22:2824 const scoped_refptr<TransportSocketParams>& proxy_server,
[email protected]df4b4ef2010-07-12 18:25:2125 bool socks_v5,
[email protected]3f6007ab2013-08-22 19:45:3926 const HostPortPair& host_port_pair)
[email protected]ab739042011-04-07 15:22:2827 : transport_params_(proxy_server),
[email protected]5109c1952013-08-20 18:44:1028 destination_(host_port_pair),
[email protected]df4b4ef2010-07-12 18:25:2129 socks_v5_(socks_v5) {
[email protected]90499482013-06-01 00:39:5030 if (transport_params_.get())
[email protected]ab739042011-04-07 15:22:2831 ignore_limits_ = transport_params_->ignore_limits();
[email protected]5acdce12011-03-30 13:00:2032 else
33 ignore_limits_ = false;
[email protected]df4b4ef2010-07-12 18:25:2134}
35
36SOCKSSocketParams::~SOCKSSocketParams() {}
37
[email protected]a796bcec2010-03-22 17:17:2638// SOCKSConnectJobs will time out after this many seconds. Note this is on
39// top of the timeout for the transport socket.
40static const int kSOCKSConnectJobTimeoutInSeconds = 30;
41
42SOCKSConnectJob::SOCKSConnectJob(
43 const std::string& group_name,
[email protected]3f6007ab2013-08-22 19:45:3944 RequestPriority priority,
[email protected]df4b4ef2010-07-12 18:25:2145 const scoped_refptr<SOCKSSocketParams>& socks_params,
[email protected]a796bcec2010-03-22 17:17:2646 const base::TimeDelta& timeout_duration,
[email protected]ab739042011-04-07 15:22:2847 TransportClientSocketPool* transport_pool,
[email protected]73c45322010-10-01 23:57:5448 HostResolver* host_resolver,
[email protected]a796bcec2010-03-22 17:17:2649 Delegate* delegate,
[email protected]06650c52010-06-03 00:49:1750 NetLog* net_log)
[email protected]3f6007ab2013-08-22 19:45:3951 : ConnectJob(group_name, timeout_duration, priority, delegate,
[email protected]06650c52010-06-03 00:49:1752 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
[email protected]a796bcec2010-03-22 17:17:2653 socks_params_(socks_params),
[email protected]ab739042011-04-07 15:22:2854 transport_pool_(transport_pool),
[email protected]a796bcec2010-03-22 17:17:2655 resolver_(host_resolver),
[email protected]aa249b52013-04-30 01:04:3256 callback_(base::Bind(&SOCKSConnectJob::OnIOComplete,
57 base::Unretained(this))) {
[email protected]06650c52010-06-03 00:49:1758}
[email protected]a796bcec2010-03-22 17:17:2659
60SOCKSConnectJob::~SOCKSConnectJob() {
61 // We don't worry about cancelling the tcp socket since the destructor in
[email protected]ab739042011-04-07 15:22:2862 // scoped_ptr<ClientSocketHandle> transport_socket_handle_ will take care of
63 // it.
[email protected]a796bcec2010-03-22 17:17:2664}
65
66LoadState SOCKSConnectJob::GetLoadState() const {
67 switch (next_state_) {
[email protected]ab739042011-04-07 15:22:2868 case STATE_TRANSPORT_CONNECT:
69 case STATE_TRANSPORT_CONNECT_COMPLETE:
70 return transport_socket_handle_->GetLoadState();
[email protected]81854c42010-09-22 03:39:3671 case STATE_SOCKS_CONNECT:
72 case STATE_SOCKS_CONNECT_COMPLETE:
[email protected]a796bcec2010-03-22 17:17:2673 return LOAD_STATE_CONNECTING;
74 default:
75 NOTREACHED();
76 return LOAD_STATE_IDLE;
77 }
78}
79
[email protected]a796bcec2010-03-22 17:17:2680void SOCKSConnectJob::OnIOComplete(int result) {
81 int rv = DoLoop(result);
82 if (rv != ERR_IO_PENDING)
83 NotifyDelegateOfCompletion(rv); // Deletes |this|
84}
85
86int SOCKSConnectJob::DoLoop(int result) {
[email protected]81854c42010-09-22 03:39:3687 DCHECK_NE(next_state_, STATE_NONE);
[email protected]a796bcec2010-03-22 17:17:2688
89 int rv = result;
90 do {
91 State state = next_state_;
[email protected]81854c42010-09-22 03:39:3692 next_state_ = STATE_NONE;
[email protected]a796bcec2010-03-22 17:17:2693 switch (state) {
[email protected]ab739042011-04-07 15:22:2894 case STATE_TRANSPORT_CONNECT:
[email protected]a796bcec2010-03-22 17:17:2695 DCHECK_EQ(OK, rv);
[email protected]ab739042011-04-07 15:22:2896 rv = DoTransportConnect();
[email protected]a796bcec2010-03-22 17:17:2697 break;
[email protected]ab739042011-04-07 15:22:2898 case STATE_TRANSPORT_CONNECT_COMPLETE:
99 rv = DoTransportConnectComplete(rv);
[email protected]a796bcec2010-03-22 17:17:26100 break;
[email protected]81854c42010-09-22 03:39:36101 case STATE_SOCKS_CONNECT:
[email protected]a796bcec2010-03-22 17:17:26102 DCHECK_EQ(OK, rv);
103 rv = DoSOCKSConnect();
104 break;
[email protected]81854c42010-09-22 03:39:36105 case STATE_SOCKS_CONNECT_COMPLETE:
[email protected]a796bcec2010-03-22 17:17:26106 rv = DoSOCKSConnectComplete(rv);
107 break;
108 default:
109 NOTREACHED() << "bad state";
110 rv = ERR_FAILED;
111 break;
112 }
[email protected]81854c42010-09-22 03:39:36113 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
[email protected]a796bcec2010-03-22 17:17:26114
115 return rv;
116}
117
[email protected]ab739042011-04-07 15:22:28118int SOCKSConnectJob::DoTransportConnect() {
119 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
120 transport_socket_handle_.reset(new ClientSocketHandle());
[email protected]5109c1952013-08-20 18:44:10121 return transport_socket_handle_->Init(group_name(),
122 socks_params_->transport_params(),
[email protected]3f6007ab2013-08-22 19:45:39123 priority(),
[email protected]5109c1952013-08-20 18:44:10124 callback_,
125 transport_pool_,
126 net_log());
[email protected]a796bcec2010-03-22 17:17:26127}
128
[email protected]ab739042011-04-07 15:22:28129int SOCKSConnectJob::DoTransportConnectComplete(int result) {
[email protected]a796bcec2010-03-22 17:17:26130 if (result != OK)
[email protected]f7fccee2010-09-16 20:53:01131 return ERR_PROXY_CONNECTION_FAILED;
[email protected]a796bcec2010-03-22 17:17:26132
133 // Reset the timer to just the length of time allowed for SOCKS handshake
134 // so that a fast TCP connection plus a slow SOCKS failure doesn't take
135 // longer to timeout than it should.
136 ResetTimer(base::TimeDelta::FromSeconds(kSOCKSConnectJobTimeoutInSeconds));
[email protected]81854c42010-09-22 03:39:36137 next_state_ = STATE_SOCKS_CONNECT;
[email protected]a796bcec2010-03-22 17:17:26138 return result;
139}
140
141int SOCKSConnectJob::DoSOCKSConnect() {
[email protected]81854c42010-09-22 03:39:36142 next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
[email protected]a796bcec2010-03-22 17:17:26143
144 // Add a SOCKS connection on top of the tcp socket.
[email protected]df4b4ef2010-07-12 18:25:21145 if (socks_params_->is_socks_v5()) {
dchengc7eeda422015-12-26 03:56:48146 socket_.reset(new SOCKS5ClientSocket(std::move(transport_socket_handle_),
[email protected]df4b4ef2010-07-12 18:25:21147 socks_params_->destination()));
[email protected]a796bcec2010-03-22 17:17:26148 } else {
dchengc7eeda422015-12-26 03:56:48149 socket_.reset(new SOCKSClientSocket(std::move(transport_socket_handle_),
[email protected]df4b4ef2010-07-12 18:25:21150 socks_params_->destination(),
dchengc7eeda422015-12-26 03:56:48151 priority(), resolver_));
[email protected]a796bcec2010-03-22 17:17:26152 }
[email protected]83039bb2011-12-09 18:43:55153 return socket_->Connect(
154 base::Bind(&SOCKSConnectJob::OnIOComplete, base::Unretained(this)));
[email protected]a796bcec2010-03-22 17:17:26155}
156
157int SOCKSConnectJob::DoSOCKSConnectComplete(int result) {
158 if (result != OK) {
159 socket_->Disconnect();
160 return result;
161 }
162
dchengc7eeda422015-12-26 03:56:48163 SetSocket(std::move(socket_));
[email protected]a796bcec2010-03-22 17:17:26164 return result;
165}
166
[email protected]ad74a592011-01-21 18:40:55167int SOCKSConnectJob::ConnectInternal() {
[email protected]ab739042011-04-07 15:22:28168 next_state_ = STATE_TRANSPORT_CONNECT;
[email protected]ad74a592011-01-21 18:40:55169 return DoLoop(OK);
170}
171
[email protected]18ccfdb2013-08-15 00:13:44172scoped_ptr<ConnectJob>
173SOCKSClientSocketPool::SOCKSConnectJobFactory::NewConnectJob(
[email protected]a796bcec2010-03-22 17:17:26174 const std::string& group_name,
175 const PoolBase::Request& request,
[email protected]06650c52010-06-03 00:49:17176 ConnectJob::Delegate* delegate) const {
[email protected]18ccfdb2013-08-15 00:13:44177 return scoped_ptr<ConnectJob>(new SOCKSConnectJob(group_name,
[email protected]3f6007ab2013-08-22 19:45:39178 request.priority(),
[email protected]18ccfdb2013-08-15 00:13:44179 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]73c45322010-10-01 23:57:54196 HostResolver* host_resolver,
[email protected]ab739042011-04-07 15:22:28197 TransportClientSocketPool* transport_pool,
[email protected]06650c52010-06-03 00:49:17198 NetLog* net_log)
[email protected]ab739042011-04-07 15:22:28199 : transport_pool_(transport_pool),
rkaplowd90695c2015-03-25 22:12:41200 base_(
201 this,
202 max_sockets,
203 max_sockets_per_group,
204 ClientSocketPool::unused_idle_socket_timeout(),
205 ClientSocketPool::used_idle_socket_timeout(),
206 new SOCKSConnectJobFactory(transport_pool, host_resolver, net_log)) {
[email protected]51fdc7c2012-04-10 19:19:48207 // We should always have a |transport_pool_| except in unit tests.
208 if (transport_pool_)
[email protected]043b68c82013-08-22 23:41:52209 base_.AddLowerLayeredPool(transport_pool_);
[email protected]66761b952010-06-25 21:30:38210}
[email protected]a796bcec2010-03-22 17:17:26211
[email protected]51fdc7c2012-04-10 19:19:48212SOCKSClientSocketPool::~SOCKSClientSocketPool() {
[email protected]51fdc7c2012-04-10 19:19:48213}
[email protected]a796bcec2010-03-22 17:17:26214
[email protected]49639fa2011-12-20 23:22:41215int SOCKSClientSocketPool::RequestSocket(
216 const std::string& group_name, const void* socket_params,
217 RequestPriority priority, ClientSocketHandle* handle,
218 const CompletionCallback& callback, const BoundNetLog& net_log) {
[email protected]df4b4ef2010-07-12 18:25:21219 const scoped_refptr<SOCKSSocketParams>* casted_socket_params =
220 static_cast<const scoped_refptr<SOCKSSocketParams>*>(socket_params);
[email protected]a796bcec2010-03-22 17:17:26221
222 return base_.RequestSocket(group_name, *casted_socket_params, priority,
223 handle, callback, net_log);
224}
225
[email protected]2c2bef152010-10-13 00:55:03226void SOCKSClientSocketPool::RequestSockets(
227 const std::string& group_name,
228 const void* params,
229 int num_sockets,
230 const BoundNetLog& net_log) {
231 const scoped_refptr<SOCKSSocketParams>* casted_params =
232 static_cast<const scoped_refptr<SOCKSSocketParams>*>(params);
233
234 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
235}
236
[email protected]df4b4ef2010-07-12 18:25:21237void SOCKSClientSocketPool::CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21238 ClientSocketHandle* handle) {
[email protected]a796bcec2010-03-22 17:17:26239 base_.CancelRequest(group_name, handle);
240}
241
[email protected]df4b4ef2010-07-12 18:25:21242void SOCKSClientSocketPool::ReleaseSocket(const std::string& group_name,
[email protected]18ccfdb2013-08-15 00:13:44243 scoped_ptr<StreamSocket> socket,
244 int id) {
dchengc7eeda422015-12-26 03:56:48245 base_.ReleaseSocket(group_name, std::move(socket), id);
[email protected]a7e38572010-06-07 18:22:24246}
247
[email protected]7af985a2012-12-14 22:40:42248void SOCKSClientSocketPool::FlushWithError(int error) {
249 base_.FlushWithError(error);
[email protected]a796bcec2010-03-22 17:17:26250}
251
252void SOCKSClientSocketPool::CloseIdleSockets() {
253 base_.CloseIdleSockets();
254}
255
[email protected]7cf40912010-12-09 18:25:03256int SOCKSClientSocketPool::IdleSocketCount() const {
257 return base_.idle_socket_count();
258}
259
[email protected]a796bcec2010-03-22 17:17:26260int SOCKSClientSocketPool::IdleSocketCountInGroup(
261 const std::string& group_name) const {
262 return base_.IdleSocketCountInGroup(group_name);
263}
264
265LoadState SOCKSClientSocketPool::GetLoadState(
266 const std::string& group_name, const ClientSocketHandle* handle) const {
267 return base_.GetLoadState(group_name, handle);
268}
269
ketan.goyalf84eda92015-06-03 10:53:36270scoped_ptr<base::DictionaryValue> SOCKSClientSocketPool::GetInfoAsValue(
[email protected]ba00b492010-09-08 14:53:38271 const std::string& name,
272 const std::string& type,
273 bool include_nested_pools) const {
ketan.goyalf84eda92015-06-03 10:53:36274 scoped_ptr<base::DictionaryValue> dict(base_.GetInfoAsValue(name, type));
[email protected]ba00b492010-09-08 14:53:38275 if (include_nested_pools) {
estadedef533b2015-05-07 17:01:21276 scoped_ptr<base::ListValue> list(new base::ListValue());
[email protected]ab739042011-04-07 15:22:28277 list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool",
278 "transport_socket_pool",
279 false));
dchengc7eeda422015-12-26 03:56:48280 dict->Set("nested_pools", std::move(list));
[email protected]ba00b492010-09-08 14:53:38281 }
dchengc7eeda422015-12-26 03:56:48282 return dict;
[email protected]ba00b492010-09-08 14:53:38283}
284
[email protected]7cf40912010-12-09 18:25:03285base::TimeDelta SOCKSClientSocketPool::ConnectionTimeout() const {
286 return base_.ConnectionTimeout();
287}
288
[email protected]043b68c82013-08-22 23:41:52289bool SOCKSClientSocketPool::IsStalled() const {
290 return base_.IsStalled();
291}
292
293void SOCKSClientSocketPool::AddHigherLayeredPool(
294 HigherLayeredPool* higher_pool) {
295 base_.AddHigherLayeredPool(higher_pool);
296}
297
298void SOCKSClientSocketPool::RemoveHigherLayeredPool(
299 HigherLayeredPool* higher_pool) {
300 base_.RemoveHigherLayeredPool(higher_pool);
301}
302
[email protected]51fdc7c2012-04-10 19:19:48303bool SOCKSClientSocketPool::CloseOneIdleConnection() {
304 if (base_.CloseOneIdleSocket())
305 return true;
[email protected]043b68c82013-08-22 23:41:52306 return base_.CloseOneIdleConnectionInHigherLayeredPool();
[email protected]51fdc7c2012-04-10 19:19:48307}
308
[email protected]a796bcec2010-03-22 17:17:26309} // namespace net