1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_stream_factory.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h"
10 #include "net/base/host_mapping_rules.h"
11 #include "net/base/host_port_pair.h"
16 // WARNING: If you modify or add any static flags, you must keep them in sync
17 // with |ResetStaticSettingsToInit|. This is critical for unit test isolation.
20 std::vector
<std::string
>* HttpStreamFactory::next_protos_
= NULL
;
22 bool HttpStreamFactory::enabled_protocols_
[NUM_VALID_ALTERNATE_PROTOCOLS
];
24 bool HttpStreamFactory::spdy_enabled_
= true;
26 bool HttpStreamFactory::use_alternate_protocols_
= false;
28 bool HttpStreamFactory::force_spdy_over_ssl_
= true;
30 bool HttpStreamFactory::force_spdy_always_
= false;
32 std::list
<HostPortPair
>* HttpStreamFactory::forced_spdy_exclusions_
= NULL
;
34 HttpStreamFactory::~HttpStreamFactory() {}
37 bool HttpStreamFactory::IsProtocolEnabled(AlternateProtocol protocol
) {
38 DCHECK(IsAlternateProtocolValid(protocol
));
39 return enabled_protocols_
[
40 protocol
- ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION
];
44 void HttpStreamFactory::SetProtocolEnabled(AlternateProtocol protocol
) {
45 DCHECK(IsAlternateProtocolValid(protocol
));
47 protocol
- ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION
] = true;
51 void HttpStreamFactory::ResetEnabledProtocols() {
52 for (int i
= ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION
;
53 i
<= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION
; ++i
) {
54 enabled_protocols_
[i
- ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION
] = false;
59 void HttpStreamFactory::ResetStaticSettingsToInit() {
60 // WARNING: These must match the initializers above.
62 delete forced_spdy_exclusions_
;
65 use_alternate_protocols_
= false;
66 force_spdy_over_ssl_
= true;
67 force_spdy_always_
= false;
68 forced_spdy_exclusions_
= NULL
;
69 ResetEnabledProtocols();
72 void HttpStreamFactory::ProcessAlternateProtocol(
73 const base::WeakPtr
<HttpServerProperties
>& http_server_properties
,
74 const std::string
& alternate_protocol_str
,
75 const HostPortPair
& http_host_port_pair
) {
76 std::vector
<std::string
> port_protocol_vector
;
77 base::SplitString(alternate_protocol_str
, ':', &port_protocol_vector
);
78 if (port_protocol_vector
.size() != 2) {
79 DVLOG(1) << kAlternateProtocolHeader
80 << " header has too many tokens: "
81 << alternate_protocol_str
;
86 if (!base::StringToInt(port_protocol_vector
[0], &port
) ||
87 port
<= 0 || port
>= 1 << 16) {
88 DVLOG(1) << kAlternateProtocolHeader
89 << " header has unrecognizable port: "
90 << port_protocol_vector
[0];
94 AlternateProtocol protocol
=
95 AlternateProtocolFromString(port_protocol_vector
[1]);
96 if (IsAlternateProtocolValid(protocol
) && !IsProtocolEnabled(protocol
)) {
97 protocol
= ALTERNATE_PROTOCOL_BROKEN
;
100 if (protocol
== ALTERNATE_PROTOCOL_BROKEN
) {
101 DVLOG(1) << kAlternateProtocolHeader
102 << " header has unrecognized protocol: "
103 << port_protocol_vector
[1];
107 HostPortPair
host_port(http_host_port_pair
);
108 const HostMappingRules
* mapping_rules
= GetHostMappingRules();
110 mapping_rules
->RewriteHost(&host_port
);
112 if (http_server_properties
->HasAlternateProtocol(host_port
)) {
113 const PortAlternateProtocolPair existing_alternate
=
114 http_server_properties
->GetAlternateProtocol(host_port
);
115 // If we think the alternate protocol is broken, don't change it.
116 if (existing_alternate
.protocol
== ALTERNATE_PROTOCOL_BROKEN
)
120 http_server_properties
->SetAlternateProtocol(host_port
, port
, protocol
);
123 GURL
HttpStreamFactory::ApplyHostMappingRules(const GURL
& url
,
124 HostPortPair
* endpoint
) {
125 const HostMappingRules
* mapping_rules
= GetHostMappingRules();
126 if (mapping_rules
&& mapping_rules
->RewriteHost(endpoint
)) {
127 url_canon::Replacements
<char> replacements
;
128 const std::string port_str
= base::IntToString(endpoint
->port());
129 replacements
.SetPort(port_str
.c_str(),
130 url_parse::Component(0, port_str
.size()));
131 replacements
.SetHost(endpoint
->host().c_str(),
132 url_parse::Component(0, endpoint
->host().size()));
133 return url
.ReplaceComponents(replacements
);
139 void HttpStreamFactory::add_forced_spdy_exclusion(const std::string
& value
) {
140 HostPortPair pair
= HostPortPair::FromURL(GURL(value
));
141 if (!forced_spdy_exclusions_
)
142 forced_spdy_exclusions_
= new std::list
<HostPortPair
>();
143 forced_spdy_exclusions_
->push_back(pair
);
147 bool HttpStreamFactory::HasSpdyExclusion(const HostPortPair
& endpoint
) {
148 std::list
<HostPortPair
>* exclusions
= forced_spdy_exclusions_
;
152 std::list
<HostPortPair
>::const_iterator it
;
153 for (it
= exclusions
->begin(); it
!= exclusions
->end(); ++it
)
154 if (it
->Equals(endpoint
))
160 void HttpStreamFactory::EnableNpnHttpOnly() {
161 // Avoid alternate protocol in this case. Otherwise, browser will try SSL
162 // and then fallback to http. This introduces extra load.
163 set_use_alternate_protocols(false);
164 std::vector
<NextProto
> next_protos
;
165 next_protos
.push_back(kProtoHTTP11
);
166 SetNextProtos(next_protos
);
170 void HttpStreamFactory::EnableNpnSpdy3() {
171 set_use_alternate_protocols(true);
172 std::vector
<NextProto
> next_protos
;
173 next_protos
.push_back(kProtoHTTP11
);
174 next_protos
.push_back(kProtoQUIC1SPDY3
);
175 next_protos
.push_back(kProtoSPDY3
);
176 SetNextProtos(next_protos
);
180 void HttpStreamFactory::EnableNpnSpdy31() {
181 set_use_alternate_protocols(true);
182 std::vector
<NextProto
> next_protos
;
183 next_protos
.push_back(kProtoHTTP11
);
184 next_protos
.push_back(kProtoQUIC1SPDY3
);
185 next_protos
.push_back(kProtoSPDY3
);
186 next_protos
.push_back(kProtoSPDY31
);
187 SetNextProtos(next_protos
);
191 void HttpStreamFactory::EnableNpnSpdy31WithSpdy2() {
192 set_use_alternate_protocols(true);
193 std::vector
<NextProto
> next_protos
;
194 next_protos
.push_back(kProtoHTTP11
);
195 next_protos
.push_back(kProtoQUIC1SPDY3
);
196 next_protos
.push_back(kProtoDeprecatedSPDY2
);
197 next_protos
.push_back(kProtoSPDY3
);
198 next_protos
.push_back(kProtoSPDY31
);
199 SetNextProtos(next_protos
);
203 void HttpStreamFactory::EnableNpnSpdy4a2() {
204 set_use_alternate_protocols(true);
205 std::vector
<NextProto
> next_protos
;
206 next_protos
.push_back(kProtoHTTP11
);
207 next_protos
.push_back(kProtoQUIC1SPDY3
);
208 next_protos
.push_back(kProtoSPDY3
);
209 next_protos
.push_back(kProtoSPDY31
);
210 next_protos
.push_back(kProtoSPDY4a2
);
211 SetNextProtos(next_protos
);
215 void HttpStreamFactory::EnableNpnHttp2Draft04() {
216 set_use_alternate_protocols(true);
217 std::vector
<NextProto
> next_protos
;
218 next_protos
.push_back(kProtoHTTP11
);
219 next_protos
.push_back(kProtoQUIC1SPDY3
);
220 next_protos
.push_back(kProtoSPDY3
);
221 next_protos
.push_back(kProtoSPDY31
);
222 next_protos
.push_back(kProtoSPDY4a2
);
223 next_protos
.push_back(kProtoHTTP2Draft04
);
224 SetNextProtos(next_protos
);
228 void HttpStreamFactory::SetNextProtos(const std::vector
<NextProto
>& value
) {
230 next_protos_
= new std::vector
<std::string
>;
232 next_protos_
->clear();
234 ResetEnabledProtocols();
236 // TODO(rtenneti): bug 116575 - consider combining the NextProto and
237 // AlternateProtocol.
238 for (uint32 i
= 0; i
< value
.size(); ++i
) {
239 NextProto proto
= value
[i
];
240 // Add the protocol to the TLS next protocol list, except for QUIC
241 // since it uses UDP.
242 if (proto
!= kProtoQUIC1SPDY3
) {
243 next_protos_
->push_back(SSLClientSocket::NextProtoToString(proto
));
246 // Enable the corresponding alternate protocol, except for HTTP
247 // which has not corresponding alternative.
248 if (proto
!= kProtoHTTP11
) {
249 AlternateProtocol alternate
= AlternateProtocolFromNextProto(proto
);
250 if (!IsAlternateProtocolValid(alternate
)) {
251 NOTREACHED() << "Invalid next proto: " << proto
;
254 SetProtocolEnabled(alternate
);
259 HttpStreamFactory::HttpStreamFactory() {}