• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #include "base/check.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "base/notreached.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "base/time/time.h"
18 #include "net/base/host_mapping_rules.h"
19 #include "net/base/host_port_pair.h"
20 #include "net/base/network_isolation_key.h"
21 #include "net/base/parse_number.h"
22 #include "net/base/port_util.h"
23 #include "net/http/http_network_session.h"
24 #include "net/http/http_response_headers.h"
25 #include "net/http/http_server_properties.h"
26 #include "net/http/http_stream_factory_job.h"
27 #include "net/http/http_stream_factory_job_controller.h"
28 #include "net/http/transport_security_state.h"
29 #include "net/quic/quic_http_utils.h"
30 #include "net/spdy/bidirectional_stream_spdy_impl.h"
31 #include "net/spdy/spdy_http_stream.h"
32 #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
33 #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h"
34 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.h"
35 #include "url/gurl.h"
36 #include "url/scheme_host_port.h"
37 #include "url/url_constants.h"
38 
39 namespace net {
40 
41 namespace {
42 const char kAlternativeServiceHeader[] = "Alt-Svc";
43 
44 }  // namespace
45 
HttpStreamFactory(HttpNetworkSession * session)46 HttpStreamFactory::HttpStreamFactory(HttpNetworkSession* session)
47     : session_(session), job_factory_(std::make_unique<JobFactory>()) {}
48 
49 HttpStreamFactory::~HttpStreamFactory() = default;
50 
ProcessAlternativeServices(HttpNetworkSession * session,const net::NetworkAnonymizationKey & network_anonymization_key,const HttpResponseHeaders * headers,const url::SchemeHostPort & http_server)51 void HttpStreamFactory::ProcessAlternativeServices(
52     HttpNetworkSession* session,
53     const net::NetworkAnonymizationKey& network_anonymization_key,
54     const HttpResponseHeaders* headers,
55     const url::SchemeHostPort& http_server) {
56   if (!headers->HasHeader(kAlternativeServiceHeader))
57     return;
58 
59   std::string alternative_service_str;
60   headers->GetNormalizedHeader(kAlternativeServiceHeader,
61                                &alternative_service_str);
62   spdy::SpdyAltSvcWireFormat::AlternativeServiceVector
63       alternative_service_vector;
64   if (!spdy::SpdyAltSvcWireFormat::ParseHeaderFieldValue(
65           alternative_service_str, &alternative_service_vector)) {
66     return;
67   }
68 
69   session->http_server_properties()->SetAlternativeServices(
70       RewriteHost(http_server), network_anonymization_key,
71       net::ProcessAlternativeServices(
72           alternative_service_vector, session->params().enable_http2,
73           session->params().enable_quic,
74           session->context().quic_context->params()->supported_versions));
75 }
76 
RewriteHost(const url::SchemeHostPort & server)77 url::SchemeHostPort HttpStreamFactory::RewriteHost(
78     const url::SchemeHostPort& server) {
79   HostPortPair host_port_pair(server.host(), server.port());
80   const HostMappingRules* mapping_rules = GetHostMappingRules();
81   if (mapping_rules)
82     mapping_rules->RewriteHost(&host_port_pair);
83   return url::SchemeHostPort(server.scheme(), host_port_pair.host(),
84                              host_port_pair.port());
85 }
86 
RequestStream(const HttpRequestInfo & request_info,RequestPriority priority,const SSLConfig & server_ssl_config,const SSLConfig & proxy_ssl_config,HttpStreamRequest::Delegate * delegate,bool enable_ip_based_pooling,bool enable_alternative_services,const NetLogWithSource & net_log)87 std::unique_ptr<HttpStreamRequest> HttpStreamFactory::RequestStream(
88     const HttpRequestInfo& request_info,
89     RequestPriority priority,
90     const SSLConfig& server_ssl_config,
91     const SSLConfig& proxy_ssl_config,
92     HttpStreamRequest::Delegate* delegate,
93     bool enable_ip_based_pooling,
94     bool enable_alternative_services,
95     const NetLogWithSource& net_log) {
96   return RequestStreamInternal(
97       request_info, priority, server_ssl_config, proxy_ssl_config, delegate,
98       nullptr, HttpStreamRequest::HTTP_STREAM, false /* is_websocket */,
99       enable_ip_based_pooling, enable_alternative_services, net_log);
100 }
101 
102 std::unique_ptr<HttpStreamRequest>
RequestWebSocketHandshakeStream(const HttpRequestInfo & request_info,RequestPriority priority,const SSLConfig & server_ssl_config,const SSLConfig & proxy_ssl_config,HttpStreamRequest::Delegate * delegate,WebSocketHandshakeStreamBase::CreateHelper * create_helper,bool enable_ip_based_pooling,bool enable_alternative_services,const NetLogWithSource & net_log)103 HttpStreamFactory::RequestWebSocketHandshakeStream(
104     const HttpRequestInfo& request_info,
105     RequestPriority priority,
106     const SSLConfig& server_ssl_config,
107     const SSLConfig& proxy_ssl_config,
108     HttpStreamRequest::Delegate* delegate,
109     WebSocketHandshakeStreamBase::CreateHelper* create_helper,
110     bool enable_ip_based_pooling,
111     bool enable_alternative_services,
112     const NetLogWithSource& net_log) {
113   DCHECK(create_helper);
114   return RequestStreamInternal(
115       request_info, priority, server_ssl_config, proxy_ssl_config, delegate,
116       create_helper, HttpStreamRequest::HTTP_STREAM, true /* is_websocket */,
117       enable_ip_based_pooling, enable_alternative_services, net_log);
118 }
119 
120 std::unique_ptr<HttpStreamRequest>
RequestBidirectionalStreamImpl(const HttpRequestInfo & request_info,RequestPriority priority,const SSLConfig & server_ssl_config,const SSLConfig & proxy_ssl_config,HttpStreamRequest::Delegate * delegate,bool enable_ip_based_pooling,bool enable_alternative_services,const NetLogWithSource & net_log)121 HttpStreamFactory::RequestBidirectionalStreamImpl(
122     const HttpRequestInfo& request_info,
123     RequestPriority priority,
124     const SSLConfig& server_ssl_config,
125     const SSLConfig& proxy_ssl_config,
126     HttpStreamRequest::Delegate* delegate,
127     bool enable_ip_based_pooling,
128     bool enable_alternative_services,
129     const NetLogWithSource& net_log) {
130   DCHECK(request_info.url.SchemeIs(url::kHttpsScheme));
131 
132   return RequestStreamInternal(
133       request_info, priority, server_ssl_config, proxy_ssl_config, delegate,
134       nullptr, HttpStreamRequest::BIDIRECTIONAL_STREAM,
135       false /* is_websocket */, enable_ip_based_pooling,
136       enable_alternative_services, net_log);
137 }
138 
RequestStreamInternal(const HttpRequestInfo & request_info,RequestPriority priority,const SSLConfig & server_ssl_config,const SSLConfig & proxy_ssl_config,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)139 std::unique_ptr<HttpStreamRequest> HttpStreamFactory::RequestStreamInternal(
140     const HttpRequestInfo& request_info,
141     RequestPriority priority,
142     const SSLConfig& server_ssl_config,
143     const SSLConfig& proxy_ssl_config,
144     HttpStreamRequest::Delegate* delegate,
145     WebSocketHandshakeStreamBase::CreateHelper*
146         websocket_handshake_stream_create_helper,
147     HttpStreamRequest::StreamType stream_type,
148     bool is_websocket,
149     bool enable_ip_based_pooling,
150     bool enable_alternative_services,
151     const NetLogWithSource& net_log) {
152   auto job_controller = std::make_unique<JobController>(
153       this, delegate, session_, job_factory_.get(), request_info,
154       /* is_preconnect = */ false, is_websocket, enable_ip_based_pooling,
155       enable_alternative_services,
156       session_->context()
157           .quic_context->params()
158           ->delay_main_job_with_available_spdy_session,
159       server_ssl_config, proxy_ssl_config);
160   JobController* job_controller_raw_ptr = job_controller.get();
161   job_controller_set_.insert(std::move(job_controller));
162   return job_controller_raw_ptr->Start(delegate,
163                                        websocket_handshake_stream_create_helper,
164                                        net_log, stream_type, priority);
165 }
166 
PreconnectStreams(int num_streams,HttpRequestInfo & request_info)167 void HttpStreamFactory::PreconnectStreams(int num_streams,
168                                           HttpRequestInfo& request_info) {
169   DCHECK(request_info.url.is_valid());
170 
171   auto job_controller = std::make_unique<JobController>(
172       this, nullptr, session_, job_factory_.get(), request_info,
173       /*is_preconnect=*/true,
174       /*is_websocket=*/false,
175       /*enable_ip_based_pooling=*/true,
176       /*enable_alternative_services=*/true,
177       session_->context()
178           .quic_context->params()
179           ->delay_main_job_with_available_spdy_session,
180       /*server_ssl_config=*/SSLConfig(),
181       /*proxy_ssl_config=*/SSLConfig());
182   JobController* job_controller_raw_ptr = job_controller.get();
183   job_controller_set_.insert(std::move(job_controller));
184   job_controller_raw_ptr->Preconnect(num_streams);
185 }
186 
GetHostMappingRules() const187 const HostMappingRules* HttpStreamFactory::GetHostMappingRules() const {
188   return &session_->params().host_mapping_rules;
189 }
190 
OnJobControllerComplete(JobController * controller)191 void HttpStreamFactory::OnJobControllerComplete(JobController* controller) {
192   auto it = job_controller_set_.find(controller);
193   if (it != job_controller_set_.end()) {
194     job_controller_set_.erase(it);
195   } else {
196     NOTREACHED();
197   }
198 }
199 
200 }  // namespace net
201