File: http_proxy_connect_job.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (330 lines) | stat: -rw-r--r-- 12,026 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_
#define NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_

#include <memory>
#include <optional>
#include <set>
#include <string>

#include "base/functional/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/proxy_chain.h"
#include "net/base/request_priority.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_auth.h"
#include "net/quic/quic_chromium_client_session.h"
#include "net/socket/connect_job.h"
#include "net/socket/connect_job_params.h"
#include "net/socket/next_proto.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_session_key.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"

namespace net {

class HttpAuthController;
class HttpResponseInfo;
class NetworkQualityEstimator;
class SocketTag;
class ProxyClientSocket;
class SpdyStreamRequest;
class SSLSocketParams;
class TransportSocketParams;
class QuicSessionRequest;

// HttpProxySocketParams only needs the socket params for one of the proxy
// types.  The other param must be NULL.  When using an HTTP proxy,
// `transport_params` must be set.  When using an HTTPS proxy, `ssl_params` must
// be set. When using a QUIC proxy, both must be `nullptr` but `quic_ssl_config`
// must be set.

class NET_EXPORT_PRIVATE HttpProxySocketParams
    : public base::RefCounted<HttpProxySocketParams> {
 public:
  // Construct an `HttpProxyConnectJob` over a transport or SSL connection
  // defined by the `ConnectJobParams`.
  HttpProxySocketParams(
      ConnectJobParams nested_params,
      const HostPortPair& endpoint,
      const ProxyChain& proxy_chain,
      size_t proxy_chain_index,
      bool tunnel,
      const NetworkTrafficAnnotationTag traffic_annotation,
      const NetworkAnonymizationKey& network_anonymization_key,
      SecureDnsPolicy secure_dns_policy);

  // Construct an `HttpProxyConnectJob` over a QUIC connection using the given
  // SSL config.
  HttpProxySocketParams(
      SSLConfig quic_ssl_config,
      const HostPortPair& endpoint,
      const ProxyChain& proxy_chain,
      size_t proxy_chain_index,
      bool tunnel,
      const NetworkTrafficAnnotationTag traffic_annotation,
      const NetworkAnonymizationKey& network_anonymization_key,
      SecureDnsPolicy secure_dns_policy);

  HttpProxySocketParams(const HttpProxySocketParams&) = delete;
  HttpProxySocketParams& operator=(const HttpProxySocketParams&) = delete;

  bool is_over_transport() const {
    return nested_params_ && nested_params_->is_transport();
  }
  bool is_over_ssl() const {
    return nested_params_ && nested_params_->is_ssl();
  }
  bool is_over_quic() const { return quic_ssl_config_.has_value(); }

  // Get the nested transport params, or fail if not `is_over_transport()`.
  const scoped_refptr<TransportSocketParams>& transport_params() const {
    return nested_params_->transport();
  }

  // Get the nested SSL params, or fail if not `is_over_ssl()`.
  const scoped_refptr<SSLSocketParams>& ssl_params() const {
    return nested_params_->ssl();
  }

  // Get the QUIC ssl config, or fail if not `is_over_quic()`.
  const std::optional<SSLConfig>& quic_ssl_config() const {
    return quic_ssl_config_;
  }

  const HostPortPair& endpoint() const { return endpoint_; }
  const ProxyChain& proxy_chain() const { return proxy_chain_; }
  const ProxyServer& proxy_server() const {
    return proxy_chain_.GetProxyServer(proxy_chain_index_);
  }
  size_t proxy_chain_index() const { return proxy_chain_index_; }
  bool tunnel() const { return tunnel_; }
  const NetworkAnonymizationKey& network_anonymization_key() const {
    return network_anonymization_key_;
  }
  const NetworkTrafficAnnotationTag traffic_annotation() const {
    return traffic_annotation_;
  }
  SecureDnsPolicy secure_dns_policy() { return secure_dns_policy_; }

 private:
  friend class base::RefCounted<HttpProxySocketParams>;
  HttpProxySocketParams(
      std::optional<ConnectJobParams> nested_params,
      std::optional<SSLConfig> quic_ssl_config,
      const HostPortPair& endpoint,
      const ProxyChain& proxy_chain,
      size_t proxy_chain_index,
      bool tunnel,
      const NetworkTrafficAnnotationTag traffic_annotation,
      const NetworkAnonymizationKey& network_anonymization_key,
      SecureDnsPolicy secure_dns_policy);
  ~HttpProxySocketParams();

  const std::optional<ConnectJobParams> nested_params_;
  const std::optional<SSLConfig> quic_ssl_config_;
  const HostPortPair endpoint_;
  const ProxyChain proxy_chain_;
  const size_t proxy_chain_index_;
  const bool tunnel_;
  const NetworkAnonymizationKey network_anonymization_key_;
  const NetworkTrafficAnnotationTag traffic_annotation_;
  const SecureDnsPolicy secure_dns_policy_;
};

// HttpProxyConnectJob optionally establishes a tunnel through the proxy
// server after connecting the underlying transport socket.
class NET_EXPORT_PRIVATE HttpProxyConnectJob : public ConnectJob,
                                               public ConnectJob::Delegate {
 public:
  class NET_EXPORT_PRIVATE Factory {
   public:
    Factory() = default;
    virtual ~Factory() = default;

    virtual std::unique_ptr<HttpProxyConnectJob> Create(
        RequestPriority priority,
        const SocketTag& socket_tag,
        const CommonConnectJobParams* common_connect_job_params,
        scoped_refptr<HttpProxySocketParams> params,
        ConnectJob::Delegate* delegate,
        const NetLogWithSource* net_log);
  };

  HttpProxyConnectJob(RequestPriority priority,
                      const SocketTag& socket_tag,
                      const CommonConnectJobParams* common_connect_job_params,
                      scoped_refptr<HttpProxySocketParams> params,
                      ConnectJob::Delegate* delegate,
                      const NetLogWithSource* net_log);

  HttpProxyConnectJob(const HttpProxyConnectJob&) = delete;
  HttpProxyConnectJob& operator=(const HttpProxyConnectJob&) = delete;

  ~HttpProxyConnectJob() override;

  // A single priority is used for tunnels over H2 and QUIC, which can be shared
  // by multiple requests of different priorities either in series (tunnels for
  // HTTP/1.x requests) or simultaneously (tunnels for H2 requests). Changing
  // the priority of the tunnel based on the current request also potentially
  // leaks private data to the proxy.
  static const RequestPriority kH2QuicTunnelPriority;

  // ConnectJob methods.
  LoadState GetLoadState() const override;
  bool HasEstablishedConnection() const override;
  ResolveErrorInfo GetResolveErrorInfo() const override;
  bool IsSSLError() const override;
  scoped_refptr<SSLCertRequestInfo> GetCertRequestInfo() override;

  // ConnectJob::Delegate implementation.
  void OnConnectJobComplete(int result, ConnectJob* job) override;
  void OnNeedsProxyAuth(const HttpResponseInfo& response,
                        HttpAuthController* auth_controller,
                        base::OnceClosure restart_with_auth_callback,
                        ConnectJob* job) override;
  Error OnDestinationDnsAliasesResolved(const std::set<std::string>& aliases,
                                        ConnectJob* job) override;

  // In some cases, a timeout that's stricter than the TCP (+SSL, if applicable)
  // is used for HTTP proxies during connection establishment and SSL
  // negotiation for the connection to the proxy itself. In those cases, returns
  // the connection timeout that will be used by a HttpProxyConnectJob created
  // with the specified parameters, given current network conditions. Otherwise,
  // returns base::TimeDelta().
  static base::TimeDelta AlternateNestedConnectionTimeout(
      const HttpProxySocketParams& params,
      const NetworkQualityEstimator* network_quality_estimator);

  // Returns the timeout for establishing a tunnel after a connection has been
  // established.
  static base::TimeDelta TunnelTimeoutForTesting();

  // Updates the field trial parameters used in calculating timeouts.
  static void UpdateFieldTrialParametersForTesting();

  enum class HttpConnectResult {
    kSuccess,
    kError,
    kTimedOut,
  };

  // Emit a Net.HttpProxy.ConnectLatency.* metric. This is used both by this
  // class and by QuicSessionPool, which handles QUIC tunnels which will carry
  // QUIC.
  static void EmitConnectLatency(NextProto http_version,
                                 ProxyServer::Scheme scheme,
                                 HttpConnectResult result,
                                 base::TimeDelta latency);

 private:
  enum State {
    STATE_BEGIN_CONNECT,
    STATE_TRANSPORT_CONNECT,
    STATE_TRANSPORT_CONNECT_COMPLETE,
    STATE_HTTP_PROXY_CONNECT,
    STATE_HTTP_PROXY_CONNECT_COMPLETE,
    STATE_SPDY_PROXY_CREATE_STREAM,
    STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE,
    STATE_QUIC_PROXY_CREATE_SESSION,
    STATE_QUIC_PROXY_CREATE_STREAM,
    STATE_QUIC_PROXY_CREATE_STREAM_COMPLETE,
    STATE_RESTART_WITH_AUTH,
    STATE_RESTART_WITH_AUTH_COMPLETE,
    STATE_NONE,
  };

  // Begins the tcp connection and the optional Http proxy tunnel.  If the
  // request is not immediately serviceable (likely), the request will return
  // ERR_IO_PENDING. An OK return from this function or the callback means
  // that the connection is established; ERR_PROXY_AUTH_REQUESTED means
  // that the tunnel needs authentication credentials, the socket will be
  // returned in this case, and must be released back to the pool; or
  // a standard net error code will be returned.
  int ConnectInternal() override;

  ProxyServer::Scheme GetProxyServerScheme() const;

  void OnIOComplete(int result);

  void RestartWithAuthCredentials();

  // Runs the state transition loop.
  int DoLoop(int result);

  // Determine if need to go through TCP or SSL path.
  int DoBeginConnect();
  // Connecting to HTTP or HTTPS Proxy
  int DoTransportConnect();
  int DoTransportConnectComplete(int result);

  int DoHttpProxyConnect();
  int DoHttpProxyConnectComplete(int result);

  int DoSpdyProxyCreateStream();
  int DoSpdyProxyCreateStreamComplete(int result);

  int DoQuicProxyCreateSession();
  int DoQuicProxyCreateStream(int result);
  int DoQuicProxyCreateStreamComplete(int result);

  int DoRestartWithAuth();
  int DoRestartWithAuthComplete(int result);

  // ConnectJob implementation.
  void ChangePriorityInternal(RequestPriority priority) override;
  void OnTimedOutInternal() override;

  void OnAuthChallenge();

  const HostPortPair& GetDestination() const;

  std::string GetUserAgent() const;

  SpdySessionKey CreateSpdySessionKey() const;

  scoped_refptr<HttpProxySocketParams> params_;

  scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_;

  State next_state_ = STATE_NONE;

  bool has_restarted_ = false;

  // Set to true once a connection has been successfully established. Remains
  // true even if a new socket is being connected to retry with auth.
  bool has_established_connection_ = false;

  ResolveErrorInfo resolve_error_info_;

  std::unique_ptr<ConnectJob> nested_connect_job_;
  std::unique_ptr<ProxyClientSocket> transport_socket_;

  std::unique_ptr<SpdyStreamRequest> spdy_stream_request_;

  std::unique_ptr<QuicSessionRequest> quic_session_request_;
  std::unique_ptr<QuicChromiumClientSession::Handle> quic_session_;

  scoped_refptr<HttpAuthController> http_auth_controller_;

  NetErrorDetails quic_net_error_details_;

  // Time when the connection to the proxy was started.
  base::TimeTicks connect_start_time_;

  base::WeakPtrFactory<HttpProxyConnectJob> weak_ptr_factory_{this};
};

}  // namespace net

#endif  // NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_