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