1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be 33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_stream_factory.h" 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/logging.h" 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h" 10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "googleurl/src/gurl.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/host_mapping_rules.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/host_port_pair.h" 13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_alternate_protocols.h" 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace net { 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst HostMappingRules* HttpStreamFactory::host_mapping_rules_ = NULL; 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst std::string* HttpStreamFactory::next_protos_ = NULL; 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool HttpStreamFactory::spdy_enabled_ = true; 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool HttpStreamFactory::use_alternate_protocols_ = false; 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool HttpStreamFactory::force_spdy_over_ssl_ = true; 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool HttpStreamFactory::force_spdy_always_ = false; 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenstd::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL; 313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// static 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool HttpStreamFactory::ignore_certificate_errors_ = false; 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 34dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpStreamFactory::~HttpStreamFactory() {} 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpStreamFactory::ProcessAlternateProtocol( 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HttpAlternateProtocols* alternate_protocols, 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& alternate_protocol_str, 393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const HostPortPair& http_host_port_pair) { 403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<std::string> port_protocol_vector; 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::SplitString(alternate_protocol_str, ':', &port_protocol_vector); 423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (port_protocol_vector.size() != 2) { 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DLOG(WARNING) << HttpAlternateProtocols::kHeader 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick << " header has too many tokens: " 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick << alternate_protocol_str; 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int port; 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!base::StringToInt(port_protocol_vector[0], &port) || 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick port <= 0 || port >= 1 << 16) { 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DLOG(WARNING) << HttpAlternateProtocols::kHeader 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick << " header has unrecognizable port: " 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick << port_protocol_vector[0]; 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HttpAlternateProtocols::Protocol protocol = HttpAlternateProtocols::BROKEN; 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We skip NPN_SPDY_1 here, because we've rolled the protocol version to 2. 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = HttpAlternateProtocols::NPN_SPDY_2; 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick i < HttpAlternateProtocols::NUM_ALTERNATE_PROTOCOLS; ++i) { 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (port_protocol_vector[1] == HttpAlternateProtocols::kProtocolStrings[i]) 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick protocol = static_cast<HttpAlternateProtocols::Protocol>(i); 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (protocol == HttpAlternateProtocols::BROKEN) { 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Currently, we only recognize the npn-spdy protocol. 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DLOG(WARNING) << HttpAlternateProtocols::kHeader 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick << " header has unrecognized protocol: " 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick << port_protocol_vector[1]; 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HostPortPair host_port(http_host_port_pair); 75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen host_mapping_rules().RewriteHost(&host_port); 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (alternate_protocols->HasAlternateProtocolFor(host_port)) { 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const HttpAlternateProtocols::PortProtocolPair existing_alternate = 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick alternate_protocols->GetAlternateProtocolFor(host_port); 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If we think the alternate protocol is broken, don't change it. 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (existing_alternate.protocol == HttpAlternateProtocols::BROKEN) 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick alternate_protocols->SetAlternateProtocolFor(host_port, port, protocol); 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickGURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url, 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HostPortPair* endpoint) { 90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (host_mapping_rules().RewriteHost(endpoint)) { 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick url_canon::Replacements<char> replacements; 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string port_str = base::IntToString(endpoint->port()); 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick replacements.SetPort(port_str.c_str(), 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick url_parse::Component(0, port_str.size())); 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick replacements.SetHost(endpoint->host().c_str(), 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick url_parse::Component(0, endpoint->host().size())); 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return url.ReplaceComponents(replacements); 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return url; 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactory::add_forced_spdy_exclusion(const std::string& value) { 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen HostPortPair pair = HostPortPair::FromURL(GURL(value)); 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!forced_spdy_exclusions_) 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen forced_spdy_exclusions_ = new std::list<HostPortPair>(); 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen forced_spdy_exclusions_->push_back(pair); 108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool HttpStreamFactory::HasSpdyExclusion(const HostPortPair& endpoint) { 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::list<HostPortPair>* exclusions = forced_spdy_exclusions_; 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!exclusions) 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::list<HostPortPair>::const_iterator it; 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (it = exclusions->begin(); it != exclusions->end(); ++it) 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (it->Equals(endpoint)) 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactory::SetHostMappingRules(const std::string& rules) { 125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen HostMappingRules* host_mapping_rules = new HostMappingRules; 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen host_mapping_rules->SetRulesFromString(rules); 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete host_mapping_rules_; 128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen host_mapping_rules_ = host_mapping_rules; 129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 131dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpStreamFactory::HttpStreamFactory() {} 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst HostMappingRules& HttpStreamFactory::host_mapping_rules() { 135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!host_mapping_rules_) 136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen host_mapping_rules_ = new HostMappingRules; 137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return *host_mapping_rules_; 138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace net 141