普通文本  |  146行  |  4.52 KB

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/http_pipelined_host_pool.h"

#include "base/logging.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "net/http/http_pipelined_host_capability.h"
#include "net/http/http_pipelined_host_forced.h"
#include "net/http/http_pipelined_host_impl.h"
#include "net/http/http_server_properties.h"

namespace net {

class HttpPipelinedHostImplFactory : public HttpPipelinedHost::Factory {
 public:
  virtual HttpPipelinedHost* CreateNewHost(
      HttpPipelinedHost::Delegate* delegate,
      const HttpPipelinedHost::Key& key,
      HttpPipelinedConnection::Factory* factory,
      HttpPipelinedHostCapability capability,
      bool force_pipelining) OVERRIDE {
    if (force_pipelining) {
      return new HttpPipelinedHostForced(delegate, key, factory);
    } else {
      return new HttpPipelinedHostImpl(delegate, key, factory, capability);
    }
  }
};

HttpPipelinedHostPool::HttpPipelinedHostPool(
    Delegate* delegate,
    HttpPipelinedHost::Factory* factory,
    const base::WeakPtr<HttpServerProperties>& http_server_properties,
    bool force_pipelining)
    : delegate_(delegate),
      factory_(factory),
      http_server_properties_(http_server_properties),
      force_pipelining_(force_pipelining) {
  if (!factory) {
    factory_.reset(new HttpPipelinedHostImplFactory);
  }
}

HttpPipelinedHostPool::~HttpPipelinedHostPool() {
  CHECK(host_map_.empty());
}

bool HttpPipelinedHostPool::IsKeyEligibleForPipelining(
    const HttpPipelinedHost::Key& key) {
  HttpPipelinedHostCapability capability =
      http_server_properties_->GetPipelineCapability(key.origin());
  return capability != PIPELINE_INCAPABLE;
}

HttpPipelinedStream* HttpPipelinedHostPool::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) {
  HttpPipelinedHost* host = GetPipelinedHost(key, true);
  if (!host) {
    return NULL;
  }
  return host->CreateStreamOnNewPipeline(connection, used_ssl_config,
                                         used_proxy_info, net_log,
                                         was_npn_negotiated,
                                         protocol_negotiated);
}

HttpPipelinedStream* HttpPipelinedHostPool::CreateStreamOnExistingPipeline(
    const HttpPipelinedHost::Key& key) {
  HttpPipelinedHost* host = GetPipelinedHost(key, false);
  if (!host) {
    return NULL;
  }
  return host->CreateStreamOnExistingPipeline();
}

bool HttpPipelinedHostPool::IsExistingPipelineAvailableForKey(
    const HttpPipelinedHost::Key& key) {
  HttpPipelinedHost* host = GetPipelinedHost(key, false);
  if (!host) {
    return false;
  }
  return host->IsExistingPipelineAvailable();
}

HttpPipelinedHost* HttpPipelinedHostPool::GetPipelinedHost(
    const HttpPipelinedHost::Key& key, bool create_if_not_found) {
  HostMap::iterator host_it = host_map_.find(key);
  if (host_it != host_map_.end()) {
    CHECK(host_it->second);
    return host_it->second;
  } else if (!create_if_not_found) {
    return NULL;
  }

  HttpPipelinedHostCapability capability =
      http_server_properties_->GetPipelineCapability(key.origin());
  if (capability == PIPELINE_INCAPABLE) {
    return NULL;
  }

  HttpPipelinedHost* host = factory_->CreateNewHost(
      this, key, NULL, capability, force_pipelining_);
  host_map_[key] = host;
  return host;
}

void HttpPipelinedHostPool::OnHostIdle(HttpPipelinedHost* host) {
  const HttpPipelinedHost::Key& key = host->GetKey();
  CHECK(ContainsKey(host_map_, key));
  host_map_.erase(key);
  delete host;
}

void HttpPipelinedHostPool::OnHostHasAdditionalCapacity(
    HttpPipelinedHost* host) {
  delegate_->OnHttpPipelinedHostHasAdditionalCapacity(host);
}

void HttpPipelinedHostPool::OnHostDeterminedCapability(
    HttpPipelinedHost* host,
    HttpPipelinedHostCapability capability) {
  http_server_properties_->SetPipelineCapability(host->GetKey().origin(),
                                                 capability);
}

base::Value* HttpPipelinedHostPool::PipelineInfoToValue() const {
  base::ListValue* list = new base::ListValue();
  for (HostMap::const_iterator it = host_map_.begin();
       it != host_map_.end(); ++it) {
    base::Value* value = it->second->PipelineInfoToValue();
    list->Append(value);
  }
  return list;
}

}  // namespace net