1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
// Copyright (c) 2006-2008 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_BASE_TCP_CLIENT_SOCKET_POOL_H_
#define NET_BASE_TCP_CLIENT_SOCKET_POOL_H_
#include <deque>
#include <map>
#include <string>
#include "base/scoped_ptr.h"
#include "base/timer.h"
#include "net/base/address_list.h"
#include "net/base/client_socket_pool.h"
#include "net/base/host_resolver.h"
namespace net {
class ClientSocketFactory;
// A TCPClientSocketPool is used to restrict the number of TCP sockets open at
// a time. It also maintains a list of idle persistent sockets.
//
class TCPClientSocketPool : public ClientSocketPool {
public:
TCPClientSocketPool(int max_sockets_per_group,
ClientSocketFactory* client_socket_factory);
// ClientSocketPool methods:
virtual int RequestSocket(const std::string& group_name,
const std::string& host,
int port,
int priority,
ClientSocketHandle* handle,
CompletionCallback* callback);
virtual void CancelRequest(const std::string& group_name,
const ClientSocketHandle* handle);
virtual void ReleaseSocket(const std::string& group_name,
ClientSocket* socket);
virtual void CloseIdleSockets();
virtual int idle_socket_count() const {
return idle_socket_count_;
}
virtual int IdleSocketCountInGroup(const std::string& group_name) const;
virtual LoadState GetLoadState(const std::string& group_name,
const ClientSocketHandle* handle) const;
private:
// A Request is allocated per call to RequestSocket that results in
// ERR_IO_PENDING.
struct Request {
ClientSocketHandle* handle;
CompletionCallback* callback;
int priority;
std::string host;
int port;
LoadState load_state;
};
// Entry for a persistent socket which became idle at time |start_time|.
struct IdleSocket {
ClientSocket* socket;
base::TimeTicks start_time;
// An idle socket should be removed if it can't be reused, or has been idle
// for too long. |now| is the current time value (TimeTicks::Now()).
//
// An idle socket can't be reused if it is disconnected or has received
// data unexpectedly (hence no longer idle). The unread data would be
// mistaken for the beginning of the next response if we were to reuse the
// socket for a new request.
bool ShouldCleanup(base::TimeTicks now) const;
};
typedef std::deque<Request> RequestQueue;
typedef std::map<const ClientSocketHandle*, Request> RequestMap;
// A Group is allocated per group_name when there are idle sockets or pending
// requests. Otherwise, the Group object is removed from the map.
struct Group {
Group() : active_socket_count(0) {}
std::deque<IdleSocket> idle_sockets;
RequestQueue pending_requests;
RequestMap connecting_requests;
int active_socket_count;
};
typedef std::map<std::string, Group> GroupMap;
// ConnectingSocket handles the host resolution necessary for socket creation
// and the Connect().
class ConnectingSocket {
public:
enum State {
STATE_RESOLVE_HOST,
STATE_CONNECT
};
ConnectingSocket(const std::string& group_name,
const ClientSocketHandle* handle,
ClientSocketFactory* client_socket_factory,
TCPClientSocketPool* pool);
~ConnectingSocket();
// Begins the host resolution and the TCP connect. Returns OK on success,
// in which case |callback| is not called. On pending IO, Connect returns
// ERR_IO_PENDING and runs |callback| on completion.
int Connect(const std::string& host,
int port,
CompletionCallback* callback);
// If Connect() returns OK, TCPClientSocketPool may invoke this method to
// get the ConnectingSocket to release |socket_| to be set into the
// ClientSocketHandle immediately.
ClientSocket* ReleaseSocket();
// Called by the TCPClientSocketPool to cancel this ConnectingSocket. Only
// necessary if a ClientSocketHandle is reused.
void Cancel();
private:
void OnIOComplete(int result);
const std::string group_name_;
const ClientSocketHandle* const handle_;
ClientSocketFactory* const client_socket_factory_;
CompletionCallbackImpl<ConnectingSocket> callback_;
scoped_ptr<ClientSocket> socket_;
scoped_refptr<TCPClientSocketPool> pool_;
HostResolver resolver_;
AddressList addresses_;
bool canceled_;
// The time the Connect() method was called (if it got called).
base::Time connect_start_time_;
DISALLOW_COPY_AND_ASSIGN(ConnectingSocket);
};
virtual ~TCPClientSocketPool();
static void InsertRequestIntoQueue(const Request& r,
RequestQueue* pending_requests);
// Closes all idle sockets if |force| is true. Else, only closes idle
// sockets that timed out or can't be reused.
void CleanupIdleSockets(bool force);
// Called when the number of idle sockets changes.
void IncrementIdleCount();
void DecrementIdleCount();
// Called via PostTask by ReleaseSocket.
void DoReleaseSocket(const std::string& group_name, ClientSocket* socket);
// Called when timer_ fires. This method scans the idle sockets removing
// sockets that timed out or can't be reused.
void OnCleanupTimerFired() {
CleanupIdleSockets(false);
}
ClientSocketFactory* const client_socket_factory_;
GroupMap group_map_;
std::map<const ClientSocketHandle*, ConnectingSocket*> connecting_socket_map_;
// Timer used to periodically prune idle sockets that timed out or can't be
// reused.
base::RepeatingTimer<TCPClientSocketPool> timer_;
// The total number of idle sockets in the system.
int idle_socket_count_;
// The maximum number of sockets kept per group.
const int max_sockets_per_group_;
DISALLOW_COPY_AND_ASSIGN(TCPClientSocketPool);
};
} // namespace net
#endif // NET_BASE_TCP_CLIENT_SOCKET_POOL_H_
|