Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Unified Diff: net/socket/websocket_transport_client_socket_pool.h

Issue 240873003: Create WebSocketTransportClientSocketPool (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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_

Powered by Google App Engine
This is Rietveld 408576698