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