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 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 36 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 45 HttpAlternateProtocols::HttpAlternateProtocols() {} 46 HttpAlternateProtocols::~HttpAlternateProtocols() {} 47 48 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 54 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 61 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 76 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 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 117 void HttpAlternateProtocols::MarkBrokenAlternateProtocolFor( 118 const HostPortPair& http_host_port_pair) { 119 protocol_map_[http_host_port_pair].protocol = BROKEN; 120 } 121 122 // static 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 132 void HttpAlternateProtocols::DisableForcedAlternateProtocol() { 133 delete forced_alternate_protocol_; 134 forced_alternate_protocol_ = NULL; 135 } 136 137 } // namespace net 138