http_stream_factory.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 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/stl_util-inl.h" 8#include "base/string_number_conversions.h" 9#include "base/string_split.h" 10#include "base/string_util.h" 11#include "net/base/net_log.h" 12#include "net/base/net_util.h" 13#include "net/http/http_network_session.h" 14#include "net/http/http_stream_request.h" 15 16namespace net { 17 18// static 19const HostMappingRules* HttpStreamFactory::host_mapping_rules_ = NULL; 20// static 21const std::string* HttpStreamFactory::next_protos_ = NULL; 22// static 23bool HttpStreamFactory::spdy_enabled_ = true; 24// static 25bool HttpStreamFactory::use_alternate_protocols_ = false; 26// static 27bool HttpStreamFactory::force_spdy_over_ssl_ = true; 28// static 29bool HttpStreamFactory::force_spdy_always_ = false; 30// static 31std::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL; 32// static 33bool HttpStreamFactory::ignore_certificate_errors_ = false; 34 35// static 36void HttpStreamFactory::SetHostMappingRules(const std::string& rules) { 37 HostMappingRules* host_mapping_rules = new HostMappingRules(); 38 host_mapping_rules->SetRulesFromString(rules); 39 delete host_mapping_rules_; 40 host_mapping_rules_ = host_mapping_rules; 41} 42 43HttpStreamFactory::HttpStreamFactory() { 44} 45 46HttpStreamFactory::~HttpStreamFactory() { 47 RequestCallbackMap request_callback_map; 48 request_callback_map.swap(request_callback_map_); 49 for (RequestCallbackMap::iterator it = request_callback_map.begin(); 50 it != request_callback_map.end(); ++it) { 51 delete it->first; 52 // We don't invoke the callback in the destructor. 53 } 54} 55 56StreamRequest* HttpStreamFactory::RequestStream( 57 const HttpRequestInfo* request_info, 58 SSLConfig* ssl_config, 59 ProxyInfo* proxy_info, 60 HttpNetworkSession* session, 61 StreamRequest::Delegate* delegate, 62 const BoundNetLog& net_log) { 63 HttpStreamRequest* stream = new HttpStreamRequest(this, session); 64 stream->Start(request_info, ssl_config, proxy_info, delegate, net_log); 65 return stream; 66} 67 68int HttpStreamFactory::PreconnectStreams( 69 int num_streams, 70 const HttpRequestInfo* request_info, 71 SSLConfig* ssl_config, 72 ProxyInfo* proxy_info, 73 HttpNetworkSession* session, 74 const BoundNetLog& net_log, 75 CompletionCallback* callback) { 76 HttpStreamRequest* stream = new HttpStreamRequest(this, session); 77 int rv = stream->Preconnect(num_streams, request_info, ssl_config, 78 proxy_info, this, net_log); 79 DCHECK_EQ(ERR_IO_PENDING, rv); 80 request_callback_map_[stream] = callback; 81 return rv; 82} 83 84void HttpStreamFactory::AddTLSIntolerantServer(const GURL& url) { 85 tls_intolerant_servers_.insert(GetHostAndPort(url)); 86} 87 88bool HttpStreamFactory::IsTLSIntolerantServer(const GURL& url) { 89 return ContainsKey(tls_intolerant_servers_, GetHostAndPort(url)); 90} 91 92void HttpStreamFactory::ProcessAlternateProtocol( 93 HttpAlternateProtocols* alternate_protocols, 94 const std::string& alternate_protocol_str, 95 const HostPortPair& http_host_port_pair) { 96 std::vector<std::string> port_protocol_vector; 97 base::SplitString(alternate_protocol_str, ':', &port_protocol_vector); 98 if (port_protocol_vector.size() != 2) { 99 DLOG(WARNING) << HttpAlternateProtocols::kHeader 100 << " header has too many tokens: " 101 << alternate_protocol_str; 102 return; 103 } 104 105 int port; 106 if (!base::StringToInt(port_protocol_vector[0], &port) || 107 port <= 0 || port >= 1 << 16) { 108 DLOG(WARNING) << HttpAlternateProtocols::kHeader 109 << " header has unrecognizable port: " 110 << port_protocol_vector[0]; 111 return; 112 } 113 114 HttpAlternateProtocols::Protocol protocol = HttpAlternateProtocols::BROKEN; 115 // We skip NPN_SPDY_1 here, because we've rolled the protocol version to 2. 116 for (int i = HttpAlternateProtocols::NPN_SPDY_2; 117 i < HttpAlternateProtocols::NUM_ALTERNATE_PROTOCOLS; ++i) { 118 if (port_protocol_vector[1] == HttpAlternateProtocols::kProtocolStrings[i]) 119 protocol = static_cast<HttpAlternateProtocols::Protocol>(i); 120 } 121 122 if (protocol == HttpAlternateProtocols::BROKEN) { 123 // Currently, we only recognize the npn-spdy protocol. 124 DLOG(WARNING) << HttpAlternateProtocols::kHeader 125 << " header has unrecognized protocol: " 126 << port_protocol_vector[1]; 127 return; 128 } 129 130 HostPortPair host_port(http_host_port_pair); 131 if (host_mapping_rules_) 132 host_mapping_rules_->RewriteHost(&host_port); 133 134 if (alternate_protocols->HasAlternateProtocolFor(host_port)) { 135 const HttpAlternateProtocols::PortProtocolPair existing_alternate = 136 alternate_protocols->GetAlternateProtocolFor(host_port); 137 // If we think the alternate protocol is broken, don't change it. 138 if (existing_alternate.protocol == HttpAlternateProtocols::BROKEN) 139 return; 140 } 141 142 alternate_protocols->SetAlternateProtocolFor(host_port, port, protocol); 143} 144 145GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url, 146 HostPortPair* endpoint) { 147 if (host_mapping_rules_ && host_mapping_rules_->RewriteHost(endpoint)) { 148 url_canon::Replacements<char> replacements; 149 const std::string port_str = base::IntToString(endpoint->port()); 150 replacements.SetPort(port_str.c_str(), 151 url_parse::Component(0, port_str.size())); 152 replacements.SetHost(endpoint->host().c_str(), 153 url_parse::Component(0, endpoint->host().size())); 154 return url.ReplaceComponents(replacements); 155 } 156 return url; 157} 158 159void HttpStreamFactory::OnPreconnectsComplete( 160 HttpStreamRequest* request, int result) { 161 RequestCallbackMap::iterator it = request_callback_map_.find(request); 162 DCHECK(it != request_callback_map_.end()); 163 CompletionCallback* callback = it->second; 164 request_callback_map_.erase(it); 165 delete request; 166 callback->Run(result); 167} 168 169} // namespace net 170 171