1 // Copyright 2016 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_STREAM_FACTORY_JOB_CONTROLLER_H_ 6 #define NET_HTTP_HTTP_STREAM_FACTORY_JOB_CONTROLLER_H_ 7 8 #include <memory> 9 #include <string> 10 11 #include "base/cancelable_callback.h" 12 #include "base/memory/raw_ptr.h" 13 #include "base/time/time.h" 14 #include "net/base/host_port_pair.h" 15 #include "net/base/net_errors.h" 16 #include "net/base/privacy_mode.h" 17 #include "net/http/http_stream_factory_job.h" 18 #include "net/http/http_stream_request.h" 19 #include "net/socket/next_proto.h" 20 #include "net/spdy/spdy_session_pool.h" 21 22 namespace net { 23 24 class ProxyResolutionRequest; 25 26 namespace test { 27 28 class JobControllerPeer; 29 30 } // namespace test 31 32 // HttpStreamFactory::JobController manages Request and Job(s). 33 class HttpStreamFactory::JobController 34 : public HttpStreamFactory::Job::Delegate, 35 public HttpStreamRequest::Helper { 36 public: 37 JobController(HttpStreamFactory* factory, 38 HttpStreamRequest::Delegate* delegate, 39 HttpNetworkSession* session, 40 JobFactory* job_factory, 41 const HttpRequestInfo& request_info, 42 bool is_preconnect, 43 bool is_websocket, 44 bool enable_ip_based_pooling, 45 bool enable_alternative_services, 46 bool delay_main_job_with_available_spdy_session, 47 const SSLConfig& server_ssl_config, 48 const SSLConfig& proxy_ssl_config); 49 50 ~JobController() override; 51 52 // Used in tests only for verification purpose. main_job()53 const Job* main_job() const { return main_job_.get(); } alternative_job()54 const Job* alternative_job() const { return alternative_job_.get(); } dns_alpn_h3_job()55 const Job* dns_alpn_h3_job() const { return dns_alpn_h3_job_.get(); } 56 57 void RewriteUrlWithHostMappingRules(GURL& url); 58 59 // Methods below are called by HttpStreamFactory only. 60 // Creates request and hands out to HttpStreamFactory, this will also create 61 // Job(s) and start serving the created request. 62 std::unique_ptr<HttpStreamRequest> Start( 63 HttpStreamRequest::Delegate* delegate, 64 WebSocketHandshakeStreamBase::CreateHelper* 65 websocket_handshake_stream_create_helper, 66 const NetLogWithSource& source_net_log, 67 HttpStreamRequest::StreamType stream_type, 68 RequestPriority priority); 69 70 void Preconnect(int num_streams); 71 72 // From HttpStreamRequest::Helper. 73 // Returns the LoadState for Request. 74 LoadState GetLoadState() const override; 75 76 // Called when Request is destructed. Job(s) associated with but not bound to 77 // |request_| will be deleted. |request_| and |bound_job_| will be nulled if 78 // ever set. 79 void OnRequestComplete() override; 80 81 // Called to resume the HttpStream creation process when necessary 82 // Proxy authentication credentials are collected. 83 int RestartTunnelWithProxyAuth() override; 84 85 // Called when the priority of transaction changes. 86 void SetPriority(RequestPriority priority) override; 87 88 // From HttpStreamFactory::Job::Delegate. 89 // Invoked when |job| has an HttpStream ready. 90 void OnStreamReady(Job* job, const SSLConfig& used_ssl_config) override; 91 92 // Invoked when |job| has a BidirectionalStream ready. 93 void OnBidirectionalStreamImplReady( 94 Job* job, 95 const SSLConfig& used_ssl_config, 96 const ProxyInfo& used_proxy_info) override; 97 98 // Invoked when |job| has a WebSocketHandshakeStream ready. 99 void OnWebSocketHandshakeStreamReady( 100 Job* job, 101 const SSLConfig& used_ssl_config, 102 const ProxyInfo& used_proxy_info, 103 std::unique_ptr<WebSocketHandshakeStreamBase> stream) override; 104 105 // Invoked when |job| fails to create a stream. 106 void OnStreamFailed(Job* job, 107 int status, 108 const SSLConfig& used_ssl_config) override; 109 110 // Invoked when |job| fails on the default network. 111 void OnFailedOnDefaultNetwork(Job* job) override; 112 113 // Invoked when |job| has a certificate error for the Request. 114 void OnCertificateError(Job* job, 115 int status, 116 const SSLConfig& used_ssl_config, 117 const SSLInfo& ssl_info) override; 118 119 // Invoked when |job| raises failure for SSL Client Auth. 120 void OnNeedsClientAuth(Job* job, 121 const SSLConfig& used_ssl_config, 122 SSLCertRequestInfo* cert_info) override; 123 124 // Invoked when |job| needs proxy authentication. 125 void OnNeedsProxyAuth(Job* job, 126 const HttpResponseInfo& proxy_response, 127 const SSLConfig& used_ssl_config, 128 const ProxyInfo& used_proxy_info, 129 HttpAuthController* auth_controller) override; 130 131 // Invoked when the |job| finishes pre-connecting sockets. 132 void OnPreconnectsComplete(Job* job, int result) override; 133 134 // Invoked to record connection attempts made by the socket layer to 135 // Request if |job| is associated with Request. 136 void AddConnectionAttemptsToRequest( 137 Job* job, 138 const ConnectionAttempts& attempts) override; 139 140 // Invoked when |job| finishes initiating a connection. 141 // Resume the other job if there's an error raised. 142 void OnConnectionInitialized(Job* job, int rv) override; 143 144 // Return false if |job| can advance to the next state. Otherwise, |job| 145 // will wait for Job::Resume() to be called before advancing. 146 bool ShouldWait(Job* job) override; 147 148 const NetLogWithSource* GetNetLog() const override; 149 150 void MaybeSetWaitTimeForMainJob(const base::TimeDelta& delay) override; 151 152 WebSocketHandshakeStreamBase::CreateHelper* 153 websocket_handshake_stream_create_helper() override; 154 is_preconnect()155 bool is_preconnect() const { return is_preconnect_; } 156 157 // Returns true if |this| has a pending request that is not completed. HasPendingRequest()158 bool HasPendingRequest() const { return request_ != nullptr; } 159 160 // Returns true if |this| has a pending main job that is not completed. 161 bool HasPendingMainJob() const; 162 163 // Returns true if |this| has a pending alternative job that is not completed. 164 bool HasPendingAltJob() const; 165 get_main_job_wait_time_for_tests()166 base::TimeDelta get_main_job_wait_time_for_tests() { 167 return main_job_wait_time_; 168 } 169 170 private: 171 friend class test::JobControllerPeer; 172 173 enum State { 174 STATE_RESOLVE_PROXY, 175 STATE_RESOLVE_PROXY_COMPLETE, 176 STATE_CREATE_JOBS, 177 STATE_NONE 178 }; 179 180 void OnIOComplete(int result); 181 void OnResolveProxyError(int error); 182 void RunLoop(int result); 183 int DoLoop(int result); 184 int DoResolveProxy(); 185 int DoResolveProxyComplete(int result); 186 // Creates Job(s) for |request_info_|. Job(s) will be owned by |this|. 187 int DoCreateJobs(); 188 189 // Called to bind |job| to the |request_| and orphan all other jobs that are 190 // still associated with |request_|. 191 void BindJob(Job* job); 192 193 // Called after BindJob() to notify the unbound job that its result should be 194 // ignored by JobController. The unbound job can be canceled or continue until 195 // completion. 196 void OrphanUnboundJob(); 197 198 // Invoked when the orphaned |job| finishes. 199 void OnOrphanedJobComplete(const Job* job); 200 201 // Called when a Job succeeds. 202 void OnJobSucceeded(Job* job); 203 204 // Clears inappropriate jobs before starting them. 205 void ClearInappropriateJobs(); 206 207 // Marks completion of the |request_|. 208 void MarkRequestComplete(Job* job); 209 210 // Called when all Jobs complete. Reports alternative service brokenness to 211 // HttpServerProperties if apply and resets net errors afterwards: 212 // - report broken if the main job has no error and the alternative job has an 213 // error; 214 // - report broken until default network change if the main job has no error, 215 // the alternative job has no error, but the alternative job failed on the 216 // default network. 217 void MaybeReportBrokenAlternativeService( 218 const AlternativeService& alt_service, 219 int alt_job_net_error, 220 bool alt_job_failed_on_default_network, 221 const std::string& histogram_name_for_failure); 222 223 void MaybeNotifyFactoryOfCompletion(); 224 225 void NotifyRequestFailed(int rv); 226 227 // Called to resume the main job with delay. Main job is resumed only when 228 // |alternative_job_| has failed or |main_job_wait_time_| elapsed. 229 void MaybeResumeMainJob(Job* job, const base::TimeDelta& delay); 230 231 // Posts a task to resume the main job after |delay|. 232 void ResumeMainJobLater(const base::TimeDelta& delay); 233 234 // Resumes the main job immediately. 235 void ResumeMainJob(); 236 237 // Reset error status to default value for Jobs: 238 // - reset |main_job_net_error_| and |alternative_job_net_error_| and 239 // |dns_alpn_h3_job_net_error_| to OK; 240 // - reset |alternative_job_failed_on_default_network_| and 241 // |dns_alpn_h3_job_failed_on_default_network_| to false. 242 void ResetErrorStatusForJobs(); 243 244 AlternativeServiceInfo GetAlternativeServiceInfoFor( 245 const HttpRequestInfo& request_info, 246 HttpStreamRequest::Delegate* delegate, 247 HttpStreamRequest::StreamType stream_type); 248 249 AlternativeServiceInfo GetAlternativeServiceInfoInternal( 250 const HttpRequestInfo& request_info, 251 HttpStreamRequest::Delegate* delegate, 252 HttpStreamRequest::StreamType stream_type); 253 254 // Returns the first quic::ParsedQuicVersion that has been advertised in 255 // |advertised_versions| and is supported, following the order of 256 // |advertised_versions|. If no mutually supported version is found, 257 // quic::ParsedQuicVersion::Unsupported() will be returned. 258 quic::ParsedQuicVersion SelectQuicVersion( 259 const quic::ParsedQuicVersionVector& advertised_versions); 260 261 // Records histogram metrics for the usage of alternative protocol. Must be 262 // called when |job| has succeeded and the other job will be orphaned. 263 void ReportAlternateProtocolUsage( 264 AlternateProtocolUsage alternate_protocol_usage, 265 bool is_google_host) const; 266 267 // Returns whether |job| is an orphaned job. 268 bool IsJobOrphaned(Job* job) const; 269 270 // Calculates why Chrome uses a specific transport protocol for HTTP semantics 271 // and returns it as an enum. 272 // This returns ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON as a default value 273 // when the reason is unknown. 274 AlternateProtocolUsage CalculateAlternateProtocolUsage(Job* job) const; 275 276 // Called when a Job encountered a network error that could be resolved by 277 // trying a new proxy configuration. If there is another proxy configuration 278 // to try then this method sets |next_state_| appropriately and returns either 279 // OK or ERR_IO_PENDING depending on whether or not the new proxy 280 // configuration is available synchronously or asynchronously. Otherwise, the 281 // given error code is simply returned. 282 int ReconsiderProxyAfterError(Job* job, int error); 283 284 // Returns true if QUIC is allowed for |host|. 285 bool IsQuicAllowedForHost(const std::string& host); 286 GetJobCount()287 int GetJobCount() const { 288 return (main_job_ ? 1 : 0) + (alternative_job_ ? 1 : 0) + 289 (dns_alpn_h3_job_ ? 1 : 0); 290 } 291 292 raw_ptr<HttpStreamFactory, DanglingUntriaged> factory_; 293 raw_ptr<HttpNetworkSession, DanglingUntriaged> session_; 294 raw_ptr<JobFactory, DanglingUntriaged> job_factory_; 295 296 // Request will be handed out to factory once created. This just keeps an 297 // reference and is safe as |request_| will notify |this| JobController 298 // when it's destructed by calling OnRequestComplete(), which nulls 299 // |request_|. 300 raw_ptr<HttpStreamRequest, DanglingUntriaged> request_ = nullptr; 301 302 const raw_ptr<HttpStreamRequest::Delegate, DanglingUntriaged> delegate_; 303 304 // True if this JobController is used to preconnect streams. 305 const bool is_preconnect_; 306 307 // True if request is for Websocket. 308 const bool is_websocket_; 309 310 // Enable pooling to a SpdySession with matching IP and certificate even if 311 // the SpdySessionKey is different. 312 const bool enable_ip_based_pooling_; 313 314 // Enable using alternative services for the request. If false, the 315 // JobController will only create a |main_job_|. 316 const bool enable_alternative_services_; 317 318 // For normal (non-preconnect) job, |main_job_| is a job waiting to see if 319 // |alternative_job_| or |dns_alpn_h3_job_| can reuse a connection. If both 320 // |alternative_job_| and |dns_alpn_h3_job_| are unable to do so, |this| will 321 // notify |main_job_| to proceed and then race the two jobs. 322 // For preconnect job, |main_job_| is started first, and if it fails with 323 // ERR_DNS_NO_MATCHING_SUPPORTED_ALPN, |preconnect_backup_job_| will be 324 // started. 325 std::unique_ptr<Job> main_job_; 326 std::unique_ptr<Job> alternative_job_; 327 std::unique_ptr<Job> dns_alpn_h3_job_; 328 329 std::unique_ptr<Job> preconnect_backup_job_; 330 331 // The alternative service used by |alternative_job_| 332 // (or by |main_job_| if |is_preconnect_|.) 333 AlternativeServiceInfo alternative_service_info_; 334 335 // Error status used for alternative service brokenness reporting. 336 // Net error code of the main job. Set to OK by default. 337 int main_job_net_error_ = OK; 338 // Net error code of the alternative job. Set to OK by default. 339 int alternative_job_net_error_ = OK; 340 // Set to true if the alternative job failed on the default network. 341 bool alternative_job_failed_on_default_network_ = false; 342 // Net error code of the DNS HTTPS ALPN job. Set to OK by default. 343 int dns_alpn_h3_job_net_error_ = OK; 344 // Set to true if the DNS HTTPS ALPN job failed on the default network. 345 bool dns_alpn_h3_job_failed_on_default_network_ = false; 346 347 // True if a Job has ever been bound to the |request_|. 348 bool job_bound_ = false; 349 350 // True if the main job has to wait for the alternative job: i.e., the main 351 // job must not create a connection until it is resumed. 352 bool main_job_is_blocked_ = false; 353 354 // Handle for cancelling any posted delayed ResumeMainJob() task. 355 base::CancelableOnceClosure resume_main_job_callback_; 356 // True if the main job was blocked and has been resumed in ResumeMainJob(). 357 bool main_job_is_resumed_ = false; 358 359 // If true, delay main job even the request can be sent immediately on an 360 // available SPDY session. 361 bool delay_main_job_with_available_spdy_session_; 362 363 // Waiting time for the main job before it is resumed. 364 base::TimeDelta main_job_wait_time_; 365 366 // At the point where a Job is irrevocably tied to |request_|, we set this. 367 // It will be nulled when the |request_| is finished. 368 raw_ptr<Job, DanglingUntriaged> bound_job_ = nullptr; 369 370 State next_state_ = STATE_RESOLVE_PROXY; 371 std::unique_ptr<ProxyResolutionRequest> proxy_resolve_request_; 372 const HttpRequestInfo request_info_; 373 ProxyInfo proxy_info_; 374 const SSLConfig server_ssl_config_; 375 const SSLConfig proxy_ssl_config_; 376 int num_streams_ = 0; 377 HttpStreamRequest::StreamType stream_type_; 378 RequestPriority priority_ = IDLE; 379 const NetLogWithSource net_log_; 380 381 base::WeakPtrFactory<JobController> ptr_factory_{this}; 382 }; 383 384 } // namespace net 385 386 #endif // NET_HTTP_HTTP_STREAM_FACTORY_JOB_CONTROLLER_H_ 387