C++程序  |  247行  |  8.73 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.

#ifndef NET_QUIC_QUIC_STREAM_FACTORY_H_
#define NET_QUIC_QUIC_STREAM_FACTORY_H_

#include <map>
#include <string>
#include <vector>

#include "base/memory/weak_ptr.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_log.h"
#include "net/base/network_change_notifier.h"
#include "net/cert/cert_database.h"
#include "net/proxy/proxy_server.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_crypto_stream.h"
#include "net/quic/quic_http_stream.h"
#include "net/quic/quic_protocol.h"

namespace net {

class CertVerifier;
class ClientSocketFactory;
class HostResolver;
class HttpServerProperties;
class QuicClock;
class QuicClientSession;
class QuicConnectionHelper;
class QuicCryptoClientStreamFactory;
class QuicRandom;
class QuicStreamFactory;

namespace test {
class QuicStreamFactoryPeer;
}  // namespace test

// Encapsulates a pending request for a QuicHttpStream.
// If the request is still pending when it is destroyed, it will
// cancel the request with the factory.
class NET_EXPORT_PRIVATE QuicStreamRequest {
 public:
  explicit QuicStreamRequest(QuicStreamFactory* factory);
  ~QuicStreamRequest();

  // For http, |is_https| is false and |cert_verifier| can be null.
  int Request(const HostPortProxyPair& host_port_proxy_pair,
              bool is_https,
              CertVerifier* cert_verifier,
              const BoundNetLog& net_log,
              const CompletionCallback& callback);

  void OnRequestComplete(int rv);

  scoped_ptr<QuicHttpStream> ReleaseStream();

  void set_stream(scoped_ptr<QuicHttpStream> stream);

  const BoundNetLog& net_log() const{
    return net_log_;
  }

 private:
  QuicStreamFactory* factory_;
  HostPortProxyPair host_port_proxy_pair_;
  bool is_https_;
  CertVerifier* cert_verifier_;
  BoundNetLog net_log_;
  CompletionCallback callback_;
  scoped_ptr<QuicHttpStream> stream_;

  DISALLOW_COPY_AND_ASSIGN(QuicStreamRequest);
};

// A factory for creating new QuicHttpStreams on top of a pool of
// QuicClientSessions.
class NET_EXPORT_PRIVATE QuicStreamFactory
    : public NetworkChangeNotifier::IPAddressObserver,
      public CertDatabase::Observer {
 public:
  QuicStreamFactory(
      HostResolver* host_resolver,
      ClientSocketFactory* client_socket_factory,
      base::WeakPtr<HttpServerProperties> http_server_properties,
      QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
      QuicRandom* random_generator,
      QuicClock* clock,
      size_t max_packet_length);
  virtual ~QuicStreamFactory();

  // Creates a new QuicHttpStream to |host_port_proxy_pair| which will be
  // owned by |request|. |is_https| specifies if the protocol is https or not.
  // |cert_verifier| is used by ProofVerifier for verifying the certificate
  // chain and signature. For http, this can be null. If a matching session
  // already exists, this method will return OK.  If no matching session exists,
  // this will return ERR_IO_PENDING and will invoke OnRequestComplete
  // asynchronously.
  int Create(const HostPortProxyPair& host_port_proxy_pair,
             bool is_https,
             CertVerifier* cert_verifier,
             const BoundNetLog& net_log,
             QuicStreamRequest* request);

  // Returns a newly created QuicHttpStream owned by the caller, if a
  // matching session already exists.  Returns NULL otherwise.
  scoped_ptr<QuicHttpStream> CreateIfSessionExists(
      const HostPortProxyPair& host_port_proxy_pair,
      const BoundNetLog& net_log);

  // Called by a session when it becomes idle.
  void OnIdleSession(QuicClientSession* session);

  // Called by a session when it is going away and no more streams should be
  // created on it.
  void OnSessionGoingAway(QuicClientSession* session);

  // Called by a session after it shuts down.
  void OnSessionClosed(QuicClientSession* session);

  // Cancels a pending request.
  void CancelRequest(QuicStreamRequest* request);

  // Closes all current sessions.
  void CloseAllSessions(int error);

  base::Value* QuicStreamFactoryInfoToValue() const;

  // NetworkChangeNotifier::IPAddressObserver methods:

  // Until the servers support roaming, close all connections when the local
  // IP address changes.
  virtual void OnIPAddressChanged() OVERRIDE;

  // CertDatabase::Observer methods:

  // We close all sessions when certificate database is changed.
  virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE;
  virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE;

  bool require_confirmation() const { return require_confirmation_; }

  void set_require_confirmation(bool require_confirmation) {
    require_confirmation_ = require_confirmation;
  }

  QuicConnectionHelper* helper() { return helper_.get(); }

 private:
  class Job;
  friend class test::QuicStreamFactoryPeer;

  typedef std::map<HostPortProxyPair, QuicClientSession*> SessionMap;
  typedef std::set<HostPortProxyPair> AliasSet;
  typedef std::map<QuicClientSession*, AliasSet> SessionAliasMap;
  typedef std::set<QuicClientSession*> SessionSet;
  typedef std::map<HostPortProxyPair, QuicCryptoClientConfig*> CryptoConfigMap;
  typedef std::map<HostPortPair, HostPortProxyPair> CanonicalHostMap;
  typedef std::map<HostPortProxyPair, Job*> JobMap;
  typedef std::map<QuicStreamRequest*, Job*> RequestMap;
  typedef std::set<QuicStreamRequest*> RequestSet;
  typedef std::map<Job*, RequestSet> JobRequestsMap;

  void OnJobComplete(Job* job, int rv);
  bool HasActiveSession(const HostPortProxyPair& host_port_proxy_pair);
  bool HasActiveJob(const HostPortProxyPair& host_port_proxy_pair);
  int CreateSession(const HostPortProxyPair& host_port_proxy_pair,
                    bool is_https,
                    CertVerifier* cert_verifier,
                    const AddressList& address_list,
                    const BoundNetLog& net_log,
                    QuicClientSession** session);
  void ActivateSession(const HostPortProxyPair& host_port_proxy_pair,
                       QuicClientSession* session);

  QuicCryptoClientConfig* GetOrCreateCryptoConfig(
      const HostPortProxyPair& host_port_proxy_pair);

  // If |host_port_proxy_pair| suffix contains ".c.youtube.com" (in future we
  // could support other suffixes), then populate |crypto_config| with a
  // canonical server config data from |canonical_hostname_to_origin_map_| for
  // that suffix.
  void PopulateFromCanonicalConfig(
      const HostPortProxyPair& host_port_proxy_pair,
      QuicCryptoClientConfig* crypto_config);

  bool require_confirmation_;
  HostResolver* host_resolver_;
  ClientSocketFactory* client_socket_factory_;
  base::WeakPtr<HttpServerProperties> http_server_properties_;
  QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory_;
  QuicRandom* random_generator_;
  scoped_ptr<QuicClock> clock_;
  const size_t max_packet_length_;

  // The helper used for all connections.
  scoped_ptr<QuicConnectionHelper> helper_;

  // Contains owning pointers to all sessions that currently exist.
  SessionSet all_sessions_;
  // Contains non-owning pointers to currently active session
  // (not going away session, once they're implemented).
  SessionMap active_sessions_;
  SessionAliasMap session_aliases_;

  // Contains owning pointers to QuicCryptoClientConfig. QuicCryptoClientConfig
  // contains configuration and cached state about servers.
  // TODO(rtenneti): Persist all_crypto_configs_ to disk and decide when to
  // clear the data in the map.
  CryptoConfigMap all_crypto_configs_;

  // Contains a map of servers which could share the same server config. Map
  // from a Canonical host/port (host is some postfix of host names) to an
  // actual origin, which has a plausible set of initial certificates (or at
  // least server public key).
  CanonicalHostMap canonical_hostname_to_origin_map_;

  // Contains list of suffixes (for exmaple ".c.youtube.com",
  // ".googlevideo.com") of cannoncial hostnames.
  std::vector<std::string> cannoncial_suffixes_;

  QuicConfig config_;

  JobMap active_jobs_;
  JobRequestsMap job_requests_map_;
  RequestMap active_requests_;

  base::WeakPtrFactory<QuicStreamFactory> weak_factory_;

  // Each profile will (probably) have a unique port_seed_ value.  This value is
  // used to help seed a pseudo-random number generator (PortSuggester) so that
  // we consistently (within this profile) suggest the same ephemeral port when
  // we re-connect to any given server/port.  The differences between profiles
  // (probablistically) prevent two profiles from colliding in their ephemeral
  // port requests.
  uint64 port_seed_;

  DISALLOW_COPY_AND_ASSIGN(QuicStreamFactory);
};

}  // namespace net

#endif  // NET_QUIC_QUIC_STREAM_FACTORY_H_