diff options
Diffstat (limited to 'chromium/net/http/http_server_properties_impl.cc')
-rw-r--r-- | chromium/net/http/http_server_properties_impl.cc | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/chromium/net/http/http_server_properties_impl.cc b/chromium/net/http/http_server_properties_impl.cc new file mode 100644 index 00000000000..a0b287de588 --- /dev/null +++ b/chromium/net/http/http_server_properties_impl.cc @@ -0,0 +1,303 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_server_properties_impl.h" + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" +#include "base/strings/stringprintf.h" +#include "net/http/http_pipelined_host_capability.h" + +namespace net { + +// TODO(simonjam): Run experiments with different values of this to see what +// value is good at avoiding evictions without eating too much memory. Until +// then, this is just a bad guess. +static const int kDefaultNumHostsToRemember = 200; + +HttpServerPropertiesImpl::HttpServerPropertiesImpl() + : weak_ptr_factory_(this), + pipeline_capability_map_( + new CachedPipelineCapabilityMap(kDefaultNumHostsToRemember)) { +} + +HttpServerPropertiesImpl::~HttpServerPropertiesImpl() { +} + +void HttpServerPropertiesImpl::InitializeSpdyServers( + std::vector<std::string>* spdy_servers, + bool support_spdy) { + DCHECK(CalledOnValidThread()); + spdy_servers_table_.clear(); + if (!spdy_servers) + return; + for (std::vector<std::string>::iterator it = spdy_servers->begin(); + it != spdy_servers->end(); ++it) { + spdy_servers_table_[*it] = support_spdy; + } +} + +void HttpServerPropertiesImpl::InitializeAlternateProtocolServers( + AlternateProtocolMap* alternate_protocol_map) { + // First swap, and then add back all the ALTERNATE_PROTOCOL_BROKEN ones since + // those don't get persisted. + alternate_protocol_map_.swap(*alternate_protocol_map); + for (AlternateProtocolMap::const_iterator it = + alternate_protocol_map->begin(); + it != alternate_protocol_map->end(); ++it) { + if (it->second.protocol == ALTERNATE_PROTOCOL_BROKEN) + alternate_protocol_map_[it->first] = it->second; + } +} + +void HttpServerPropertiesImpl::InitializeSpdySettingsServers( + SpdySettingsMap* spdy_settings_map) { + spdy_settings_map_.swap(*spdy_settings_map); +} + +void HttpServerPropertiesImpl::InitializePipelineCapabilities( + const PipelineCapabilityMap* pipeline_capability_map) { + PipelineCapabilityMap::const_iterator it; + pipeline_capability_map_->Clear(); + for (it = pipeline_capability_map->begin(); + it != pipeline_capability_map->end(); ++it) { + pipeline_capability_map_->Put(it->first, it->second); + } +} + +void HttpServerPropertiesImpl::SetNumPipelinedHostsToRemember(int max_size) { + DCHECK(pipeline_capability_map_->empty()); + pipeline_capability_map_.reset(new CachedPipelineCapabilityMap(max_size)); +} + +void HttpServerPropertiesImpl::GetSpdyServerList( + base::ListValue* spdy_server_list) const { + DCHECK(CalledOnValidThread()); + DCHECK(spdy_server_list); + spdy_server_list->Clear(); + // Get the list of servers (host/port) that support SPDY. + for (SpdyServerHostPortTable::const_iterator it = spdy_servers_table_.begin(); + it != spdy_servers_table_.end(); ++it) { + const std::string spdy_server_host_port = it->first; + if (it->second) + spdy_server_list->Append(new base::StringValue(spdy_server_host_port)); + } +} + +// static +std::string HttpServerPropertiesImpl::GetFlattenedSpdyServer( + const net::HostPortPair& host_port_pair) { + std::string spdy_server; + spdy_server.append(host_port_pair.host()); + spdy_server.append(":"); + base::StringAppendF(&spdy_server, "%d", host_port_pair.port()); + return spdy_server; +} + +static const PortAlternateProtocolPair* g_forced_alternate_protocol = NULL; + +// static +void HttpServerPropertiesImpl::ForceAlternateProtocol( + const PortAlternateProtocolPair& pair) { + // Note: we're going to leak this. + if (g_forced_alternate_protocol) + delete g_forced_alternate_protocol; + g_forced_alternate_protocol = new PortAlternateProtocolPair(pair); +} + +// static +void HttpServerPropertiesImpl::DisableForcedAlternateProtocol() { + delete g_forced_alternate_protocol; + g_forced_alternate_protocol = NULL; +} + +base::WeakPtr<HttpServerProperties> HttpServerPropertiesImpl::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +void HttpServerPropertiesImpl::Clear() { + DCHECK(CalledOnValidThread()); + spdy_servers_table_.clear(); + alternate_protocol_map_.clear(); + spdy_settings_map_.clear(); + pipeline_capability_map_->Clear(); +} + +bool HttpServerPropertiesImpl::SupportsSpdy( + const net::HostPortPair& host_port_pair) const { + DCHECK(CalledOnValidThread()); + if (host_port_pair.host().empty()) + return false; + std::string spdy_server = GetFlattenedSpdyServer(host_port_pair); + + SpdyServerHostPortTable::const_iterator spdy_host_port = + spdy_servers_table_.find(spdy_server); + if (spdy_host_port != spdy_servers_table_.end()) + return spdy_host_port->second; + return false; +} + +void HttpServerPropertiesImpl::SetSupportsSpdy( + const net::HostPortPair& host_port_pair, + bool support_spdy) { + DCHECK(CalledOnValidThread()); + if (host_port_pair.host().empty()) + return; + std::string spdy_server = GetFlattenedSpdyServer(host_port_pair); + + SpdyServerHostPortTable::iterator spdy_host_port = + spdy_servers_table_.find(spdy_server); + if ((spdy_host_port != spdy_servers_table_.end()) && + (spdy_host_port->second == support_spdy)) { + return; + } + // Cache the data. + spdy_servers_table_[spdy_server] = support_spdy; +} + +bool HttpServerPropertiesImpl::HasAlternateProtocol( + const HostPortPair& server) const { + return ContainsKey(alternate_protocol_map_, server) || + g_forced_alternate_protocol; +} + +PortAlternateProtocolPair +HttpServerPropertiesImpl::GetAlternateProtocol( + const HostPortPair& server) const { + DCHECK(HasAlternateProtocol(server)); + + // First check the map. + AlternateProtocolMap::const_iterator it = + alternate_protocol_map_.find(server); + if (it != alternate_protocol_map_.end()) + return it->second; + + // We must be forcing an alternate. + DCHECK(g_forced_alternate_protocol); + return *g_forced_alternate_protocol; +} + +void HttpServerPropertiesImpl::SetAlternateProtocol( + const HostPortPair& server, + uint16 alternate_port, + AlternateProtocol alternate_protocol) { + if (alternate_protocol == ALTERNATE_PROTOCOL_BROKEN) { + LOG(DFATAL) << "Call SetBrokenAlternateProtocol() instead."; + return; + } + + PortAlternateProtocolPair alternate; + alternate.port = alternate_port; + alternate.protocol = alternate_protocol; + if (HasAlternateProtocol(server)) { + const PortAlternateProtocolPair existing_alternate = + GetAlternateProtocol(server); + + if (existing_alternate.protocol == ALTERNATE_PROTOCOL_BROKEN) { + DVLOG(1) << "Ignore alternate protocol since it's known to be broken."; + return; + } + + if (alternate_protocol != ALTERNATE_PROTOCOL_BROKEN && + !existing_alternate.Equals(alternate)) { + LOG(WARNING) << "Changing the alternate protocol for: " + << server.ToString() + << " from [Port: " << existing_alternate.port + << ", Protocol: " << existing_alternate.protocol + << "] to [Port: " << alternate_port + << ", Protocol: " << alternate_protocol + << "]."; + } + } + + alternate_protocol_map_[server] = alternate; +} + +void HttpServerPropertiesImpl::SetBrokenAlternateProtocol( + const HostPortPair& server) { + alternate_protocol_map_[server].protocol = ALTERNATE_PROTOCOL_BROKEN; +} + +const AlternateProtocolMap& +HttpServerPropertiesImpl::alternate_protocol_map() const { + return alternate_protocol_map_; +} + +const SettingsMap& HttpServerPropertiesImpl::GetSpdySettings( + const HostPortPair& host_port_pair) const { + SpdySettingsMap::const_iterator it = spdy_settings_map_.find(host_port_pair); + if (it == spdy_settings_map_.end()) { + CR_DEFINE_STATIC_LOCAL(SettingsMap, kEmptySettingsMap, ()); + return kEmptySettingsMap; + } + return it->second; +} + +bool HttpServerPropertiesImpl::SetSpdySetting( + const HostPortPair& host_port_pair, + SpdySettingsIds id, + SpdySettingsFlags flags, + uint32 value) { + if (!(flags & SETTINGS_FLAG_PLEASE_PERSIST)) + return false; + + SettingsMap& settings_map = spdy_settings_map_[host_port_pair]; + SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value); + settings_map[id] = flags_and_value; + return true; +} + +void HttpServerPropertiesImpl::ClearSpdySettings( + const HostPortPair& host_port_pair) { + spdy_settings_map_.erase(host_port_pair); +} + +void HttpServerPropertiesImpl::ClearAllSpdySettings() { + spdy_settings_map_.clear(); +} + +const SpdySettingsMap& +HttpServerPropertiesImpl::spdy_settings_map() const { + return spdy_settings_map_; +} + +HttpPipelinedHostCapability HttpServerPropertiesImpl::GetPipelineCapability( + const HostPortPair& origin) { + HttpPipelinedHostCapability capability = PIPELINE_UNKNOWN; + CachedPipelineCapabilityMap::const_iterator it = + pipeline_capability_map_->Get(origin); + if (it != pipeline_capability_map_->end()) { + capability = it->second; + } + return capability; +} + +void HttpServerPropertiesImpl::SetPipelineCapability( + const HostPortPair& origin, + HttpPipelinedHostCapability capability) { + CachedPipelineCapabilityMap::iterator it = + pipeline_capability_map_->Peek(origin); + if (it == pipeline_capability_map_->end() || + it->second != PIPELINE_INCAPABLE) { + pipeline_capability_map_->Put(origin, capability); + } +} + +void HttpServerPropertiesImpl::ClearPipelineCapabilities() { + pipeline_capability_map_->Clear(); +} + +PipelineCapabilityMap +HttpServerPropertiesImpl::GetPipelineCapabilityMap() const { + PipelineCapabilityMap result; + CachedPipelineCapabilityMap::const_iterator it; + for (it = pipeline_capability_map_->begin(); + it != pipeline_capability_map_->end(); ++it) { + result[it->first] = it->second; + } + return result; +} + +} // namespace net |