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.
5 #ifndef NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
6 #define NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
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"
28 class URLRequestContext;
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
35 class NET_EXPORT WebSocketChannel {
37 // The type of a WebSocketStream factory callback. Must match the signature of
38 // WebSocketStream::CreateAndConnectStream().
39 typedef base::Callback<scoped_ptr<WebSocketStreamRequest>(
41 const std::vector<std::string>&,
45 scoped_ptr<WebSocketStream::ConnectDelegate>)> WebSocketStreamFactory;
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();
54 // Starts the connection process.
55 void SendAddChannelRequest(
56 const GURL& socket_url,
57 const std::vector<std::string>& requested_protocols,
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);
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);
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.
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);
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,
97 const WebSocketStreamFactory& factory);
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);
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;
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.
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
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.
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.
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;
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,
148 const WebSocketStreamFactory& factory);
150 // Success callback from WebSocketStream::CreateAndConnectStream(). Reports
151 // success to the event interface. May delete |this|.
152 void OnConnectSuccess(scoped_ptr<WebSocketStream> stream);
154 // Failure callback from WebSocketStream::CreateAndConnectStream(). Reports
155 // failure to the event interface. May delete |this|.
156 void OnConnectFailure(uint16 websocket_error);
158 // Returns true if state_ is SEND_CLOSED, CLOSE_WAIT or CLOSED.
159 bool InClosingState() const;
161 // Calls WebSocketStream::WriteFrames() with the appropriate arguments
162 ChannelState WriteFrames() WARN_UNUSED_RESULT;
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;
171 // Calls WebSocketStream::ReadFrames() with the appropriate arguments.
172 ChannelState ReadFrames() WARN_UNUSED_RESULT;
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;
180 // Processes a single frame that has been read from the stream.
181 ChannelState ProcessFrame(
182 scoped_ptr<WebSocketFrame> frame) WARN_UNUSED_RESULT;
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,
189 const scoped_refptr<IOBuffer>& data_buffer,
190 size_t size) WARN_UNUSED_RESULT;
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
197 ChannelState SendIOBuffer(bool fin,
198 WebSocketFrameHeader::OpCode op_code,
199 const scoped_refptr<IOBuffer>& buffer,
200 size_t size) WARN_UNUSED_RESULT;
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,
212 const std::string& reason) WARN_UNUSED_RESULT;
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;
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
226 void ParseClose(const scoped_refptr<IOBuffer>& buffer,
229 std::string* reason);
231 // Called if the closing handshake times out. Closes the connection and
232 // informs the |event_interface_| if appropriate.
235 // The URL of the remote server.
238 // The object receiving events.
239 const scoped_ptr<WebSocketEventInterface> event_interface_;
241 // The URLRequestContext to pass to the WebSocketStream factory.
242 URLRequestContext* const url_request_context_;
244 // The WebSocketStream on which to send and receive data.
245 scoped_ptr<WebSocketStream> stream_;
247 // A data structure containing a vector of frames to be sent and the total
248 // number of bytes contained in the vector.
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_;
256 // Destination for the current call to WebSocketStream::ReadFrames
257 ScopedVector<WebSocketFrame> read_frames_;
259 // Handle to an in-progress WebSocketStream creation request. Only non-NULL
260 // during the connection process.
261 scoped_ptr<WebSocketStreamRequest> stream_request_;
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
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_;
274 // Timer for the closing handshake.
275 base::OneShotTimer<WebSocketChannel> timer_;
277 // Timeout for the closing handshake.
278 base::TimeDelta timeout_;
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
283 uint16 closing_code_;
284 std::string closing_reason_;
286 // The current state of the channel. Mainly used for sanity checking, but also
287 // used to track the close state.
290 DISALLOW_COPY_AND_ASSIGN(WebSocketChannel);
295 #endif // NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_