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