1 // Copyright 2019 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_ 6 #define NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_ 7 8 #include <memory> 9 #include <string> 10 11 #include "base/functional/callback_forward.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/time/time.h" 14 #include "net/base/host_port_pair.h" 15 #include "net/base/net_export.h" 16 #include "net/base/network_anonymization_key.h" 17 #include "net/base/request_priority.h" 18 #include "net/dns/public/resolve_error_info.h" 19 #include "net/http/http_auth.h" 20 #include "net/quic/quic_chromium_client_session.h" 21 #include "net/socket/connect_job.h" 22 #include "net/socket/ssl_client_socket.h" 23 #include "net/spdy/spdy_session_key.h" 24 #include "net/ssl/ssl_cert_request_info.h" 25 #include "net/traffic_annotation/network_traffic_annotation.h" 26 27 namespace net { 28 29 class HttpAuthController; 30 class HttpResponseInfo; 31 class NetworkQualityEstimator; 32 class SocketTag; 33 class ProxyClientSocket; 34 class SpdyStreamRequest; 35 class SSLSocketParams; 36 class TransportSocketParams; 37 class QuicStreamRequest; 38 39 // HttpProxySocketParams only needs the socket params for one of the proxy 40 // types. The other param must be NULL. When using an HTTP proxy, 41 // |transport_params| must be set. When using an HTTPS proxy or QUIC proxy, 42 // |ssl_params| must be set. 43 class NET_EXPORT_PRIVATE HttpProxySocketParams 44 : public base::RefCounted<HttpProxySocketParams> { 45 public: 46 HttpProxySocketParams( 47 scoped_refptr<TransportSocketParams> transport_params, 48 scoped_refptr<SSLSocketParams> ssl_params, 49 bool is_quic, 50 const HostPortPair& endpoint, 51 bool tunnel, 52 const NetworkTrafficAnnotationTag traffic_annotation, 53 const NetworkAnonymizationKey& network_anonymization_key); 54 55 HttpProxySocketParams(const HttpProxySocketParams&) = delete; 56 HttpProxySocketParams& operator=(const HttpProxySocketParams&) = delete; 57 transport_params()58 const scoped_refptr<TransportSocketParams>& transport_params() const { 59 return transport_params_; 60 } ssl_params()61 const scoped_refptr<SSLSocketParams>& ssl_params() const { 62 return ssl_params_; 63 } is_quic()64 bool is_quic() const { return is_quic_; } endpoint()65 const HostPortPair& endpoint() const { return endpoint_; } tunnel()66 bool tunnel() const { return tunnel_; } network_anonymization_key()67 const NetworkAnonymizationKey& network_anonymization_key() const { 68 return network_anonymization_key_; 69 } traffic_annotation()70 const NetworkTrafficAnnotationTag traffic_annotation() const { 71 return traffic_annotation_; 72 } 73 74 private: 75 friend class base::RefCounted<HttpProxySocketParams>; 76 ~HttpProxySocketParams(); 77 78 const scoped_refptr<TransportSocketParams> transport_params_; 79 const scoped_refptr<SSLSocketParams> ssl_params_; 80 bool is_quic_; 81 const HostPortPair endpoint_; 82 const bool tunnel_; 83 const NetworkAnonymizationKey network_anonymization_key_; 84 const NetworkTrafficAnnotationTag traffic_annotation_; 85 }; 86 87 // HttpProxyConnectJob optionally establishes a tunnel through the proxy 88 // server after connecting the underlying transport socket. 89 class NET_EXPORT_PRIVATE HttpProxyConnectJob : public ConnectJob, 90 public ConnectJob::Delegate { 91 public: 92 class NET_EXPORT_PRIVATE Factory { 93 public: 94 Factory() = default; 95 virtual ~Factory() = default; 96 97 virtual std::unique_ptr<HttpProxyConnectJob> Create( 98 RequestPriority priority, 99 const SocketTag& socket_tag, 100 const CommonConnectJobParams* common_connect_job_params, 101 scoped_refptr<HttpProxySocketParams> params, 102 ConnectJob::Delegate* delegate, 103 const NetLogWithSource* net_log); 104 }; 105 106 HttpProxyConnectJob(RequestPriority priority, 107 const SocketTag& socket_tag, 108 const CommonConnectJobParams* common_connect_job_params, 109 scoped_refptr<HttpProxySocketParams> params, 110 ConnectJob::Delegate* delegate, 111 const NetLogWithSource* net_log); 112 113 HttpProxyConnectJob(const HttpProxyConnectJob&) = delete; 114 HttpProxyConnectJob& operator=(const HttpProxyConnectJob&) = delete; 115 116 ~HttpProxyConnectJob() override; 117 118 // A single priority is used for tunnels over H2 and QUIC, which can be shared 119 // by multiple requests of different priorities either in series (tunnels for 120 // HTTP/1.x requests) or simultaneously (tunnels for H2 requests). Changing 121 // the priority of the tunnel based on the current request also potentially 122 // leaks private data to the proxy. 123 static const RequestPriority kH2QuicTunnelPriority; 124 125 // ConnectJob methods. 126 LoadState GetLoadState() const override; 127 bool HasEstablishedConnection() const override; 128 ResolveErrorInfo GetResolveErrorInfo() const override; 129 bool IsSSLError() const override; 130 scoped_refptr<SSLCertRequestInfo> GetCertRequestInfo() override; 131 132 // ConnectJob::Delegate implementation. 133 void OnConnectJobComplete(int result, ConnectJob* job) override; 134 void OnNeedsProxyAuth(const HttpResponseInfo& response, 135 HttpAuthController* auth_controller, 136 base::OnceClosure restart_with_auth_callback, 137 ConnectJob* job) override; 138 139 // In some cases, a timeout that's stricter than the TCP (+SSL, if applicable) 140 // is used for HTTP proxies during connection establishment and SSL 141 // negotiation for the connection to the proxy itself. In those cases, returns 142 // the connection timeout that will be used by a HttpProxyConnectJob created 143 // with the specified parameters, given current network conditions. Otherwise, 144 // returns base::TimeDelta(). 145 static base::TimeDelta AlternateNestedConnectionTimeout( 146 const HttpProxySocketParams& params, 147 const NetworkQualityEstimator* network_quality_estimator); 148 149 // Returns the timeout for establishing a tunnel after a connection has been 150 // established. 151 static base::TimeDelta TunnelTimeoutForTesting(); 152 153 // Updates the field trial parameters used in calculating timeouts. 154 static void UpdateFieldTrialParametersForTesting(); 155 156 private: 157 enum State { 158 STATE_BEGIN_CONNECT, 159 STATE_TRANSPORT_CONNECT, 160 STATE_TRANSPORT_CONNECT_COMPLETE, 161 STATE_HTTP_PROXY_CONNECT, 162 STATE_HTTP_PROXY_CONNECT_COMPLETE, 163 STATE_SPDY_PROXY_CREATE_STREAM, 164 STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE, 165 STATE_QUIC_PROXY_CREATE_SESSION, 166 STATE_QUIC_PROXY_CREATE_STREAM, 167 STATE_QUIC_PROXY_CREATE_STREAM_COMPLETE, 168 STATE_RESTART_WITH_AUTH, 169 STATE_RESTART_WITH_AUTH_COMPLETE, 170 STATE_NONE, 171 }; 172 173 // Begins the tcp connection and the optional Http proxy tunnel. If the 174 // request is not immediately serviceable (likely), the request will return 175 // ERR_IO_PENDING. An OK return from this function or the callback means 176 // that the connection is established; ERR_PROXY_AUTH_REQUESTED means 177 // that the tunnel needs authentication credentials, the socket will be 178 // returned in this case, and must be released back to the pool; or 179 // a standard net error code will be returned. 180 int ConnectInternal() override; 181 182 ProxyServer::Scheme GetProxyServerScheme() const; 183 184 void OnIOComplete(int result); 185 186 void RestartWithAuthCredentials(); 187 188 // Runs the state transition loop. 189 int DoLoop(int result); 190 191 // Determine if need to go through TCP or SSL path. 192 int DoBeginConnect(); 193 // Connecting to HTTP or HTTPS Proxy 194 int DoTransportConnect(); 195 int DoTransportConnectComplete(int result); 196 197 int DoHttpProxyConnect(); 198 int DoHttpProxyConnectComplete(int result); 199 200 int DoSpdyProxyCreateStream(); 201 int DoSpdyProxyCreateStreamComplete(int result); 202 203 int DoQuicProxyCreateSession(); 204 int DoQuicProxyCreateStream(int result); 205 int DoQuicProxyCreateStreamComplete(int result); 206 207 int DoRestartWithAuth(); 208 int DoRestartWithAuthComplete(int result); 209 210 // ConnectJob implementation. 211 void ChangePriorityInternal(RequestPriority priority) override; 212 void OnTimedOutInternal() override; 213 214 void OnAuthChallenge(); 215 216 const HostPortPair& GetDestination() const; 217 218 std::string GetUserAgent() const; 219 220 SpdySessionKey CreateSpdySessionKey() const; 221 222 scoped_refptr<HttpProxySocketParams> params_; 223 224 scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_; 225 226 State next_state_ = STATE_NONE; 227 228 bool has_restarted_ = false; 229 230 // Set to true once a connection has been successfully established. Remains 231 // true even if a new socket is being connected to retry with auth. 232 bool has_established_connection_ = false; 233 234 ResolveErrorInfo resolve_error_info_; 235 236 std::unique_ptr<ConnectJob> nested_connect_job_; 237 std::unique_ptr<ProxyClientSocket> transport_socket_; 238 239 std::unique_ptr<SpdyStreamRequest> spdy_stream_request_; 240 241 std::unique_ptr<QuicStreamRequest> quic_stream_request_; 242 std::unique_ptr<QuicChromiumClientSession::Handle> quic_session_; 243 244 scoped_refptr<HttpAuthController> http_auth_controller_; 245 246 NetErrorDetails quic_net_error_details_; 247 248 // Time when the connection to the proxy was started. 249 base::TimeTicks connect_start_time_; 250 251 base::WeakPtrFactory<HttpProxyConnectJob> weak_ptr_factory_{this}; 252 }; 253 254 } // namespace net 255 256 #endif // NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_ 257