| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_server_properties_impl.h" | 5 #include "net/http/http_server_properties_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 it != spdy_servers->rend(); ++it) { | 46 it != spdy_servers->rend(); ++it) { |
| 47 spdy_servers_map_.Put(*it, support_spdy); | 47 spdy_servers_map_.Put(*it, support_spdy); |
| 48 } | 48 } |
| 49 } | 49 } |
| 50 | 50 |
| 51 void HttpServerPropertiesImpl::InitializeAlternateProtocolServers( | 51 void HttpServerPropertiesImpl::InitializeAlternateProtocolServers( |
| 52 AlternateProtocolMap* alternate_protocol_map) { | 52 AlternateProtocolMap* alternate_protocol_map) { |
| 53 // Keep all the broken ones since those don't get persisted. | 53 // Keep all the broken ones since those don't get persisted. |
| 54 for (AlternateProtocolMap::iterator it = alternate_protocol_map_.begin(); | 54 for (AlternateProtocolMap::iterator it = alternate_protocol_map_.begin(); |
| 55 it != alternate_protocol_map_.end();) { | 55 it != alternate_protocol_map_.end();) { |
| 56 if (it->second.is_broken) { | 56 const AlternativeService alternative_service( |
| 57 it->second.protocol, it->first.host(), it->second.port); |
| 58 if (IsAlternativeServiceBroken(alternative_service)) { |
| 57 ++it; | 59 ++it; |
| 58 } else { | 60 } else { |
| 59 it = alternate_protocol_map_.Erase(it); | 61 it = alternate_protocol_map_.Erase(it); |
| 60 } | 62 } |
| 61 } | 63 } |
| 62 | 64 |
| 63 // Add the entries from persisted data. | 65 // Add the entries from persisted data. |
| 64 for (AlternateProtocolMap::reverse_iterator it = | 66 for (AlternateProtocolMap::reverse_iterator it = |
| 65 alternate_protocol_map->rbegin(); | 67 alternate_protocol_map->rbegin(); |
| 66 it != alternate_protocol_map->rend(); ++it) { | 68 it != alternate_protocol_map->rend(); ++it) { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 | 250 |
| 249 AlternateProtocolInfo uninitialized_alternate_protocol; | 251 AlternateProtocolInfo uninitialized_alternate_protocol; |
| 250 return uninitialized_alternate_protocol; | 252 return uninitialized_alternate_protocol; |
| 251 } | 253 } |
| 252 | 254 |
| 253 void HttpServerPropertiesImpl::SetAlternateProtocol( | 255 void HttpServerPropertiesImpl::SetAlternateProtocol( |
| 254 const HostPortPair& server, | 256 const HostPortPair& server, |
| 255 uint16 alternate_port, | 257 uint16 alternate_port, |
| 256 AlternateProtocol alternate_protocol, | 258 AlternateProtocol alternate_protocol, |
| 257 double alternate_probability) { | 259 double alternate_probability) { |
| 260 const AlternativeService alternative_service(alternate_protocol, |
| 261 server.host(), alternate_port); |
| 262 if (IsAlternativeServiceBroken(alternative_service)) { |
| 263 DVLOG(1) << "Ignore alternative service since it is known to be broken."; |
| 264 return; |
| 265 } |
| 258 | 266 |
| 259 AlternateProtocolInfo alternate(alternate_port, | 267 const AlternateProtocolInfo alternate(alternate_port, alternate_protocol, |
| 260 alternate_protocol, | 268 alternate_probability); |
| 261 alternate_probability); | |
| 262 AlternateProtocolMap::const_iterator it = | 269 AlternateProtocolMap::const_iterator it = |
| 263 GetAlternateProtocolIterator(server); | 270 GetAlternateProtocolIterator(server); |
| 264 if (it != alternate_protocol_map_.end()) { | 271 if (it != alternate_protocol_map_.end()) { |
| 265 const AlternateProtocolInfo existing_alternate = it->second; | 272 const AlternateProtocolInfo existing_alternate = it->second; |
| 266 | 273 |
| 267 if (existing_alternate.is_broken) { | |
| 268 DVLOG(1) << "Ignore alternate protocol since it's known to be broken."; | |
| 269 return; | |
| 270 } | |
| 271 | |
| 272 if (!existing_alternate.Equals(alternate)) { | 274 if (!existing_alternate.Equals(alternate)) { |
| 273 LOG(WARNING) << "Changing the alternate protocol for: " | 275 LOG(WARNING) << "Changing the alternate protocol for: " |
| 274 << server.ToString() | 276 << server.ToString() |
| 275 << " from [Port: " << existing_alternate.port | 277 << " from [Port: " << existing_alternate.port |
| 276 << ", Protocol: " << existing_alternate.protocol | 278 << ", Protocol: " << existing_alternate.protocol |
| 277 << ", Probability: " << existing_alternate.probability | 279 << ", Probability: " << existing_alternate.probability |
| 278 << "] to [Port: " << alternate_port | 280 << "] to [Port: " << alternate_port |
| 279 << ", Protocol: " << alternate_protocol | 281 << ", Protocol: " << alternate_protocol |
| 280 << ", Probability: " << alternate_probability | 282 << ", Probability: " << alternate_probability |
| 281 << "]."; | 283 << "]."; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 310 if (it == alternate_protocol_map_.end()) { | 312 if (it == alternate_protocol_map_.end()) { |
| 311 if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) { | 313 if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| 312 LOG(DFATAL) << "Trying to mark unknown alternate protocol broken."; | 314 LOG(DFATAL) << "Trying to mark unknown alternate protocol broken."; |
| 313 return; | 315 return; |
| 314 } | 316 } |
| 315 // This server's alternate protocol information is coming from a canonical | 317 // This server's alternate protocol information is coming from a canonical |
| 316 // server. Add an entry in the map for this server explicitly so that | 318 // server. Add an entry in the map for this server explicitly so that |
| 317 // it can be marked as broken. | 319 // it can be marked as broken. |
| 318 it = alternate_protocol_map_.Put(server, alternate); | 320 it = alternate_protocol_map_.Put(server, alternate); |
| 319 } | 321 } |
| 320 it->second.is_broken = true; | |
| 321 const AlternativeService alternative_service(alternate.protocol, | 322 const AlternativeService alternative_service(alternate.protocol, |
| 322 server.host(), alternate.port); | 323 server.host(), alternate.port); |
| 323 int count = ++recently_broken_alternative_services_[alternative_service]; | 324 int count = ++recently_broken_alternative_services_[alternative_service]; |
| 324 base::TimeDelta delay = | 325 base::TimeDelta delay = |
| 325 base::TimeDelta::FromSeconds(kBrokenAlternateProtocolDelaySecs); | 326 base::TimeDelta::FromSeconds(kBrokenAlternateProtocolDelaySecs); |
| 326 base::TimeTicks when = base::TimeTicks::Now() + delay * (1 << (count - 1)); | 327 base::TimeTicks when = base::TimeTicks::Now() + delay * (1 << (count - 1)); |
| 327 auto result = broken_alternative_services_.insert( | 328 auto result = broken_alternative_services_.insert( |
| 328 std::make_pair(alternative_service, when)); | 329 std::make_pair(alternative_service, when)); |
| 329 // Return if alternative service is already in expiration queue. | 330 // Return if alternative service is already in expiration queue. |
| 330 if (!result.second) { | 331 if (!result.second) { |
| 331 return; | 332 return; |
| 332 } | 333 } |
| 333 | 334 |
| 334 // Do not leave this host as canonical so that we don't infer the other | 335 // Do not leave this host as canonical so that we don't infer the other |
| 335 // hosts are also broken without testing them first. | 336 // hosts are also broken without testing them first. |
| 336 RemoveCanonicalHost(server); | 337 RemoveCanonicalHost(server); |
| 337 | 338 |
| 338 // If this is the only entry in the list, schedule an expiration task. | 339 // If this is the only entry in the list, schedule an expiration task. |
| 339 // Otherwise it will be rescheduled automatically when the pending task runs. | 340 // Otherwise it will be rescheduled automatically when the pending task runs. |
| 340 if (broken_alternative_services_.size() == 1) { | 341 if (broken_alternative_services_.size() == 1) { |
| 341 ScheduleBrokenAlternateProtocolMappingsExpiration(); | 342 ScheduleBrokenAlternateProtocolMappingsExpiration(); |
| 342 } | 343 } |
| 343 } | 344 } |
| 344 | 345 |
| 346 bool HttpServerPropertiesImpl::IsAlternativeServiceBroken( |
| 347 const AlternativeService& alternative_service) { |
| 348 return ContainsKey(broken_alternative_services_, alternative_service); |
| 349 } |
| 350 |
| 345 bool HttpServerPropertiesImpl::WasAlternateProtocolRecentlyBroken( | 351 bool HttpServerPropertiesImpl::WasAlternateProtocolRecentlyBroken( |
| 346 const HostPortPair& server) { | 352 const HostPortPair& server) { |
| 347 const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server); | 353 const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server); |
| 348 if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) | 354 if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) |
| 349 return false; | 355 return false; |
| 350 const AlternativeService alternative_service( | 356 const AlternativeService alternative_service( |
| 351 alternate_protocol.protocol, server.host(), alternate_protocol.port); | 357 alternate_protocol.protocol, server.host(), alternate_protocol.port); |
| 352 return ContainsKey(recently_broken_alternative_services_, | 358 return ContainsKey(recently_broken_alternative_services_, |
| 353 alternative_service); | 359 alternative_service); |
| 354 } | 360 } |
| 355 | 361 |
| 356 void HttpServerPropertiesImpl::ConfirmAlternateProtocol( | 362 void HttpServerPropertiesImpl::ConfirmAlternateProtocol( |
| 357 const HostPortPair& server) { | 363 const HostPortPair& server) { |
| 358 const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server); | 364 const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server); |
| 359 if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) | 365 if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) |
| 360 return; | 366 return; |
| 361 const AlternativeService alternative_service( | 367 const AlternativeService alternative_service( |
| 362 alternate_protocol.protocol, server.host(), alternate_protocol.port); | 368 alternate_protocol.protocol, server.host(), alternate_protocol.port); |
| 369 broken_alternative_services_.erase(alternative_service); |
| 363 recently_broken_alternative_services_.erase(alternative_service); | 370 recently_broken_alternative_services_.erase(alternative_service); |
| 364 } | 371 } |
| 365 | 372 |
| 366 void HttpServerPropertiesImpl::ClearAlternateProtocol( | 373 void HttpServerPropertiesImpl::ClearAlternateProtocol( |
| 367 const HostPortPair& server) { | 374 const HostPortPair& server) { |
| 375 RemoveCanonicalHost(server); |
| 376 |
| 368 AlternateProtocolMap::iterator it = alternate_protocol_map_.Peek(server); | 377 AlternateProtocolMap::iterator it = alternate_protocol_map_.Peek(server); |
| 369 if (it != alternate_protocol_map_.end()) | 378 if (it == alternate_protocol_map_.end()) { |
| 370 alternate_protocol_map_.Erase(it); | 379 return; |
| 380 } |
| 381 const AlternativeService alternative_service( |
| 382 it->second.protocol, it->first.host(), it->second.port); |
| 383 alternate_protocol_map_.Erase(it); |
| 371 | 384 |
| 372 RemoveCanonicalHost(server); | 385 // The following is temporary to keep the existing semantics, which is that if |
| 386 // there is a broken alternative service in the mapping, then this method |
| 387 // leaves it in a non-broken, but recently broken state. |
| 388 // |
| 389 // TODO(bnc): |
| 390 // 1. Verify and document the class invariant that no broken alternative |
| 391 // service can be in the mapping. |
| 392 // 2. Remove the rest of this method as it will be moot. |
| 393 // 3. Provide a SetAlternativeServiceRecentlyBroken if necessary. |
| 394 ignore_result(broken_alternative_services_.erase(alternative_service)); |
| 373 } | 395 } |
| 374 | 396 |
| 375 const AlternateProtocolMap& | 397 const AlternateProtocolMap& |
| 376 HttpServerPropertiesImpl::alternate_protocol_map() const { | 398 HttpServerPropertiesImpl::alternate_protocol_map() const { |
| 377 return alternate_protocol_map_; | 399 return alternate_protocol_map_; |
| 378 } | 400 } |
| 379 | 401 |
| 380 const SettingsMap& HttpServerPropertiesImpl::GetSpdySettings( | 402 const SettingsMap& HttpServerPropertiesImpl::GetSpdySettings( |
| 381 const HostPortPair& host_port_pair) { | 403 const HostPortPair& host_port_pair) { |
| 382 SpdySettingsMap::iterator it = spdy_settings_map_.Get(host_port_pair); | 404 SpdySettingsMap::iterator it = spdy_settings_map_.Get(host_port_pair); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 base::TimeDelta delay = when > now ? when - now : base::TimeDelta(); | 556 base::TimeDelta delay = when > now ? when - now : base::TimeDelta(); |
| 535 base::MessageLoop::current()->PostDelayedTask( | 557 base::MessageLoop::current()->PostDelayedTask( |
| 536 FROM_HERE, | 558 FROM_HERE, |
| 537 base::Bind( | 559 base::Bind( |
| 538 &HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings, | 560 &HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings, |
| 539 weak_ptr_factory_.GetWeakPtr()), | 561 weak_ptr_factory_.GetWeakPtr()), |
| 540 delay); | 562 delay); |
| 541 } | 563 } |
| 542 | 564 |
| 543 } // namespace net | 565 } // namespace net |
| OLD | NEW |