blob: 819db111b2648d9b20d4742d2481309409ac918a [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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_SPDY_SPDY_SESSION_H_
6#define NET_SPDY_SPDY_SESSION_H_
7
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008#include <deque>
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009#include <map>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010#include <set>
Torne (Richard Coles)58218062012-11-14 11:43:16 +000011#include <string>
12
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000013#include "base/basictypes.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000014#include "base/gtest_prod_util.h"
15#include "base/memory/ref_counted.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010016#include "base/memory/scoped_ptr.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000017#include "base/memory/weak_ptr.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010018#include "base/time/time.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000019#include "net/base/io_buffer.h"
20#include "net/base/load_states.h"
21#include "net/base/net_errors.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010022#include "net/base/net_export.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000023#include "net/base/request_priority.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000024#include "net/socket/client_socket_handle.h"
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010025#include "net/socket/client_socket_pool.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010026#include "net/socket/next_proto.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000027#include "net/socket/ssl_client_socket.h"
28#include "net/socket/stream_socket.h"
29#include "net/spdy/buffered_spdy_framer.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010030#include "net/spdy/spdy_buffer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000031#include "net/spdy/spdy_credential_state.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010032#include "net/spdy/spdy_framer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000033#include "net/spdy/spdy_header_block.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000034#include "net/spdy/spdy_protocol.h"
35#include "net/spdy/spdy_session_pool.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010036#include "net/spdy/spdy_stream.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010037#include "net/spdy/spdy_write_queue.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000038#include "net/ssl/ssl_config_service.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +010039#include "url/gurl.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000040
41namespace net {
42
43// This is somewhat arbitrary and not really fixed, but it will always work
44// reasonably with ethernet. Chop the world into 2-packet chunks. This is
45// somewhat arbitrary, but is reasonably small and ensures that we elicit
46// ACKs quickly from TCP (because TCP tries to only ACK every other packet).
47const int kMss = 1430;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000048// The 8 is the size of the SPDY frame header.
49const int kMaxSpdyFrameChunkSize = (2 * kMss) - 8;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000050
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010051// Maximum number of concurrent streams we will create, unless the server
52// sends a SETTINGS frame with a different value.
53const size_t kInitialMaxConcurrentStreams = 100;
54
Torne (Richard Coles)58218062012-11-14 11:43:16 +000055// Specifies the maxiumum concurrent streams server could send (via push).
56const int kMaxConcurrentPushedStreams = 1000;
57
Ben Murdochca12bfa2013-07-23 11:17:05 +010058// Specifies the maximum number of bytes to read synchronously before
59// yielding.
60const int kMaxReadBytesWithoutYielding = 32 * 1024;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000061
62// The initial receive window size for both streams and sessions.
63const int32 kDefaultInitialRecvWindowSize = 10 * 1024 * 1024; // 10MB
64
Torne (Richard Coles)58218062012-11-14 11:43:16 +000065class BoundNetLog;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000066struct LoadTimingInfo;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000067class SpdyStream;
68class SSLInfo;
69
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010070// NOTE: There's an enum of the same name (also with numeric suffixes)
71// in histograms.xml.
72//
73// WARNING: DO NOT INSERT ENUMS INTO THIS LIST! Add only to the end.
Torne (Richard Coles)58218062012-11-14 11:43:16 +000074enum SpdyProtocolErrorDetails {
75 // SpdyFramer::SpdyErrors
76 SPDY_ERROR_NO_ERROR,
77 SPDY_ERROR_INVALID_CONTROL_FRAME,
78 SPDY_ERROR_CONTROL_PAYLOAD_TOO_LARGE,
79 SPDY_ERROR_ZLIB_INIT_FAILURE,
80 SPDY_ERROR_UNSUPPORTED_VERSION,
81 SPDY_ERROR_DECOMPRESS_FAILURE,
82 SPDY_ERROR_COMPRESS_FAILURE,
83 SPDY_ERROR_CREDENTIAL_FRAME_CORRUPT,
84 SPDY_ERROR_INVALID_DATA_FRAME_FLAGS,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000085 SPDY_ERROR_INVALID_CONTROL_FRAME_FLAGS,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000086 // SpdyRstStreamStatus
Torne (Richard Coles)58218062012-11-14 11:43:16 +000087 STATUS_CODE_INVALID,
88 STATUS_CODE_PROTOCOL_ERROR,
89 STATUS_CODE_INVALID_STREAM,
90 STATUS_CODE_REFUSED_STREAM,
91 STATUS_CODE_UNSUPPORTED_VERSION,
92 STATUS_CODE_CANCEL,
93 STATUS_CODE_INTERNAL_ERROR,
94 STATUS_CODE_FLOW_CONTROL_ERROR,
95 STATUS_CODE_STREAM_IN_USE,
96 STATUS_CODE_STREAM_ALREADY_CLOSED,
97 STATUS_CODE_INVALID_CREDENTIALS,
98 STATUS_CODE_FRAME_TOO_LARGE,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000099 // SpdySession errors
100 PROTOCOL_ERROR_UNEXPECTED_PING,
101 PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM,
102 PROTOCOL_ERROR_SPDY_COMPRESSION_FAILURE,
103 PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION,
104 PROTOCOL_ERROR_SYN_REPLY_NOT_RECEIVED,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100105 PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE,
106 PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000107 NUM_SPDY_PROTOCOL_ERROR_DETAILS
108};
109
110COMPILE_ASSERT(STATUS_CODE_INVALID ==
111 static_cast<SpdyProtocolErrorDetails>(SpdyFramer::LAST_ERROR),
112 SpdyProtocolErrorDetails_SpdyErrors_mismatch);
113
114COMPILE_ASSERT(PROTOCOL_ERROR_UNEXPECTED_PING ==
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000115 static_cast<SpdyProtocolErrorDetails>(
116 RST_STREAM_NUM_STATUS_CODES + STATUS_CODE_INVALID),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000117 SpdyProtocolErrorDetails_SpdyErrors_mismatch);
118
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000119// A helper class used to manage a request to create a stream.
120class NET_EXPORT_PRIVATE SpdyStreamRequest {
121 public:
122 SpdyStreamRequest();
123 // Calls CancelRequest().
124 ~SpdyStreamRequest();
125
126 // Starts the request to create a stream. If OK is returned, then
127 // ReleaseStream() may be called. If ERR_IO_PENDING is returned,
128 // then when the stream is created, |callback| will be called, at
129 // which point ReleaseStream() may be called. Otherwise, the stream
130 // is not created, an error is returned, and ReleaseStream() may not
131 // be called.
132 //
133 // If OK is returned, must not be called again without
134 // ReleaseStream() being called first. If ERR_IO_PENDING is
135 // returned, must not be called again without CancelRequest() or
136 // ReleaseStream() being called first. Otherwise, in case of an
137 // immediate error, this may be called again.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100138 int StartRequest(SpdyStreamType type,
Ben Murdochca12bfa2013-07-23 11:17:05 +0100139 const base::WeakPtr<SpdySession>& session,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000140 const GURL& url,
141 RequestPriority priority,
142 const BoundNetLog& net_log,
143 const CompletionCallback& callback);
144
145 // Cancels any pending stream creation request. May be called
146 // repeatedly.
147 void CancelRequest();
148
149 // Transfers the created stream (guaranteed to not be NULL) to the
150 // caller. Must be called at most once after StartRequest() returns
151 // OK or |callback| is called with OK. The caller must immediately
152 // set a delegate for the returned stream (except for test code).
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100153 base::WeakPtr<SpdyStream> ReleaseStream();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000154
155 private:
156 friend class SpdySession;
157
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100158 // Called by |session_| when the stream attempt has finished
159 // successfully.
160 void OnRequestCompleteSuccess(base::WeakPtr<SpdyStream>* stream);
161
162 // Called by |session_| when the stream attempt has finished with an
163 // error. Also called with ERR_ABORTED if |session_| is destroyed
164 // while the stream attempt is still pending.
165 void OnRequestCompleteFailure(int rv);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000166
167 // Accessors called by |session_|.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100168 SpdyStreamType type() const { return type_; }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000169 const GURL& url() const { return url_; }
170 RequestPriority priority() const { return priority_; }
171 const BoundNetLog& net_log() const { return net_log_; }
172
173 void Reset();
174
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100175 SpdyStreamType type_;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100176 base::WeakPtr<SpdySession> session_;
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100177 base::WeakPtr<SpdyStream> stream_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000178 GURL url_;
179 RequestPriority priority_;
180 BoundNetLog net_log_;
181 CompletionCallback callback_;
182
183 DISALLOW_COPY_AND_ASSIGN(SpdyStreamRequest);
184};
185
Ben Murdochca12bfa2013-07-23 11:17:05 +0100186class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100187 public SpdyFramerDebugVisitorInterface,
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100188 public LayeredPool {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000189 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000190 // TODO(akalin): Use base::TickClock when it becomes available.
191 typedef base::TimeTicks (*TimeFunc)(void);
192
193 // How we handle flow control (version-dependent).
194 enum FlowControlState {
195 FLOW_CONTROL_NONE,
196 FLOW_CONTROL_STREAM,
197 FLOW_CONTROL_STREAM_AND_SESSION
198 };
199
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000200 // Create a new SpdySession.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100201 // |spdy_session_key| is the host/port that this session connects to, privacy
202 // and proxy configuration settings that it's using.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000203 // |session| is the HttpNetworkSession. |net_log| is the NetLog that we log
204 // network events to.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100205 SpdySession(const SpdySessionKey& spdy_session_key,
Ben Murdochca12bfa2013-07-23 11:17:05 +0100206 const base::WeakPtr<HttpServerProperties>& http_server_properties,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000207 bool verify_domain_authentication,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100208 bool enable_sending_initial_data,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000209 bool enable_credential_frames,
210 bool enable_compression,
211 bool enable_ping_based_connection_checking,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100212 NextProto default_protocol,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000213 size_t stream_initial_recv_window_size,
214 size_t initial_max_concurrent_streams,
215 size_t max_concurrent_streams_limit,
216 TimeFunc time_func,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000217 const HostPortPair& trusted_spdy_proxy,
218 NetLog* net_log);
219
Ben Murdochca12bfa2013-07-23 11:17:05 +0100220 virtual ~SpdySession();
221
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000222 const HostPortPair& host_port_pair() const {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100223 return spdy_session_key_.host_port_proxy_pair().first;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000224 }
225 const HostPortProxyPair& host_port_proxy_pair() const {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100226 return spdy_session_key_.host_port_proxy_pair();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000227 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100228 const SpdySessionKey& spdy_session_key() const {
229 return spdy_session_key_;
230 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000231 // Get a pushed stream for a given |url|. If the server initiates a
232 // stream, it might already exist for a given path. The server
233 // might also not have initiated the stream yet, but indicated it
234 // will via X-Associated-Content. Returns OK if a stream was found
235 // and put into |spdy_stream|, or if one was not found but it is
Ben Murdochca12bfa2013-07-23 11:17:05 +0100236 // okay to create a new stream (in which case |spdy_stream| is
237 // reset). Returns an error (not ERR_IO_PENDING) otherwise, and
238 // resets |spdy_stream|.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000239 int GetPushStream(
240 const GURL& url,
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100241 base::WeakPtr<SpdyStream>* spdy_stream,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000242 const BoundNetLog& stream_net_log);
243
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100244 // Initialize the session with the given connection. |is_secure|
245 // must indicate whether |connection| uses an SSL socket or not; it
246 // is usually true, but it can be false for testing or when SPDY is
247 // configured to work with non-secure sockets.
248 //
Ben Murdochca12bfa2013-07-23 11:17:05 +0100249 // |pool| is the SpdySessionPool that owns us. Its lifetime must
250 // strictly be greater than |this|.
251 //
252 // |certificate_error_code| must either be OK or less than
253 // ERR_IO_PENDING.
254 //
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100255 // Returns OK on success, or an error on failure. Never returns
256 // ERR_IO_PENDING. If an error is returned, the session must be
257 // destroyed immediately.
258 Error InitializeWithSocket(scoped_ptr<ClientSocketHandle> connection,
Ben Murdochca12bfa2013-07-23 11:17:05 +0100259 SpdySessionPool* pool,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100260 bool is_secure,
261 int certificate_error_code);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000262
Ben Murdoch558790d2013-07-30 15:19:42 +0100263 // Returns the protocol used by this session. Always between
264 // kProtoSPDY2 and kProtoSPDYMaximumVersion.
265 //
266 // TODO(akalin): Change the lower bound to kProtoSPDYMinimumVersion
267 // once we stop supporting SPDY/1.
268 NextProto protocol() const { return protocol_; }
269
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000270 // Check to see if this SPDY session can support an additional domain.
271 // If the session is un-authenticated, then this call always returns true.
272 // For SSL-based sessions, verifies that the server certificate in use by
273 // this session provides authentication for the domain and no client
274 // certificate or channel ID was sent to the original server during the SSL
275 // handshake. NOTE: This function can have false negatives on some
276 // platforms.
277 // TODO(wtc): rename this function and the Net.SpdyIPPoolDomainMatch
278 // histogram because this function does more than verifying domain
279 // authentication now.
280 bool VerifyDomainAuthentication(const std::string& domain);
281
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100282 // Pushes the given producer into the write queue for
283 // |stream|. |stream| is guaranteed to be activated before the
284 // producer is used to produce its frame.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100285 void EnqueueStreamWrite(const base::WeakPtr<SpdyStream>& stream,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100286 SpdyFrameType frame_type,
287 scoped_ptr<SpdyBufferProducer> producer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000288
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100289 // Creates and returns a SYN frame for |stream_id|.
290 scoped_ptr<SpdyFrame> CreateSynStream(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000291 SpdyStreamId stream_id,
292 RequestPriority priority,
293 uint8 credential_slot,
294 SpdyControlFlags flags,
295 const SpdyHeaderBlock& headers);
296
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100297 // Tries to create a CREDENTIAL frame. If successful, fills in
298 // |credential_frame| and returns OK. Returns the error (guaranteed
299 // to not be ERR_IO_PENDING) otherwise.
300 int CreateCredentialFrame(const std::string& origin,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100301 const std::string& key,
302 const std::string& cert,
303 RequestPriority priority,
304 scoped_ptr<SpdyFrame>* credential_frame);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000305
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100306 // Creates and returns a SpdyBuffer holding a data frame with the
307 // given data. May return NULL if stalled by flow control.
308 scoped_ptr<SpdyBuffer> CreateDataBuffer(SpdyStreamId stream_id,
309 IOBuffer* data,
310 int len,
311 SpdyDataFlags flags);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000312
Ben Murdocheb525c52013-07-10 11:40:50 +0100313 // Close the stream with the given ID, which must exist and be
314 // active. Note that that stream may hold the last reference to the
315 // session.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100316 void CloseActiveStream(SpdyStreamId stream_id, int status);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000317
Ben Murdocheb525c52013-07-10 11:40:50 +0100318 // Close the given created stream, which must exist but not yet be
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100319 // active. Note that |stream| may hold the last reference to the
320 // session.
321 void CloseCreatedStream(const base::WeakPtr<SpdyStream>& stream, int status);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000322
Ben Murdocheb525c52013-07-10 11:40:50 +0100323 // Send a RST_STREAM frame with the given status code and close the
324 // stream with the given ID, which must exist and be active. Note
325 // that that stream may hold the last reference to the session.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000326 void ResetStream(SpdyStreamId stream_id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000327 SpdyRstStreamStatus status,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000328 const std::string& description);
329
330 // Check if a stream is active.
331 bool IsStreamActive(SpdyStreamId stream_id) const;
332
333 // The LoadState is used for informing the user of the current network
334 // status, such as "resolving host", "connecting", etc.
335 LoadState GetLoadState() const;
336
337 // Fills SSL info in |ssl_info| and returns true when SSL is in use.
338 bool GetSSLInfo(SSLInfo* ssl_info,
339 bool* was_npn_negotiated,
340 NextProto* protocol_negotiated);
341
342 // Fills SSL Certificate Request info |cert_request_info| and returns
343 // true when SSL is in use.
344 bool GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
345
346 // Returns the ServerBoundCertService used by this Socket, or NULL
347 // if server bound certs are not supported in this session.
348 ServerBoundCertService* GetServerBoundCertService() const;
349
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000350 // Send a WINDOW_UPDATE frame for a stream. Called by a stream
351 // whenever receive window size is increased.
352 void SendStreamWindowUpdate(SpdyStreamId stream_id,
353 uint32 delta_window_size);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000354
Ben Murdochca12bfa2013-07-23 11:17:05 +0100355 // Whether the stream is closed, i.e. it has stopped processing data
356 // and is about to be destroyed.
357 //
358 // TODO(akalin): This is only used in tests. Remove this function
359 // and have tests test the WeakPtr instead.
360 bool IsClosed() const { return availability_state_ == STATE_CLOSED; }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000361
Ben Murdochca12bfa2013-07-23 11:17:05 +0100362 // Closes this session. This will close all active streams and mark
363 // the session as permanently closed. Callers must assume that the
364 // session is destroyed after this is called. (However, it may not
365 // be destroyed right away, e.g. when a SpdySession function is
366 // present in the call stack.)
367 //
368 // |err| should be < ERR_IO_PENDING; this function is intended to be
369 // called on error.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000370 // |description| indicates the reason for the error.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100371 void CloseSessionOnError(Error err, const std::string& description);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000372
373 // Retrieves information on the current state of the SPDY session as a
374 // Value. Caller takes possession of the returned value.
375 base::Value* GetInfoAsValue() const;
376
377 // Indicates whether the session is being reused after having successfully
378 // used to send/receive data in the past.
379 bool IsReused() const;
380
381 // Returns true if the underlying transport socket ever had any reads or
382 // writes.
383 bool WasEverUsed() const {
384 return connection_->socket()->WasEverUsed();
385 }
386
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000387 // Returns the load timing information from the perspective of the given
388 // stream. If it's not the first stream, the connection is considered reused
389 // for that stream.
390 //
391 // This uses a different notion of reuse than IsReused(). This function
392 // sets |socket_reused| to false only if |stream_id| is the ID of the first
393 // stream using the session. IsReused(), on the other hand, indicates if the
394 // session has been used to send/receive data at all.
395 bool GetLoadTimingInfo(SpdyStreamId stream_id,
396 LoadTimingInfo* load_timing_info) const;
397
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000398 // Returns true if session is not currently active
399 bool is_active() const {
400 return !active_streams_.empty() || !created_streams_.empty();
401 }
402
403 // Access to the number of active and pending streams. These are primarily
404 // available for testing and diagnostics.
405 size_t num_active_streams() const { return active_streams_.size(); }
406 size_t num_unclaimed_pushed_streams() const {
407 return unclaimed_pushed_streams_.size();
408 }
409 size_t num_created_streams() const { return created_streams_.size(); }
410
Ben Murdochca12bfa2013-07-23 11:17:05 +0100411 size_t pending_create_stream_queue_size(RequestPriority priority) const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000412 DCHECK_LT(priority, NUM_PRIORITIES);
413 return pending_create_stream_queues_[priority].size();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000414 }
415
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000416 // Returns the (version-dependent) flow control state.
417 FlowControlState flow_control_state() const {
418 return flow_control_state_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000419 }
420
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000421 // Returns the current |stream_initial_send_window_size_|.
422 int32 stream_initial_send_window_size() const {
423 return stream_initial_send_window_size_;
424 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000425
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000426 // Returns the current |stream_initial_recv_window_size_|.
427 int32 stream_initial_recv_window_size() const {
428 return stream_initial_recv_window_size_;
429 }
430
431 // Returns true if no stream in the session can send data due to
432 // session flow control.
433 bool IsSendStalled() const {
434 return
435 flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION &&
436 session_send_window_size_ == 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000437 }
438
439 const BoundNetLog& net_log() const { return net_log_; }
440
441 int GetPeerAddress(IPEndPoint* address) const;
442 int GetLocalAddress(IPEndPoint* address) const;
443
444 // Returns true if requests on this session require credentials.
445 bool NeedsCredentials() const;
446
447 SpdyCredentialState* credential_state() { return &credential_state_; }
448
449 // Adds |alias| to set of aliases associated with this session.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100450 void AddPooledAlias(const SpdySessionKey& alias_key);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000451
452 // Returns the set of aliases associated with this session.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100453 const std::set<SpdySessionKey>& pooled_aliases() const {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000454 return pooled_aliases_;
455 }
456
457 int GetProtocolVersion() const;
458
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100459 size_t GetDataFrameMinimumSize() const {
460 return buffered_spdy_framer_->GetDataFrameMinimumSize();
461 }
462
463 size_t GetControlFrameHeaderSize() const {
464 return buffered_spdy_framer_->GetControlFrameHeaderSize();
465 }
466
467 size_t GetFrameMinimumSize() const {
468 return buffered_spdy_framer_->GetFrameMinimumSize();
469 }
470
471 size_t GetFrameMaximumSize() const {
472 return buffered_spdy_framer_->GetFrameMaximumSize();
473 }
474
475 size_t GetDataFrameMaximumPayload() const {
476 return buffered_spdy_framer_->GetDataFrameMaximumPayload();
477 }
478
Ben Murdochca12bfa2013-07-23 11:17:05 +0100479 // Must be used only by |pool_|.
480 base::WeakPtr<SpdySession> GetWeakPtr();
481
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100482 // LayeredPool implementation:
483 virtual bool CloseOneIdleConnection() OVERRIDE;
484
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000485 private:
486 friend class base::RefCounted<SpdySession>;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000487 friend class SpdyStreamRequest;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100488 friend class SpdySessionTest;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000489
490 // Allow tests to access our innards for testing purposes.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100491 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, ClientPing);
492 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, FailedPing);
493 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, GetActivePushStream);
494 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, DeleteExpiredPushStreams);
495 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, ProtocolNegotiation);
496 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, ClearSettings);
497 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, AdjustRecvWindowSize);
498 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, AdjustSendWindowSize);
499 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlInactiveStream);
500 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlNoReceiveLeaks);
501 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlNoSendLeaks);
502 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlEndToEnd);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000503
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000504 typedef std::deque<SpdyStreamRequest*> PendingStreamRequestQueue;
505 typedef std::set<SpdyStreamRequest*> PendingStreamRequestCompletionSet;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000506
Ben Murdocheb525c52013-07-10 11:40:50 +0100507 struct ActiveStreamInfo {
508 ActiveStreamInfo();
509 explicit ActiveStreamInfo(SpdyStream* stream);
510 ~ActiveStreamInfo();
511
512 SpdyStream* stream;
513 bool waiting_for_syn_reply;
514 };
515 typedef std::map<SpdyStreamId, ActiveStreamInfo> ActiveStreamMap;
516
517 struct PushedStreamInfo {
518 PushedStreamInfo();
519 PushedStreamInfo(SpdyStreamId stream_id, base::TimeTicks creation_time);
520 ~PushedStreamInfo();
521
522 SpdyStreamId stream_id;
523 base::TimeTicks creation_time;
524 };
Ben Murdochca12bfa2013-07-23 11:17:05 +0100525 typedef std::map<GURL, PushedStreamInfo> PushedStreamMap;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000526
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100527 typedef std::set<SpdyStream*> CreatedStreamSet;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000528
Ben Murdochca12bfa2013-07-23 11:17:05 +0100529 enum AvailabilityState {
530 // The session is available in its socket pool and can be used
531 // freely.
532 STATE_AVAILABLE,
533 // The session can process data on existing streams but will
534 // refuse to create new ones.
535 STATE_GOING_AWAY,
536 // The session has been closed, is waiting to be deleted, and will
537 // refuse to process any more data.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000538 STATE_CLOSED
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000539 };
540
Ben Murdochca12bfa2013-07-23 11:17:05 +0100541 enum ReadState {
542 READ_STATE_DO_READ,
543 READ_STATE_DO_READ_COMPLETE,
544 };
545
546 enum WriteState {
547 // There is no in-flight write and the write queue is empty.
548 WRITE_STATE_IDLE,
549 WRITE_STATE_DO_WRITE,
550 WRITE_STATE_DO_WRITE_COMPLETE,
551 };
552
553 // The return value of DoCloseSession() describing what was done.
554 enum CloseSessionResult {
555 // The session was already closed so nothing was done.
556 SESSION_ALREADY_CLOSED,
557 // The session was moved into the closed state but was not removed
558 // from |pool_| (because we're in an IO loop).
559 SESSION_CLOSED_BUT_NOT_REMOVED,
560 // The session was moved into the closed state and removed from
561 // |pool_|.
562 SESSION_CLOSED_AND_REMOVED,
563 };
564
565 // Checks whether a stream for the given |url| can be created or
566 // retrieved from the set of unclaimed push streams. Returns OK if
567 // so. Otherwise, the session is closed and an error <
568 // ERR_IO_PENDING is returned.
569 Error TryAccessStream(const GURL& url);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000570
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000571 // Called by SpdyStreamRequest to start a request to create a
572 // stream. If OK is returned, then |stream| will be filled in with a
573 // valid stream. If ERR_IO_PENDING is returned, then
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100574 // |request->OnRequestComplete{Success,Failure}()| will be called
575 // when the stream is created (unless it is cancelled). Otherwise,
576 // no stream is created and the error is returned.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000577 int TryCreateStream(SpdyStreamRequest* request,
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100578 base::WeakPtr<SpdyStream>* stream);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000579
580 // Actually create a stream into |stream|. Returns OK if successful;
581 // otherwise, returns an error and |stream| is not filled.
582 int CreateStream(const SpdyStreamRequest& request,
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100583 base::WeakPtr<SpdyStream>* stream);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000584
585 // Called by SpdyStreamRequest to remove |request| from the stream
586 // creation queue.
587 void CancelStreamRequest(SpdyStreamRequest* request);
588
589 // Called when there is room to create more streams (e.g., a stream
590 // was closed). Processes as many pending stream requests as
591 // possible.
592 void ProcessPendingStreamRequests();
593
Ben Murdocheb525c52013-07-10 11:40:50 +0100594 // Close the stream pointed to by the given iterator. Note that that
595 // stream may hold the last reference to the session.
596 void CloseActiveStreamIterator(ActiveStreamMap::iterator it, int status);
597
598 // Close the stream pointed to by the given iterator. Note that that
599 // stream may hold the last reference to the session.
600 void CloseCreatedStreamIterator(CreatedStreamSet::iterator it, int status);
601
Ben Murdochbbcdd452013-07-25 10:06:34 +0100602 // Calls EnqueueResetStreamFrame() and then
603 // CloseActiveStreamIterator().
Ben Murdocheb525c52013-07-10 11:40:50 +0100604 void ResetStreamIterator(ActiveStreamMap::iterator it,
605 SpdyRstStreamStatus status,
606 const std::string& description);
607
Ben Murdochbbcdd452013-07-25 10:06:34 +0100608 // Send a RST_STREAM frame with the given parameters. There should
609 // either be no active stream with the given ID, or that active
610 // stream should be closed shortly after this function is called.
611 //
612 // TODO(akalin): Rename this to EnqueueResetStreamFrame().
613 void EnqueueResetStreamFrame(SpdyStreamId stream_id,
614 RequestPriority priority,
615 SpdyRstStreamStatus status,
616 const std::string& description);
Ben Murdocheb525c52013-07-10 11:40:50 +0100617
Ben Murdochca12bfa2013-07-23 11:17:05 +0100618 // Calls DoReadLoop and then if |availability_state_| is
619 // STATE_CLOSED, calls RemoveFromPool().
620 //
621 // Use this function instead of DoReadLoop when posting a task to
622 // pump the read loop.
623 void PumpReadLoop(ReadState expected_read_state, int result);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000624
Ben Murdochca12bfa2013-07-23 11:17:05 +0100625 // Advance the ReadState state machine. |expected_read_state| is the
626 // expected starting read state.
627 //
628 // This function must always be called via PumpReadLoop() except for
629 // from InitializeWithSocket().
630 int DoReadLoop(ReadState expected_read_state, int result);
631 // The implementations of the states of the ReadState state machine.
Ben Murdoch9ab55632013-07-18 11:57:30 +0100632 int DoRead();
Ben Murdochca12bfa2013-07-23 11:17:05 +0100633 int DoReadComplete(int result);
Ben Murdoch9ab55632013-07-18 11:57:30 +0100634
Ben Murdochca12bfa2013-07-23 11:17:05 +0100635 // Calls DoWriteLoop and then if |availability_state_| is
636 // STATE_CLOSED, calls RemoveFromPool().
637 //
638 // Use this function instead of DoWriteLoop when posting a task to
639 // pump the write loop.
640 void PumpWriteLoop(WriteState expected_write_state, int result);
Ben Murdoch9ab55632013-07-18 11:57:30 +0100641
Ben Murdochca12bfa2013-07-23 11:17:05 +0100642 // Advance the WriteState state machine. |expected_write_state| is
643 // the expected starting write state.
644 //
645 // This function must always be called via PumpWriteLoop().
646 int DoWriteLoop(WriteState expected_write_state, int result);
647 // The implementations of the states of the WriteState state machine.
648 int DoWrite();
649 int DoWriteComplete(int result);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000650
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100651 // TODO(akalin): Rename the Send* and Write* functions below to
652 // Enqueue*.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000653
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100654 // Send initial data. Called when a connection is successfully
655 // established in InitializeWithSocket() and
656 // |enable_sending_initial_data_| is true.
657 void SendInitialData();
658
659 // Helper method to send a SETTINGS frame.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000660 void SendSettings(const SettingsMap& settings);
661
662 // Handle SETTING. Either when we send settings, or when we receive a
663 // SETTINGS control frame, update our SpdySession accordingly.
664 void HandleSetting(uint32 id, uint32 value);
665
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000666 // Adjust the send window size of all ActiveStreams and PendingStreamRequests.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000667 void UpdateStreamsSendWindowSize(int32 delta_window_size);
668
669 // Send the PING (preface-PING) frame.
670 void SendPrefacePingIfNoneInFlight();
671
672 // Send PING if there are no PINGs in flight and we haven't heard from server.
673 void SendPrefacePing();
674
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000675 // Send a single WINDOW_UPDATE frame.
676 void SendWindowUpdateFrame(SpdyStreamId stream_id, uint32 delta_window_size,
677 RequestPriority priority);
678
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000679 // Send the PING frame.
680 void WritePingFrame(uint32 unique_id);
681
682 // Post a CheckPingStatus call after delay. Don't post if there is already
683 // CheckPingStatus running.
684 void PlanToCheckPingStatus();
685
686 // Check the status of the connection. It calls |CloseSessionOnError| if we
687 // haven't received any data in |kHungInterval| time period.
688 void CheckPingStatus(base::TimeTicks last_check_time);
689
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000690 // Get a new stream id.
691 int GetNewStreamId();
692
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100693 // Pushes the given frame with the given priority into the write
694 // queue for the session.
695 void EnqueueSessionWrite(RequestPriority priority,
696 SpdyFrameType frame_type,
697 scoped_ptr<SpdyFrame> frame);
698
699 // Puts |producer| associated with |stream| onto the write queue
700 // with the given priority.
701 void EnqueueWrite(RequestPriority priority,
702 SpdyFrameType frame_type,
703 scoped_ptr<SpdyBufferProducer> producer,
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100704 const base::WeakPtr<SpdyStream>& stream);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000705
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100706 // Inserts a newly-created stream into |created_streams_|.
707 void InsertCreatedStream(scoped_ptr<SpdyStream> stream);
708
709 // Activates |stream| (which must be in |created_streams_|) by
710 // assigning it an ID and returns it.
711 scoped_ptr<SpdyStream> ActivateCreatedStream(SpdyStream* stream);
712
713 // Inserts a newly-activated stream into |active_streams_|.
714 void InsertActivatedStream(scoped_ptr<SpdyStream> stream);
715
716 // Remove all internal references to |stream|, call OnClose() on it,
717 // and process any pending stream requests before deleting it. Note
718 // that |stream| may hold the last reference to the session.
719 void DeleteStream(scoped_ptr<SpdyStream> stream, int status);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000720
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000721 // Check if we have a pending pushed-stream for this url
722 // Returns the stream if found (and returns it from the pending
Ben Murdochca12bfa2013-07-23 11:17:05 +0100723 // list). Returns NULL otherwise.
724 base::WeakPtr<SpdyStream> GetActivePushStream(const GURL& url);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000725
Ben Murdocheb525c52013-07-10 11:40:50 +0100726 // Delegates to |stream->OnInitialResponseHeadersReceived()|. If an
727 // error is returned, the last reference to |this| may have been
728 // released.
729 int OnInitialResponseHeadersReceived(const SpdyHeaderBlock& response_headers,
730 base::Time response_time,
731 base::TimeTicks recv_first_byte_time,
732 SpdyStream* stream);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000733
734 void RecordPingRTTHistogram(base::TimeDelta duration);
735 void RecordHistograms();
736 void RecordProtocolErrorHistogram(SpdyProtocolErrorDetails details);
737
Ben Murdochca12bfa2013-07-23 11:17:05 +0100738 // DCHECKs that |availability_state_| >= STATE_GOING_AWAY, that
739 // there are no pending stream creation requests, and that there are
740 // no created streams.
741 void DcheckGoingAway() const;
742
743 // Calls DcheckGoingAway(), then DCHECKs that |availability_state_|
744 // == STATE_CLOSED, |error_on_close_| has a valid value, that there
745 // are no active streams or unclaimed pushed streams, and that the
746 // write queue is empty.
747 void DcheckClosed() const;
748
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100749 // Closes all active streams with stream id's greater than
Ben Murdochca12bfa2013-07-23 11:17:05 +0100750 // |last_good_stream_id|, as well as any created or pending
751 // streams. Must be called only when |availability_state_| >=
752 // STATE_GOING_AWAY. After this function, DcheckGoingAway() will
753 // pass. May be called multiple times.
754 void StartGoingAway(SpdyStreamId last_good_stream_id, Error status);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100755
Ben Murdochca12bfa2013-07-23 11:17:05 +0100756 // Must be called only when going away (i.e., DcheckGoingAway()
757 // passes). If there are no more active streams and the session
758 // isn't closed yet, close it.
759 void MaybeFinishGoingAway();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000760
Ben Murdochca12bfa2013-07-23 11:17:05 +0100761 // If the stream is already closed, does nothing. Otherwise, moves
762 // the session to a closed state. Then, if we're in an IO loop,
763 // returns (as the IO loop will do the pool removal itself when its
764 // done). Otherwise, also removes |this| from |pool_|. The returned
765 // result describes what was done.
766 CloseSessionResult DoCloseSession(Error err, const std::string& description);
767
768 // Remove this session from its pool, which must exist. Must be
769 // called only when the session is closed.
770 //
771 // Must be called only via Pump{Read,Write}Loop() or
772 // DoCloseSession().
773 void RemoveFromPool();
774
775 // Called right before closing a (possibly-inactive) stream for a
776 // reason other than being requested to by the stream.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100777 void LogAbandonedStream(SpdyStream* stream, Error status);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000778
Ben Murdochca12bfa2013-07-23 11:17:05 +0100779 // Called right before closing an active stream for a reason other
780 // than being requested to by the stream.
781 void LogAbandonedActiveStream(ActiveStreamMap::const_iterator it,
782 Error status);
783
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000784 // Invokes a user callback for stream creation. We provide this method so it
785 // can be deferred to the MessageLoop, so we avoid re-entrancy problems.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000786 void CompleteStreamRequest(SpdyStreamRequest* pending_request);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000787
788 // Remove old unclaimed pushed streams.
789 void DeleteExpiredPushedStreams();
790
791 // BufferedSpdyFramerVisitorInterface:
792 virtual void OnError(SpdyFramer::SpdyError error_code) OVERRIDE;
793 virtual void OnStreamError(SpdyStreamId stream_id,
794 const std::string& description) OVERRIDE;
795 virtual void OnPing(uint32 unique_id) OVERRIDE;
796 virtual void OnRstStream(SpdyStreamId stream_id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000797 SpdyRstStreamStatus status) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000798 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
799 SpdyGoAwayStatus status) OVERRIDE;
800 virtual void OnStreamFrameData(SpdyStreamId stream_id,
801 const char* data,
802 size_t len,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000803 bool fin) OVERRIDE;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100804 virtual void OnSettings(bool clear_persisted) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000805 virtual void OnSetting(
806 SpdySettingsIds id, uint8 flags, uint32 value) OVERRIDE;
807 virtual void OnWindowUpdate(SpdyStreamId stream_id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000808 uint32 delta_window_size) OVERRIDE;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100809 virtual void OnPushPromise(SpdyStreamId stream_id,
810 SpdyStreamId promised_stream_id) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000811 virtual void OnSynStream(SpdyStreamId stream_id,
812 SpdyStreamId associated_stream_id,
813 SpdyPriority priority,
814 uint8 credential_slot,
815 bool fin,
816 bool unidirectional,
817 const SpdyHeaderBlock& headers) OVERRIDE;
818 virtual void OnSynReply(
819 SpdyStreamId stream_id,
820 bool fin,
821 const SpdyHeaderBlock& headers) OVERRIDE;
822 virtual void OnHeaders(
823 SpdyStreamId stream_id,
824 bool fin,
825 const SpdyHeaderBlock& headers) OVERRIDE;
826
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100827 // SpdyFramerDebugVisitorInterface
828 virtual void OnSendCompressedFrame(
829 SpdyStreamId stream_id,
830 SpdyFrameType type,
831 size_t payload_len,
832 size_t frame_len) OVERRIDE;
833 virtual void OnReceiveCompressedFrame(
834 SpdyStreamId stream_id,
835 SpdyFrameType type,
836 size_t frame_len) OVERRIDE {}
837
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100838 // Called when bytes are consumed from a SpdyBuffer for a DATA frame
839 // that is to be written or is being written. Increases the send
840 // window size accordingly if some or all of the SpdyBuffer is being
841 // discarded.
842 //
843 // If session flow control is turned off, this must not be called.
844 void OnWriteBufferConsumed(size_t frame_payload_size,
845 size_t consume_size,
846 SpdyBuffer::ConsumeSource consume_source);
847
848 // Called by OnWindowUpdate() (which is in turn called by the
849 // framer) to increase this session's send window size by
850 // |delta_window_size| from a WINDOW_UPDATE frome, which must be at
851 // least 1. If |delta_window_size| would cause this session's send
852 // window size to overflow, does nothing.
853 //
854 // If session flow control is turned off, this must not be called.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000855 void IncreaseSendWindowSize(int32 delta_window_size);
856
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100857 // If session flow control is turned on, called by CreateDataFrame()
858 // (which is in turn called by a stream) to decrease this session's
859 // send window size by |delta_window_size|, which must be at least 1
860 // and at most kMaxSpdyFrameChunkSize. |delta_window_size| must not
861 // cause this session's send window size to go negative.
862 //
863 // If session flow control is turned off, this must not be called.
864 void DecreaseSendWindowSize(int32 delta_window_size);
865
866 // Called when bytes are consumed by the delegate from a SpdyBuffer
867 // containing received data. Increases the receive window size
868 // accordingly.
869 //
870 // If session flow control is turned off, this must not be called.
871 void OnReadBufferConsumed(size_t consume_size,
872 SpdyBuffer::ConsumeSource consume_source);
873
874 // Called by OnReadBufferConsume to increase this session's receive
875 // window size by |delta_window_size|, which must be at least 1 and
876 // must not cause this session's receive window size to overflow,
877 // possibly also sending a WINDOW_UPDATE frame. Also called during
878 // initialization to set the initial receive window size.
879 //
880 // If session flow control is turned off, this must not be called.
881 void IncreaseRecvWindowSize(int32 delta_window_size);
882
883 // Called by OnStreamFrameData (which is in turn called by the
884 // framer) to decrease this session's receive window size by
885 // |delta_window_size|, which must be at least 1 and must not cause
886 // this session's receive window size to go negative.
887 //
888 // If session flow control is turned off, this must not be called.
889 void DecreaseRecvWindowSize(int32 delta_window_size);
890
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000891 // Queue a send-stalled stream for possibly resuming once we're not
892 // send-stalled anymore.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100893 void QueueSendStalledStream(const SpdyStream& stream);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000894
895 // Go through the queue of send-stalled streams and try to resume as
896 // many as possible.
897 void ResumeSendStalledStreams();
898
899 // Returns the next stream to possibly resume, or 0 if the queue is
900 // empty.
901 SpdyStreamId PopStreamToPossiblyResume();
902
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000903 // --------------------------
904 // Helper methods for testing
905 // --------------------------
906
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000907 void set_connection_at_risk_of_loss_time(base::TimeDelta duration) {
908 connection_at_risk_of_loss_time_ = duration;
909 }
910
911 void set_hung_interval(base::TimeDelta duration) {
912 hung_interval_ = duration;
913 }
914
915 int64 pings_in_flight() const { return pings_in_flight_; }
916
917 uint32 next_ping_id() const { return next_ping_id_; }
918
919 base::TimeTicks last_activity_time() const { return last_activity_time_; }
920
921 bool check_ping_status_pending() const { return check_ping_status_pending_; }
922
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100923 size_t max_concurrent_streams() const { return max_concurrent_streams_; }
924
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000925 // Returns the SSLClientSocket that this SPDY session sits on top of,
926 // or NULL, if the transport is not SSL.
927 SSLClientSocket* GetSSLClientSocket() const;
928
929 // Used for posting asynchronous IO tasks. We use this even though
930 // SpdySession is refcounted because we don't need to keep the SpdySession
931 // alive if the last reference is within a RunnableMethod. Just revoke the
932 // method.
933 base::WeakPtrFactory<SpdySession> weak_factory_;
934
Ben Murdochca12bfa2013-07-23 11:17:05 +0100935 // Whether Do{Read,Write}Loop() is in the call stack. Useful for
936 // making sure we don't destroy ourselves prematurely in that case.
937 bool in_io_loop_;
938
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100939 // The key used to identify this session.
940 const SpdySessionKey spdy_session_key_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000941
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100942 // Set set of SpdySessionKeys for which this session has serviced
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000943 // requests.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100944 std::set<SpdySessionKey> pooled_aliases_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000945
Ben Murdochca12bfa2013-07-23 11:17:05 +0100946 // |pool_| owns us, therefore its lifetime must exceed ours. We set
947 // this to NULL after we are removed from the pool.
948 SpdySessionPool* pool_;
949 const base::WeakPtr<HttpServerProperties> http_server_properties_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000950
951 // The socket handle for this session.
952 scoped_ptr<ClientSocketHandle> connection_;
953
954 // The read buffer used to read data from the socket.
955 scoped_refptr<IOBuffer> read_buffer_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000956
957 int stream_hi_water_mark_; // The next stream id to use.
958
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000959 // Queue, for each priority, of pending stream requests that have
960 // not yet been satisfied.
961 PendingStreamRequestQueue pending_create_stream_queues_[NUM_PRIORITIES];
962
963 // A set of requests that are waiting to be completed (i.e., for the
964 // stream to actually be created). This is necessary since we kick
965 // off the stream creation asynchronously, and so the request may be
966 // cancelled before the asynchronous task to create the stream runs.
967 PendingStreamRequestCompletionSet pending_stream_request_completions_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000968
969 // Map from stream id to all active streams. Streams are active in the sense
970 // that they have a consumer (typically SpdyNetworkTransaction and regardless
971 // of whether or not there is currently any ongoing IO [might be waiting for
972 // the server to start pushing the stream]) or there are still network events
973 // incoming even though the consumer has already gone away (cancellation).
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100974 //
975 // |active_streams_| owns all its SpdyStream objects.
976 //
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000977 // TODO(willchan): Perhaps we should separate out cancelled streams and move
978 // them into a separate ActiveStreamMap, and not deliver network events to
979 // them?
980 ActiveStreamMap active_streams_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000981
Ben Murdochca12bfa2013-07-23 11:17:05 +0100982 // (Bijective) map from the URL to the ID of the streams that have
983 // already started to be pushed by the server, but do not have
984 // consumers yet. Contains a subset of |active_streams_|.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000985 PushedStreamMap unclaimed_pushed_streams_;
986
987 // Set of all created streams but that have not yet sent any frames.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100988 //
989 // |created_streams_| owns all its SpdyStream objects.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000990 CreatedStreamSet created_streams_;
991
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100992 // The write queue.
993 SpdyWriteQueue write_queue_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000994
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100995 // Data for the frame we are currently sending.
Ben Murdochca12bfa2013-07-23 11:17:05 +0100996
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100997 // The buffer we're currently writing.
998 scoped_ptr<SpdyBuffer> in_flight_write_;
999 // The type of the frame in |in_flight_write_|.
1000 SpdyFrameType in_flight_write_frame_type_;
1001 // The size of the frame in |in_flight_write_|.
1002 size_t in_flight_write_frame_size_;
1003 // The stream to notify when |in_flight_write_| has been written to
1004 // the socket completely.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001005 base::WeakPtr<SpdyStream> in_flight_write_stream_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001006
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001007 // Flag if we're using an SSL connection for this SpdySession.
1008 bool is_secure_;
1009
1010 // Certificate error code when using a secure connection.
1011 int certificate_error_code_;
1012
1013 // Spdy Frame state.
1014 scoped_ptr<BufferedSpdyFramer> buffered_spdy_framer_;
1015
Ben Murdochca12bfa2013-07-23 11:17:05 +01001016 // The state variables.
1017 AvailabilityState availability_state_;
1018 ReadState read_state_;
1019 WriteState write_state_;
1020
1021 // If the session was closed (i.e., |availability_state_| is
1022 // STATE_CLOSED), then |error_on_close_| holds the error with which
1023 // it was closed, which is < ERR_IO_PENDING. Otherwise, it is set to
1024 // OK.
1025 Error error_on_close_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001026
1027 // Limits
1028 size_t max_concurrent_streams_; // 0 if no limit
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001029 size_t max_concurrent_streams_limit_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001030
1031 // Some statistics counters for the session.
1032 int streams_initiated_count_;
1033 int streams_pushed_count_;
1034 int streams_pushed_and_claimed_count_;
1035 int streams_abandoned_count_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001036
1037 // |total_bytes_received_| keeps track of all the bytes read by the
1038 // SpdySession. It is used by the |Net.SpdySettingsCwnd...| histograms.
1039 int total_bytes_received_;
1040
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001041 bool sent_settings_; // Did this session send settings when it started.
1042 bool received_settings_; // Did this session receive at least one settings
1043 // frame.
1044 int stalled_streams_; // Count of streams that were ever stalled.
1045
1046 // Count of all pings on the wire, for which we have not gotten a response.
1047 int64 pings_in_flight_;
1048
1049 // This is the next ping_id (unique_id) to be sent in PING frame.
1050 uint32 next_ping_id_;
1051
1052 // This is the last time we have sent a PING.
1053 base::TimeTicks last_ping_sent_time_;
1054
1055 // This is the last time we had activity in the session.
1056 base::TimeTicks last_activity_time_;
1057
1058 // This is the next time that unclaimed push streams should be checked for
1059 // expirations.
1060 base::TimeTicks next_unclaimed_push_stream_sweep_time_;
1061
1062 // Indicate if we have already scheduled a delayed task to check the ping
1063 // status.
1064 bool check_ping_status_pending_;
1065
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01001066 // Whether to send the (HTTP/2) connection header prefix.
1067 bool send_connection_header_prefix_;
1068
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001069 // The (version-dependent) flow control state.
1070 FlowControlState flow_control_state_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001071
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001072 // Initial send window size for this session's streams. Can be
1073 // changed by an arriving SETTINGS frame. Newly created streams use
1074 // this value for the initial send window size.
1075 int32 stream_initial_send_window_size_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001076
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001077 // Initial receive window size for this session's streams. There are
1078 // plans to add a command line switch that would cause a SETTINGS
1079 // frame with window size announcement to be sent on startup. Newly
1080 // created streams will use this value for the initial receive
1081 // window size.
1082 int32 stream_initial_recv_window_size_;
1083
1084 // Session flow control variables. All zero unless session flow
1085 // control is turned on.
1086 int32 session_send_window_size_;
1087 int32 session_recv_window_size_;
1088 int32 session_unacked_recv_window_bytes_;
1089
1090 // A queue of stream IDs that have been send-stalled at some point
1091 // in the past.
1092 std::deque<SpdyStreamId> stream_send_unstall_queue_[NUM_PRIORITIES];
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001093
1094 BoundNetLog net_log_;
1095
1096 // Outside of tests, these should always be true.
1097 bool verify_domain_authentication_;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01001098 bool enable_sending_initial_data_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001099 bool enable_credential_frames_;
1100 bool enable_compression_;
1101 bool enable_ping_based_connection_checking_;
Ben Murdoch558790d2013-07-30 15:19:42 +01001102
1103 // The SPDY protocol used. Always between kProtoSPDY2 and
1104 // kProtoSPDYMaximumVersion.
1105 //
1106 // TODO(akalin): Change the lower bound to kProtoSPDYMinimumVersion
1107 // once we stop supporting SPDY/1.
1108 NextProto protocol_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001109
1110 SpdyCredentialState credential_state_;
1111
1112 // |connection_at_risk_of_loss_time_| is an optimization to avoid sending
1113 // wasteful preface pings (when we just got some data).
1114 //
1115 // If it is zero (the most conservative figure), then we always send the
1116 // preface ping (when none are in flight).
1117 //
1118 // It is common for TCP/IP sessions to time out in about 3-5 minutes.
1119 // Certainly if it has been more than 3 minutes, we do want to send a preface
1120 // ping.
1121 //
1122 // We don't think any connection will time out in under about 10 seconds. So
1123 // this might as well be set to something conservative like 10 seconds. Later,
1124 // we could adjust it to send fewer pings perhaps.
1125 base::TimeDelta connection_at_risk_of_loss_time_;
1126
1127 // The amount of time that we are willing to tolerate with no activity (of any
1128 // form), while there is a ping in flight, before we declare the connection to
1129 // be hung. TODO(rtenneti): When hung, instead of resetting connection, race
1130 // to build a new connection, and see if that completes before we (finally)
1131 // get a PING response (http://crbug.com/127812).
1132 base::TimeDelta hung_interval_;
1133
1134 // This SPDY proxy is allowed to push resources from origins that are
1135 // different from those of their associated streams.
1136 HostPortPair trusted_spdy_proxy_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001137
1138 TimeFunc time_func_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001139};
1140
1141} // namespace net
1142
1143#endif // NET_SPDY_SPDY_SESSION_H_