OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef NET_SOCKET_CLIENT_SOCKET_HANDLE_H_ | |
6 #define NET_SOCKET_CLIENT_SOCKET_HANDLE_H_ | |
7 | |
8 #include <string> | |
9 | |
10 #include "base/logging.h" | |
11 #include "base/memory/ref_counted.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/time/time.h" | |
14 #include "net/base/completion_callback.h" | |
15 #include "net/base/load_states.h" | |
16 #include "net/base/load_timing_info.h" | |
17 #include "net/base/net_errors.h" | |
18 #include "net/base/net_export.h" | |
19 #include "net/base/net_log.h" | |
20 #include "net/base/request_priority.h" | |
21 #include "net/http/http_response_info.h" | |
22 #include "net/socket/client_socket_pool.h" | |
23 #include "net/socket/stream_socket.h" | |
24 | |
25 namespace net { | |
26 | |
27 // A container for a StreamSocket. | |
28 // | |
29 // The handle's |group_name| uniquely identifies the origin and type of the | |
30 // connection. It is used by the ClientSocketPool to group similar connected | |
31 // client socket objects. | |
32 // | |
33 class NET_EXPORT ClientSocketHandle { | |
34 public: | |
35 enum SocketReuseType { | |
36 UNUSED = 0, // unused socket that just finished connecting | |
37 UNUSED_IDLE, // unused socket that has been idle for awhile | |
38 REUSED_IDLE, // previously used socket | |
39 NUM_TYPES, | |
40 }; | |
41 | |
42 ClientSocketHandle(); | |
43 ~ClientSocketHandle(); | |
44 | |
45 // Initializes a ClientSocketHandle object, which involves talking to the | |
46 // ClientSocketPool to obtain a connected socket, possibly reusing one. This | |
47 // method returns either OK or ERR_IO_PENDING. On ERR_IO_PENDING, |priority| | |
48 // is used to determine the placement in ClientSocketPool's wait list. | |
49 // | |
50 // If this method succeeds, then the socket member will be set to an existing | |
51 // connected socket if an existing connected socket was available to reuse, | |
52 // otherwise it will be set to a new connected socket. Consumers can then | |
53 // call is_reused() to see if the socket was reused. If not reusing an | |
54 // existing socket, ClientSocketPool may need to establish a new | |
55 // connection using |socket_params|. | |
56 // | |
57 // This method returns ERR_IO_PENDING if it cannot complete synchronously, in | |
58 // which case the consumer will be notified of completion via |callback|. | |
59 // | |
60 // If the pool was not able to reuse an existing socket, the new socket | |
61 // may report a recoverable error. In this case, the return value will | |
62 // indicate an error and the socket member will be set. If it is determined | |
63 // that the error is not recoverable, the Disconnect method should be used | |
64 // on the socket, so that it does not get reused. | |
65 // | |
66 // A non-recoverable error may set additional state in the ClientSocketHandle | |
67 // to allow the caller to determine what went wrong. | |
68 // | |
69 // Init may be called multiple times. | |
70 // | |
71 // Profiling information for the request is saved to |net_log| if non-NULL. | |
72 // | |
73 template <typename PoolType> | |
74 int Init(const std::string& group_name, | |
75 const scoped_refptr<typename PoolType::SocketParams>& socket_params, | |
76 RequestPriority priority, | |
77 const CompletionCallback& callback, | |
78 PoolType* pool, | |
79 const BoundNetLog& net_log); | |
80 | |
81 // An initialized handle can be reset, which causes it to return to the | |
82 // un-initialized state. This releases the underlying socket, which in the | |
83 // case of a socket that still has an established connection, indicates that | |
84 // the socket may be kept alive for use by a subsequent ClientSocketHandle. | |
85 // | |
86 // NOTE: To prevent the socket from being kept alive, be sure to call its | |
87 // Disconnect method. This will result in the ClientSocketPool deleting the | |
88 // StreamSocket. | |
89 void Reset(); | |
90 | |
91 // Used after Init() is called, but before the ClientSocketPool has | |
92 // initialized the ClientSocketHandle. | |
93 LoadState GetLoadState() const; | |
94 | |
95 bool IsPoolStalled() const; | |
96 | |
97 // Adds a higher layered pool on top of the socket pool that |socket_| belongs | |
98 // to. At most one higher layered pool can be added to a | |
99 // ClientSocketHandle at a time. On destruction or reset, automatically | |
100 // removes the higher pool if RemoveHigherLayeredPool has not been called. | |
101 void AddHigherLayeredPool(HigherLayeredPool* higher_pool); | |
102 | |
103 // Removes a higher layered pool from the socket pool that |socket_| belongs | |
104 // to. |higher_pool| must have been added by the above function. | |
105 void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool); | |
106 | |
107 // Returns true when Init() has completed successfully. | |
108 bool is_initialized() const { return is_initialized_; } | |
109 | |
110 // Returns the time tick when Init() was called. | |
111 base::TimeTicks init_time() const { return init_time_; } | |
112 | |
113 // Returns the time between Init() and when is_initialized() becomes true. | |
114 base::TimeDelta setup_time() const { return setup_time_; } | |
115 | |
116 // Sets the portion of LoadTimingInfo related to connection establishment, and | |
117 // the socket id. |is_reused| is needed because the handle may not have full | |
118 // reuse information. |load_timing_info| must have all default values when | |
119 // called. Returns false and makes no changes to |load_timing_info| when | |
120 // |socket_| is NULL. | |
121 bool GetLoadTimingInfo(bool is_reused, | |
122 LoadTimingInfo* load_timing_info) const; | |
123 | |
124 // Used by ClientSocketPool to initialize the ClientSocketHandle. | |
125 // | |
126 // SetSocket() may also be used if this handle is used as simply for | |
127 // socket storage (e.g., http://crbug.com/37810). | |
128 void SetSocket(scoped_ptr<StreamSocket> s); | |
129 void set_reuse_type(SocketReuseType reuse_type) { reuse_type_ = reuse_type; } | |
130 void set_idle_time(base::TimeDelta idle_time) { idle_time_ = idle_time; } | |
131 void set_pool_id(int id) { pool_id_ = id; } | |
132 void set_is_ssl_error(bool is_ssl_error) { is_ssl_error_ = is_ssl_error; } | |
133 void set_ssl_error_response_info(const HttpResponseInfo& ssl_error_state) { | |
134 ssl_error_response_info_ = ssl_error_state; | |
135 } | |
136 void set_pending_http_proxy_connection(ClientSocketHandle* connection) { | |
137 pending_http_proxy_connection_.reset(connection); | |
138 } | |
139 | |
140 // Only valid if there is no |socket_|. | |
141 bool is_ssl_error() const { | |
142 DCHECK(socket_.get() == NULL); | |
143 return is_ssl_error_; | |
144 } | |
145 // On an ERR_PROXY_AUTH_REQUESTED error, the |headers| and |auth_challenge| | |
146 // fields are filled in. On an ERR_SSL_CLIENT_AUTH_CERT_NEEDED error, | |
147 // the |cert_request_info| field is set. | |
148 const HttpResponseInfo& ssl_error_response_info() const { | |
149 return ssl_error_response_info_; | |
150 } | |
151 ClientSocketHandle* release_pending_http_proxy_connection() { | |
152 return pending_http_proxy_connection_.release(); | |
153 } | |
154 | |
155 StreamSocket* socket() { return socket_.get(); } | |
156 | |
157 // SetSocket() must be called with a new socket before this handle | |
158 // is destroyed if is_initialized() is true. | |
159 scoped_ptr<StreamSocket> PassSocket(); | |
160 | |
161 // These may only be used if is_initialized() is true. | |
162 const std::string& group_name() const { return group_name_; } | |
163 int id() const { return pool_id_; } | |
164 bool is_reused() const { return reuse_type_ == REUSED_IDLE; } | |
165 base::TimeDelta idle_time() const { return idle_time_; } | |
166 SocketReuseType reuse_type() const { return reuse_type_; } | |
167 const LoadTimingInfo::ConnectTiming& connect_timing() const { | |
168 return connect_timing_; | |
169 } | |
170 void set_connect_timing(const LoadTimingInfo::ConnectTiming& connect_timing) { | |
171 connect_timing_ = connect_timing; | |
172 } | |
173 | |
174 private: | |
175 // Called on asynchronous completion of an Init() request. | |
176 void OnIOComplete(int result); | |
177 | |
178 // Called on completion (both asynchronous & synchronous) of an Init() | |
179 // request. | |
180 void HandleInitCompletion(int result); | |
181 | |
182 // Resets the state of the ClientSocketHandle. |cancel| indicates whether or | |
183 // not to try to cancel the request with the ClientSocketPool. Does not | |
184 // reset the supplemental error state. | |
185 void ResetInternal(bool cancel); | |
186 | |
187 // Resets the supplemental error state. | |
188 void ResetErrorState(); | |
189 | |
190 bool is_initialized_; | |
191 ClientSocketPool* pool_; | |
192 HigherLayeredPool* higher_pool_; | |
193 scoped_ptr<StreamSocket> socket_; | |
194 std::string group_name_; | |
195 SocketReuseType reuse_type_; | |
196 CompletionCallback callback_; | |
197 CompletionCallback user_callback_; | |
198 base::TimeDelta idle_time_; | |
199 int pool_id_; // See ClientSocketPool::ReleaseSocket() for an explanation. | |
200 bool is_ssl_error_; | |
201 HttpResponseInfo ssl_error_response_info_; | |
202 scoped_ptr<ClientSocketHandle> pending_http_proxy_connection_; | |
203 base::TimeTicks init_time_; | |
204 base::TimeDelta setup_time_; | |
205 | |
206 NetLog::Source requesting_source_; | |
207 | |
208 // Timing information is set when a connection is successfully established. | |
209 LoadTimingInfo::ConnectTiming connect_timing_; | |
210 | |
211 DISALLOW_COPY_AND_ASSIGN(ClientSocketHandle); | |
212 }; | |
213 | |
214 // Template function implementation: | |
215 template <typename PoolType> | |
216 int ClientSocketHandle::Init( | |
217 const std::string& group_name, | |
218 const scoped_refptr<typename PoolType::SocketParams>& socket_params, | |
219 RequestPriority priority, | |
220 const CompletionCallback& callback, | |
221 PoolType* pool, | |
222 const BoundNetLog& net_log) { | |
223 requesting_source_ = net_log.source(); | |
224 | |
225 CHECK(!group_name.empty()); | |
226 ResetInternal(true); | |
227 ResetErrorState(); | |
228 pool_ = pool; | |
229 group_name_ = group_name; | |
230 init_time_ = base::TimeTicks::Now(); | |
231 int rv = pool_->RequestSocket( | |
232 group_name, &socket_params, priority, this, callback_, net_log); | |
233 if (rv == ERR_IO_PENDING) { | |
234 user_callback_ = callback; | |
235 } else { | |
236 HandleInitCompletion(rv); | |
237 } | |
238 return rv; | |
239 } | |
240 | |
241 } // namespace net | |
242 | |
243 #endif // NET_SOCKET_CLIENT_SOCKET_HANDLE_H_ | |
OLD | NEW |