Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Side by Side Diff: sdk/lib/io/websocket.dart

Issue 1208473005: WebSocket Compression (Closed) Base URL: https://github.com/dart-lang/sdk.git
Patch Set: Take Suggestions Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | sdk/lib/io/websocket_impl.dart » ('j') | sdk/lib/io/websocket_impl.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.io; 5 part of dart.io;
6 6
7 /** 7 /**
8 * WebSocket status codes used when closing a WebSocket connection. 8 * WebSocket status codes used when closing a WebSocket connection.
9 */ 9 */
10 abstract class WebSocketStatus { 10 abstract class WebSocketStatus {
11 static const int NORMAL_CLOSURE = 1000; 11 static const int NORMAL_CLOSURE = 1000;
12 static const int GOING_AWAY = 1001; 12 static const int GOING_AWAY = 1001;
13 static const int PROTOCOL_ERROR = 1002; 13 static const int PROTOCOL_ERROR = 1002;
14 static const int UNSUPPORTED_DATA = 1003; 14 static const int UNSUPPORTED_DATA = 1003;
15 static const int RESERVED_1004 = 1004; 15 static const int RESERVED_1004 = 1004;
16 static const int NO_STATUS_RECEIVED = 1005; 16 static const int NO_STATUS_RECEIVED = 1005;
17 static const int ABNORMAL_CLOSURE = 1006; 17 static const int ABNORMAL_CLOSURE = 1006;
18 static const int INVALID_FRAME_PAYLOAD_DATA = 1007; 18 static const int INVALID_FRAME_PAYLOAD_DATA = 1007;
19 static const int POLICY_VIOLATION = 1008; 19 static const int POLICY_VIOLATION = 1008;
20 static const int MESSAGE_TOO_BIG = 1009; 20 static const int MESSAGE_TOO_BIG = 1009;
21 static const int MISSING_MANDATORY_EXTENSION = 1010; 21 static const int MISSING_MANDATORY_EXTENSION = 1010;
22 static const int INTERNAL_SERVER_ERROR = 1011; 22 static const int INTERNAL_SERVER_ERROR = 1011;
23 static const int RESERVED_1015 = 1015; 23 static const int RESERVED_1015 = 1015;
24 } 24 }
25 25
26 /** 26 /**
27 * The [CompressionOptions] class allows you to control 27 * The [CompressionOptions] class allows you to control
28 * the options of WebSocket compression. 28 * the options of WebSocket compression.
29 */ 29 */
30 class CompressionOptions { 30 class CompressionOptions {
31 /** 31 /**
32 * Default WebSocket Compression options. 32 * Default WebSocket Compression options.
33 * Compression will be enabled with the following options: 33 * Compression will be enabled with the following options:
34 * clientNoContextTakeover: false 34 * clientNoContextTakeover: false
35 * serverNoContextTakeover: false 35 * serverNoContextTakeover: false
36 * clientMaxWindowBits: 15 36 * clientMaxWindowBits: 15
37 * serverMaxWindowBits: 15 37 * serverMaxWindowBits: 15
38 */ 38 */
39 static const CompressionOptions DEFAULT = const CompressionOptions(); 39 static const CompressionOptions DEFAULT = const CompressionOptions();
40 40
41 /** 41 /**
42 * Disables WebSocket Compression. 42 * Disables WebSocket Compression.
43 */ 43 */
44 static const CompressionOptions OFF = const CompressionOptions(enabled: false) ; 44 static const CompressionOptions OFF =
45 const CompressionOptions(enabled: false);
45 46
46 /** 47 /**
47 * Control whether the client will reuse it's compression instances. 48 * Control whether the client will reuse it's compression instances.
48 */ 49 */
49 final bool clientNoContextTakeover; 50 final bool clientNoContextTakeover;
50 51
51 /** 52 /**
52 * Control whether the server will reuse it's compression instances. 53 * Control whether the server will reuse it's compression instances.
53 */ 54 */
54 final bool serverNoContextTakeover; 55 final bool serverNoContextTakeover;
55 56
56 /** 57 /**
57 * Sets the Max Window Bits for the Client. 58 * Sets the Max Window Bits for the Client.
58 */ 59 */
59 final int clientMaxWindowBits; 60 final int clientMaxWindowBits;
60 61
61 /** 62 /**
62 * Sets the Max Window Bits for the Server. 63 * Sets the Max Window Bits for the Server.
63 */ 64 */
64 final int serverMaxWindowBits; 65 final int serverMaxWindowBits;
65 66
66 /** 67 /**
67 * Enables or disables WebSocket compression. 68 * Enables or disables WebSocket compression.
68 */ 69 */
69 final bool enabled; 70 final bool enabled;
70 71
71 const CompressionOptions({this.clientNoContextTakeover: false, 72 const CompressionOptions(
72 this.serverNoContextTakeover: false, this.clientMaxWindowBits, 73 {this.clientNoContextTakeover: false,
73 this.serverMaxWindowBits, this.enabled: true}); 74 this.serverNoContextTakeover: false,
75 this.clientMaxWindowBits,
76 this.serverMaxWindowBits,
77 this.enabled: true});
74 78
75 /** 79 /**
76 * Create a Compression Header 80 * Create a Compression Header
77 */ 81 */
78 String _createHeader([List<String> requested]) { 82 String _createHeader([List<String> requested]) {
79 if (!enabled) { 83 if (!enabled) {
80 return ""; 84 return "";
81 } 85 }
82 86
83 var header = "permessage-deflate"; 87 var header = "permessage-deflate";
Søren Gjesse 2015/07/03 13:14:54 Please add constants for all these strings.
84 88
85 if (requested == null) { 89 if (requested == null) {
86 header += "; client_max_window_bits"; 90 header += "; client_max_window_bits";
87 } else { 91 } else {
88 if (requested.contains("client_max_window_bits")) { 92 if (requested.contains("client_max_window_bits")) {
89 var myMaxWindowBits = clientMaxWindowBits == null ? 15 : clientMaxWindow Bits; 93 var myMaxWindowBits =
94 clientMaxWindowBits == null ? 15 : clientMaxWindowBits;
Søren Gjesse 2015/07/03 13:14:54 Please use a constant for 15.
90 header += "; client_max_window_bits=${myMaxWindowBits}"; 95 header += "; client_max_window_bits=${myMaxWindowBits}";
91 } 96 }
92 } 97 }
93 98
94 if (clientNoContextTakeover && (requested != null 99 if (clientNoContextTakeover &&
95 && requested.contains("client_no_context_takeover"))) { 100 (requested != null &&
101 requested.contains("client_no_context_takeover"))) {
96 header += "; client_no_context_takeover"; 102 header += "; client_no_context_takeover";
97 } 103 }
98 104
99 if (serverNoContextTakeover && (requested != null 105 if (serverNoContextTakeover &&
100 && requested.contains("server_no_context_takeover"))) { 106 (requested != null &&
107 requested.contains("server_no_context_takeover"))) {
101 header += "; server_no_context_takeover"; 108 header += "; server_no_context_takeover";
102 } 109 }
103 110
104 if (requested != null) { 111 if (requested != null) {
105 var mwb = serverMaxWindowBits == null ? 15 : serverMaxWindowBits; 112 var mwb = serverMaxWindowBits == null ? 15 : serverMaxWindowBits;
106 header += "; server_max_window_bits=${mwb}"; 113 header += "; server_max_window_bits=${mwb}";
107 } 114 }
108 115
109 return header; 116 return header;
110 } 117 }
(...skipping 22 matching lines...) Expand all
133 * stream transformer that transforms a stream of HttpRequest into a 140 * stream transformer that transforms a stream of HttpRequest into a
134 * stream of WebSockets by upgrading each HttpRequest from the HTTP or 141 * stream of WebSockets by upgrading each HttpRequest from the HTTP or
135 * HTTPS server, to the WebSocket protocol. 142 * HTTPS server, to the WebSocket protocol.
136 * 143 *
137 * server.transform(new WebSocketTransformer()).listen((webSocket) => ...); 144 * server.transform(new WebSocketTransformer()).listen((webSocket) => ...);
138 * 145 *
139 * This transformer strives to implement WebSockets as specified by RFC6455. 146 * This transformer strives to implement WebSockets as specified by RFC6455.
140 */ 147 */
141 abstract class WebSocketTransformer 148 abstract class WebSocketTransformer
142 implements StreamTransformer<HttpRequest, WebSocket> { 149 implements StreamTransformer<HttpRequest, WebSocket> {
143
144 /** 150 /**
145 * Create a new [WebSocketTransformer]. 151 * Create a new [WebSocketTransformer].
146 * 152 *
147 * If [protocolSelector] is provided, [protocolSelector] will be called to 153 * If [protocolSelector] is provided, [protocolSelector] will be called to
148 * select what protocol to use, if any were provided by the client. 154 * select what protocol to use, if any were provided by the client.
149 * [protocolSelector] is should return either a [String] or a [Future] 155 * [protocolSelector] is should return either a [String] or a [Future]
150 * completing with a [String]. The [String] must exist in the list of 156 * completing with a [String]. The [String] must exist in the list of
151 * protocols. 157 * protocols.
152 */ 158 */
153 factory WebSocketTransformer({protocolSelector(List<String> protocols), 159 factory WebSocketTransformer(
154 CompressionOptions compression: CompressionOptions.DEFAULT}) 160 {protocolSelector(List<String> protocols),
155 => new _WebSocketTransformerImpl(protocolSelector, compression); 161 CompressionOptions compression: CompressionOptions.DEFAULT}) =>
162 new _WebSocketTransformerImpl(protocolSelector, compression);
156 163
157 /** 164 /**
158 * Upgrades a [HttpRequest] to a [WebSocket] connection. If the 165 * Upgrades a [HttpRequest] to a [WebSocket] connection. If the
159 * request is not a valid WebSocket upgrade request an HTTP response 166 * request is not a valid WebSocket upgrade request an HTTP response
160 * with status code 500 will be returned. Otherwise the returned 167 * with status code 500 will be returned. Otherwise the returned
161 * future will complete with the [WebSocket] when the upgrade pocess 168 * future will complete with the [WebSocket] when the upgrade pocess
162 * is complete. 169 * is complete.
163 * 170 *
164 * If [protocolSelector] is provided, [protocolSelector] will be called to 171 * If [protocolSelector] is provided, [protocolSelector] will be called to
165 * select what protocol to use, if any were provided by the client. 172 * select what protocol to use, if any were provided by the client.
166 * [protocolSelector] is should return either a [String] or a [Future] 173 * [protocolSelector] is should return either a [String] or a [Future]
167 * completing with a [String]. The [String] must exist in the list of 174 * completing with a [String]. The [String] must exist in the list of
168 * protocols. 175 * protocols.
169 */ 176 */
170 static Future<WebSocket> upgrade(HttpRequest request, 177 static Future<WebSocket> upgrade(HttpRequest request,
171 {protocolSelector(List<String> protocols), 178 {protocolSelector(List<String> protocols),
172 CompressionOptions compression: CompressionO ptions.DEFAULT}) { 179 CompressionOptions compression: CompressionOptions.DEFAULT}) {
173 return _WebSocketTransformerImpl._upgrade(request, protocolSelector, compres sion); 180 return _WebSocketTransformerImpl._upgrade(
181 request, protocolSelector, compression);
174 } 182 }
175 183
176 /** 184 /**
177 * Checks whether the request is a valid WebSocket upgrade request. 185 * Checks whether the request is a valid WebSocket upgrade request.
178 */ 186 */
179 static bool isUpgradeRequest(HttpRequest request) { 187 static bool isUpgradeRequest(HttpRequest request) {
180 return _WebSocketTransformerImpl._isUpgradeRequest(request); 188 return _WebSocketTransformerImpl._isUpgradeRequest(request);
181 } 189 }
182 } 190 }
183 191
184
185 /** 192 /**
186 * A two-way HTTP communication object for client or server applications. 193 * A two-way HTTP communication object for client or server applications.
187 * 194 *
188 * The stream exposes the messages received. A text message will be of type 195 * The stream exposes the messages received. A text message will be of type
189 * [:String:] and a binary message will be of type [:List<int>:]. 196 * [:String:] and a binary message will be of type [:List<int>:].
190 */ 197 */
191 abstract class WebSocket implements Stream, StreamSink { 198 abstract class WebSocket implements Stream, StreamSink {
192 /** 199 /**
193 * Possible states of the connection. 200 * Possible states of the connection.
194 */ 201 */
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 * - `sec-websocket-protocol` 241 * - `sec-websocket-protocol`
235 * - `sec-websocket-version` 242 * - `sec-websocket-version`
236 * - `upgrade` 243 * - `upgrade`
237 * 244 *
238 * If any of these are passed in the `headers` map they will be ignored. 245 * If any of these are passed in the `headers` map they will be ignored.
239 * 246 *
240 * If the `url` contains user information this will be passed as basic 247 * If the `url` contains user information this will be passed as basic
241 * authentication when setting up the connection. 248 * authentication when setting up the connection.
242 */ 249 */
243 static Future<WebSocket> connect(String url, 250 static Future<WebSocket> connect(String url,
244 {Iterable<String> protocols, 251 {Iterable<String> protocols, Map<String, dynamic> headers}) =>
245 Map<String, dynamic> headers}) =>
246 _WebSocketImpl.connect(url, protocols, headers); 252 _WebSocketImpl.connect(url, protocols, headers);
247 253
248 @Deprecated('This constructor will be removed in Dart 2.0. Use `implements`' 254 @Deprecated('This constructor will be removed in Dart 2.0. Use `implements`'
249 ' instead of `extends` if implementing this abstract class.') 255 ' instead of `extends` if implementing this abstract class.')
250 WebSocket(); 256 WebSocket();
251 257
252 /** 258 /**
253 * Creates a WebSocket from an already-upgraded socket. 259 * Creates a WebSocket from an already-upgraded socket.
254 * 260 *
255 * The initial WebSocket handshake must have occurred prior to this call. A 261 * The initial WebSocket handshake must have occurred prior to this call. A
256 * WebSocket client can automatically perform the handshake using 262 * WebSocket client can automatically perform the handshake using
257 * [WebSocket.connect], while a server can do so using 263 * [WebSocket.connect], while a server can do so using
258 * [WebSocketTransformer.upgrade]. To manually upgrade an [HttpRequest], 264 * [WebSocketTransformer.upgrade]. To manually upgrade an [HttpRequest],
259 * [HttpRequest.detachSocket] may be called. 265 * [HttpRequest.detachSocket] may be called.
260 * 266 *
261 * [protocol] should be the protocol negotiated by this handshake, if any. 267 * [protocol] should be the protocol negotiated by this handshake, if any.
262 * 268 *
263 * [serverSide] must be passed explicitly. If it's `false`, the WebSocket will 269 * [serverSide] must be passed explicitly. If it's `false`, the WebSocket will
264 * act as the client and mask the messages it sends. If it's `true`, it will 270 * act as the client and mask the messages it sends. If it's `true`, it will
265 * act as the server and will not mask its messages. 271 * act as the server and will not mask its messages.
266 */ 272 */
267 factory WebSocket.fromUpgradedSocket(Socket socket, {String protocol, 273 factory WebSocket.fromUpgradedSocket(Socket socket,
268 bool serverSide, CompressionOptions compression: CompressionOptions.DEFA ULT}) { 274 {String protocol,
275 bool serverSide,
276 CompressionOptions compression: CompressionOptions.DEFAULT}) {
269 if (serverSide == null) { 277 if (serverSide == null) {
270 throw new ArgumentError("The serverSide argument must be passed " 278 throw new ArgumentError("The serverSide argument must be passed "
271 "explicitly to WebSocket.fromUpgradedSocket."); 279 "explicitly to WebSocket.fromUpgradedSocket.");
272 } 280 }
273 return new _WebSocketImpl._fromSocket(socket, protocol, compression, serverS ide); 281 return new _WebSocketImpl._fromSocket(
282 socket, protocol, compression, serverSide);
274 } 283 }
275 284
276 /** 285 /**
277 * Returns the current state of the connection. 286 * Returns the current state of the connection.
278 */ 287 */
279 int get readyState; 288 int get readyState;
280 289
281 /** 290 /**
282 * The extensions property is initially the empty string. After the 291 * The extensions property is initially the empty string. After the
283 * WebSocket connection is established this string reflects the 292 * WebSocket connection is established this string reflects the
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 void add(data); 329 void add(data);
321 330
322 /** 331 /**
323 * Sends data from a stream on WebSocket connection. Each data event from 332 * Sends data from a stream on WebSocket connection. Each data event from
324 * [stream] will be send as a single WebSocket frame. The data from [stream] 333 * [stream] will be send as a single WebSocket frame. The data from [stream]
325 * must be either [:String:]s, or [:List<int>:]s holding bytes. 334 * must be either [:String:]s, or [:List<int>:]s holding bytes.
326 */ 335 */
327 Future addStream(Stream stream); 336 Future addStream(Stream stream);
328 } 337 }
329 338
330
331 class WebSocketException implements IOException { 339 class WebSocketException implements IOException {
332 final String message; 340 final String message;
341
333 const WebSocketException([this.message = ""]); 342 const WebSocketException([this.message = ""]);
343
334 String toString() => "WebSocketException: $message"; 344 String toString() => "WebSocketException: $message";
335 } 345 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/io/websocket_impl.dart » ('j') | sdk/lib/io/websocket_impl.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698