xref: /aosp_15_r20/external/cronet/net/socket/socks_connect_job.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/socket/socks_connect_job.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
11*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_source_type.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_with_source.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/socket/client_socket_factory.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/socket/client_socket_handle.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/socket/connect_job_params.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/socket/socks5_client_socket.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/socket/socks_client_socket.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/socket/transport_connect_job.h"
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker namespace net {
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker // SOCKSConnectJobs will time out if the SOCKS handshake takes longer than this.
24*6777b538SAndroid Build Coastguard Worker static constexpr base::TimeDelta kSOCKSConnectJobTimeout = base::Seconds(30);
25*6777b538SAndroid Build Coastguard Worker 
SOCKSSocketParams(ConnectJobParams nested_params,bool socks_v5,const HostPortPair & host_port_pair,const NetworkAnonymizationKey & network_anonymization_key,const NetworkTrafficAnnotationTag & traffic_annotation)26*6777b538SAndroid Build Coastguard Worker SOCKSSocketParams::SOCKSSocketParams(
27*6777b538SAndroid Build Coastguard Worker     ConnectJobParams nested_params,
28*6777b538SAndroid Build Coastguard Worker     bool socks_v5,
29*6777b538SAndroid Build Coastguard Worker     const HostPortPair& host_port_pair,
30*6777b538SAndroid Build Coastguard Worker     const NetworkAnonymizationKey& network_anonymization_key,
31*6777b538SAndroid Build Coastguard Worker     const NetworkTrafficAnnotationTag& traffic_annotation)
32*6777b538SAndroid Build Coastguard Worker     : transport_params_(nested_params.take_transport()),
33*6777b538SAndroid Build Coastguard Worker       destination_(host_port_pair),
34*6777b538SAndroid Build Coastguard Worker       socks_v5_(socks_v5),
35*6777b538SAndroid Build Coastguard Worker       network_anonymization_key_(network_anonymization_key),
36*6777b538SAndroid Build Coastguard Worker       traffic_annotation_(traffic_annotation) {}
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker SOCKSSocketParams::~SOCKSSocketParams() = default;
39*6777b538SAndroid Build Coastguard Worker 
Create(RequestPriority priority,const SocketTag & socket_tag,const CommonConnectJobParams * common_connect_job_params,scoped_refptr<SOCKSSocketParams> socks_params,ConnectJob::Delegate * delegate,const NetLogWithSource * net_log)40*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SOCKSConnectJob> SOCKSConnectJob::Factory::Create(
41*6777b538SAndroid Build Coastguard Worker     RequestPriority priority,
42*6777b538SAndroid Build Coastguard Worker     const SocketTag& socket_tag,
43*6777b538SAndroid Build Coastguard Worker     const CommonConnectJobParams* common_connect_job_params,
44*6777b538SAndroid Build Coastguard Worker     scoped_refptr<SOCKSSocketParams> socks_params,
45*6777b538SAndroid Build Coastguard Worker     ConnectJob::Delegate* delegate,
46*6777b538SAndroid Build Coastguard Worker     const NetLogWithSource* net_log) {
47*6777b538SAndroid Build Coastguard Worker   return std::make_unique<SOCKSConnectJob>(
48*6777b538SAndroid Build Coastguard Worker       priority, socket_tag, common_connect_job_params, std::move(socks_params),
49*6777b538SAndroid Build Coastguard Worker       delegate, net_log);
50*6777b538SAndroid Build Coastguard Worker }
51*6777b538SAndroid Build Coastguard Worker 
SOCKSConnectJob(RequestPriority priority,const SocketTag & socket_tag,const CommonConnectJobParams * common_connect_job_params,scoped_refptr<SOCKSSocketParams> socks_params,ConnectJob::Delegate * delegate,const NetLogWithSource * net_log)52*6777b538SAndroid Build Coastguard Worker SOCKSConnectJob::SOCKSConnectJob(
53*6777b538SAndroid Build Coastguard Worker     RequestPriority priority,
54*6777b538SAndroid Build Coastguard Worker     const SocketTag& socket_tag,
55*6777b538SAndroid Build Coastguard Worker     const CommonConnectJobParams* common_connect_job_params,
56*6777b538SAndroid Build Coastguard Worker     scoped_refptr<SOCKSSocketParams> socks_params,
57*6777b538SAndroid Build Coastguard Worker     ConnectJob::Delegate* delegate,
58*6777b538SAndroid Build Coastguard Worker     const NetLogWithSource* net_log)
59*6777b538SAndroid Build Coastguard Worker     : ConnectJob(priority,
60*6777b538SAndroid Build Coastguard Worker                  socket_tag,
61*6777b538SAndroid Build Coastguard Worker                  base::TimeDelta(),
62*6777b538SAndroid Build Coastguard Worker                  common_connect_job_params,
63*6777b538SAndroid Build Coastguard Worker                  delegate,
64*6777b538SAndroid Build Coastguard Worker                  net_log,
65*6777b538SAndroid Build Coastguard Worker                  NetLogSourceType::SOCKS_CONNECT_JOB,
66*6777b538SAndroid Build Coastguard Worker                  NetLogEventType::SOCKS_CONNECT_JOB_CONNECT),
67*6777b538SAndroid Build Coastguard Worker       socks_params_(std::move(socks_params)) {}
68*6777b538SAndroid Build Coastguard Worker 
~SOCKSConnectJob()69*6777b538SAndroid Build Coastguard Worker SOCKSConnectJob::~SOCKSConnectJob() {
70*6777b538SAndroid Build Coastguard Worker   // In the case the job was canceled, need to delete nested job first to
71*6777b538SAndroid Build Coastguard Worker   // correctly order NetLog events.
72*6777b538SAndroid Build Coastguard Worker   transport_connect_job_.reset();
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker 
GetLoadState() const75*6777b538SAndroid Build Coastguard Worker LoadState SOCKSConnectJob::GetLoadState() const {
76*6777b538SAndroid Build Coastguard Worker   switch (next_state_) {
77*6777b538SAndroid Build Coastguard Worker     case STATE_TRANSPORT_CONNECT:
78*6777b538SAndroid Build Coastguard Worker       return LOAD_STATE_IDLE;
79*6777b538SAndroid Build Coastguard Worker     case STATE_TRANSPORT_CONNECT_COMPLETE:
80*6777b538SAndroid Build Coastguard Worker       return transport_connect_job_->GetLoadState();
81*6777b538SAndroid Build Coastguard Worker     case STATE_SOCKS_CONNECT:
82*6777b538SAndroid Build Coastguard Worker     case STATE_SOCKS_CONNECT_COMPLETE:
83*6777b538SAndroid Build Coastguard Worker       return LOAD_STATE_CONNECTING;
84*6777b538SAndroid Build Coastguard Worker     default:
85*6777b538SAndroid Build Coastguard Worker       NOTREACHED();
86*6777b538SAndroid Build Coastguard Worker       return LOAD_STATE_IDLE;
87*6777b538SAndroid Build Coastguard Worker   }
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker 
HasEstablishedConnection() const90*6777b538SAndroid Build Coastguard Worker bool SOCKSConnectJob::HasEstablishedConnection() const {
91*6777b538SAndroid Build Coastguard Worker   return next_state_ == STATE_SOCKS_CONNECT ||
92*6777b538SAndroid Build Coastguard Worker          next_state_ == STATE_SOCKS_CONNECT_COMPLETE;
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker 
GetResolveErrorInfo() const95*6777b538SAndroid Build Coastguard Worker ResolveErrorInfo SOCKSConnectJob::GetResolveErrorInfo() const {
96*6777b538SAndroid Build Coastguard Worker   return resolve_error_info_;
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker 
HandshakeTimeoutForTesting()99*6777b538SAndroid Build Coastguard Worker base::TimeDelta SOCKSConnectJob::HandshakeTimeoutForTesting() {
100*6777b538SAndroid Build Coastguard Worker   return kSOCKSConnectJobTimeout;
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker 
OnIOComplete(int result)103*6777b538SAndroid Build Coastguard Worker void SOCKSConnectJob::OnIOComplete(int result) {
104*6777b538SAndroid Build Coastguard Worker   int rv = DoLoop(result);
105*6777b538SAndroid Build Coastguard Worker   if (rv != ERR_IO_PENDING)
106*6777b538SAndroid Build Coastguard Worker     NotifyDelegateOfCompletion(rv);  // Deletes |this|
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker 
OnConnectJobComplete(int result,ConnectJob * job)109*6777b538SAndroid Build Coastguard Worker void SOCKSConnectJob::OnConnectJobComplete(int result, ConnectJob* job) {
110*6777b538SAndroid Build Coastguard Worker   DCHECK(transport_connect_job_);
111*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(next_state_, STATE_TRANSPORT_CONNECT_COMPLETE);
112*6777b538SAndroid Build Coastguard Worker   OnIOComplete(result);
113*6777b538SAndroid Build Coastguard Worker }
114*6777b538SAndroid Build Coastguard Worker 
OnNeedsProxyAuth(const HttpResponseInfo & response,HttpAuthController * auth_controller,base::OnceClosure restart_with_auth_callback,ConnectJob * job)115*6777b538SAndroid Build Coastguard Worker void SOCKSConnectJob::OnNeedsProxyAuth(
116*6777b538SAndroid Build Coastguard Worker     const HttpResponseInfo& response,
117*6777b538SAndroid Build Coastguard Worker     HttpAuthController* auth_controller,
118*6777b538SAndroid Build Coastguard Worker     base::OnceClosure restart_with_auth_callback,
119*6777b538SAndroid Build Coastguard Worker     ConnectJob* job) {
120*6777b538SAndroid Build Coastguard Worker   // A SOCKSConnectJob can't be on top of an HttpProxyConnectJob.
121*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker 
DoLoop(int result)124*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoLoop(int result) {
125*6777b538SAndroid Build Coastguard Worker   DCHECK_NE(next_state_, STATE_NONE);
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker   int rv = result;
128*6777b538SAndroid Build Coastguard Worker   do {
129*6777b538SAndroid Build Coastguard Worker     State state = next_state_;
130*6777b538SAndroid Build Coastguard Worker     next_state_ = STATE_NONE;
131*6777b538SAndroid Build Coastguard Worker     switch (state) {
132*6777b538SAndroid Build Coastguard Worker       case STATE_TRANSPORT_CONNECT:
133*6777b538SAndroid Build Coastguard Worker         DCHECK_EQ(OK, rv);
134*6777b538SAndroid Build Coastguard Worker         rv = DoTransportConnect();
135*6777b538SAndroid Build Coastguard Worker         break;
136*6777b538SAndroid Build Coastguard Worker       case STATE_TRANSPORT_CONNECT_COMPLETE:
137*6777b538SAndroid Build Coastguard Worker         rv = DoTransportConnectComplete(rv);
138*6777b538SAndroid Build Coastguard Worker         break;
139*6777b538SAndroid Build Coastguard Worker       case STATE_SOCKS_CONNECT:
140*6777b538SAndroid Build Coastguard Worker         DCHECK_EQ(OK, rv);
141*6777b538SAndroid Build Coastguard Worker         rv = DoSOCKSConnect();
142*6777b538SAndroid Build Coastguard Worker         break;
143*6777b538SAndroid Build Coastguard Worker       case STATE_SOCKS_CONNECT_COMPLETE:
144*6777b538SAndroid Build Coastguard Worker         rv = DoSOCKSConnectComplete(rv);
145*6777b538SAndroid Build Coastguard Worker         break;
146*6777b538SAndroid Build Coastguard Worker       default:
147*6777b538SAndroid Build Coastguard Worker         NOTREACHED() << "bad state";
148*6777b538SAndroid Build Coastguard Worker         rv = ERR_FAILED;
149*6777b538SAndroid Build Coastguard Worker         break;
150*6777b538SAndroid Build Coastguard Worker     }
151*6777b538SAndroid Build Coastguard Worker   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker   return rv;
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker 
DoTransportConnect()156*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoTransportConnect() {
157*6777b538SAndroid Build Coastguard Worker   DCHECK(!transport_connect_job_);
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker   next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
160*6777b538SAndroid Build Coastguard Worker   transport_connect_job_ = std::make_unique<TransportConnectJob>(
161*6777b538SAndroid Build Coastguard Worker       priority(), socket_tag(), common_connect_job_params(),
162*6777b538SAndroid Build Coastguard Worker       socks_params_->transport_params(), this, &net_log());
163*6777b538SAndroid Build Coastguard Worker   return transport_connect_job_->Connect();
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker 
DoTransportConnectComplete(int result)166*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoTransportConnectComplete(int result) {
167*6777b538SAndroid Build Coastguard Worker   resolve_error_info_ = transport_connect_job_->GetResolveErrorInfo();
168*6777b538SAndroid Build Coastguard Worker   if (result != OK)
169*6777b538SAndroid Build Coastguard Worker     return ERR_PROXY_CONNECTION_FAILED;
170*6777b538SAndroid Build Coastguard Worker 
171*6777b538SAndroid Build Coastguard Worker   // Start the timer to time allowed for SOCKS handshake.
172*6777b538SAndroid Build Coastguard Worker   ResetTimer(kSOCKSConnectJobTimeout);
173*6777b538SAndroid Build Coastguard Worker   next_state_ = STATE_SOCKS_CONNECT;
174*6777b538SAndroid Build Coastguard Worker   return result;
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker 
DoSOCKSConnect()177*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoSOCKSConnect() {
178*6777b538SAndroid Build Coastguard Worker   next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker   // Add a SOCKS connection on top of the tcp socket.
181*6777b538SAndroid Build Coastguard Worker   if (socks_params_->is_socks_v5()) {
182*6777b538SAndroid Build Coastguard Worker     socket_ = std::make_unique<SOCKS5ClientSocket>(
183*6777b538SAndroid Build Coastguard Worker         transport_connect_job_->PassSocket(), socks_params_->destination(),
184*6777b538SAndroid Build Coastguard Worker         socks_params_->traffic_annotation());
185*6777b538SAndroid Build Coastguard Worker   } else {
186*6777b538SAndroid Build Coastguard Worker     auto socks_socket = std::make_unique<SOCKSClientSocket>(
187*6777b538SAndroid Build Coastguard Worker         transport_connect_job_->PassSocket(), socks_params_->destination(),
188*6777b538SAndroid Build Coastguard Worker         socks_params_->network_anonymization_key(), priority(), host_resolver(),
189*6777b538SAndroid Build Coastguard Worker         socks_params_->transport_params()->secure_dns_policy(),
190*6777b538SAndroid Build Coastguard Worker         socks_params_->traffic_annotation());
191*6777b538SAndroid Build Coastguard Worker     socks_socket_ptr_ = socks_socket.get();
192*6777b538SAndroid Build Coastguard Worker     socket_ = std::move(socks_socket);
193*6777b538SAndroid Build Coastguard Worker   }
194*6777b538SAndroid Build Coastguard Worker   transport_connect_job_.reset();
195*6777b538SAndroid Build Coastguard Worker   return socket_->Connect(
196*6777b538SAndroid Build Coastguard Worker       base::BindOnce(&SOCKSConnectJob::OnIOComplete, base::Unretained(this)));
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker 
DoSOCKSConnectComplete(int result)199*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::DoSOCKSConnectComplete(int result) {
200*6777b538SAndroid Build Coastguard Worker   if (!socks_params_->is_socks_v5())
201*6777b538SAndroid Build Coastguard Worker     resolve_error_info_ = socks_socket_ptr_->GetResolveErrorInfo();
202*6777b538SAndroid Build Coastguard Worker   if (result != OK) {
203*6777b538SAndroid Build Coastguard Worker     socket_->Disconnect();
204*6777b538SAndroid Build Coastguard Worker     return result;
205*6777b538SAndroid Build Coastguard Worker   }
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker   SetSocket(std::move(socket_), std::nullopt /* dns_aliases */);
208*6777b538SAndroid Build Coastguard Worker   return result;
209*6777b538SAndroid Build Coastguard Worker }
210*6777b538SAndroid Build Coastguard Worker 
ConnectInternal()211*6777b538SAndroid Build Coastguard Worker int SOCKSConnectJob::ConnectInternal() {
212*6777b538SAndroid Build Coastguard Worker   next_state_ = STATE_TRANSPORT_CONNECT;
213*6777b538SAndroid Build Coastguard Worker   return DoLoop(OK);
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker 
ChangePriorityInternal(RequestPriority priority)216*6777b538SAndroid Build Coastguard Worker void SOCKSConnectJob::ChangePriorityInternal(RequestPriority priority) {
217*6777b538SAndroid Build Coastguard Worker   // Currently doesn't change host resolution request priority for SOCKS4 case.
218*6777b538SAndroid Build Coastguard Worker   if (transport_connect_job_)
219*6777b538SAndroid Build Coastguard Worker     transport_connect_job_->ChangePriority(priority);
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker }  // namespace net
223