Chromium Code Reviews| 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..2aabdca8691aa8a145bea7dd77f728d5621e1131 |
| --- /dev/null |
| +++ b/net/socket/websocket_transport_client_socket_pool.h |
| @@ -0,0 +1,227 @@ |
| +// 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_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ |
| +#define NET_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ |
| + |
| +#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/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; |
| + |
| +typedef base::Callback<int(const AddressList&, const BoundNetLog& net_log)> |
| + OnHostResolutionCallback; |
| + |
| +class WebSocketEndpointLockManager; |
| + |
| +// 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 a 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: |
| + class SubJob; |
| + friend class SubJob; |
| + friend class TransportConnectJobCommon; |
| + 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, SubJob* 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; |
| + |
| + TransportConnectJobCommon data_; |
| + |
| + // 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<SubJob> ipv4_job_; |
| + scoped_ptr<SubJob> ipv6_job_; |
| + |
| + base::OneShotTimer<WebSocketTransportConnectJob> fallback_timer_; |
| + TransportConnectJobCommon::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: |
| + typedef TransportSocketParams SocketParams; |
|
tyoshino (SeeGerritForStatus)
2014/06/11 06:46:45
remove?
Adam Rice
2014/06/11 08:17:09
Done.
|
| + |
| + 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; |
| + virtual void AddHigherLayeredPool(HigherLayeredPool* higher_pool) OVERRIDE; |
| + virtual void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) 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); |
| + }; |
| + friend class ConnectJobDelegate; |
| + typedef std::map<const ClientSocketHandle*, WebSocketTransportConnectJob*> |
| + PendingConnectsMap; |
| + |
| + 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); |
| + void CancelJob(ClientSocketHandle* handle); |
| + void CancelAllConnectJobs(); |
| + const WebSocketTransportConnectJob* LookupConnectJob( |
| + const ClientSocketHandle* handle) const; |
| + |
| + ConnectJobDelegate connect_job_delegate_; |
| + std::set<HigherLayeredPool*> higher_pools_; |
| + std::set<const ClientSocketHandle*> pending_callbacks_; |
| + PendingConnectsMap pending_connects_; |
| + 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 is_stalled_; |
| + |
| + base::WeakPtrFactory<WebSocketTransportClientSocketPool> weak_factory_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WebSocketTransportClientSocketPool); |
| +}; |
| + |
| +} // namespace net |
| + |
| +#endif // NET_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ |