Home | History | Annotate | Download | only in http
      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