blob: 61f191af97839b03fdc0c4cd3949cba92aef793a [file] [log] [blame]
[email protected]999bcaa2013-07-17 13:42:541// 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"
[email protected]f485985e2013-10-24 13:47:4413#include "base/compiler_specific.h" // for WARN_UNUSED_RESULT
[email protected]999bcaa2013-07-17 13:42:5414#include "base/memory/scoped_ptr.h"
15#include "base/memory/scoped_vector.h"
[email protected]3a266762013-10-23 08:15:1016#include "base/time/time.h"
17#include "base/timer/timer.h"
[email protected]999bcaa2013-07-17 13:42:5418#include "net/base/net_export.h"
[email protected]f485985e2013-10-24 13:47:4419#include "net/websockets/websocket_event_interface.h"
[email protected]999bcaa2013-07-17 13:42:5420#include "net/websockets/websocket_frame.h"
21#include "net/websockets/websocket_stream.h"
[email protected]15fbdb42013-07-20 00:09:3822#include "url/gurl.h"
[email protected]999bcaa2013-07-17 13:42:5423
24namespace net {
25
[email protected]2f5d9f62013-09-26 12:14:2826class BoundNetLog;
27class IOBuffer;
[email protected]999bcaa2013-07-17 13:42:5428class URLRequestContext;
[email protected]999bcaa2013-07-17 13:42:5429
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.
35class NET_EXPORT WebSocketChannel {
36 public:
[email protected]969dde72013-11-13 15:59:1437 // The type of a WebSocketStream creator callback. Must match the signature of
[email protected]999bcaa2013-07-17 13:42:5438 // 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&,
[email protected]969dde72013-11-13 15:59:1445 scoped_ptr<WebSocketStream::ConnectDelegate>)> WebSocketStreamCreator;
[email protected]999bcaa2013-07-17 13:42:5446
[email protected]dab33eb2013-10-08 02:27:5147 // Creates a new WebSocketChannel in an idle state.
[email protected]999bcaa2013-07-17 13:42:5448 // SendAddChannelRequest() must be called immediately afterwards to start the
49 // connection process.
[email protected]dab33eb2013-10-08 02:27:5150 WebSocketChannel(scoped_ptr<WebSocketEventInterface> event_interface,
51 URLRequestContext* url_request_context);
[email protected]999bcaa2013-07-17 13:42:5452 virtual ~WebSocketChannel();
53
54 // Starts the connection process.
55 void SendAddChannelRequest(
[email protected]dab33eb2013-10-08 02:27:5156 const GURL& socket_url,
[email protected]999bcaa2013-07-17 13:42:5457 const std::vector<std::string>& requested_protocols,
[email protected]dab33eb2013-10-08 02:27:5158 const GURL& origin);
[email protected]999bcaa2013-07-17 13:42:5459
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
[email protected]caab2cc2013-08-27 10:24:3780 // Starts the closing handshake for a client-initiated shutdown of the
[email protected]999bcaa2013-07-17 13:42:5481 // 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
[email protected]969dde72013-11-13 15:59:1491 // Starts the connection process, using a specified creator callback rather
[email protected]999bcaa2013-07-17 13:42:5492 // than the default. This is exposed for testing.
93 void SendAddChannelRequestForTesting(
[email protected]dab33eb2013-10-08 02:27:5194 const GURL& socket_url,
[email protected]999bcaa2013-07-17 13:42:5495 const std::vector<std::string>& requested_protocols,
96 const GURL& origin,
[email protected]969dde72013-11-13 15:59:1497 const WebSocketStreamCreator& creator);
[email protected]999bcaa2013-07-17 13:42:5498
[email protected]3a266762013-10-23 08:15:1099 // 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
[email protected]999bcaa2013-07-17 13:42:54104 private:
[email protected]f485985e2013-10-24 13:47:44105 // 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
[email protected]caab2cc2013-08-27 10:24:37110 // 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.
[email protected]999bcaa2013-07-17 13:42:54113 enum State {
114 FRESHLY_CONSTRUCTED,
115 CONNECTING,
116 CONNECTED,
[email protected]caab2cc2013-08-27 10:24:37117 SEND_CLOSED, // A Close frame has been sent but not received.
[email protected]999bcaa2013-07-17 13:42:54118 RECV_CLOSED, // Used briefly between receiving a Close frame and sending
[email protected]caab2cc2013-08-27 10:24:37119 // the response. Once the response is sent, the state changes
[email protected]999bcaa2013-07-17 13:42:54120 // to CLOSED.
[email protected]c0d29c22013-07-26 20:40:41121 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.
[email protected]999bcaa2013-07-17 13:42:54125 };
126
[email protected]caab2cc2013-08-27 10:24:37127 // 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.
[email protected]999bcaa2013-07-17 13:42:54130 enum ExposeError {
131 SEND_REAL_ERROR,
132 SEND_GOING_AWAY,
133 };
134
[email protected]caab2cc2013-08-27 10:24:37135 // 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
[email protected]999bcaa2013-07-17 13:42:54139 // lifetime of a WebSocketChannel is longer than the lifetime of the
140 // connection process.
141 class ConnectDelegate;
142
[email protected]969dde72013-11-13 15:59:14143 // Starts the connection process, using the supplied creator callback.
144 void SendAddChannelRequestWithSuppliedCreator(
[email protected]dab33eb2013-10-08 02:27:51145 const GURL& socket_url,
[email protected]999bcaa2013-07-17 13:42:54146 const std::vector<std::string>& requested_protocols,
147 const GURL& origin,
[email protected]969dde72013-11-13 15:59:14148 const WebSocketStreamCreator& creator);
[email protected]999bcaa2013-07-17 13:42:54149
150 // Success callback from WebSocketStream::CreateAndConnectStream(). Reports
[email protected]f485985e2013-10-24 13:47:44151 // success to the event interface. May delete |this|.
[email protected]999bcaa2013-07-17 13:42:54152 void OnConnectSuccess(scoped_ptr<WebSocketStream> stream);
153
154 // Failure callback from WebSocketStream::CreateAndConnectStream(). Reports
[email protected]f485985e2013-10-24 13:47:44155 // failure to the event interface. May delete |this|.
[email protected]999bcaa2013-07-17 13:42:54156 void OnConnectFailure(uint16 websocket_error);
157
[email protected]c0d29c22013-07-26 20:40:41158 // Returns true if state_ is SEND_CLOSED, CLOSE_WAIT or CLOSED.
159 bool InClosingState() const;
160
[email protected]999bcaa2013-07-17 13:42:54161 // Calls WebSocketStream::WriteFrames() with the appropriate arguments
[email protected]f485985e2013-10-24 13:47:44162 ChannelState WriteFrames() WARN_UNUSED_RESULT;
[email protected]999bcaa2013-07-17 13:42:54163
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.
[email protected]f485985e2013-10-24 13:47:44169 ChannelState OnWriteDone(bool synchronous, int result) WARN_UNUSED_RESULT;
[email protected]999bcaa2013-07-17 13:42:54170
171 // Calls WebSocketStream::ReadFrames() with the appropriate arguments.
[email protected]f485985e2013-10-24 13:47:44172 ChannelState ReadFrames() WARN_UNUSED_RESULT;
[email protected]999bcaa2013-07-17 13:42:54173
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.
[email protected]f485985e2013-10-24 13:47:44178 ChannelState OnReadDone(bool synchronous, int result) WARN_UNUSED_RESULT;
[email protected]999bcaa2013-07-17 13:42:54179
[email protected]2f5d9f62013-09-26 12:14:28180 // Processes a single frame that has been read from the stream.
[email protected]f485985e2013-10-24 13:47:44181 ChannelState ProcessFrame(
182 scoped_ptr<WebSocketFrame> frame) WARN_UNUSED_RESULT;
[email protected]caab2cc2013-08-27 10:24:37183
184 // Handles a frame that the object has received enough of to process. May call
[email protected]2f5d9f62013-09-26 12:14:28185 // |event_interface_| methods, send responses to the server, and change the
186 // value of |state_|.
[email protected]f485985e2013-10-24 13:47:44187 ChannelState HandleFrame(const WebSocketFrameHeader::OpCode opcode,
188 bool final,
189 const scoped_refptr<IOBuffer>& data_buffer,
190 size_t size) WARN_UNUSED_RESULT;
[email protected]999bcaa2013-07-17 13:42:54191
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.
[email protected]f485985e2013-10-24 13:47:44197 ChannelState SendIOBuffer(bool fin,
198 WebSocketFrameHeader::OpCode op_code,
199 const scoped_refptr<IOBuffer>& buffer,
200 size_t size) WARN_UNUSED_RESULT;
[email protected]999bcaa2013-07-17 13:42:54201
[email protected]caab2cc2013-08-27 10:24:37202 // Performs the "Fail the WebSocket Connection" operation as defined in
[email protected]999bcaa2013-07-17 13:42:54203 // 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
[email protected]caab2cc2013-08-27 10:24:37206 // given the same status code passed to the renderer; otherwise it is sent a
[email protected]2f5d9f62013-09-26 12:14:28207 // fixed "Going Away" code. Closes the stream_ and sets state_ to CLOSED.
[email protected]f485985e2013-10-24 13:47:44208 // 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;
[email protected]999bcaa2013-07-17 13:42:54213
214 // Sends a Close frame to Start the WebSocket Closing Handshake, or to respond
[email protected]c0d29c22013-07-26 20:40:41215 // 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.
[email protected]f485985e2013-10-24 13:47:44218 ChannelState SendClose(uint16 code,
219 const std::string& reason) WARN_UNUSED_RESULT;
[email protected]999bcaa2013-07-17 13:42:54220
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.
[email protected]2f5d9f62013-09-26 12:14:28226 void ParseClose(const scoped_refptr<IOBuffer>& buffer,
227 size_t size,
[email protected]999bcaa2013-07-17 13:42:54228 uint16* code,
229 std::string* reason);
230
[email protected]3a266762013-10-23 08:15:10231 // Called if the closing handshake times out. Closes the connection and
232 // informs the |event_interface_| if appropriate.
233 void CloseTimeout();
234
[email protected]caab2cc2013-08-27 10:24:37235 // The URL of the remote server.
[email protected]dab33eb2013-10-08 02:27:51236 GURL socket_url_;
[email protected]999bcaa2013-07-17 13:42:54237
238 // The object receiving events.
239 const scoped_ptr<WebSocketEventInterface> event_interface_;
240
[email protected]969dde72013-11-13 15:59:14241 // The URLRequestContext to pass to the WebSocketStream creator.
[email protected]dab33eb2013-10-08 02:27:51242 URLRequestContext* const url_request_context_;
243
[email protected]caab2cc2013-08-27 10:24:37244 // The WebSocketStream on which to send and receive data.
[email protected]999bcaa2013-07-17 13:42:54245 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
[email protected]2f5d9f62013-09-26 12:14:28257 ScopedVector<WebSocketFrame> read_frames_;
258
[email protected]999bcaa2013-07-17 13:42:54259 // Handle to an in-progress WebSocketStream creation request. Only non-NULL
260 // during the connection process.
261 scoped_ptr<WebSocketStreamRequest> stream_request_;
[email protected]2f5d9f62013-09-26 12:14:28262
[email protected]caab2cc2013-08-27 10:24:37263 // 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.
[email protected]999bcaa2013-07-17 13:42:54266 int send_quota_low_water_mark_;
[email protected]caab2cc2013-08-27 10:24:37267 // The level the quota is refreshed to when it reaches the low_water_mark
268 // (quota units).
[email protected]999bcaa2013-07-17 13:42:54269 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
[email protected]3a266762013-10-23 08:15:10274 // Timer for the closing handshake.
275 base::OneShotTimer<WebSocketChannel> timer_;
276
277 // Timeout for the closing handshake.
278 base::TimeDelta timeout_;
279
[email protected]caab2cc2013-08-27 10:24:37280 // 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().
[email protected]999bcaa2013-07-17 13:42:54283 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_