xref: /aosp_15_r20/external/cronet/net/http/http_stream_factory.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 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 #include "net/http/http_stream_factory.h"
6 
7 #include <cstddef>
8 #include <tuple>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/check.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/notreached.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_split.h"
17 #include "base/strings/string_util.h"
18 #include "base/time/time.h"
19 #include "net/base/host_mapping_rules.h"
20 #include "net/base/host_port_pair.h"
21 #include "net/base/network_anonymization_key.h"
22 #include "net/base/network_isolation_key.h"
23 #include "net/base/parse_number.h"
24 #include "net/base/port_util.h"
25 #include "net/base/privacy_mode.h"
26 #include "net/base/upload_data_stream.h"
27 #include "net/dns/public/secure_dns_policy.h"
28 #include "net/http/http_network_session.h"
29 #include "net/http/http_response_headers.h"
30 #include "net/http/http_server_properties.h"
31 #include "net/http/http_stream_factory_job.h"
32 #include "net/http/http_stream_factory_job_controller.h"
33 #include "net/http/transport_security_state.h"
34 #include "net/quic/quic_http_utils.h"
35 #include "net/socket/socket_tag.h"
36 #include "net/spdy/bidirectional_stream_spdy_impl.h"
37 #include "net/spdy/spdy_http_stream.h"
38 #include "net/ssl/ssl_config.h"
39 #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
40 #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h"
41 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.h"
42 #include "url/gurl.h"
43 #include "url/scheme_host_port.h"
44 #include "url/url_constants.h"
45 
46 namespace net {
47 
48 namespace {
49 const char kAlternativeServiceHeader[] = "Alt-Svc";
50 
51 }  // namespace
52 
53 HttpStreamFactory::StreamRequestInfo::StreamRequestInfo() = default;
54 
StreamRequestInfo(const HttpRequestInfo & http_request_info)55 HttpStreamFactory::StreamRequestInfo::StreamRequestInfo(
56     const HttpRequestInfo& http_request_info)
57     : method(http_request_info.method),
58       network_anonymization_key(http_request_info.network_anonymization_key),
59       is_http1_allowed(!http_request_info.upload_data_stream ||
60                        http_request_info.upload_data_stream->AllowHTTP1()),
61       load_flags(http_request_info.load_flags),
62       privacy_mode(http_request_info.privacy_mode),
63       secure_dns_policy(http_request_info.secure_dns_policy),
64       socket_tag(http_request_info.socket_tag) {}
65 
66 HttpStreamFactory::StreamRequestInfo::StreamRequestInfo(
67     const StreamRequestInfo& other) = default;
68 HttpStreamFactory::StreamRequestInfo&
69 HttpStreamFactory::StreamRequestInfo::operator=(
70     const StreamRequestInfo& other) = default;
71 HttpStreamFactory::StreamRequestInfo::StreamRequestInfo(
72     StreamRequestInfo&& other) = default;
73 HttpStreamFactory::StreamRequestInfo&
74 HttpStreamFactory::StreamRequestInfo::operator=(StreamRequestInfo&& other) =
75     default;
76 
77 HttpStreamFactory::StreamRequestInfo::~StreamRequestInfo() = default;
78 
HttpStreamFactory(HttpNetworkSession * session)79 HttpStreamFactory::HttpStreamFactory(HttpNetworkSession* session)
80     : session_(session), job_factory_(std::make_unique<JobFactory>()) {}
81 
82 HttpStreamFactory::~HttpStreamFactory() = default;
83 
ProcessAlternativeServices(HttpNetworkSession * session,const net::NetworkAnonymizationKey & network_anonymization_key,const HttpResponseHeaders * headers,const url::SchemeHostPort & http_server)84 void HttpStreamFactory::ProcessAlternativeServices(
85     HttpNetworkSession* session,
86     const net::NetworkAnonymizationKey& network_anonymization_key,
87     const HttpResponseHeaders* headers,
88     const url::SchemeHostPort& http_server) {
89   if (!headers->HasHeader(kAlternativeServiceHeader))
90     return;
91 
92   std::string alternative_service_str;
93   headers->GetNormalizedHeader(kAlternativeServiceHeader,
94                                &alternative_service_str);
95   spdy::SpdyAltSvcWireFormat::AlternativeServiceVector
96       alternative_service_vector;
97   if (!spdy::SpdyAltSvcWireFormat::ParseHeaderFieldValue(
98           alternative_service_str, &alternative_service_vector)) {
99     return;
100   }
101 
102   session->http_server_properties()->SetAlternativeServices(
103       RewriteHost(http_server), network_anonymization_key,
104       net::ProcessAlternativeServices(
105           alternative_service_vector, session->params().enable_http2,
106           session->params().enable_quic,
107           session->context().quic_context->params()->supported_versions));
108 }
109 
RewriteHost(const url::SchemeHostPort & server)110 url::SchemeHostPort HttpStreamFactory::RewriteHost(
111     const url::SchemeHostPort& server) {
112   HostPortPair host_port_pair(server.host(), server.port());
113   const HostMappingRules* mapping_rules = GetHostMappingRules();
114   if (mapping_rules)
115     mapping_rules->RewriteHost(&host_port_pair);
116   return url::SchemeHostPort(server.scheme(), host_port_pair.host(),
117                              host_port_pair.port());
118 }
119 
RequestStream(const HttpRequestInfo & request_info,RequestPriority priority,const std::vector<SSLConfig::CertAndStatus> & allowed_bad_certs,HttpStreamRequest::Delegate * delegate,bool enable_ip_based_pooling,bool enable_alternative_services,const NetLogWithSource & net_log)120 std::unique_ptr<HttpStreamRequest> HttpStreamFactory::RequestStream(
121     const HttpRequestInfo& request_info,
122     RequestPriority priority,
123     const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs,
124     HttpStreamRequest::Delegate* delegate,
125     bool enable_ip_based_pooling,
126     bool enable_alternative_services,
127     const NetLogWithSource& net_log) {
128   return RequestStreamInternal(request_info, priority, allowed_bad_certs,
129                                delegate, nullptr,
130                                HttpStreamRequest::HTTP_STREAM,
131                                /*is_websocket=*/false, enable_ip_based_pooling,
132                                enable_alternative_services, net_log);
133 }
134 
135 std::unique_ptr<HttpStreamRequest>
RequestWebSocketHandshakeStream(const HttpRequestInfo & request_info,RequestPriority priority,const std::vector<SSLConfig::CertAndStatus> & allowed_bad_certs,HttpStreamRequest::Delegate * delegate,WebSocketHandshakeStreamBase::CreateHelper * create_helper,bool enable_ip_based_pooling,bool enable_alternative_services,const NetLogWithSource & net_log)136 HttpStreamFactory::RequestWebSocketHandshakeStream(
137     const HttpRequestInfo& request_info,
138     RequestPriority priority,
139     const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs,
140     HttpStreamRequest::Delegate* delegate,
141     WebSocketHandshakeStreamBase::CreateHelper* create_helper,
142     bool enable_ip_based_pooling,
143     bool enable_alternative_services,
144     const NetLogWithSource& net_log) {
145   DCHECK(create_helper);
146   return RequestStreamInternal(request_info, priority, allowed_bad_certs,
147                                delegate, create_helper,
148                                HttpStreamRequest::HTTP_STREAM,
149                                /*is_websocket=*/true, enable_ip_based_pooling,
150                                enable_alternative_services, net_log);
151 }
152 
153 std::unique_ptr<HttpStreamRequest>
RequestBidirectionalStreamImpl(const HttpRequestInfo & request_info,RequestPriority priority,const std::vector<SSLConfig::CertAndStatus> & allowed_bad_certs,HttpStreamRequest::Delegate * delegate,bool enable_ip_based_pooling,bool enable_alternative_services,const NetLogWithSource & net_log)154 HttpStreamFactory::RequestBidirectionalStreamImpl(
155     const HttpRequestInfo& request_info,
156     RequestPriority priority,
157     const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs,
158     HttpStreamRequest::Delegate* delegate,
159     bool enable_ip_based_pooling,
160     bool enable_alternative_services,
161     const NetLogWithSource& net_log) {
162   DCHECK(request_info.url.SchemeIs(url::kHttpsScheme));
163 
164   return RequestStreamInternal(request_info, priority, allowed_bad_certs,
165                                delegate, nullptr,
166                                HttpStreamRequest::BIDIRECTIONAL_STREAM,
167                                /*is_websocket=*/false, enable_ip_based_pooling,
168                                enable_alternative_services, net_log);
169 }
170 
RequestStreamInternal(const HttpRequestInfo & request_info,RequestPriority priority,const std::vector<SSLConfig::CertAndStatus> & allowed_bad_certs,HttpStreamRequest::Delegate * delegate,WebSocketHandshakeStreamBase::CreateHelper * websocket_handshake_stream_create_helper,HttpStreamRequest::StreamType stream_type,bool is_websocket,bool enable_ip_based_pooling,bool enable_alternative_services,const NetLogWithSource & net_log)171 std::unique_ptr<HttpStreamRequest> HttpStreamFactory::RequestStreamInternal(
172     const HttpRequestInfo& request_info,
173     RequestPriority priority,
174     const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs,
175     HttpStreamRequest::Delegate* delegate,
176     WebSocketHandshakeStreamBase::CreateHelper*
177         websocket_handshake_stream_create_helper,
178     HttpStreamRequest::StreamType stream_type,
179     bool is_websocket,
180     bool enable_ip_based_pooling,
181     bool enable_alternative_services,
182     const NetLogWithSource& net_log) {
183   // This is only needed in the non-preconnect path, as preconnects do not
184   // require a NetworkIsolationKey.
185   DCHECK(request_info.IsConsistent());
186 
187   auto job_controller = std::make_unique<JobController>(
188       this, delegate, session_, job_factory_.get(), request_info,
189       /* is_preconnect = */ false, is_websocket, enable_ip_based_pooling,
190       enable_alternative_services,
191       session_->context()
192           .quic_context->params()
193           ->delay_main_job_with_available_spdy_session,
194       allowed_bad_certs);
195   JobController* job_controller_raw_ptr = job_controller.get();
196   job_controller_set_.insert(std::move(job_controller));
197   return job_controller_raw_ptr->Start(delegate,
198                                        websocket_handshake_stream_create_helper,
199                                        net_log, stream_type, priority);
200 }
201 
PreconnectStreams(int num_streams,HttpRequestInfo & request_info)202 void HttpStreamFactory::PreconnectStreams(int num_streams,
203                                           HttpRequestInfo& request_info) {
204   DCHECK(request_info.url.is_valid());
205 
206   auto job_controller = std::make_unique<JobController>(
207       this, nullptr, session_, job_factory_.get(), request_info,
208       /*is_preconnect=*/true,
209       /*is_websocket=*/false,
210       /*enable_ip_based_pooling=*/true,
211       /*enable_alternative_services=*/true,
212       session_->context()
213           .quic_context->params()
214           ->delay_main_job_with_available_spdy_session,
215       /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
216   JobController* job_controller_raw_ptr = job_controller.get();
217   job_controller_set_.insert(std::move(job_controller));
218   job_controller_raw_ptr->Preconnect(num_streams);
219 }
220 
GetHostMappingRules() const221 const HostMappingRules* HttpStreamFactory::GetHostMappingRules() const {
222   return &session_->params().host_mapping_rules;
223 }
224 
OnJobControllerComplete(JobController * controller)225 void HttpStreamFactory::OnJobControllerComplete(JobController* controller) {
226   auto it = job_controller_set_.find(controller);
227   if (it != job_controller_set_.end()) {
228     job_controller_set_.erase(it);
229   } else {
230     NOTREACHED();
231   }
232 }
233 
234 }  // namespace net
235