blob: 2894471263fc2443f388924e5d9d8e2a06f67bf1 [file] [log] [blame]
[email protected]5af3c572010-07-20 14:16:271// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]aea80602009-09-18 00:55:082// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]dab9c7d2010-02-06 21:44:325#ifndef NET_SPDY_SPDY_SESSION_H_
6#define NET_SPDY_SPDY_SESSION_H_
[email protected]32b76ef2010-07-26 23:08:247#pragma once
[email protected]aea80602009-09-18 00:55:088
9#include <deque>
10#include <list>
11#include <map>
12#include <queue>
13#include <string>
14
[email protected]8822f382010-07-30 21:49:0315#include "base/gtest_prod_util.h"
[email protected]33c477b2010-05-13 19:21:0716#include "base/linked_ptr.h"
[email protected]aea80602009-09-18 00:55:0817#include "base/ref_counted.h"
18#include "net/base/io_buffer.h"
19#include "net/base/load_states.h"
20#include "net/base/net_errors.h"
[email protected]635909f2010-05-12 18:19:3621#include "net/base/net_log.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]18c53ae2009-10-01 18:18:5223#include "net/base/ssl_config_service.h"
[email protected]aea80602009-09-18 00:55:0824#include "net/base/upload_data_stream.h"
[email protected]aea80602009-09-18 00:55:0825#include "net/socket/client_socket.h"
26#include "net/socket/client_socket_handle.h"
[email protected]7fc5b09a2010-02-27 00:07:3827#include "net/socket/tcp_client_socket_pool.h"
[email protected]dab9c7d2010-02-06 21:44:3228#include "net/spdy/spdy_framer.h"
29#include "net/spdy/spdy_io_buffer.h"
30#include "net/spdy/spdy_protocol.h"
31#include "net/spdy/spdy_session_pool.h"
[email protected]aea80602009-09-18 00:55:0832
33namespace net {
34
[email protected]7349c6b12010-07-22 02:29:1635// This is somewhat arbitrary and not really fixed, but it will always work
36// reasonably with ethernet. Chop the world into 2-packet chunks. This is
37// somewhat arbitrary, but is reasonably small and ensures that we elicit
38// ACKs quickly from TCP (because TCP tries to only ACK every other packet).
39const int kMss = 1430;
40const int kMaxSpdyFrameChunkSize = (2 * kMss) - spdy::SpdyFrame::size();
41
[email protected]9e743cd2010-03-16 07:03:5342class BoundNetLog;
[email protected]f4580332010-09-25 21:20:2743class SpdySettingsStorage;
44class SpdyStream;
[email protected]dcc6bbb2009-12-09 19:09:0145class SSLInfo;
[email protected]aea80602009-09-18 00:55:0846
[email protected]955fc2e72010-02-08 20:37:3047class SpdySession : public base::RefCounted<SpdySession>,
48 public spdy::SpdyFramerVisitorInterface {
[email protected]aea80602009-09-18 00:55:0849 public:
[email protected]807c01a2010-04-21 16:57:4550 // Create a new SpdySession.
[email protected]b261d0e2010-08-02 19:13:2451 // |host_port_proxy_pair| is the host/port that this session connects to, and
52 // the proxy configuration settings that it's using.
[email protected]635909f2010-05-12 18:19:3653 // |session| is the HttpNetworkSession. |net_log| is the NetLog that we log
54 // network events to.
[email protected]b261d0e2010-08-02 19:13:2455 SpdySession(const HostPortProxyPair& host_port_proxy_pair,
[email protected]f4580332010-09-25 21:20:2756 SpdySessionPool* spdy_session_pool,
57 SpdySettingsStorage* spdy_settings,
[email protected]44297002010-05-16 00:59:1058 NetLog* net_log);
[email protected]807c01a2010-04-21 16:57:4559
[email protected]b261d0e2010-08-02 19:13:2460 const HostPortPair& host_port_pair() const {
61 return host_port_proxy_pair_.first;
62 }
63 const HostPortProxyPair& host_port_proxy_pair() const {
64 return host_port_proxy_pair_;
65 }
[email protected]aea80602009-09-18 00:55:0866
[email protected]9be804c82010-06-24 17:59:4667 // Get a pushed stream for a given |url|.
68 // If the server initiates a stream, it might already exist for a given path.
69 // The server might also not have initiated the stream yet, but indicated it
[email protected]bdbda462010-06-28 17:30:3770 // will via X-Associated-Content. Writes the stream out to |spdy_stream|.
71 // Returns a net error code.
72 int GetPushStream(
[email protected]9be804c82010-06-24 17:59:4673 const GURL& url,
[email protected]bdbda462010-06-28 17:30:3774 scoped_refptr<SpdyStream>* spdy_stream,
[email protected]9be804c82010-06-24 17:59:4675 const BoundNetLog& stream_net_log);
76
[email protected]bdbda462010-06-28 17:30:3777 // Create a new stream for a given |url|. Writes it out to |spdy_stream|.
[email protected]2bd93022010-07-17 00:58:4478 // Returns a net error code, possibly ERR_IO_PENDING.
[email protected]bdbda462010-06-28 17:30:3779 int CreateStream(
[email protected]9be804c82010-06-24 17:59:4680 const GURL& url,
81 RequestPriority priority,
[email protected]bdbda462010-06-28 17:30:3782 scoped_refptr<SpdyStream>* spdy_stream,
[email protected]2bd93022010-07-17 00:58:4483 const BoundNetLog& stream_net_log,
[email protected]971746e2010-07-21 03:02:2384 CompletionCallback* callback);
[email protected]2bd93022010-07-17 00:58:4485
86 // Remove PendingCreateStream objects on transaction deletion
[email protected]971746e2010-07-21 03:02:2387 void CancelPendingCreateStreams(const scoped_refptr<SpdyStream>* spdy_stream);
[email protected]aea80602009-09-18 00:55:0888
[email protected]9e9e842e2010-07-23 23:09:1589 // Used by SpdySessionPool to initialize with a pre-existing SSL socket. For
90 // testing, setting is_secure to false allows initialization with a
91 // pre-existing TCP socket.
[email protected]26ef6582010-06-24 02:30:4792 // Returns OK on success, or an error on failure.
[email protected]9e9e842e2010-07-23 23:09:1593 net::Error InitializeWithSocket(ClientSocketHandle* connection,
94 bool is_secure,
95 int certificate_error_code);
[email protected]807c01a2010-04-21 16:57:4596
[email protected]9be804c82010-06-24 17:59:4697 // Send the SYN frame for |stream_id|.
98 int WriteSynStream(
99 spdy::SpdyStreamId stream_id,
100 RequestPriority priority,
101 spdy::SpdyControlFlags flags,
102 const linked_ptr<spdy::SpdyHeaderBlock>& headers);
103
[email protected]ff57bb82009-11-12 06:52:14104 // Write a data frame to the stream.
105 // Used to create and queue a data frame for the given stream.
[email protected]955fc2e72010-02-08 20:37:30106 int WriteStreamData(spdy::SpdyStreamId stream_id, net::IOBuffer* data,
[email protected]4f386422010-07-20 04:19:49107 int len,
108 spdy::SpdyDataFlags flags);
[email protected]ff57bb82009-11-12 06:52:14109
[email protected]56e7c63d2010-07-12 18:42:17110 // Close a stream.
111 void CloseStream(spdy::SpdyStreamId stream_id, int status);
[email protected]aea80602009-09-18 00:55:08112
[email protected]5af3c572010-07-20 14:16:27113 // Reset a stream by sending a RST_STREAM frame with given status code.
114 // Also closes the stream. Was not piggybacked to CloseStream since not
115 // all of the calls to CloseStream necessitate sending a RST_STREAM.
116 void ResetStream(spdy::SpdyStreamId stream_id, spdy::SpdyStatusCodes status);
117
[email protected]aea80602009-09-18 00:55:08118 // Check if a stream is active.
[email protected]955fc2e72010-02-08 20:37:30119 bool IsStreamActive(spdy::SpdyStreamId stream_id) const;
[email protected]aea80602009-09-18 00:55:08120
121 // The LoadState is used for informing the user of the current network
122 // status, such as "resolving host", "connecting", etc.
123 LoadState GetLoadState() const;
[email protected]d1eda932009-11-04 01:03:10124
[email protected]9be804c82010-06-24 17:59:46125 // Fills SSL info in |ssl_info| and returns true when SSL is in use.
126 bool GetSSLInfo(SSLInfo* ssl_info, bool* was_npn_negotiated);
127
[email protected]8e6441ca2010-08-19 05:56:38128 // Fills SSL Certificate Request info |cert_request_info| and returns
129 // true when SSL is in use.
130 bool GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
131
[email protected]34437af82009-11-06 02:28:49132 // Enable or disable SSL.
133 static void SetSSLMode(bool enable) { use_ssl_ = enable; }
[email protected]85c0ed82009-12-15 23:14:14134 static bool SSLMode() { return use_ssl_; }
[email protected]34437af82009-11-06 02:28:49135
[email protected]7349c6b12010-07-22 02:29:16136 // Enable or disable flow control.
[email protected]450c5022010-08-26 02:38:28137 static void set_flow_control(bool enable) { use_flow_control_ = enable; }
138 static bool flow_control() { return use_flow_control_; }
139
140 // Send WINDOW_UPDATE frame, called by a stream whenever receive window
141 // size is increased.
142 void SendWindowUpdate(spdy::SpdyStreamId stream_id, int delta_window_size);
[email protected]7349c6b12010-07-22 02:29:16143
[email protected]b278eb72010-07-09 20:17:00144 // If session is closed, no new streams/transactions should be created.
145 bool IsClosed() const { return state_ == CLOSED; }
146
147 // Closes this session. This will close all active streams and mark
148 // the session as permanently closed.
149 // |err| should not be OK; this function is intended to be called on
150 // error.
[email protected]a01ea222010-08-19 16:50:53151 // |remove_from_pool| indicates whether to also remove the session from the
152 // session pool.
153 void CloseSessionOnError(net::Error err, bool remove_from_pool);
[email protected]b278eb72010-07-09 20:17:00154
[email protected]8e6441ca2010-08-19 05:56:38155 // Indicates whether the session is being reused after having successfully
156 // used to send/receive data in the past.
157 bool IsReused() const {
[email protected]58cebf8f2010-07-31 19:20:16158 return frames_received_ > 0;
159 }
160
[email protected]a01ea222010-08-19 16:50:53161 void set_in_session_pool(bool val) { in_session_pool_ = val; }
162
[email protected]19ec8a72010-08-23 03:38:23163 // Access to the number of active and pending streams. These are primarily
164 // available for testing and diagnostics.
165 size_t num_active_streams() const { return active_streams_.size(); }
166 size_t num_unclaimed_pushed_streams() const {
167 return unclaimed_pushed_streams_.size();
168 }
169
[email protected]6cd3bd202010-08-30 05:23:06170 const BoundNetLog& net_log() const { return net_log_; }
171
[email protected]807c01a2010-04-21 16:57:45172 private:
173 friend class base::RefCounted<SpdySession>;
[email protected]8822f382010-07-30 21:49:03174 FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, GetActivePushStream);
[email protected]aea80602009-09-18 00:55:08175
[email protected]60253bd2009-12-01 01:16:39176 enum State {
177 IDLE,
178 CONNECTING,
179 CONNECTED,
180 CLOSED
181 };
182
[email protected]2bd93022010-07-17 00:58:44183 enum { kDefaultMaxConcurrentStreams = 100 }; // TODO(mbelshe) remove this
184
185 struct PendingCreateStream {
186 const GURL* url;
187 RequestPriority priority;
188 scoped_refptr<SpdyStream>* spdy_stream;
189 const BoundNetLog* stream_net_log;
190 CompletionCallback* callback;
191
[email protected]2bd93022010-07-17 00:58:44192 PendingCreateStream(const GURL& url, RequestPriority priority,
193 scoped_refptr<SpdyStream>* spdy_stream,
194 const BoundNetLog& stream_net_log,
[email protected]971746e2010-07-21 03:02:23195 CompletionCallback* callback)
[email protected]2bd93022010-07-17 00:58:44196 : url(&url), priority(priority), spdy_stream(spdy_stream),
[email protected]971746e2010-07-21 03:02:23197 stream_net_log(&stream_net_log), callback(callback) { }
[email protected]2bd93022010-07-17 00:58:44198 };
199 typedef std::queue<PendingCreateStream, std::list< PendingCreateStream> >
200 PendingCreateStreamQueue;
[email protected]955fc2e72010-02-08 20:37:30201 typedef std::map<int, scoped_refptr<SpdyStream> > ActiveStreamMap;
[email protected]65d56aa2010-06-14 04:13:40202 // Only HTTP push a stream.
[email protected]e3ebba0f2010-08-05 17:59:58203 typedef std::map<std::string, scoped_refptr<SpdyStream> > PushedStreamMap;
[email protected]955fc2e72010-02-08 20:37:30204 typedef std::priority_queue<SpdyIOBuffer> OutputQueue;
[email protected]a677f2b2009-11-22 00:43:00205
[email protected]955fc2e72010-02-08 20:37:30206 virtual ~SpdySession();
[email protected]5389bc72009-11-05 23:34:24207
[email protected]2bd93022010-07-17 00:58:44208 void ProcessPendingCreateStreams();
209 int CreateStreamImpl(
210 const GURL& url,
211 RequestPriority priority,
212 scoped_refptr<SpdyStream>* spdy_stream,
213 const BoundNetLog& stream_net_log);
214
[email protected]955fc2e72010-02-08 20:37:30215 // SpdyFramerVisitorInterface
216 virtual void OnError(spdy::SpdyFramer*);
217 virtual void OnStreamFrameData(spdy::SpdyStreamId stream_id,
[email protected]aea80602009-09-18 00:55:08218 const char* data,
[email protected]aeac1e42009-10-10 00:26:01219 size_t len);
[email protected]955fc2e72010-02-08 20:37:30220 virtual void OnControl(const spdy::SpdyControlFrame* frame);
[email protected]aea80602009-09-18 00:55:08221
222 // Control frame handlers.
[email protected]651b77c2010-03-10 19:29:42223 void OnSyn(const spdy::SpdySynStreamControlFrame& frame,
[email protected]33c477b2010-05-13 19:21:07224 const linked_ptr<spdy::SpdyHeaderBlock>& headers);
[email protected]651b77c2010-03-10 19:29:42225 void OnSynReply(const spdy::SpdySynReplyControlFrame& frame,
[email protected]33c477b2010-05-13 19:21:07226 const linked_ptr<spdy::SpdyHeaderBlock>& headers);
[email protected]e3ebba0f2010-08-05 17:59:58227 void OnRst(const spdy::SpdyRstStreamControlFrame& frame);
[email protected]651b77c2010-03-10 19:29:42228 void OnGoAway(const spdy::SpdyGoAwayControlFrame& frame);
[email protected]74188f22010-04-09 20:18:50229 void OnSettings(const spdy::SpdySettingsControlFrame& frame);
[email protected]5af3c572010-07-20 14:16:27230 void OnWindowUpdate(const spdy::SpdyWindowUpdateControlFrame& frame);
[email protected]aea80602009-09-18 00:55:08231
232 // IO Callbacks
[email protected]aea80602009-09-18 00:55:08233 void OnReadComplete(int result);
234 void OnWriteComplete(int result);
235
[email protected]74188f22010-04-09 20:18:50236 // Send relevant SETTINGS. This is generally called on connection setup.
237 void SendSettings();
238
[email protected]2bd93022010-07-17 00:58:44239 // Handle SETTINGS. Either when we send settings, or when we receive a
240 // SETTINGS ontrol frame, update our SpdySession accordingly.
241 void HandleSettings(const spdy::SpdySettings& settings);
242
[email protected]aea80602009-09-18 00:55:08243 // Start reading from the socket.
[email protected]26ef6582010-06-24 02:30:47244 // Returns OK on success, or an error on failure.
245 net::Error ReadSocket();
[email protected]aea80602009-09-18 00:55:08246
247 // Write current data to the socket.
248 void WriteSocketLater();
249 void WriteSocket();
250
251 // Get a new stream id.
252 int GetNewStreamId();
253
[email protected]74188f22010-04-09 20:18:50254 // Queue a frame for sending.
255 // |frame| is the frame to send.
256 // |priority| is the priority for insertion into the queue.
257 // |stream| is the stream which this IO is associated with (or NULL).
258 void QueueFrame(spdy::SpdyFrame* frame, spdy::SpdyPriority priority,
259 SpdyStream* stream);
260
[email protected]aea80602009-09-18 00:55:08261 // Track active streams in the active stream list.
[email protected]955fc2e72010-02-08 20:37:30262 void ActivateStream(SpdyStream* stream);
[email protected]56e7c63d2010-07-12 18:42:17263 void DeleteStream(spdy::SpdyStreamId id, int status);
[email protected]aea80602009-09-18 00:55:08264
[email protected]4b4762a2010-04-23 16:04:14265 // Removes this session from the session pool.
266 void RemoveFromPool();
267
[email protected]aea80602009-09-18 00:55:08268 // Check if we have a pending pushed-stream for this url
269 // Returns the stream if found (and returns it from the pending
270 // list), returns NULL otherwise.
[email protected]9be804c82010-06-24 17:59:46271 scoped_refptr<SpdyStream> GetActivePushStream(const std::string& url);
[email protected]aea80602009-09-18 00:55:08272
[email protected]9be804c82010-06-24 17:59:46273 // Calls OnResponseReceived().
[email protected]3f662f12010-03-25 19:56:12274 // Returns true if successful.
275 bool Respond(const spdy::SpdyHeaderBlock& headers,
276 const scoped_refptr<SpdyStream> stream);
277
[email protected]0aebc002010-05-21 06:50:19278 void RecordHistograms();
279
[email protected]b278eb72010-07-09 20:17:00280 // Closes all streams. Used as part of shutdown.
281 void CloseAllStreams(net::Error status);
282
[email protected]955fc2e72010-02-08 20:37:30283 // Callbacks for the Spdy session.
[email protected]955fc2e72010-02-08 20:37:30284 CompletionCallbackImpl<SpdySession> read_callback_;
285 CompletionCallbackImpl<SpdySession> write_callback_;
[email protected]aea80602009-09-18 00:55:08286
287 // The domain this session is connected to.
[email protected]b261d0e2010-08-02 19:13:24288 const HostPortProxyPair host_port_proxy_pair_;
[email protected]aea80602009-09-18 00:55:08289
[email protected]f4580332010-09-25 21:20:27290 scoped_refptr<SpdySessionPool> spdy_session_pool_;
291 SpdySettingsStorage* spdy_settings_;
[email protected]aea80602009-09-18 00:55:08292
293 // The socket handle for this session.
[email protected]1f14a912009-12-21 20:32:44294 scoped_ptr<ClientSocketHandle> connection_;
[email protected]aea80602009-09-18 00:55:08295
296 // The read buffer used to read data from the socket.
[email protected]230cadd2009-09-22 16:33:59297 scoped_refptr<IOBuffer> read_buffer_;
[email protected]aea80602009-09-18 00:55:08298 bool read_pending_;
299
300 int stream_hi_water_mark_; // The next stream id to use.
301
[email protected]2bd93022010-07-17 00:58:44302 // Queue, for each priority, of pending Create Streams that have not
303 // yet been satisfied
304 PendingCreateStreamQueue create_stream_queues_[NUM_PRIORITIES];
305
[email protected]a677f2b2009-11-22 00:43:00306 // Map from stream id to all active streams. Streams are active in the sense
[email protected]955fc2e72010-02-08 20:37:30307 // that they have a consumer (typically SpdyNetworkTransaction and regardless
[email protected]a677f2b2009-11-22 00:43:00308 // of whether or not there is currently any ongoing IO [might be waiting for
309 // the server to start pushing the stream]) or there are still network events
310 // incoming even though the consumer has already gone away (cancellation).
311 // TODO(willchan): Perhaps we should separate out cancelled streams and move
312 // them into a separate ActiveStreamMap, and not deliver network events to
313 // them?
314 ActiveStreamMap active_streams_;
[email protected]e3ebba0f2010-08-05 17:59:58315 // Map of all the streams that have already started to be pushed by the
[email protected]a677f2b2009-11-22 00:43:00316 // server, but do not have consumers yet.
[email protected]e3ebba0f2010-08-05 17:59:58317 PushedStreamMap unclaimed_pushed_streams_;
[email protected]aea80602009-09-18 00:55:08318
319 // As we gather data to be sent, we put it into the output queue.
[email protected]aea80602009-09-18 00:55:08320 OutputQueue queue_;
321
[email protected]aea80602009-09-18 00:55:08322 // The packet we are currently sending.
[email protected]e1245352009-11-30 19:42:42323 bool write_pending_; // Will be true when a write is in progress.
[email protected]955fc2e72010-02-08 20:37:30324 SpdyIOBuffer in_flight_write_; // This is the write buffer in progress.
[email protected]e1245352009-11-30 19:42:42325
326 // Flag if we have a pending message scheduled for WriteSocket.
[email protected]aea80602009-09-18 00:55:08327 bool delayed_write_pending_;
[email protected]aea80602009-09-18 00:55:08328
[email protected]955fc2e72010-02-08 20:37:30329 // Flag if we're using an SSL connection for this SpdySession.
[email protected]dcc6bbb2009-12-09 19:09:01330 bool is_secure_;
331
[email protected]bdbda462010-06-28 17:30:37332 // Certificate error code when using a secure connection.
333 int certificate_error_code_;
334
[email protected]955fc2e72010-02-08 20:37:30335 // Spdy Frame state.
336 spdy::SpdyFramer spdy_framer_;
[email protected]aea80602009-09-18 00:55:08337
[email protected]60253bd2009-12-01 01:16:39338 // If an error has occurred on the session, the session is effectively
339 // dead. Record this error here. When no error has occurred, |error_| will
340 // be OK.
341 net::Error error_;
342 State state_;
343
[email protected]2bd93022010-07-17 00:58:44344 // Limits
345 size_t max_concurrent_streams_; // 0 if no limit
346
[email protected]9b010802009-12-27 22:55:30347 // Some statistics counters for the session.
348 int streams_initiated_count_;
349 int streams_pushed_count_;
350 int streams_pushed_and_claimed_count_;
[email protected]56e7c63d2010-07-12 18:42:17351 int streams_abandoned_count_;
[email protected]58cebf8f2010-07-31 19:20:16352 int frames_received_;
[email protected]0aebc002010-05-21 06:50:19353 bool sent_settings_; // Did this session send settings when it started.
354 bool received_settings_; // Did this session receive at least one settings
355 // frame.
[email protected]9b010802009-12-27 22:55:30356
[email protected]4b4762a2010-04-23 16:04:14357 bool in_session_pool_; // True if the session is currently in the pool.
358
[email protected]7349c6b12010-07-22 02:29:16359 // Initial send window size for the session; can be changed by an
360 // arriving SETTINGS frame; newly created streams use this value for the
361 // initial send window size.
362 int initial_send_window_size_;
[email protected]5af3c572010-07-20 14:16:27363
[email protected]450c5022010-08-26 02:38:28364 // Initial receive window size for the session; there are plans to add a
365 // command line switch that would cause a SETTINGS frame with window size
366 // announcement to be sent on startup; newly created streams will use
367 // this value for the initial receive window size.
368 int initial_recv_window_size_;
369
[email protected]635909f2010-05-12 18:19:36370 BoundNetLog net_log_;
371
[email protected]affe8fe2009-10-14 20:06:05372 static bool use_ssl_;
[email protected]7349c6b12010-07-22 02:29:16373 static bool use_flow_control_;
[email protected]aea80602009-09-18 00:55:08374};
375
376} // namespace net
377
[email protected]dab9c7d2010-02-06 21:44:32378#endif // NET_SPDY_SPDY_SESSION_H_