blob: 5016fb2bf91385fe6f1f05fca123c7b0820a31a8 [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"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/scoped_vector.h"
[email protected]3a266762013-10-23 08:15:1015#include "base/time/time.h"
16#include "base/timer/timer.h"
[email protected]999bcaa2013-07-17 13:42:5417#include "net/base/net_export.h"
18#include "net/websockets/websocket_frame.h"
19#include "net/websockets/websocket_stream.h"
[email protected]15fbdb42013-07-20 00:09:3820#include "url/gurl.h"
[email protected]999bcaa2013-07-17 13:42:5421
22namespace net {
23
[email protected]2f5d9f62013-09-26 12:14:2824class BoundNetLog;
25class IOBuffer;
[email protected]999bcaa2013-07-17 13:42:5426class URLRequestContext;
27class WebSocketEventInterface;
28
29// Transport-independent implementation of WebSockets. Implements protocol
30// semantics that do not depend on the underlying transport. Provides the
31// interface to the content layer. Some WebSocket concepts are used here without
32// definition; please see the RFC at http://tools.ietf.org/html/rfc6455 for
33// clarification.
34class NET_EXPORT WebSocketChannel {
35 public:
36 // The type of a WebSocketStream factory callback. Must match the signature of
37 // WebSocketStream::CreateAndConnectStream().
38 typedef base::Callback<scoped_ptr<WebSocketStreamRequest>(
39 const GURL&,
40 const std::vector<std::string>&,
41 const GURL&,
42 URLRequestContext*,
43 const BoundNetLog&,
44 scoped_ptr<WebSocketStream::ConnectDelegate>)> WebSocketStreamFactory;
45
[email protected]dab33eb2013-10-08 02:27:5146 // Creates a new WebSocketChannel in an idle state.
[email protected]999bcaa2013-07-17 13:42:5447 // SendAddChannelRequest() must be called immediately afterwards to start the
48 // connection process.
[email protected]dab33eb2013-10-08 02:27:5149 WebSocketChannel(scoped_ptr<WebSocketEventInterface> event_interface,
50 URLRequestContext* url_request_context);
[email protected]999bcaa2013-07-17 13:42:5451 virtual ~WebSocketChannel();
52
53 // Starts the connection process.
54 void SendAddChannelRequest(
[email protected]dab33eb2013-10-08 02:27:5155 const GURL& socket_url,
[email protected]999bcaa2013-07-17 13:42:5456 const std::vector<std::string>& requested_protocols,
[email protected]dab33eb2013-10-08 02:27:5157 const GURL& origin);
[email protected]999bcaa2013-07-17 13:42:5458
59 // Sends a data frame to the remote side. The frame should usually be no
60 // larger than 32KB to prevent the time required to copy the buffers from from
61 // unduly delaying other tasks that need to run on the IO thread. This method
62 // has a hard limit of 2GB. It is the responsibility of the caller to ensure
63 // that they have sufficient send quota to send this data, otherwise the
64 // connection will be closed without sending. |fin| indicates the last frame
65 // in a message, equivalent to "FIN" as specified in section 5.2 of
66 // RFC6455. |data| is the "Payload Data". If |op_code| is kOpCodeText, or it
67 // is kOpCodeContinuation and the type the message is Text, then |data| must
68 // be a chunk of a valid UTF-8 message, however there is no requirement for
69 // |data| to be split on character boundaries.
70 void SendFrame(bool fin,
71 WebSocketFrameHeader::OpCode op_code,
72 const std::vector<char>& data);
73
74 // Sends |quota| units of flow control to the remote side. If the underlying
75 // transport has a concept of |quota|, then it permits the remote server to
76 // send up to |quota| units of data.
77 void SendFlowControl(int64 quota);
78
[email protected]caab2cc2013-08-27 10:24:3779 // Starts the closing handshake for a client-initiated shutdown of the
[email protected]999bcaa2013-07-17 13:42:5480 // connection. There is no API to close the connection without a closing
81 // handshake, but destroying the WebSocketChannel object while connected will
82 // effectively do that. |code| must be in the range 1000-4999. |reason| should
83 // be a valid UTF-8 string or empty.
84 //
85 // This does *not* trigger the event OnClosingHandshake(). The caller should
86 // assume that the closing handshake has started and perform the equivalent
87 // processing to OnClosingHandshake() if necessary.
88 void StartClosingHandshake(uint16 code, const std::string& reason);
89
90 // Starts the connection process, using a specified factory function rather
91 // than the default. This is exposed for testing.
92 void SendAddChannelRequestForTesting(
[email protected]dab33eb2013-10-08 02:27:5193 const GURL& socket_url,
[email protected]999bcaa2013-07-17 13:42:5494 const std::vector<std::string>& requested_protocols,
95 const GURL& origin,
[email protected]999bcaa2013-07-17 13:42:5496 const WebSocketStreamFactory& factory);
97
[email protected]3a266762013-10-23 08:15:1098 // The default timout for the closing handshake is a sensible value (see
99 // kClosingHandshakeTimeoutSeconds in websocket_channel.cc). However, we can
100 // set it to a very small value for testing purposes.
101 void SetClosingHandshakeTimeoutForTesting(base::TimeDelta delay);
102
[email protected]999bcaa2013-07-17 13:42:54103 private:
[email protected]caab2cc2013-08-27 10:24:37104 // The object passes through a linear progression of states from
105 // FRESHLY_CONSTRUCTED to CLOSED, except that the SEND_CLOSED and RECV_CLOSED
106 // states may be skipped in case of error.
[email protected]999bcaa2013-07-17 13:42:54107 enum State {
108 FRESHLY_CONSTRUCTED,
109 CONNECTING,
110 CONNECTED,
[email protected]caab2cc2013-08-27 10:24:37111 SEND_CLOSED, // A Close frame has been sent but not received.
[email protected]999bcaa2013-07-17 13:42:54112 RECV_CLOSED, // Used briefly between receiving a Close frame and sending
[email protected]caab2cc2013-08-27 10:24:37113 // the response. Once the response is sent, the state changes
[email protected]999bcaa2013-07-17 13:42:54114 // to CLOSED.
[email protected]c0d29c22013-07-26 20:40:41115 CLOSE_WAIT, // The Closing Handshake has completed, but the remote server
116 // has not yet closed the connection.
117 CLOSED, // The Closing Handshake has completed and the connection
118 // has been closed; or the connection is failed.
[email protected]999bcaa2013-07-17 13:42:54119 };
120
[email protected]caab2cc2013-08-27 10:24:37121 // When failing a channel, sometimes it is inappropriate to expose the real
122 // reason for failing to the remote server. This enum is used by FailChannel()
123 // to select between sending the real status or a "Going Away" status.
[email protected]999bcaa2013-07-17 13:42:54124 enum ExposeError {
125 SEND_REAL_ERROR,
126 SEND_GOING_AWAY,
127 };
128
[email protected]caab2cc2013-08-27 10:24:37129 // Implementation of WebSocketStream::ConnectDelegate for
130 // WebSocketChannel. WebSocketChannel does not inherit from
131 // WebSocketStream::ConnectDelegate directly to avoid cluttering the public
132 // interface with the implementation of those methods, and because the
[email protected]999bcaa2013-07-17 13:42:54133 // lifetime of a WebSocketChannel is longer than the lifetime of the
134 // connection process.
135 class ConnectDelegate;
136
137 // Starts the connection progress, using a specified factory function.
138 void SendAddChannelRequestWithFactory(
[email protected]dab33eb2013-10-08 02:27:51139 const GURL& socket_url,
[email protected]999bcaa2013-07-17 13:42:54140 const std::vector<std::string>& requested_protocols,
141 const GURL& origin,
[email protected]999bcaa2013-07-17 13:42:54142 const WebSocketStreamFactory& factory);
143
144 // Success callback from WebSocketStream::CreateAndConnectStream(). Reports
145 // success to the event interface.
146 void OnConnectSuccess(scoped_ptr<WebSocketStream> stream);
147
148 // Failure callback from WebSocketStream::CreateAndConnectStream(). Reports
149 // failure to the event interface.
150 void OnConnectFailure(uint16 websocket_error);
151
[email protected]c0d29c22013-07-26 20:40:41152 // Returns true if state_ is SEND_CLOSED, CLOSE_WAIT or CLOSED.
153 bool InClosingState() const;
154
[email protected]999bcaa2013-07-17 13:42:54155 // Calls WebSocketStream::WriteFrames() with the appropriate arguments
156 void WriteFrames();
157
158 // Callback from WebSocketStream::WriteFrames. Sends pending data or adjusts
159 // the send quota of the renderer channel as appropriate. |result| is a net
160 // error code, usually OK. If |synchronous| is true, then OnWriteDone() is
161 // being called from within the WriteFrames() loop and does not need to call
162 // WriteFrames() itself.
163 void OnWriteDone(bool synchronous, int result);
164
165 // Calls WebSocketStream::ReadFrames() with the appropriate arguments.
166 void ReadFrames();
167
168 // Callback from WebSocketStream::ReadFrames. Handles any errors and processes
169 // the returned chunks appropriately to their type. |result| is a net error
170 // code. If |synchronous| is true, then OnReadDone() is being called from
171 // within the ReadFrames() loop and does not need to call ReadFrames() itself.
172 void OnReadDone(bool synchronous, int result);
173
[email protected]2f5d9f62013-09-26 12:14:28174 // Processes a single frame that has been read from the stream.
175 void ProcessFrame(scoped_ptr<WebSocketFrame> frame);
[email protected]caab2cc2013-08-27 10:24:37176
177 // Handles a frame that the object has received enough of to process. May call
[email protected]2f5d9f62013-09-26 12:14:28178 // |event_interface_| methods, send responses to the server, and change the
179 // value of |state_|.
[email protected]999bcaa2013-07-17 13:42:54180 void HandleFrame(const WebSocketFrameHeader::OpCode opcode,
[email protected]2f5d9f62013-09-26 12:14:28181 bool final,
182 const scoped_refptr<IOBuffer>& data_buffer,
183 size_t size);
[email protected]999bcaa2013-07-17 13:42:54184
185 // Low-level method to send a single frame. Used for both data and control
186 // frames. Either sends the frame immediately or buffers it to be scheduled
187 // when the current write finishes. |fin| and |op_code| are defined as for
188 // SendFrame() above, except that |op_code| may also be a control frame
189 // opcode.
[email protected]2f5d9f62013-09-26 12:14:28190 void SendIOBuffer(bool fin,
191 WebSocketFrameHeader::OpCode op_code,
192 const scoped_refptr<IOBuffer>& buffer,
193 size_t size);
[email protected]999bcaa2013-07-17 13:42:54194
[email protected]caab2cc2013-08-27 10:24:37195 // Performs the "Fail the WebSocket Connection" operation as defined in
[email protected]999bcaa2013-07-17 13:42:54196 // RFC6455. The supplied code and reason are sent back to the renderer in an
197 // OnDropChannel message. If state_ is CONNECTED then a Close message is sent
198 // to the remote host. If |expose| is SEND_REAL_ERROR then the remote host is
[email protected]caab2cc2013-08-27 10:24:37199 // given the same status code passed to the renderer; otherwise it is sent a
[email protected]2f5d9f62013-09-26 12:14:28200 // fixed "Going Away" code. Closes the stream_ and sets state_ to CLOSED.
[email protected]999bcaa2013-07-17 13:42:54201 void FailChannel(ExposeError expose, uint16 code, const std::string& reason);
202
203 // Sends a Close frame to Start the WebSocket Closing Handshake, or to respond
[email protected]c0d29c22013-07-26 20:40:41204 // to a Close frame from the server. As a special case, setting |code| to
205 // kWebSocketErrorNoStatusReceived will create a Close frame with no payload;
206 // this is symmetric with the behaviour of ParseClose.
[email protected]999bcaa2013-07-17 13:42:54207 void SendClose(uint16 code, const std::string& reason);
208
209 // Parses a Close frame. If no status code is supplied, then |code| is set to
210 // 1005 (No status code) with empty |reason|. If the supplied code is
211 // outside the valid range, then 1002 (Protocol error) is set instead. If the
212 // reason text is not valid UTF-8, then |reason| is set to an empty string
213 // instead.
[email protected]2f5d9f62013-09-26 12:14:28214 void ParseClose(const scoped_refptr<IOBuffer>& buffer,
215 size_t size,
[email protected]999bcaa2013-07-17 13:42:54216 uint16* code,
217 std::string* reason);
218
[email protected]3a266762013-10-23 08:15:10219 // Called if the closing handshake times out. Closes the connection and
220 // informs the |event_interface_| if appropriate.
221 void CloseTimeout();
222
[email protected]caab2cc2013-08-27 10:24:37223 // The URL of the remote server.
[email protected]dab33eb2013-10-08 02:27:51224 GURL socket_url_;
[email protected]999bcaa2013-07-17 13:42:54225
226 // The object receiving events.
227 const scoped_ptr<WebSocketEventInterface> event_interface_;
228
[email protected]dab33eb2013-10-08 02:27:51229 // The URLRequestContext to pass to the WebSocketStream factory.
230 URLRequestContext* const url_request_context_;
231
[email protected]caab2cc2013-08-27 10:24:37232 // The WebSocketStream on which to send and receive data.
[email protected]999bcaa2013-07-17 13:42:54233 scoped_ptr<WebSocketStream> stream_;
234
235 // A data structure containing a vector of frames to be sent and the total
236 // number of bytes contained in the vector.
237 class SendBuffer;
238 // Data that is currently pending write, or NULL if no write is pending.
239 scoped_ptr<SendBuffer> data_being_sent_;
240 // Data that is queued up to write after the current write completes.
241 // Only non-NULL when such data actually exists.
242 scoped_ptr<SendBuffer> data_to_send_next_;
243
244 // Destination for the current call to WebSocketStream::ReadFrames
[email protected]2f5d9f62013-09-26 12:14:28245 ScopedVector<WebSocketFrame> read_frames_;
246
[email protected]999bcaa2013-07-17 13:42:54247 // Handle to an in-progress WebSocketStream creation request. Only non-NULL
248 // during the connection process.
249 scoped_ptr<WebSocketStreamRequest> stream_request_;
[email protected]2f5d9f62013-09-26 12:14:28250
[email protected]caab2cc2013-08-27 10:24:37251 // If the renderer's send quota reaches this level, it is sent a quota
252 // refresh. "quota units" are currently bytes. TODO(ricea): Update the
253 // definition of quota units when necessary.
[email protected]999bcaa2013-07-17 13:42:54254 int send_quota_low_water_mark_;
[email protected]caab2cc2013-08-27 10:24:37255 // The level the quota is refreshed to when it reaches the low_water_mark
256 // (quota units).
[email protected]999bcaa2013-07-17 13:42:54257 int send_quota_high_water_mark_;
258 // The current amount of quota that the renderer has available for sending
259 // on this logical channel (quota units).
260 int current_send_quota_;
261
[email protected]3a266762013-10-23 08:15:10262 // Timer for the closing handshake.
263 base::OneShotTimer<WebSocketChannel> timer_;
264
265 // Timeout for the closing handshake.
266 base::TimeDelta timeout_;
267
[email protected]caab2cc2013-08-27 10:24:37268 // Storage for the status code and reason from the time the Close frame
269 // arrives until the connection is closed and they are passed to
270 // OnDropChannel().
[email protected]999bcaa2013-07-17 13:42:54271 uint16 closing_code_;
272 std::string closing_reason_;
273
274 // The current state of the channel. Mainly used for sanity checking, but also
275 // used to track the close state.
276 State state_;
277
278 DISALLOW_COPY_AND_ASSIGN(WebSocketChannel);
279};
280
281} // namespace net
282
283#endif // NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_