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. 4 5 #include "net/http/http_stream_factory.h" 6 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" 12 #include "url/gurl.h" 13 14 namespace net { 15 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. 18 19 // static 20 std::vector<std::string>* HttpStreamFactory::next_protos_ = NULL; 21 // static 22 bool HttpStreamFactory::enabled_protocols_[NUM_ALTERNATE_PROTOCOLS]; 23 // static 24 bool HttpStreamFactory::spdy_enabled_ = true; 25 // static 26 bool HttpStreamFactory::use_alternate_protocols_ = false; 27 // static 28 bool HttpStreamFactory::force_spdy_over_ssl_ = true; 29 // static 30 bool HttpStreamFactory::force_spdy_always_ = false; 31 // static 32 std::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL; 33 34 HttpStreamFactory::~HttpStreamFactory() {} 35 36 // static 37 void HttpStreamFactory::ResetStaticSettingsToInit() { 38 // WARNING: These must match the initializers above. 39 delete next_protos_; 40 delete forced_spdy_exclusions_; 41 next_protos_ = NULL; 42 spdy_enabled_ = true; 43 use_alternate_protocols_ = false; 44 force_spdy_over_ssl_ = true; 45 force_spdy_always_ = false; 46 forced_spdy_exclusions_ = NULL; 47 for (int i = 0; i < NUM_ALTERNATE_PROTOCOLS; ++i) 48 enabled_protocols_[i] = false; 49 } 50 51 void HttpStreamFactory::ProcessAlternateProtocol( 52 const base::WeakPtr<HttpServerProperties>& http_server_properties, 53 const std::string& alternate_protocol_str, 54 const HostPortPair& http_host_port_pair) { 55 std::vector<std::string> port_protocol_vector; 56 base::SplitString(alternate_protocol_str, ':', &port_protocol_vector); 57 if (port_protocol_vector.size() != 2) { 58 DLOG(WARNING) << kAlternateProtocolHeader 59 << " header has too many tokens: " 60 << alternate_protocol_str; 61 return; 62 } 63 64 int port; 65 if (!base::StringToInt(port_protocol_vector[0], &port) || 66 port <= 0 || port >= 1 << 16) { 67 DLOG(WARNING) << kAlternateProtocolHeader 68 << " header has unrecognizable port: " 69 << port_protocol_vector[0]; 70 return; 71 } 72 73 AlternateProtocol protocol = 74 AlternateProtocolFromString(port_protocol_vector[1]); 75 if (protocol < NUM_ALTERNATE_PROTOCOLS && !enabled_protocols_[protocol]) 76 protocol = ALTERNATE_PROTOCOL_BROKEN; 77 78 if (protocol == ALTERNATE_PROTOCOL_BROKEN) { 79 // Currently, we only recognize the npn-spdy protocol. 80 DLOG(WARNING) << kAlternateProtocolHeader 81 << " header has unrecognized protocol: " 82 << port_protocol_vector[1]; 83 return; 84 } 85 86 HostPortPair host_port(http_host_port_pair); 87 const HostMappingRules* mapping_rules = GetHostMappingRules(); 88 if (mapping_rules) 89 mapping_rules->RewriteHost(&host_port); 90 91 if (http_server_properties->HasAlternateProtocol(host_port)) { 92 const PortAlternateProtocolPair existing_alternate = 93 http_server_properties->GetAlternateProtocol(host_port); 94 // If we think the alternate protocol is broken, don't change it. 95 if (existing_alternate.protocol == ALTERNATE_PROTOCOL_BROKEN) 96 return; 97 } 98 99 http_server_properties->SetAlternateProtocol(host_port, port, protocol); 100 } 101 102 GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url, 103 HostPortPair* endpoint) { 104 const HostMappingRules* mapping_rules = GetHostMappingRules(); 105 if (mapping_rules && mapping_rules->RewriteHost(endpoint)) { 106 url_canon::Replacements<char> replacements; 107 const std::string port_str = base::IntToString(endpoint->port()); 108 replacements.SetPort(port_str.c_str(), 109 url_parse::Component(0, port_str.size())); 110 replacements.SetHost(endpoint->host().c_str(), 111 url_parse::Component(0, endpoint->host().size())); 112 return url.ReplaceComponents(replacements); 113 } 114 return url; 115 } 116 117 // static 118 void HttpStreamFactory::add_forced_spdy_exclusion(const std::string& value) { 119 HostPortPair pair = HostPortPair::FromURL(GURL(value)); 120 if (!forced_spdy_exclusions_) 121 forced_spdy_exclusions_ = new std::list<HostPortPair>(); 122 forced_spdy_exclusions_->push_back(pair); 123 } 124 125 // static 126 bool HttpStreamFactory::HasSpdyExclusion(const HostPortPair& endpoint) { 127 std::list<HostPortPair>* exclusions = forced_spdy_exclusions_; 128 if (!exclusions) 129 return false; 130 131 std::list<HostPortPair>::const_iterator it; 132 for (it = exclusions->begin(); it != exclusions->end(); ++it) 133 if (it->Equals(endpoint)) 134 return true; 135 return false; 136 } 137 138 // static 139 void HttpStreamFactory::EnableNpnSpdy() { 140 set_use_alternate_protocols(true); 141 std::vector<NextProto> next_protos; 142 next_protos.push_back(kProtoHTTP11); 143 next_protos.push_back(kProtoQUIC1SPDY3); 144 next_protos.push_back(kProtoSPDY2); 145 SetNextProtos(next_protos); 146 } 147 148 // static 149 void HttpStreamFactory::EnableNpnHttpOnly() { 150 // Avoid alternate protocol in this case. Otherwise, browser will try SSL 151 // and then fallback to http. This introduces extra load. 152 set_use_alternate_protocols(false); 153 std::vector<NextProto> next_protos; 154 next_protos.push_back(kProtoHTTP11); 155 SetNextProtos(next_protos); 156 } 157 158 // static 159 void HttpStreamFactory::EnableNpnSpdy3() { 160 set_use_alternate_protocols(true); 161 std::vector<NextProto> next_protos; 162 next_protos.push_back(kProtoHTTP11); 163 next_protos.push_back(kProtoQUIC1SPDY3); 164 next_protos.push_back(kProtoSPDY2); 165 next_protos.push_back(kProtoSPDY3); 166 SetNextProtos(next_protos); 167 } 168 169 // static 170 void HttpStreamFactory::EnableNpnSpdy31() { 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(kProtoSPDY2); 176 next_protos.push_back(kProtoSPDY3); 177 next_protos.push_back(kProtoSPDY31); 178 SetNextProtos(next_protos); 179 } 180 181 // static 182 void HttpStreamFactory::EnableNpnSpdy4a2() { 183 set_use_alternate_protocols(true); 184 std::vector<NextProto> next_protos; 185 next_protos.push_back(kProtoHTTP11); 186 next_protos.push_back(kProtoQUIC1SPDY3); 187 next_protos.push_back(kProtoSPDY2); 188 next_protos.push_back(kProtoSPDY3); 189 next_protos.push_back(kProtoSPDY31); 190 next_protos.push_back(kProtoSPDY4a2); 191 SetNextProtos(next_protos); 192 } 193 194 // static 195 void HttpStreamFactory::EnableNpnHttp2Draft04() { 196 set_use_alternate_protocols(true); 197 std::vector<NextProto> next_protos; 198 next_protos.push_back(kProtoHTTP11); 199 next_protos.push_back(kProtoQUIC1SPDY3); 200 next_protos.push_back(kProtoSPDY2); 201 next_protos.push_back(kProtoSPDY3); 202 next_protos.push_back(kProtoSPDY31); 203 next_protos.push_back(kProtoSPDY4a2); 204 next_protos.push_back(kProtoHTTP2Draft04); 205 SetNextProtos(next_protos); 206 } 207 208 // static 209 void HttpStreamFactory::SetNextProtos(const std::vector<NextProto>& value) { 210 if (!next_protos_) 211 next_protos_ = new std::vector<std::string>; 212 213 next_protos_->clear(); 214 215 for (uint32 i = 0; i < NUM_ALTERNATE_PROTOCOLS; ++i) 216 enabled_protocols_[i] = false; 217 218 // TODO(rtenneti): bug 116575 - consider combining the NextProto and 219 // AlternateProtocol. 220 for (uint32 i = 0; i < value.size(); ++i) { 221 NextProto proto = value[i]; 222 // Add the protocol to the TLS next protocol list, except for QUIC 223 // since it uses UDP. 224 if (proto != kProtoQUIC1SPDY3) { 225 next_protos_->push_back(SSLClientSocket::NextProtoToString(proto)); 226 } 227 228 // Enable the corresponding alternate protocol, except for HTTP 229 // which has not corresponding alternative. 230 if (proto != kProtoHTTP11) { 231 AlternateProtocol alternate = AlternateProtocolFromNextProto(proto); 232 if (alternate == UNINITIALIZED_ALTERNATE_PROTOCOL) { 233 NOTREACHED() << "Invalid next proto: " << proto; 234 continue; 235 } 236 enabled_protocols_[alternate] = true; 237 } 238 } 239 } 240 241 HttpStreamFactory::HttpStreamFactory() {} 242 243 } // namespace net 244