• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_alternate_protocols.h"
6 
7 #include "base/logging.h"
8 #include "base/stringprintf.h"
9 #include "base/stl_util-inl.h"
10 
11 namespace net {
12 
13 const char HttpAlternateProtocols::kHeader[] = "Alternate-Protocol";
14 const char* const HttpAlternateProtocols::kProtocolStrings[] = {
15   "npn-spdy/1",
16   "npn-spdy/2",
17 };
18 
ProtocolToString(HttpAlternateProtocols::Protocol protocol)19 const char* HttpAlternateProtocols::ProtocolToString(
20     HttpAlternateProtocols::Protocol protocol) {
21   switch (protocol) {
22     case HttpAlternateProtocols::NPN_SPDY_1:
23     case HttpAlternateProtocols::NPN_SPDY_2:
24       return HttpAlternateProtocols::kProtocolStrings[protocol];
25     case HttpAlternateProtocols::BROKEN:
26       return "Broken";
27     case HttpAlternateProtocols::UNINITIALIZED:
28       return "Uninitialized";
29     default:
30       NOTREACHED();
31       return "";
32   }
33 }
34 
35 
ToString() const36 std::string HttpAlternateProtocols::PortProtocolPair::ToString() const {
37   return base::StringPrintf("%d:%s", port,
38                             HttpAlternateProtocols::ProtocolToString(protocol));
39 }
40 
41 // static
42 HttpAlternateProtocols::PortProtocolPair*
43     HttpAlternateProtocols::forced_alternate_protocol_ = NULL;
44 
HttpAlternateProtocols()45 HttpAlternateProtocols::HttpAlternateProtocols() {}
~HttpAlternateProtocols()46 HttpAlternateProtocols::~HttpAlternateProtocols() {}
47 
HasAlternateProtocolFor(const HostPortPair & http_host_port_pair) const48 bool HttpAlternateProtocols::HasAlternateProtocolFor(
49     const HostPortPair& http_host_port_pair) const {
50   return ContainsKey(protocol_map_, http_host_port_pair) ||
51       forced_alternate_protocol_;
52 }
53 
HasAlternateProtocolFor(const std::string & host,uint16 port) const54 bool HttpAlternateProtocols::HasAlternateProtocolFor(
55     const std::string& host, uint16 port) const {
56   HostPortPair http_host_port_pair(host, port);
57   return HasAlternateProtocolFor(http_host_port_pair);
58 }
59 
60 HttpAlternateProtocols::PortProtocolPair
GetAlternateProtocolFor(const HostPortPair & http_host_port_pair) const61 HttpAlternateProtocols::GetAlternateProtocolFor(
62     const HostPortPair& http_host_port_pair) const {
63   DCHECK(HasAlternateProtocolFor(http_host_port_pair));
64 
65   // First check the map.
66   ProtocolMap::const_iterator it = protocol_map_.find(http_host_port_pair);
67   if (it != protocol_map_.end())
68     return it->second;
69 
70   // We must be forcing an alternate.
71   DCHECK(forced_alternate_protocol_);
72   return *forced_alternate_protocol_;
73 }
74 
75 HttpAlternateProtocols::PortProtocolPair
GetAlternateProtocolFor(const std::string & host,uint16 port) const76 HttpAlternateProtocols::GetAlternateProtocolFor(
77     const std::string& host, uint16 port) const {
78   HostPortPair http_host_port_pair(host, port);
79   return GetAlternateProtocolFor(http_host_port_pair);
80 }
81 
SetAlternateProtocolFor(const HostPortPair & http_host_port_pair,uint16 alternate_port,Protocol alternate_protocol)82 void HttpAlternateProtocols::SetAlternateProtocolFor(
83     const HostPortPair& http_host_port_pair,
84     uint16 alternate_port,
85     Protocol alternate_protocol) {
86   if (alternate_protocol == BROKEN) {
87     LOG(DFATAL) << "Call MarkBrokenAlternateProtocolFor() instead.";
88     return;
89   }
90 
91   PortProtocolPair alternate;
92   alternate.port = alternate_port;
93   alternate.protocol = alternate_protocol;
94   if (HasAlternateProtocolFor(http_host_port_pair)) {
95     const PortProtocolPair existing_alternate =
96         GetAlternateProtocolFor(http_host_port_pair);
97 
98     if (existing_alternate.protocol == BROKEN) {
99       DVLOG(1) << "Ignore alternate protocol since it's known to be broken.";
100       return;
101     }
102 
103     if (alternate_protocol != BROKEN && !existing_alternate.Equals(alternate)) {
104       LOG(WARNING) << "Changing the alternate protocol for: "
105                    << http_host_port_pair.ToString()
106                    << " from [Port: " << existing_alternate.port
107                    << ", Protocol: " << existing_alternate.protocol
108                    << "] to [Port: " << alternate_port
109                    << ", Protocol: " << alternate_protocol
110                    << "].";
111     }
112   }
113 
114   protocol_map_[http_host_port_pair] = alternate;
115 }
116 
MarkBrokenAlternateProtocolFor(const HostPortPair & http_host_port_pair)117 void HttpAlternateProtocols::MarkBrokenAlternateProtocolFor(
118     const HostPortPair& http_host_port_pair) {
119   protocol_map_[http_host_port_pair].protocol = BROKEN;
120 }
121 
122 // static
ForceAlternateProtocol(const PortProtocolPair & pair)123 void HttpAlternateProtocols::ForceAlternateProtocol(
124     const PortProtocolPair& pair) {
125   // Note: we're going to leak this.
126   if (forced_alternate_protocol_)
127     delete forced_alternate_protocol_;
128   forced_alternate_protocol_ = new PortProtocolPair(pair);
129 }
130 
131 // static
DisableForcedAlternateProtocol()132 void HttpAlternateProtocols::DisableForcedAlternateProtocol() {
133   delete forced_alternate_protocol_;
134   forced_alternate_protocol_ = NULL;
135 }
136 
137 }  // namespace net
138