1// Copyright (c) 2009 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_FLIP_FLIP_SESSION_H_
6#define NET_FLIP_FLIP_SESSION_H_
7
8#include <deque>
9#include <list>
10#include <map>
11#include <queue>
12#include <string>
13
14#include "base/ref_counted.h"
15#include "net/base/io_buffer.h"
16#include "net/base/load_states.h"
17#include "net/base/net_errors.h"
18#include "net/base/request_priority.h"
19#include "net/base/ssl_config_service.h"
20#include "net/base/upload_data_stream.h"
21#include "net/flip/flip_framer.h"
22#include "net/flip/flip_io_buffer.h"
23#include "net/flip/flip_protocol.h"
24#include "net/flip/flip_session_pool.h"
25#include "net/socket/client_socket.h"
26#include "net/socket/client_socket_handle.h"
27#include "testing/platform_test.h"
28
29namespace net {
30
31class FlipStream;
32class HttpNetworkSession;
33class HttpRequestInfo;
34class HttpResponseInfo;
35class LoadLog;
36class SSLInfo;
37
38class FlipSession : public base::RefCounted<FlipSession>,
39                    public flip::FlipFramerVisitorInterface {
40 public:
41  // Get the domain for this FlipSession.
42  const std::string& domain() const { return domain_; }
43
44  // Connect the FLIP Socket.
45  // Returns net::Error::OK on success.
46  // Note that this call does not wait for the connect to complete. Callers can
47  // immediately start using the FlipSession while it connects.
48  net::Error Connect(const std::string& group_name,
49                     const HostResolver::RequestInfo& host,
50                     RequestPriority priority,
51                     LoadLog* load_log);
52
53  // Get a stream for a given |request|.  In the typical case, this will involve
54  // the creation of a new stream (and will send the SYN frame).  If the server
55  // initiates a stream, it might already exist for a given path.  The server
56  // might also not have initiated the stream yet, but indicated it will via
57  // X-Associated-Content.
58  // Returns the new or existing stream.  Never returns NULL.
59  scoped_refptr<FlipStream> GetOrCreateStream(const HttpRequestInfo& request,
60      const UploadDataStream* upload_data, LoadLog* log);
61
62  // Write a data frame to the stream.
63  // Used to create and queue a data frame for the given stream.
64  int WriteStreamData(flip::FlipStreamId stream_id, net::IOBuffer* data,
65                      int len);
66
67  // Cancel a stream.
68  bool CancelStream(flip::FlipStreamId stream_id);
69
70  // Check if a stream is active.
71  bool IsStreamActive(flip::FlipStreamId stream_id) const;
72
73  // The LoadState is used for informing the user of the current network
74  // status, such as "resolving host", "connecting", etc.
75  LoadState GetLoadState() const;
76
77  // Enable or disable SSL.
78  static void SetSSLMode(bool enable) { use_ssl_ = enable; }
79  static bool SSLMode() { return use_ssl_; }
80
81 protected:
82  friend class FlipSessionPool;
83
84  enum State {
85    IDLE,
86    CONNECTING,
87    CONNECTED,
88    CLOSED
89  };
90
91  // Provide access to the framer for testing.
92  flip::FlipFramer* GetFramer() { return &flip_framer_; }
93
94  // Create a new FlipSession.
95  // |host| is the hostname that this session connects to.
96  FlipSession(const std::string& host, HttpNetworkSession* session);
97
98  // Closes all open streams.  Used as part of shutdown.
99  void CloseAllStreams(net::Error code);
100
101 private:
102  friend class base::RefCounted<FlipSession>;
103
104  typedef std::map<int, scoped_refptr<FlipStream> > ActiveStreamMap;
105  typedef std::list<scoped_refptr<FlipStream> > ActiveStreamList;
106  typedef std::map<std::string, scoped_refptr<FlipStream> > PendingStreamMap;
107  typedef std::priority_queue<FlipIOBuffer> OutputQueue;
108
109  virtual ~FlipSession();
110
111  // Used by FlipSessionPool to initialize with a pre-existing socket.
112  void InitializeWithSocket(ClientSocketHandle* connection);
113
114  // FlipFramerVisitorInterface
115  virtual void OnError(flip::FlipFramer*);
116  virtual void OnStreamFrameData(flip::FlipStreamId stream_id,
117                                 const char* data,
118                                 size_t len);
119  virtual void OnControl(const flip::FlipControlFrame* frame);
120
121  // Control frame handlers.
122  void OnSyn(const flip::FlipSynStreamControlFrame* frame,
123             const flip::FlipHeaderBlock* headers);
124  void OnSynReply(const flip::FlipSynReplyControlFrame* frame,
125                  const flip::FlipHeaderBlock* headers);
126  void OnFin(const flip::FlipFinStreamControlFrame* frame);
127
128  // IO Callbacks
129  void OnTCPConnect(int result);
130  void OnSSLConnect(int result);
131  void OnReadComplete(int result);
132  void OnWriteComplete(int result);
133
134  // Start reading from the socket.
135  void ReadSocket();
136
137  // Write current data to the socket.
138  void WriteSocketLater();
139  void WriteSocket();
140
141  // Get a new stream id.
142  int GetNewStreamId();
143
144  // Closes this session.  This will close all active streams and mark
145  // the session as permanently closed.
146  // |err| should not be OK; this function is intended to be called on
147  // error.
148  void CloseSessionOnError(net::Error err);
149
150  // Track active streams in the active stream list.
151  void ActivateStream(FlipStream* stream);
152  void DeactivateStream(flip::FlipStreamId id);
153
154  // Check if we have a pending pushed-stream for this url
155  // Returns the stream if found (and returns it from the pending
156  // list), returns NULL otherwise.
157  scoped_refptr<FlipStream> GetPushStream(const std::string& url);
158
159  void GetSSLInfo(SSLInfo* ssl_info);
160
161  // Callbacks for the Flip session.
162  CompletionCallbackImpl<FlipSession> connect_callback_;
163  CompletionCallbackImpl<FlipSession> ssl_connect_callback_;
164  CompletionCallbackImpl<FlipSession> read_callback_;
165  CompletionCallbackImpl<FlipSession> write_callback_;
166
167  // The domain this session is connected to.
168  std::string domain_;
169
170  SSLConfig ssl_config_;
171
172  scoped_refptr<HttpNetworkSession> session_;
173
174  // The socket handle for this session.
175  scoped_ptr<ClientSocketHandle> connection_;
176
177  // The read buffer used to read data from the socket.
178  scoped_refptr<IOBuffer> read_buffer_;
179  bool read_pending_;
180
181  int stream_hi_water_mark_;  // The next stream id to use.
182
183  // TODO(mbelshe): We need to track these stream lists better.
184  //                I suspect it is possible to remove a stream from
185  //                one list, but not the other.
186
187  // Map from stream id to all active streams.  Streams are active in the sense
188  // that they have a consumer (typically FlipNetworkTransaction and regardless
189  // of whether or not there is currently any ongoing IO [might be waiting for
190  // the server to start pushing the stream]) or there are still network events
191  // incoming even though the consumer has already gone away (cancellation).
192  // TODO(willchan): Perhaps we should separate out cancelled streams and move
193  // them into a separate ActiveStreamMap, and not deliver network events to
194  // them?
195  ActiveStreamMap active_streams_;
196  // List of all the streams that have already started to be pushed by the
197  // server, but do not have consumers yet.
198  ActiveStreamList pushed_streams_;
199  // List of streams declared in X-Associated-Content headers, but do not have
200  // consumers yet.
201  // The key is a string representing the path of the URI being pushed.
202  PendingStreamMap pending_streams_;
203
204  // As we gather data to be sent, we put it into the output queue.
205  OutputQueue queue_;
206
207  // The packet we are currently sending.
208  bool write_pending_;            // Will be true when a write is in progress.
209  FlipIOBuffer in_flight_write_;  // This is the write buffer in progress.
210
211  // Flag if we have a pending message scheduled for WriteSocket.
212  bool delayed_write_pending_;
213
214  // Flag if we're using an SSL connection for this FlipSession.
215  bool is_secure_;
216
217  // Flip Frame state.
218  flip::FlipFramer flip_framer_;
219
220  // If an error has occurred on the session, the session is effectively
221  // dead.  Record this error here.  When no error has occurred, |error_| will
222  // be OK.
223  net::Error error_;
224  State state_;
225
226  // Some statistics counters for the session.
227  int streams_initiated_count_;
228  int streams_pushed_count_;
229  int streams_pushed_and_claimed_count_;
230  int streams_abandoned_count_;
231
232  static bool use_ssl_;
233};
234
235}  // namespace net
236
237#endif  // NET_FLIP_FLIP_SESSION_H_
238