| Index: net/socket/websocket_transport_client_socket_pool.h
|
| diff --git a/net/socket/websocket_transport_client_socket_pool.h b/net/socket/websocket_transport_client_socket_pool.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d0d2d9df22637ae28a5925690548bc7e4ae8407a
|
| --- /dev/null
|
| +++ b/net/socket/websocket_transport_client_socket_pool.h
|
| @@ -0,0 +1,245 @@
|
| +// Copyright 2014 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_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_
|
| +#define NET_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_
|
| +
|
| +#include <list>
|
| +#include <map>
|
| +#include <set>
|
| +#include <string>
|
| +
|
| +#include "base/basictypes.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/memory/weak_ptr.h"
|
| +#include "base/time/time.h"
|
| +#include "base/timer/timer.h"
|
| +#include "net/base/net_export.h"
|
| +#include "net/base/net_log.h"
|
| +#include "net/socket/client_socket_pool.h"
|
| +#include "net/socket/client_socket_pool_base.h"
|
| +#include "net/socket/transport_client_socket_pool.h"
|
| +
|
| +namespace net {
|
| +
|
| +class ClientSocketFactory;
|
| +class ClientSocketPoolHistograms;
|
| +class HostResolver;
|
| +class NetLog;
|
| +class WebSocketEndpointLockManager;
|
| +class WebSocketTransportConnectSubJob;
|
| +
|
| +// WebSocketTransportConnectJob handles the host resolution necessary for socket
|
| +// creation and the TCP connect. WebSocketTransportConnectJob also has fallback
|
| +// logic for IPv6 connect() timeouts (which may happen due to networks / routers
|
| +// with broken IPv6 support). Those timeouts take 20s, so rather than make the
|
| +// user wait 20s for the timeout to fire, we use a fallback timer
|
| +// (kIPv6FallbackTimerInMs) and start a connect() to an IPv4 address if the
|
| +// timer fires. Then we race the IPv4 connect(s) against the IPv6 connect(s) and
|
| +// use the socket that completes successfully first or fails last.
|
| +class NET_EXPORT_PRIVATE WebSocketTransportConnectJob : public ConnectJob {
|
| + public:
|
| + WebSocketTransportConnectJob(
|
| + const std::string& group_name,
|
| + RequestPriority priority,
|
| + const scoped_refptr<TransportSocketParams>& params,
|
| + base::TimeDelta timeout_duration,
|
| + const CompletionCallback& callback,
|
| + ClientSocketFactory* client_socket_factory,
|
| + HostResolver* host_resolver,
|
| + ClientSocketHandle* handle,
|
| + Delegate* delegate,
|
| + NetLog* pool_net_log,
|
| + const BoundNetLog& request_net_log);
|
| + virtual ~WebSocketTransportConnectJob();
|
| +
|
| + // Unlike normal socket pools, the WebSocketTransportClientPool uses
|
| + // early-binding of sockets.
|
| + ClientSocketHandle* handle() const { return handle_; }
|
| +
|
| + // Stash the callback from RequestSocket() here for convenience.
|
| + const CompletionCallback& callback() const { return callback_; }
|
| +
|
| + const BoundNetLog& request_net_log() const { return request_net_log_; }
|
| +
|
| + // ConnectJob methods.
|
| + virtual LoadState GetLoadState() const OVERRIDE;
|
| +
|
| + private:
|
| + friend class WebSocketTransportConnectSubJob;
|
| + friend class TransportConnectJobHelper;
|
| + friend class WebSocketEndpointLockManager;
|
| +
|
| + // Although it is not strictly necessary, it makes the code simpler if each
|
| + // subjob knows what type it is.
|
| + enum SubJobType { SUB_JOB_IPV4, SUB_JOB_IPV6 };
|
| +
|
| + int DoResolveHost();
|
| + int DoResolveHostComplete(int result);
|
| + int DoTransportConnect();
|
| + int DoTransportConnectComplete(int result);
|
| +
|
| + // Called back from a SubJob when it completes.
|
| + void OnSubJobComplete(int result, WebSocketTransportConnectSubJob* job);
|
| +
|
| + // Called from |fallback_timer_|.
|
| + void StartIPv4JobAsync();
|
| +
|
| + // Begins the host resolution and the TCP connect. Returns OK on success
|
| + // and ERR_IO_PENDING if it cannot immediately service the request.
|
| + // Otherwise, it returns a net error code.
|
| + virtual int ConnectInternal() OVERRIDE;
|
| +
|
| + TransportConnectJobHelper helper_;
|
| +
|
| + // The addresses are divided into IPv4 and IPv6, which are performed partially
|
| + // in parallel. If the list of IPv6 addresses is non-empty, then the IPv6 jobs
|
| + // go first, followed after |kIPv6FallbackTimerInMs| by the IPv4
|
| + // addresses. First sub-job to establish a connection wins.
|
| + scoped_ptr<WebSocketTransportConnectSubJob> ipv4_job_;
|
| + scoped_ptr<WebSocketTransportConnectSubJob> ipv6_job_;
|
| +
|
| + base::OneShotTimer<WebSocketTransportConnectJob> fallback_timer_;
|
| + TransportConnectJobHelper::ConnectionLatencyHistogram race_result_;
|
| + ClientSocketHandle* const handle_;
|
| + CompletionCallback callback_;
|
| + BoundNetLog request_net_log_;
|
| +
|
| + bool had_ipv4_;
|
| + bool had_ipv6_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(WebSocketTransportConnectJob);
|
| +};
|
| +
|
| +class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool
|
| + : public TransportClientSocketPool {
|
| + public:
|
| + WebSocketTransportClientSocketPool(int max_sockets,
|
| + int max_sockets_per_group,
|
| + ClientSocketPoolHistograms* histograms,
|
| + HostResolver* host_resolver,
|
| + ClientSocketFactory* client_socket_factory,
|
| + NetLog* net_log);
|
| +
|
| + virtual ~WebSocketTransportClientSocketPool();
|
| +
|
| + // Allow another connection to be started to the IPEndPoint that this |handle|
|
| + // is connected to. Used when the WebSocket handshake completes successfully.
|
| + static void UnlockEndpoint(ClientSocketHandle* handle);
|
| +
|
| + // ClientSocketPool implementation.
|
| + virtual int RequestSocket(const std::string& group_name,
|
| + const void* resolve_info,
|
| + RequestPriority priority,
|
| + ClientSocketHandle* handle,
|
| + const CompletionCallback& callback,
|
| + const BoundNetLog& net_log) OVERRIDE;
|
| + virtual void RequestSockets(const std::string& group_name,
|
| + const void* params,
|
| + int num_sockets,
|
| + const BoundNetLog& net_log) OVERRIDE;
|
| + virtual void CancelRequest(const std::string& group_name,
|
| + ClientSocketHandle* handle) OVERRIDE;
|
| + virtual void ReleaseSocket(const std::string& group_name,
|
| + scoped_ptr<StreamSocket> socket,
|
| + int id) OVERRIDE;
|
| + virtual void FlushWithError(int error) OVERRIDE;
|
| + virtual void CloseIdleSockets() OVERRIDE;
|
| + virtual int IdleSocketCount() const OVERRIDE;
|
| + virtual int IdleSocketCountInGroup(
|
| + const std::string& group_name) const OVERRIDE;
|
| + virtual LoadState GetLoadState(
|
| + const std::string& group_name,
|
| + const ClientSocketHandle* handle) const OVERRIDE;
|
| + virtual base::DictionaryValue* GetInfoAsValue(
|
| + const std::string& name,
|
| + const std::string& type,
|
| + bool include_nested_pools) const OVERRIDE;
|
| + virtual base::TimeDelta ConnectionTimeout() const OVERRIDE;
|
| + virtual ClientSocketPoolHistograms* histograms() const OVERRIDE;
|
| +
|
| + // HigherLayeredPool implementation.
|
| + virtual bool IsStalled() const OVERRIDE;
|
| +
|
| + private:
|
| + class ConnectJobDelegate : public ConnectJob::Delegate {
|
| + public:
|
| + explicit ConnectJobDelegate(WebSocketTransportClientSocketPool* owner);
|
| + virtual ~ConnectJobDelegate();
|
| +
|
| + virtual void OnConnectJobComplete(int result, ConnectJob* job) OVERRIDE;
|
| +
|
| + private:
|
| + WebSocketTransportClientSocketPool* owner_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ConnectJobDelegate);
|
| + };
|
| +
|
| + // Store the arguments from a call to RequestSocket() that has stalled so we
|
| + // can replay it when there are available socket slots.
|
| + struct StalledRequest {
|
| + StalledRequest(const scoped_refptr<TransportSocketParams>& params,
|
| + RequestPriority priority,
|
| + ClientSocketHandle* handle,
|
| + const CompletionCallback& callback,
|
| + const BoundNetLog& net_log);
|
| + ~StalledRequest();
|
| + const scoped_refptr<TransportSocketParams> params;
|
| + const RequestPriority priority;
|
| + ClientSocketHandle* const handle;
|
| + const CompletionCallback callback;
|
| + const BoundNetLog net_log;
|
| + };
|
| + friend class ConnectJobDelegate;
|
| + typedef std::map<const ClientSocketHandle*, WebSocketTransportConnectJob*>
|
| + PendingConnectsMap;
|
| + // This is a list so that we can remove requests from the middle, and also
|
| + // so that iterators are not invalidated unless the corresponding request is
|
| + // removed.
|
| + typedef std::list<StalledRequest> StalledRequestQueue;
|
| + typedef std::map<const ClientSocketHandle*, StalledRequestQueue::iterator>
|
| + StalledRequestMap;
|
| +
|
| + void OnConnectJobComplete(int result, WebSocketTransportConnectJob* job);
|
| + void InvokeUserCallbackLater(ClientSocketHandle* handle,
|
| + const CompletionCallback& callback,
|
| + int rv);
|
| + void InvokeUserCallback(ClientSocketHandle* handle,
|
| + const CompletionCallback& callback,
|
| + int rv);
|
| + bool ReachedMaxSocketsLimit() const;
|
| + void HandOutSocket(scoped_ptr<StreamSocket> socket,
|
| + const LoadTimingInfo::ConnectTiming& connect_timing,
|
| + ClientSocketHandle* handle,
|
| + const BoundNetLog& net_log);
|
| + void AddJob(ClientSocketHandle* handle,
|
| + scoped_ptr<WebSocketTransportConnectJob> connect_job);
|
| + bool DeleteJob(ClientSocketHandle* handle);
|
| + const WebSocketTransportConnectJob* LookupConnectJob(
|
| + const ClientSocketHandle* handle) const;
|
| + void ActivateStalledRequest();
|
| + bool DeleteStalledRequest(ClientSocketHandle* handle);
|
| +
|
| + ConnectJobDelegate connect_job_delegate_;
|
| + std::set<const ClientSocketHandle*> pending_callbacks_;
|
| + PendingConnectsMap pending_connects_;
|
| + StalledRequestQueue stalled_request_queue_;
|
| + StalledRequestMap stalled_request_map_;
|
| + ClientSocketPoolHistograms* const histograms_;
|
| + NetLog* const pool_net_log_;
|
| + ClientSocketFactory* const client_socket_factory_;
|
| + HostResolver* const host_resolver_;
|
| + const int max_sockets_;
|
| + int handed_out_socket_count_;
|
| + bool flushing_;
|
| +
|
| + base::WeakPtrFactory<WebSocketTransportClientSocketPool> weak_factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(WebSocketTransportClientSocketPool);
|
| +};
|
| +
|
| +} // namespace net
|
| +
|
| +#endif // NET_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_
|
|
|