Home | History | Annotate | Download | only in http
      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
      3 // found in the LICENSE file.
      4 
      5 #include "net/http/http_pipelined_host_pool.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/stl_util.h"
      9 #include "base/values.h"
     10 #include "net/http/http_pipelined_host_capability.h"
     11 #include "net/http/http_pipelined_host_forced.h"
     12 #include "net/http/http_pipelined_host_impl.h"
     13 #include "net/http/http_server_properties.h"
     14 
     15 namespace net {
     16 
     17 class HttpPipelinedHostImplFactory : public HttpPipelinedHost::Factory {
     18  public:
     19   virtual HttpPipelinedHost* CreateNewHost(
     20       HttpPipelinedHost::Delegate* delegate,
     21       const HttpPipelinedHost::Key& key,
     22       HttpPipelinedConnection::Factory* factory,
     23       HttpPipelinedHostCapability capability,
     24       bool force_pipelining) OVERRIDE {
     25     if (force_pipelining) {
     26       return new HttpPipelinedHostForced(delegate, key, factory);
     27     } else {
     28       return new HttpPipelinedHostImpl(delegate, key, factory, capability);
     29     }
     30   }
     31 };
     32 
     33 HttpPipelinedHostPool::HttpPipelinedHostPool(
     34     Delegate* delegate,
     35     HttpPipelinedHost::Factory* factory,
     36     const base::WeakPtr<HttpServerProperties>& http_server_properties,
     37     bool force_pipelining)
     38     : delegate_(delegate),
     39       factory_(factory),
     40       http_server_properties_(http_server_properties),
     41       force_pipelining_(force_pipelining) {
     42   if (!factory) {
     43     factory_.reset(new HttpPipelinedHostImplFactory);
     44   }
     45 }
     46 
     47 HttpPipelinedHostPool::~HttpPipelinedHostPool() {
     48   CHECK(host_map_.empty());
     49 }
     50 
     51 bool HttpPipelinedHostPool::IsKeyEligibleForPipelining(
     52     const HttpPipelinedHost::Key& key) {
     53   HttpPipelinedHostCapability capability =
     54       http_server_properties_->GetPipelineCapability(key.origin());
     55   return capability != PIPELINE_INCAPABLE;
     56 }
     57 
     58 HttpPipelinedStream* HttpPipelinedHostPool::CreateStreamOnNewPipeline(
     59     const HttpPipelinedHost::Key& key,
     60     ClientSocketHandle* connection,
     61     const SSLConfig& used_ssl_config,
     62     const ProxyInfo& used_proxy_info,
     63     const BoundNetLog& net_log,
     64     bool was_npn_negotiated,
     65     NextProto protocol_negotiated) {
     66   HttpPipelinedHost* host = GetPipelinedHost(key, true);
     67   if (!host) {
     68     return NULL;
     69   }
     70   return host->CreateStreamOnNewPipeline(connection, used_ssl_config,
     71                                          used_proxy_info, net_log,
     72                                          was_npn_negotiated,
     73                                          protocol_negotiated);
     74 }
     75 
     76 HttpPipelinedStream* HttpPipelinedHostPool::CreateStreamOnExistingPipeline(
     77     const HttpPipelinedHost::Key& key) {
     78   HttpPipelinedHost* host = GetPipelinedHost(key, false);
     79   if (!host) {
     80     return NULL;
     81   }
     82   return host->CreateStreamOnExistingPipeline();
     83 }
     84 
     85 bool HttpPipelinedHostPool::IsExistingPipelineAvailableForKey(
     86     const HttpPipelinedHost::Key& key) {
     87   HttpPipelinedHost* host = GetPipelinedHost(key, false);
     88   if (!host) {
     89     return false;
     90   }
     91   return host->IsExistingPipelineAvailable();
     92 }
     93 
     94 HttpPipelinedHost* HttpPipelinedHostPool::GetPipelinedHost(
     95     const HttpPipelinedHost::Key& key, bool create_if_not_found) {
     96   HostMap::iterator host_it = host_map_.find(key);
     97   if (host_it != host_map_.end()) {
     98     CHECK(host_it->second);
     99     return host_it->second;
    100   } else if (!create_if_not_found) {
    101     return NULL;
    102   }
    103 
    104   HttpPipelinedHostCapability capability =
    105       http_server_properties_->GetPipelineCapability(key.origin());
    106   if (capability == PIPELINE_INCAPABLE) {
    107     return NULL;
    108   }
    109 
    110   HttpPipelinedHost* host = factory_->CreateNewHost(
    111       this, key, NULL, capability, force_pipelining_);
    112   host_map_[key] = host;
    113   return host;
    114 }
    115 
    116 void HttpPipelinedHostPool::OnHostIdle(HttpPipelinedHost* host) {
    117   const HttpPipelinedHost::Key& key = host->GetKey();
    118   CHECK(ContainsKey(host_map_, key));
    119   host_map_.erase(key);
    120   delete host;
    121 }
    122 
    123 void HttpPipelinedHostPool::OnHostHasAdditionalCapacity(
    124     HttpPipelinedHost* host) {
    125   delegate_->OnHttpPipelinedHostHasAdditionalCapacity(host);
    126 }
    127 
    128 void HttpPipelinedHostPool::OnHostDeterminedCapability(
    129     HttpPipelinedHost* host,
    130     HttpPipelinedHostCapability capability) {
    131   http_server_properties_->SetPipelineCapability(host->GetKey().origin(),
    132                                                  capability);
    133 }
    134 
    135 base::Value* HttpPipelinedHostPool::PipelineInfoToValue() const {
    136   base::ListValue* list = new base::ListValue();
    137   for (HostMap::const_iterator it = host_map_.begin();
    138        it != host_map_.end(); ++it) {
    139     base::Value* value = it->second->PipelineInfoToValue();
    140     list->Append(value);
    141   }
    142   return list;
    143 }
    144 
    145 }  // namespace net
    146