Index: net/http/http_server_properties_impl.cc |
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc |
index 9f17afc9ca054a0f9a78a2e6efd03a6db6091016..c1247dc3dbf3a9c3d20ff0be9adbdf69e77200f4 100644 |
--- a/net/http/http_server_properties_impl.cc |
+++ b/net/http/http_server_properties_impl.cc |
@@ -50,13 +50,22 @@ void HttpServerPropertiesImpl::InitializeSpdyServers( |
void HttpServerPropertiesImpl::InitializeAlternateProtocolServers( |
AlternateProtocolMap* alternate_protocol_map) { |
- // Keep all the broken ones since those don't get persisted. |
- for (AlternateProtocolMap::iterator it = alternate_protocol_map_.begin(); |
- it != alternate_protocol_map_.end();) { |
- AlternateProtocolMap::iterator old_it = it; |
- ++it; |
- if (!old_it->second.is_broken) { |
- alternate_protocol_map_.Erase(old_it); |
+ for (AlternateProtocolMap::iterator alternate_protocols = |
+ alternate_protocol_map_.begin(); |
+ alternate_protocols != alternate_protocol_map_.end();) { |
+ // Keep all the broken ones since those do not get persisted. |
+ for (AlternateProtocols::iterator it = alternate_protocols->second.begin(); |
+ it != alternate_protocols->second.end();) { |
+ if (!it->is_broken) { |
+ it = alternate_protocols->second.erase(it); |
+ } else { |
+ ++it; |
+ } |
+ } |
+ if (alternate_protocols->second.size() == 0) { |
+ alternate_protocols = alternate_protocol_map_.Erase(alternate_protocols); |
+ } else { |
+ ++alternate_protocols; |
} |
} |
@@ -176,8 +185,13 @@ bool HttpServerPropertiesImpl::SupportsRequestPriority( |
if (spdy_host_port != spdy_servers_map_.end() && spdy_host_port->second) |
return true; |
- const AlternateProtocolInfo info = GetAlternateProtocol(host_port_pair); |
- return info.protocol == QUIC; |
+ const AlternateProtocols alternates = GetAlternateProtocols(host_port_pair); |
+ for (const AlternateProtocolInfo& alternate : alternates) { |
+ if (alternate.protocol == QUIC) { |
+ return true; |
+ } |
+ } |
+ return false; |
} |
void HttpServerPropertiesImpl::SetSupportsSpdy( |
@@ -235,51 +249,68 @@ std::string HttpServerPropertiesImpl::GetCanonicalSuffix( |
return std::string(); |
} |
-AlternateProtocolInfo HttpServerPropertiesImpl::GetAlternateProtocol( |
+AlternateProtocols HttpServerPropertiesImpl::GetAlternateProtocols( |
const HostPortPair& server) { |
- AlternateProtocolMap::const_iterator it = |
+ AlternateProtocols alternate_protocols_above_threshold; |
+ AlternateProtocolMap::const_iterator const alternate_protocols = |
GetAlternateProtocolIterator(server); |
- if (it != alternate_protocol_map_.end() && |
- it->second.probability >= alternate_protocol_probability_threshold_) |
- return it->second; |
+ if (alternate_protocols != alternate_protocol_map_.end()) { |
+ for (const AlternateProtocolInfo& alternate : alternate_protocols->second) { |
+ if (alternate.probability >= alternate_protocol_probability_threshold_) |
+ alternate_protocols_above_threshold.push_back(alternate); |
+ } |
+ return alternate_protocols_above_threshold; |
+ } |
- if (g_forced_alternate_protocol) |
- return *g_forced_alternate_protocol; |
+ if (g_forced_alternate_protocol) { |
+ alternate_protocols_above_threshold.push_back(*g_forced_alternate_protocol); |
+ } |
- AlternateProtocolInfo uninitialized_alternate_protocol; |
- return uninitialized_alternate_protocol; |
+ return alternate_protocols_above_threshold; |
} |
-void HttpServerPropertiesImpl::SetAlternateProtocol( |
+void HttpServerPropertiesImpl::AddAlternateProtocol( |
const HostPortPair& server, |
uint16 alternate_port, |
AlternateProtocol alternate_protocol, |
double alternate_probability) { |
- |
+ if (!IsAlternateProtocolValid(alternate_protocol)) |
+ return; |
AlternateProtocolInfo alternate(alternate_port, |
alternate_protocol, |
alternate_probability); |
- AlternateProtocolMap::const_iterator it = |
- GetAlternateProtocolIterator(server); |
- if (it != alternate_protocol_map_.end()) { |
- const AlternateProtocolInfo existing_alternate = it->second; |
- |
- if (existing_alternate.is_broken) { |
- DVLOG(1) << "Ignore alternate protocol since it's known to be broken."; |
- return; |
+ AlternateProtocolMap::const_iterator map_it = |
+ alternate_protocol_map_.Get(server); |
+ if (map_it != alternate_protocol_map_.end()) { |
+ AlternateProtocols existing_alternates = map_it->second; |
+ AlternateProtocols::iterator it; |
+ for (it = existing_alternates.begin(); it != existing_alternates.end(); |
+ ++it) { |
+ if (it->EqualsModuloProbability(alternate)) { |
+ break; |
+ } |
} |
- if (!existing_alternate.Equals(alternate)) { |
- LOG(WARNING) << "Changing the alternate protocol for: " |
- << server.ToString() |
- << " from [Port: " << existing_alternate.port |
- << ", Protocol: " << existing_alternate.protocol |
- << ", Probability: " << existing_alternate.probability |
- << "] to [Port: " << alternate_port |
- << ", Protocol: " << alternate_protocol |
- << ", Probability: " << alternate_probability |
- << "]."; |
+ if (it != existing_alternates.end()) { |
+ if (it->is_broken) { |
+ DVLOG(1) << "Ignore alternate protocol since it's known to be broken."; |
+ return; |
+ } |
+ if (it->probability != alternate_probability) { |
+ LOG(WARNING) << "Changing alternate protocol probability from " |
+ << it->ToString() << server.ToString() |
+ << " Port: " << it->port << " to " << alternate.ToString() |
+ << "."; |
+ it->probability = alternate_probability; |
+ } else { |
+ // Alternate protocol is identical to existing one. |
+ return; |
+ } |
+ } else { |
+ existing_alternates.push_back(alternate); |
} |
+ |
+ alternate_protocol_map_.Put(server, existing_alternates); |
} else { |
if (alternate_probability >= alternate_protocol_probability_threshold_) { |
// TODO(rch): Consider the case where multiple requests are started |
@@ -287,10 +318,10 @@ void HttpServerPropertiesImpl::SetAlternateProtocol( |
// would reach this code, whereas all of them should should have. |
HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING); |
} |
+ alternate_protocol_map_.Put(server, |
+ AlternateProtocols(/*size=*/1, alternate)); |
} |
- alternate_protocol_map_.Put(server, alternate); |
- |
// If this host ends with a canonical suffix, then set it as the |
// canonical host. |
for (size_t i = 0; i < canonical_suffixes_.size(); ++i) { |
@@ -304,22 +335,29 @@ void HttpServerPropertiesImpl::SetAlternateProtocol( |
} |
void HttpServerPropertiesImpl::SetBrokenAlternateProtocol( |
- const HostPortPair& server) { |
- AlternateProtocolMap::iterator it = alternate_protocol_map_.Get(server); |
- const AlternateProtocolInfo alternate = GetAlternateProtocol(server); |
- if (it == alternate_protocol_map_.end()) { |
- if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) { |
- LOG(DFATAL) << "Trying to mark unknown alternate protocol broken."; |
- return; |
+ const HostPortPair& server, |
+ const AlternateProtocolInfo& broken_alternate_protocol) { |
+ if (!IsAlternateProtocolValid(broken_alternate_protocol.protocol)) |
+ return; |
+ AddAlternateProtocol(server, broken_alternate_protocol.port, |
+ broken_alternate_protocol.protocol, |
+ broken_alternate_protocol.probability); |
+ AlternateProtocolMap::iterator alternate_protocols = |
+ alternate_protocol_map_.Get(server); |
+ DCHECK(alternate_protocols != alternate_protocol_map_.end()); |
+ AlternateProtocols::iterator it; |
+ for (it = alternate_protocols->second.begin(); |
+ it != alternate_protocols->second.end(); ++it) { |
+ if (it->Equals(broken_alternate_protocol)) { |
+ it->is_broken = true; |
+ break; |
} |
- // This server's alternate protocol information is coming from a canonical |
- // server. Add an entry in the map for this server explicitly so that |
- // it can be marked as broken. |
- it = alternate_protocol_map_.Put(server, alternate); |
} |
- it->second.is_broken = true; |
- const BrokenAlternateProtocolEntry entry(server, alternate.port, |
- alternate.protocol); |
+ DCHECK(it != alternate_protocols->second.end()); |
+ |
+ const BrokenAlternateProtocolEntry entry(server, |
+ broken_alternate_protocol.port, |
+ broken_alternate_protocol.protocol); |
int count = ++broken_alternate_protocol_map_[entry]; |
base::TimeDelta delay = |
base::TimeDelta::FromSeconds(kBrokenAlternateProtocolDelaySecs); |
@@ -339,26 +377,22 @@ void HttpServerPropertiesImpl::SetBrokenAlternateProtocol( |
} |
bool HttpServerPropertiesImpl::WasAlternateProtocolRecentlyBroken( |
- const HostPortPair& server) { |
- const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server); |
- if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) |
- return false; |
+ const HostPortPair& server, |
+ const AlternateProtocolInfo& alternate_protocol) const { |
const BrokenAlternateProtocolEntry entry(server, alternate_protocol.port, |
alternate_protocol.protocol); |
return ContainsKey(broken_alternate_protocol_map_, entry); |
} |
void HttpServerPropertiesImpl::ConfirmAlternateProtocol( |
- const HostPortPair& server) { |
- const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server); |
- if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) |
- return; |
+ const HostPortPair& server, |
+ const AlternateProtocolInfo& alternate_protocol) { |
const BrokenAlternateProtocolEntry entry(server, alternate_protocol.port, |
alternate_protocol.protocol); |
broken_alternate_protocol_map_.erase(entry); |
} |
-void HttpServerPropertiesImpl::ClearAlternateProtocol( |
+void HttpServerPropertiesImpl::ClearAlternateProtocols( |
const HostPortPair& server) { |
AlternateProtocolMap::iterator it = alternate_protocol_map_.Peek(server); |
if (it != alternate_protocol_map_.end()) |
@@ -367,6 +401,48 @@ void HttpServerPropertiesImpl::ClearAlternateProtocol( |
RemoveCanonicalHost(server); |
} |
+void HttpServerPropertiesImpl::ClearNonBrokenAlternateProtocols( |
+ const HostPortPair& server) { |
+ AlternateProtocolMap::iterator alternate_protocols = |
+ alternate_protocol_map_.Peek(server); |
+ if (alternate_protocols == alternate_protocol_map_.end()) { |
+ return; |
+ } |
+ for (AlternateProtocols::iterator it = alternate_protocols->second.begin(); |
+ it != alternate_protocols->second.end();) { |
+ if (!it->is_broken) { |
+ it = alternate_protocols->second.erase(it); |
+ } else { |
+ ++it; |
+ } |
+ } |
+ if (alternate_protocols->second.size() == 0) { |
+ alternate_protocol_map_.Erase(alternate_protocols); |
+ RemoveCanonicalHost(server); |
+ } |
+} |
+ |
+void HttpServerPropertiesImpl::RemoveAlternateProtocol( |
+ const HostPortPair& server, |
+ const AlternateProtocolInfo& alternate_protocol) { |
+ AlternateProtocolMap::iterator alternate_protocols = |
+ alternate_protocol_map_.Peek(server); |
+ if (alternate_protocols == alternate_protocol_map_.end()) { |
+ return; |
+ } |
+ for (AlternateProtocols::iterator it = alternate_protocols->second.begin(); |
+ it != alternate_protocols->second.end(); ++it) { |
+ if (it->EqualsModuloProbability(alternate_protocol)) { |
+ alternate_protocols->second.erase(it); |
+ break; |
+ } |
+ } |
+ if (alternate_protocols->second.size() == 0) { |
+ alternate_protocol_map_.Erase(alternate_protocols); |
+ RemoveCanonicalHost(server); |
+ } |
+} |
+ |
const AlternateProtocolMap& |
HttpServerPropertiesImpl::alternate_protocol_map() const { |
return alternate_protocol_map_; |
@@ -513,7 +589,9 @@ void HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings() { |
const BrokenAlternateProtocolEntry& entry = |
entry_with_time.broken_alternate_protocol_entry; |
- ClearAlternateProtocol(entry.server); |
+ const AlternateProtocolInfo alternate_protocol(entry.port, entry.protocol, |
+ 1.0); |
+ RemoveAlternateProtocol(entry.server, alternate_protocol); |
broken_alternate_protocol_list_.pop_front(); |
} |
ScheduleBrokenAlternateProtocolMappingsExpiration(); |