xref: /aosp_15_r20/external/cronet/net/http/http_stream_factory_job_controller.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #include <vector>
11 
12 #include "base/cancelable_callback.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/time/time.h"
15 #include "net/base/host_port_pair.h"
16 #include "net/base/net_errors.h"
17 #include "net/http/http_stream_factory_job.h"
18 #include "net/http/http_stream_request.h"
19 #include "net/spdy/spdy_session_pool.h"
20 #include "net/ssl/ssl_config.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& http_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 std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs);
48 
49   ~JobController() override;
50 
51   // Used in tests only for verification purpose.
main_job()52   const Job* main_job() const { return main_job_.get(); }
alternative_job()53   const Job* alternative_job() const { return alternative_job_.get(); }
dns_alpn_h3_job()54   const Job* dns_alpn_h3_job() const { return dns_alpn_h3_job_.get(); }
55 
56   // Modifies `url` in-place, applying any applicable HostMappingRules of
57   // `session_` to it.
58   void RewriteUrlWithHostMappingRules(GURL& url) const;
59 
60   // Same as RewriteUrlWithHostMappingRules(), but duplicates `url` instead of
61   // modifying it.
62   GURL DuplicateUrlWithHostMappingRules(const GURL& url) const;
63 
64   // Methods below are called by HttpStreamFactory only.
65   // Creates request and hands out to HttpStreamFactory, this will also create
66   // Job(s) and start serving the created request.
67   std::unique_ptr<HttpStreamRequest> Start(
68       HttpStreamRequest::Delegate* delegate,
69       WebSocketHandshakeStreamBase::CreateHelper*
70           websocket_handshake_stream_create_helper,
71       const NetLogWithSource& source_net_log,
72       HttpStreamRequest::StreamType stream_type,
73       RequestPriority priority);
74 
75   void Preconnect(int num_streams);
76 
77   // From HttpStreamRequest::Helper.
78   // Returns the LoadState for Request.
79   LoadState GetLoadState() const override;
80 
81   // Called when Request is destructed. Job(s) associated with but not bound to
82   // |request_| will be deleted. |request_| and |bound_job_| will be nulled if
83   // ever set.
84   void OnRequestComplete() override;
85 
86   // Called to resume the HttpStream creation process when necessary
87   // Proxy authentication credentials are collected.
88   int RestartTunnelWithProxyAuth() override;
89 
90   // Called when the priority of transaction changes.
91   void SetPriority(RequestPriority priority) override;
92 
93   // From HttpStreamFactory::Job::Delegate.
94   // Invoked when |job| has an HttpStream ready.
95   void OnStreamReady(Job* job) override;
96 
97   // Invoked when |job| has a BidirectionalStream ready.
98   void OnBidirectionalStreamImplReady(
99       Job* job,
100       const ProxyInfo& used_proxy_info) override;
101 
102   // Invoked when |job| has a WebSocketHandshakeStream ready.
103   void OnWebSocketHandshakeStreamReady(
104       Job* job,
105       const ProxyInfo& used_proxy_info,
106       std::unique_ptr<WebSocketHandshakeStreamBase> stream) override;
107 
108   // Invoked when |job| fails to create a stream.
109   void OnStreamFailed(Job* job, int status) override;
110 
111   // Invoked when |job| fails on the default network.
112   void OnFailedOnDefaultNetwork(Job* job) override;
113 
114   // Invoked when |job| has a certificate error for the Request.
115   void OnCertificateError(Job* job,
116                           int status,
117                           const SSLInfo& ssl_info) override;
118 
119   // Invoked when |job| raises failure for SSL Client Auth.
120   void OnNeedsClientAuth(Job* job, SSLCertRequestInfo* cert_info) override;
121 
122   // Invoked when |job| needs proxy authentication.
123   void OnNeedsProxyAuth(Job* job,
124                         const HttpResponseInfo& proxy_response,
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 GURL& http_request_info_url,
243       const StreamRequestInfo& request_info,
244       HttpStreamRequest::Delegate* delegate,
245       HttpStreamRequest::StreamType stream_type);
246 
247   AlternativeServiceInfo GetAlternativeServiceInfoInternal(
248       const GURL& http_request_info_url,
249       const StreamRequestInfo& request_info,
250       HttpStreamRequest::Delegate* delegate,
251       HttpStreamRequest::StreamType stream_type);
252 
253   // Returns the first quic::ParsedQuicVersion that has been advertised in
254   // |advertised_versions| and is supported, following the order of
255   // |advertised_versions|.  If no mutually supported version is found,
256   // quic::ParsedQuicVersion::Unsupported() will be returned.
257   quic::ParsedQuicVersion SelectQuicVersion(
258       const quic::ParsedQuicVersionVector& advertised_versions);
259 
260   // Records histogram metrics for the usage of alternative protocol. Must be
261   // called when |job| has succeeded and the other job will be orphaned.
262   void ReportAlternateProtocolUsage(
263       AlternateProtocolUsage alternate_protocol_usage,
264       bool is_google_host) const;
265 
266   // Returns whether |job| is an orphaned job.
267   bool IsJobOrphaned(Job* job) const;
268 
269   // Calculates why Chrome uses a specific transport protocol for HTTP semantics
270   // and returns it as an enum.
271   // This returns ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON as a default value
272   // when the reason is unknown.
273   AlternateProtocolUsage CalculateAlternateProtocolUsage(Job* job) const;
274 
275   // Called when a Job encountered a network error that could be resolved by
276   // trying a new proxy configuration. If there is another proxy configuration
277   // to try then this method sets |next_state_| appropriately and returns either
278   // OK or ERR_IO_PENDING depending on whether or not the new proxy
279   // configuration is available synchronously or asynchronously.  Otherwise, the
280   // given error code is simply returned.
281   int ReconsiderProxyAfterError(Job* job, int error);
282 
283   // Returns true if QUIC is allowed for |host|.
284   bool IsQuicAllowedForHost(const std::string& host);
285 
GetJobCount()286   int GetJobCount() const {
287     return (main_job_ ? 1 : 0) + (alternative_job_ ? 1 : 0) +
288            (dns_alpn_h3_job_ ? 1 : 0);
289   }
290 
291   raw_ptr<HttpStreamFactory> factory_;
292   raw_ptr<HttpNetworkSession> session_;
293   raw_ptr<JobFactory> job_factory_;
294 
295   // Request will be handed out to factory once created. This just keeps an
296   // reference and is safe as |request_| will notify |this| JobController
297   // when it's destructed by calling OnRequestComplete(), which nulls
298   // |request_|.
299   raw_ptr<HttpStreamRequest> request_ = nullptr;
300 
301   raw_ptr<HttpStreamRequest::Delegate> delegate_;
302 
303   // True if this JobController is used to preconnect streams.
304   const bool is_preconnect_;
305 
306   // True if request is for Websocket.
307   const bool is_websocket_;
308 
309   // Enable pooling to a SpdySession with matching IP and certificate even if
310   // the SpdySessionKey is different.
311   const bool enable_ip_based_pooling_;
312 
313   // Enable using alternative services for the request. If false, the
314   // JobController will only create a |main_job_|.
315   const bool enable_alternative_services_;
316 
317   // For normal (non-preconnect) job, |main_job_| is a job waiting to see if
318   // |alternative_job_| or |dns_alpn_h3_job_| can reuse a connection. If both
319   // |alternative_job_| and |dns_alpn_h3_job_| are unable to do so, |this| will
320   // notify |main_job_| to proceed and then race the two jobs.
321   // For preconnect job, |main_job_| is started first, and if it fails with
322   // ERR_DNS_NO_MATCHING_SUPPORTED_ALPN, |preconnect_backup_job_| will be
323   // started.
324   std::unique_ptr<Job> main_job_;
325   std::unique_ptr<Job> alternative_job_;
326   std::unique_ptr<Job> dns_alpn_h3_job_;
327 
328   std::unique_ptr<Job> preconnect_backup_job_;
329 
330   // The alternative service used by |alternative_job_|
331   // (or by |main_job_| if |is_preconnect_|.)
332   AlternativeServiceInfo alternative_service_info_;
333 
334   // Error status used for alternative service brokenness reporting.
335   // Net error code of the main job. Set to OK by default.
336   int main_job_net_error_ = OK;
337   // Net error code of the alternative job. Set to OK by default.
338   int alternative_job_net_error_ = OK;
339   // Set to true if the alternative job failed on the default network.
340   bool alternative_job_failed_on_default_network_ = false;
341   // Net error code of the DNS HTTPS ALPN job. Set to OK by default.
342   int dns_alpn_h3_job_net_error_ = OK;
343   // Set to true if the DNS HTTPS ALPN job failed on the default network.
344   bool dns_alpn_h3_job_failed_on_default_network_ = false;
345 
346   // True if a Job has ever been bound to the |request_|.
347   bool job_bound_ = false;
348 
349   // True if the main job has to wait for the alternative job: i.e., the main
350   // job must not create a connection until it is resumed.
351   bool main_job_is_blocked_ = false;
352 
353   // Handle for cancelling any posted delayed ResumeMainJob() task.
354   base::CancelableOnceClosure resume_main_job_callback_;
355   // True if the main job was blocked and has been resumed in ResumeMainJob().
356   bool main_job_is_resumed_ = false;
357 
358   // If true, delay main job even the request can be sent immediately on an
359   // available SPDY session.
360   bool delay_main_job_with_available_spdy_session_;
361 
362   // Waiting time for the main job before it is resumed.
363   base::TimeDelta main_job_wait_time_;
364 
365   // At the point where a Job is irrevocably tied to |request_|, we set this.
366   // It will be nulled when the |request_| is finished.
367   raw_ptr<Job> bound_job_ = nullptr;
368 
369   State next_state_ = STATE_RESOLVE_PROXY;
370   std::unique_ptr<ProxyResolutionRequest> proxy_resolve_request_;
371   // The URL from the input `http_request_info`.
372   // TODO(https://crbug.com/332724851): Remove this, and update code to use
373   // `origin_url_`.
374   const GURL http_request_info_url_;
375   // The same as `request_info_url_`, but with any applicable rules in
376   // HostMappingRules applied to it.
377   // TODO: Make this use SchemeHostPort instead, and rename it.
378   const GURL origin_url_;
379   const StreamRequestInfo request_info_;
380   ProxyInfo proxy_info_;
381   const std::vector<SSLConfig::CertAndStatus> allowed_bad_certs_;
382   int num_streams_ = 0;
383   HttpStreamRequest::StreamType stream_type_;
384   RequestPriority priority_ = IDLE;
385   const NetLogWithSource net_log_;
386 
387   base::WeakPtrFactory<JobController> ptr_factory_{this};
388 };
389 
390 }  // namespace net
391 
392 #endif  // NET_HTTP_HTTP_STREAM_FACTORY_JOB_CONTROLLER_H_
393