| // 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 <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_export.h" |
| #include "net/base/network_anonymization_key.h" |
| #include "net/base/request_priority.h" |
| #include "net/dns/public/resolve_error_info.h" |
| #include "net/http/http_auth.h" |
| #include "net/quic/quic_chromium_client_session.h" |
| #include "net/socket/connect_job.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 QuicStreamRequest; |
| |
| // 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 or QUIC proxy, |
| // |ssl_params| must be set. |
| class NET_EXPORT_PRIVATE HttpProxySocketParams |
| : public base::RefCounted<HttpProxySocketParams> { |
| public: |
| HttpProxySocketParams( |
| scoped_refptr<TransportSocketParams> transport_params, |
| scoped_refptr<SSLSocketParams> ssl_params, |
| bool is_quic, |
| const HostPortPair& endpoint, |
| bool tunnel, |
| const NetworkTrafficAnnotationTag traffic_annotation, |
| const NetworkAnonymizationKey& network_anonymization_key); |
| |
| HttpProxySocketParams(const HttpProxySocketParams&) = delete; |
| HttpProxySocketParams& operator=(const HttpProxySocketParams&) = delete; |
| |
| const scoped_refptr<TransportSocketParams>& transport_params() const { |
| return transport_params_; |
| } |
| const scoped_refptr<SSLSocketParams>& ssl_params() const { |
| return ssl_params_; |
| } |
| bool is_quic() const { return is_quic_; } |
| const HostPortPair& endpoint() const { return endpoint_; } |
| bool tunnel() const { return tunnel_; } |
| const NetworkAnonymizationKey& network_anonymization_key() const { |
| return network_anonymization_key_; |
| } |
| const NetworkTrafficAnnotationTag traffic_annotation() const { |
| return traffic_annotation_; |
| } |
| |
| private: |
| friend class base::RefCounted<HttpProxySocketParams>; |
| ~HttpProxySocketParams(); |
| |
| const scoped_refptr<TransportSocketParams> transport_params_; |
| const scoped_refptr<SSLSocketParams> ssl_params_; |
| bool is_quic_; |
| const HostPortPair endpoint_; |
| const bool tunnel_; |
| const NetworkAnonymizationKey network_anonymization_key_; |
| const NetworkTrafficAnnotationTag traffic_annotation_; |
| }; |
| |
| // 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; |
| |
| // 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(); |
| |
| 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<QuicStreamRequest> quic_stream_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_ |