15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NET_SOCKET_CLIENT_SOCKET_POOL_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NET_SOCKET_CLIENT_SOCKET_POOL_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/template_util.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_states.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/request_priority.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/host_resolver.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DictionaryValue; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClientSocketHandle; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClientSocketPoolHistograms; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StreamSocket; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ClientSocketPools are layered. This defines an interface for lower level 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// socket pools to communicate with higher layer pools. 343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class NET_EXPORT HigherLayeredPool { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) virtual ~HigherLayeredPool() {} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Instructs the HigherLayeredPool to close an idle connection. Return true if 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // one was closed. Closing an idle connection will call into the lower layer 403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // pool it came from, so must be careful of re-entrancy when using this. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool CloseOneIdleConnection() = 0; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// ClientSocketPools are layered. This defines an interface for higher level 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// socket pools to communicate with lower layer pools. 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class NET_EXPORT LowerLayeredPool { 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public: 483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) virtual ~LowerLayeredPool() {} 493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Returns true if a there is currently a request blocked on the per-pool 513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // (not per-host) max socket limit, either in this pool, or one that it is 523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // layered on top of. 533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) virtual bool IsStalled() const = 0; 543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Called to add or remove a higher layer pool on top of |this|. A higher 563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // layer pool may be added at most once to |this|, and must be removed prior 573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // to destruction of |this|. 583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) virtual void AddHigherLayeredPool(HigherLayeredPool* higher_pool) = 0; 593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) virtual void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) = 0; 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A ClientSocketPool is used to restrict the number of sockets open at a time. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It also maintains a list of idle persistent sockets. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class NET_EXPORT ClientSocketPool : public LowerLayeredPool { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Subclasses must also have an inner class SocketParams which is 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // the type for the |params| argument in RequestSocket() and 693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // RequestSockets() below. 703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Requests a connected socket for a group_name. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There are five possible results from calling this function: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1) RequestSocket returns OK and initializes |handle| with a reused socket. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2) RequestSocket returns OK with a newly connected socket. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3) RequestSocket returns ERR_IO_PENDING. The handle will be added to a 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wait list until a socket is available to reuse or a new socket finishes 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // connecting. |priority| will determine the placement into the wait list. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4) An error occurred early on, so RequestSocket returns an error code. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5) A recoverable error occurred while setting up the socket. An error 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // code is returned, but the |handle| is initialized with the new socket. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The caller must recover from the error before using the connection, or 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disconnect the socket before releasing or resetting the |handle|. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current recoverable errors are: the errors accepted by 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IsCertificateError(err) and PROXY_AUTH_REQUESTED, or 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HTTPS_PROXY_TUNNEL_RESPONSE when reported by HttpProxyClientSocketPool. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this function returns OK, then |handle| is initialized upon return. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The |handle|'s is_initialized method will return true in this case. If a 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // StreamSocket was reused, then ClientSocketPool will call 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |handle|->set_reused(true). In either case, the socket will have been 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allocated and will be connected. A client might want to know whether or 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not the socket is reused in order to request a new socket if he encounters 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an error with the reused socket. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If ERR_IO_PENDING is returned, then the callback will be used to notify the 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // client of completion. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Profiling information for the request is saved to |net_log| if non-NULL. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int RequestSocket(const std::string& group_name, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* params, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestPriority priority, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSocketHandle* handle, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& net_log) = 0; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RequestSockets is used to request that |num_sockets| be connected in the 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // connection group for |group_name|. If the connection group already has 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |num_sockets| idle sockets / active sockets / currently connecting sockets, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then this function doesn't do anything. Otherwise, it will start up as 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // many connections as necessary to reach |num_sockets| total sockets for the 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // group. It uses |params| to control how to connect the sockets. The 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ClientSocketPool will assign a priority to the new connections, if any. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This priority will probably be lower than all others, since this method 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is intended to make sure ahead of time that |num_sockets| sockets are 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // available to talk to a host. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void RequestSockets(const std::string& group_name, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* params, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_sockets, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& net_log) = 0; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same handle parameter must be passed to this method as was passed to the 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RequestSocket call being cancelled. The associated CompletionCallback is 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not run. However, for performance, we will let one ConnectJob complete 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and go idle. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CancelRequest(const std::string& group_name, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSocketHandle* handle) = 0; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called to release a socket once the socket is no longer needed. If the 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // socket still has an established connection, then it will be added to the 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set of idle sockets to be used to satisfy future RequestSocket calls. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise, the StreamSocket is destroyed. |id| is used to differentiate 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // between updated versions of the same pool instance. The pool's id will 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change when it flushes, so it can use this |id| to discard sockets with 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mismatched ids. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ReleaseSocket(const std::string& group_name, 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<StreamSocket> socket, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id) = 0; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This flushes all state from the ClientSocketPool. This means that all 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // idle and connecting sockets are discarded with the given |error|. 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Active sockets being held by ClientSocketPool clients will be discarded 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // when released back to the pool. 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Does not flush any pools wrapped by |this|. 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void FlushWithError(int error) = 0; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called to close any idle connections held by the connection manager. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CloseIdleSockets() = 0; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The total number of idle sockets in the pool. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int IdleSocketCount() const = 0; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The total number of idle sockets in a connection group. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int IdleSocketCountInGroup(const std::string& group_name) const = 0; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine the LoadState of a connecting ClientSocketHandle. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual LoadState GetLoadState(const std::string& group_name, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ClientSocketHandle* handle) const = 0; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieves information on the current state of the pool as a 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DictionaryValue. Caller takes possession of the returned value. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |include_nested_pools| is true, the states of any nested 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ClientSocketPools will be included. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual base::DictionaryValue* GetInfoAsValue( 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& type, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool include_nested_pools) const = 0; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the maximum amount of time to wait before retrying a connect. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kMaxConnectRetryIntervalMs = 250; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The set of histograms specific to this pool. We can't use the standard 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // UMA_HISTOGRAM_* macros because they are callsite static. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ClientSocketPoolHistograms* histograms() const = 0; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static base::TimeDelta unused_idle_socket_timeout(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void set_unused_idle_socket_timeout(base::TimeDelta timeout); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static base::TimeDelta used_idle_socket_timeout(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void set_used_idle_socket_timeout(base::TimeDelta timeout); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSocketPool(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ClientSocketPool(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return the connection timeout for this pool. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual base::TimeDelta ConnectionTimeout() const = 0; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)template <typename PoolType> 1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void RequestSocketsForPool( 1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PoolType* pool, 1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& group_name, 1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const scoped_refptr<typename PoolType::SocketParams>& params, 1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int num_sockets, 2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const BoundNetLog& net_log) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pool->RequestSockets(group_name, ¶ms, num_sockets, net_log); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // NET_SOCKET_CLIENT_SOCKET_POOL_H_ 207