• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
CreateNewHost(HttpPipelinedHost::Delegate * delegate,const HttpPipelinedHost::Key & key,HttpPipelinedConnection::Factory * factory,HttpPipelinedHostCapability capability,bool force_pipelining)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 
HttpPipelinedHostPool(Delegate * delegate,HttpPipelinedHost::Factory * factory,const base::WeakPtr<HttpServerProperties> & http_server_properties,bool force_pipelining)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 
~HttpPipelinedHostPool()47 HttpPipelinedHostPool::~HttpPipelinedHostPool() {
48   CHECK(host_map_.empty());
49 }
50 
IsKeyEligibleForPipelining(const HttpPipelinedHost::Key & key)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 
CreateStreamOnNewPipeline(const HttpPipelinedHost::Key & key,ClientSocketHandle * connection,const SSLConfig & used_ssl_config,const ProxyInfo & used_proxy_info,const BoundNetLog & net_log,bool was_npn_negotiated,NextProto protocol_negotiated)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 
CreateStreamOnExistingPipeline(const HttpPipelinedHost::Key & key)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 
IsExistingPipelineAvailableForKey(const HttpPipelinedHost::Key & key)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 
GetPipelinedHost(const HttpPipelinedHost::Key & key,bool create_if_not_found)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 
OnHostIdle(HttpPipelinedHost * host)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 
OnHostHasAdditionalCapacity(HttpPipelinedHost * host)123 void HttpPipelinedHostPool::OnHostHasAdditionalCapacity(
124     HttpPipelinedHost* host) {
125   delegate_->OnHttpPipelinedHostHasAdditionalCapacity(host);
126 }
127 
OnHostDeterminedCapability(HttpPipelinedHost * host,HttpPipelinedHostCapability capability)128 void HttpPipelinedHostPool::OnHostDeterminedCapability(
129     HttpPipelinedHost* host,
130     HttpPipelinedHostCapability capability) {
131   http_server_properties_->SetPipelineCapability(host->GetKey().origin(),
132                                                  capability);
133 }
134 
PipelineInfoToValue() const135 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