- add sources.
[platform/framework/web/crosswalk.git] / src / net / websockets / websocket_channel.h
1 // Copyright 2013 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_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
6 #define NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
7
8 #include <string>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/callback.h"
13 #include "base/compiler_specific.h"  // for WARN_UNUSED_RESULT
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/time/time.h"
17 #include "base/timer/timer.h"
18 #include "net/base/net_export.h"
19 #include "net/websockets/websocket_event_interface.h"
20 #include "net/websockets/websocket_frame.h"
21 #include "net/websockets/websocket_stream.h"
22 #include "url/gurl.h"
23
24 namespace net {
25
26 class BoundNetLog;
27 class IOBuffer;
28 class URLRequestContext;
29
30 // Transport-independent implementation of WebSockets. Implements protocol
31 // semantics that do not depend on the underlying transport. Provides the
32 // interface to the content layer. Some WebSocket concepts are used here without
33 // definition; please see the RFC at http://tools.ietf.org/html/rfc6455 for
34 // clarification.
35 class NET_EXPORT WebSocketChannel {
36  public:
37   // The type of a WebSocketStream factory callback. Must match the signature of
38   // WebSocketStream::CreateAndConnectStream().
39   typedef base::Callback<scoped_ptr<WebSocketStreamRequest>(
40       const GURL&,
41       const std::vector<std::string>&,
42       const GURL&,
43       URLRequestContext*,
44       const BoundNetLog&,
45       scoped_ptr<WebSocketStream::ConnectDelegate>)> WebSocketStreamFactory;
46
47   // Creates a new WebSocketChannel in an idle state.
48   // SendAddChannelRequest() must be called immediately afterwards to start the
49   // connection process.
50   WebSocketChannel(scoped_ptr<WebSocketEventInterface> event_interface,
51                    URLRequestContext* url_request_context);
52   virtual ~WebSocketChannel();
53
54   // Starts the connection process.
55   void SendAddChannelRequest(
56       const GURL& socket_url,
57       const std::vector<std::string>& requested_protocols,
58       const GURL& origin);
59
60   // Sends a data frame to the remote side. The frame should usually be no
61   // larger than 32KB to prevent the time required to copy the buffers from from
62   // unduly delaying other tasks that need to run on the IO thread. This method
63   // has a hard limit of 2GB. It is the responsibility of the caller to ensure
64   // that they have sufficient send quota to send this data, otherwise the
65   // connection will be closed without sending. |fin| indicates the last frame
66   // in a message, equivalent to "FIN" as specified in section 5.2 of
67   // RFC6455. |data| is the "Payload Data". If |op_code| is kOpCodeText, or it
68   // is kOpCodeContinuation and the type the message is Text, then |data| must
69   // be a chunk of a valid UTF-8 message, however there is no requirement for
70   // |data| to be split on character boundaries.
71   void SendFrame(bool fin,
72                  WebSocketFrameHeader::OpCode op_code,
73                  const std::vector<char>& data);
74
75   // Sends |quota| units of flow control to the remote side. If the underlying
76   // transport has a concept of |quota|, then it permits the remote server to
77   // send up to |quota| units of data.
78   void SendFlowControl(int64 quota);
79
80   // Starts the closing handshake for a client-initiated shutdown of the
81   // connection. There is no API to close the connection without a closing
82   // handshake, but destroying the WebSocketChannel object while connected will
83   // effectively do that. |code| must be in the range 1000-4999. |reason| should
84   // be a valid UTF-8 string or empty.
85   //
86   // This does *not* trigger the event OnClosingHandshake(). The caller should
87   // assume that the closing handshake has started and perform the equivalent
88   // processing to OnClosingHandshake() if necessary.
89   void StartClosingHandshake(uint16 code, const std::string& reason);
90
91   // Starts the connection process, using a specified factory function rather
92   // than the default. This is exposed for testing.
93   void SendAddChannelRequestForTesting(
94       const GURL& socket_url,
95       const std::vector<std::string>& requested_protocols,
96       const GURL& origin,
97       const WebSocketStreamFactory& factory);
98
99   // The default timout for the closing handshake is a sensible value (see
100   // kClosingHandshakeTimeoutSeconds in websocket_channel.cc). However, we can
101   // set it to a very small value for testing purposes.
102   void SetClosingHandshakeTimeoutForTesting(base::TimeDelta delay);
103
104  private:
105   // Methods which return a value of type ChannelState may delete |this|. If the
106   // return value is CHANNEL_DELETED, then the caller must return without making
107   // any further access to member variables or methods.
108   typedef WebSocketEventInterface::ChannelState ChannelState;
109
110   // The object passes through a linear progression of states from
111   // FRESHLY_CONSTRUCTED to CLOSED, except that the SEND_CLOSED and RECV_CLOSED
112   // states may be skipped in case of error.
113   enum State {
114     FRESHLY_CONSTRUCTED,
115     CONNECTING,
116     CONNECTED,
117     SEND_CLOSED,  // A Close frame has been sent but not received.
118     RECV_CLOSED,  // Used briefly between receiving a Close frame and sending
119                   // the response. Once the response is sent, the state changes
120                   // to CLOSED.
121     CLOSE_WAIT,   // The Closing Handshake has completed, but the remote server
122                   // has not yet closed the connection.
123     CLOSED,       // The Closing Handshake has completed and the connection
124                   // has been closed; or the connection is failed.
125   };
126
127   // When failing a channel, sometimes it is inappropriate to expose the real
128   // reason for failing to the remote server. This enum is used by FailChannel()
129   // to select between sending the real status or a "Going Away" status.
130   enum ExposeError {
131     SEND_REAL_ERROR,
132     SEND_GOING_AWAY,
133   };
134
135   // Implementation of WebSocketStream::ConnectDelegate for
136   // WebSocketChannel. WebSocketChannel does not inherit from
137   // WebSocketStream::ConnectDelegate directly to avoid cluttering the public
138   // interface with the implementation of those methods, and because the
139   // lifetime of a WebSocketChannel is longer than the lifetime of the
140   // connection process.
141   class ConnectDelegate;
142
143   // Starts the connection progress, using a specified factory function.
144   void SendAddChannelRequestWithFactory(
145       const GURL& socket_url,
146       const std::vector<std::string>& requested_protocols,
147       const GURL& origin,
148       const WebSocketStreamFactory& factory);
149
150   // Success callback from WebSocketStream::CreateAndConnectStream(). Reports
151   // success to the event interface. May delete |this|.
152   void OnConnectSuccess(scoped_ptr<WebSocketStream> stream);
153
154   // Failure callback from WebSocketStream::CreateAndConnectStream(). Reports
155   // failure to the event interface. May delete |this|.
156   void OnConnectFailure(uint16 websocket_error);
157
158   // Returns true if state_ is SEND_CLOSED, CLOSE_WAIT or CLOSED.
159   bool InClosingState() const;
160
161   // Calls WebSocketStream::WriteFrames() with the appropriate arguments
162   ChannelState WriteFrames() WARN_UNUSED_RESULT;
163
164   // Callback from WebSocketStream::WriteFrames. Sends pending data or adjusts
165   // the send quota of the renderer channel as appropriate. |result| is a net
166   // error code, usually OK. If |synchronous| is true, then OnWriteDone() is
167   // being called from within the WriteFrames() loop and does not need to call
168   // WriteFrames() itself.
169   ChannelState OnWriteDone(bool synchronous, int result) WARN_UNUSED_RESULT;
170
171   // Calls WebSocketStream::ReadFrames() with the appropriate arguments.
172   ChannelState ReadFrames() WARN_UNUSED_RESULT;
173
174   // Callback from WebSocketStream::ReadFrames. Handles any errors and processes
175   // the returned chunks appropriately to their type. |result| is a net error
176   // code. If |synchronous| is true, then OnReadDone() is being called from
177   // within the ReadFrames() loop and does not need to call ReadFrames() itself.
178   ChannelState OnReadDone(bool synchronous, int result) WARN_UNUSED_RESULT;
179
180   // Processes a single frame that has been read from the stream.
181   ChannelState ProcessFrame(
182       scoped_ptr<WebSocketFrame> frame) WARN_UNUSED_RESULT;
183
184   // Handles a frame that the object has received enough of to process. May call
185   // |event_interface_| methods, send responses to the server, and change the
186   // value of |state_|.
187   ChannelState HandleFrame(const WebSocketFrameHeader::OpCode opcode,
188                            bool final,
189                            const scoped_refptr<IOBuffer>& data_buffer,
190                            size_t size) WARN_UNUSED_RESULT;
191
192   // Low-level method to send a single frame. Used for both data and control
193   // frames. Either sends the frame immediately or buffers it to be scheduled
194   // when the current write finishes. |fin| and |op_code| are defined as for
195   // SendFrame() above, except that |op_code| may also be a control frame
196   // opcode.
197   ChannelState SendIOBuffer(bool fin,
198                             WebSocketFrameHeader::OpCode op_code,
199                             const scoped_refptr<IOBuffer>& buffer,
200                             size_t size) WARN_UNUSED_RESULT;
201
202   // Performs the "Fail the WebSocket Connection" operation as defined in
203   // RFC6455. The supplied code and reason are sent back to the renderer in an
204   // OnDropChannel message. If state_ is CONNECTED then a Close message is sent
205   // to the remote host. If |expose| is SEND_REAL_ERROR then the remote host is
206   // given the same status code passed to the renderer; otherwise it is sent a
207   // fixed "Going Away" code.  Closes the stream_ and sets state_ to CLOSED.
208   // FailChannel() always returns CHANNEL_DELETED. It is not valid to access any
209   // member variables or methods after calling FailChannel().
210   ChannelState FailChannel(ExposeError expose,
211                            uint16 code,
212                            const std::string& reason) WARN_UNUSED_RESULT;
213
214   // Sends a Close frame to Start the WebSocket Closing Handshake, or to respond
215   // to a Close frame from the server. As a special case, setting |code| to
216   // kWebSocketErrorNoStatusReceived will create a Close frame with no payload;
217   // this is symmetric with the behaviour of ParseClose.
218   ChannelState SendClose(uint16 code,
219                          const std::string& reason) WARN_UNUSED_RESULT;
220
221   // Parses a Close frame. If no status code is supplied, then |code| is set to
222   // 1005 (No status code) with empty |reason|. If the supplied code is
223   // outside the valid range, then 1002 (Protocol error) is set instead. If the
224   // reason text is not valid UTF-8, then |reason| is set to an empty string
225   // instead.
226   void ParseClose(const scoped_refptr<IOBuffer>& buffer,
227                   size_t size,
228                   uint16* code,
229                   std::string* reason);
230
231   // Called if the closing handshake times out. Closes the connection and
232   // informs the |event_interface_| if appropriate.
233   void CloseTimeout();
234
235   // The URL of the remote server.
236   GURL socket_url_;
237
238   // The object receiving events.
239   const scoped_ptr<WebSocketEventInterface> event_interface_;
240
241   // The URLRequestContext to pass to the WebSocketStream factory.
242   URLRequestContext* const url_request_context_;
243
244   // The WebSocketStream on which to send and receive data.
245   scoped_ptr<WebSocketStream> stream_;
246
247   // A data structure containing a vector of frames to be sent and the total
248   // number of bytes contained in the vector.
249   class SendBuffer;
250   // Data that is currently pending write, or NULL if no write is pending.
251   scoped_ptr<SendBuffer> data_being_sent_;
252   // Data that is queued up to write after the current write completes.
253   // Only non-NULL when such data actually exists.
254   scoped_ptr<SendBuffer> data_to_send_next_;
255
256   // Destination for the current call to WebSocketStream::ReadFrames
257   ScopedVector<WebSocketFrame> read_frames_;
258
259   // Handle to an in-progress WebSocketStream creation request. Only non-NULL
260   // during the connection process.
261   scoped_ptr<WebSocketStreamRequest> stream_request_;
262
263   // If the renderer's send quota reaches this level, it is sent a quota
264   // refresh. "quota units" are currently bytes. TODO(ricea): Update the
265   // definition of quota units when necessary.
266   int send_quota_low_water_mark_;
267   // The level the quota is refreshed to when it reaches the low_water_mark
268   // (quota units).
269   int send_quota_high_water_mark_;
270   // The current amount of quota that the renderer has available for sending
271   // on this logical channel (quota units).
272   int current_send_quota_;
273
274   // Timer for the closing handshake.
275   base::OneShotTimer<WebSocketChannel> timer_;
276
277   // Timeout for the closing handshake.
278   base::TimeDelta timeout_;
279
280   // Storage for the status code and reason from the time the Close frame
281   // arrives until the connection is closed and they are passed to
282   // OnDropChannel().
283   uint16 closing_code_;
284   std::string closing_reason_;
285
286   // The current state of the channel. Mainly used for sanity checking, but also
287   // used to track the close state.
288   State state_;
289
290   DISALLOW_COPY_AND_ASSIGN(WebSocketChannel);
291 };
292
293 }  // namespace net
294
295 #endif  // NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_