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

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

Issue 1426043002: Revert "Web Socket compression - take two" (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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 | « sdk/lib/io/http_headers.dart ('k') | sdk/lib/io/websocket_impl.dart » ('j') | no next file with comments »
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
28 * the options of WebSocket compression.
29 */
30 class CompressionOptions {
31 /**
32 * Default WebSocket Compression options.
33 * Compression will be enabled with the following options:
34 * clientNoContextTakeover: false
35 * serverNoContextTakeover: false
36 * clientMaxWindowBits: 15
37 * serverMaxWindowBits: 15
38 */
39 static const CompressionOptions DEFAULT = const CompressionOptions();
40
41 /**
42 * Disables WebSocket Compression.
43 */
44 static const CompressionOptions OFF =
45 const CompressionOptions(enabled: false);
46
47 /**
48 * Control whether the client will reuse it's compression instances.
49 */
50 final bool clientNoContextTakeover;
51
52 /**
53 * Control whether the server will reuse it's compression instances.
54 */
55 final bool serverNoContextTakeover;
56
57 /**
58 * Sets the Max Window Bits for the Client.
59 */
60 final int clientMaxWindowBits;
61
62 /**
63 * Sets the Max Window Bits for the Server.
64 */
65 final int serverMaxWindowBits;
66
67 /**
68 * Enables or disables WebSocket compression.
69 */
70 final bool enabled;
71
72 const CompressionOptions(
73 {this.clientNoContextTakeover: false,
74 this.serverNoContextTakeover: false,
75 this.clientMaxWindowBits: _WebSocketImpl.DEFAULT_WINDOW_BITS,
76 this.serverMaxWindowBits: _WebSocketImpl.DEFAULT_WINDOW_BITS,
77 this.enabled: true});
78
79 /// Parses list of requested server headers to return server compression
80 /// response headers. Uses [serverMaxWindowBits] value if set, otherwise will
81 /// attempt to use value from headers. Defaults to
82 /// [WebSocket.DEFAULT_WINDOW_BITS]
83 List _createServerResponseHeader(HeaderValue requested) {
84 var info = new List(2);
85
86 int mwb;
87 var part = requested.parameters[_serverMaxWindowBits];
88 if (part != null) {
89 if (part.length >= 2 && part.startsWith('0')) {
90 throw new ArgumentError("Illegal 0 padding on value.");
91 } else {
92 mwb = serverMaxWindowBits == null
93 ? int.parse(part,
94 onError: (source) => _WebSocketImpl.DEFAULT_WINDOW_BITS)
95 : serverMaxWindowBits;
96 info[0] = "; server_max_window_bits=${mwb}";
97 info[1] = mwb;
98 }
99 } else {
100 info[1] = _WebSocketImpl.DEFAULT_WINDOW_BITS;
101 }
102 return info;
103 }
104
105 /// Returns default values for client compression request headers.
106 List _createClientRequestHeader(HeaderValue requested) {
107 var info = new List(2);
108
109 info[1] = _WebSocketImpl.DEFAULT_WINDOW_BITS;
110 if (requested != null &&
111 requested.parameters[_clientMaxWindowBits] != null) {
112 info[0] = "; client_max_window_bits=${info[1]}";
113 } else {
114 info[0] = "; client_max_window_bits";
115 }
116
117 return info;
118 }
119
120 /// Create a Compression Header. If [requested] is null or contains
121 /// client request headers, returns Client compression request headers.
122 /// If [requested] contains server response headers this method returns
123 /// a Server compression response header.
124 List _createHeader([HeaderValue requested]) {
125 if (!enabled) {
126 return ["", 0];
127 }
128
129 var info = new List(2);
130 var header = _WebSocketImpl.PER_MESSAGE_DEFLATE;
131
132 if (clientNoContextTakeover &&
133 (requested != null &&
134 requested.parameters.containsKey(_clientNoContextTakeover))) {
135 header += "; client_no_context_takeover";
136 }
137
138 if (serverNoContextTakeover &&
139 (requested != null &&
140 requested.parameters.containsKey(_serverNoContextTakeover))) {
141 header += "; server_no_context_takeover";
142 }
143
144 if (requested == null ||
145 requested.parameters.containsKey(_clientMaxWindowBits)) {
146 var clientList = _createClientRequestHeader(requested);
147 header += clientList[0];
148 info[1] = clientList[1];
149 } else {
150 var headerList = _createServerResponseHeader(requested);
151 header += headerList[0];
152 info[1] = headerList[1];
153 }
154
155 info[0] = header;
156
157 return info;
158 }
159 }
160
161 /**
162 * The [WebSocketTransformer] provides the ability to upgrade a 27 * The [WebSocketTransformer] provides the ability to upgrade a
163 * [HttpRequest] to a [WebSocket] connection. It supports both 28 * [HttpRequest] to a [WebSocket] connection. It supports both
164 * upgrading a single [HttpRequest] and upgrading a stream of 29 * upgrading a single [HttpRequest] and upgrading a stream of
165 * [HttpRequest]s. 30 * [HttpRequest]s.
166 * 31 *
167 * To upgrade a single [HttpRequest] use the static [upgrade] method. 32 * To upgrade a single [HttpRequest] use the static [upgrade] method.
168 * 33 *
169 * HttpServer server; 34 * HttpServer server;
170 * server.listen((request) { 35 * server.listen((request) {
171 * if (...) { 36 * if (...) {
172 * WebSocketTransformer.upgrade(request).then((websocket) { 37 * WebSocketTransformer.upgrade(request).then((websocket) {
173 * ... 38 * ...
174 * }); 39 * });
175 * } else { 40 * } else {
176 * // Do normal HTTP request processing. 41 * // Do normal HTTP request processing.
177 * } 42 * }
178 * }); 43 * });
179 * 44 *
180 * To transform a stream of [HttpRequest] events as it implements a 45 * To transform a stream of [HttpRequest] events as it implements a
181 * stream transformer that transforms a stream of HttpRequest into a 46 * stream transformer that transforms a stream of HttpRequest into a
182 * stream of WebSockets by upgrading each HttpRequest from the HTTP or 47 * stream of WebSockets by upgrading each HttpRequest from the HTTP or
183 * HTTPS server, to the WebSocket protocol. 48 * HTTPS server, to the WebSocket protocol.
184 * 49 *
185 * server.transform(new WebSocketTransformer()).listen((webSocket) => ...); 50 * server.transform(new WebSocketTransformer()).listen((webSocket) => ...);
186 * 51 *
187 * This transformer strives to implement WebSockets as specified by RFC6455. 52 * This transformer strives to implement WebSockets as specified by RFC6455.
188 */ 53 */
189 abstract class WebSocketTransformer 54 abstract class WebSocketTransformer
190 implements StreamTransformer<HttpRequest, WebSocket> { 55 implements StreamTransformer<HttpRequest, WebSocket> {
56
191 /** 57 /**
192 * Create a new [WebSocketTransformer]. 58 * Create a new [WebSocketTransformer].
193 * 59 *
194 * If [protocolSelector] is provided, [protocolSelector] will be called to 60 * If [protocolSelector] is provided, [protocolSelector] will be called to
195 * select what protocol to use, if any were provided by the client. 61 * select what protocol to use, if any were provided by the client.
196 * [protocolSelector] is should return either a [String] or a [Future] 62 * [protocolSelector] is should return either a [String] or a [Future]
197 * completing with a [String]. The [String] must exist in the list of 63 * completing with a [String]. The [String] must exist in the list of
198 * protocols. 64 * protocols.
199 *
200 * If [compression] is provided, the [WebSocket] created will be configured
201 * to negotiate with the specified [CompressionOptions]. If none is specified
202 * then the [WebSocket] will be created with the default [CompressionOptions].
203 */ 65 */
204 factory WebSocketTransformer( 66 factory WebSocketTransformer({protocolSelector(List<String> protocols)})
205 {protocolSelector(List<String> protocols), 67 => new _WebSocketTransformerImpl(protocolSelector);
206 CompressionOptions compression: CompressionOptions.DEFAULT}) =>
207 new _WebSocketTransformerImpl(protocolSelector, compression);
208 68
209 /** 69 /**
210 * Upgrades a [HttpRequest] to a [WebSocket] connection. If the 70 * Upgrades a [HttpRequest] to a [WebSocket] connection. If the
211 * request is not a valid WebSocket upgrade request an HTTP response 71 * request is not a valid WebSocket upgrade request an HTTP response
212 * with status code 500 will be returned. Otherwise the returned 72 * with status code 500 will be returned. Otherwise the returned
213 * future will complete with the [WebSocket] when the upgrade pocess 73 * future will complete with the [WebSocket] when the upgrade pocess
214 * is complete. 74 * is complete.
215 * 75 *
216 * If [protocolSelector] is provided, [protocolSelector] will be called to 76 * If [protocolSelector] is provided, [protocolSelector] will be called to
217 * select what protocol to use, if any were provided by the client. 77 * select what protocol to use, if any were provided by the client.
218 * [protocolSelector] is should return either a [String] or a [Future] 78 * [protocolSelector] is should return either a [String] or a [Future]
219 * completing with a [String]. The [String] must exist in the list of 79 * completing with a [String]. The [String] must exist in the list of
220 * protocols. 80 * protocols.
221 *
222 * If [compression] is provided, the [WebSocket] created will be configured
223 * to negotiate with the specified [CompressionOptions]. If none is specified
224 * then the [WebSocket] will be created with the default [CompressionOptions].
225 */ 81 */
226 static Future<WebSocket> upgrade(HttpRequest request, 82 static Future<WebSocket> upgrade(HttpRequest request,
227 {protocolSelector(List<String> protocols), 83 {protocolSelector(List<String> protocols)}) {
228 CompressionOptions compression: CompressionOptions.DEFAULT}) { 84 return _WebSocketTransformerImpl._upgrade(request, protocolSelector);
229 return _WebSocketTransformerImpl._upgrade(
230 request, protocolSelector, compression);
231 } 85 }
232 86
233 /** 87 /**
234 * Checks whether the request is a valid WebSocket upgrade request. 88 * Checks whether the request is a valid WebSocket upgrade request.
235 */ 89 */
236 static bool isUpgradeRequest(HttpRequest request) { 90 static bool isUpgradeRequest(HttpRequest request) {
237 return _WebSocketTransformerImpl._isUpgradeRequest(request); 91 return _WebSocketTransformerImpl._isUpgradeRequest(request);
238 } 92 }
239 } 93 }
240 94
95
241 /** 96 /**
242 * A two-way HTTP communication object for client or server applications. 97 * A two-way HTTP communication object for client or server applications.
243 * 98 *
244 * The stream exposes the messages received. A text message will be of type 99 * The stream exposes the messages received. A text message will be of type
245 * [:String:] and a binary message will be of type [:List<int>:]. 100 * [:String:] and a binary message will be of type [:List<int>:].
246 */ 101 */
247 abstract class WebSocket implements Stream, StreamSink { 102 abstract class WebSocket implements Stream, StreamSink {
248 /** 103 /**
249 * Possible states of the connection. 104 * Possible states of the connection.
250 */ 105 */
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 * - `sec-websocket-protocol` 145 * - `sec-websocket-protocol`
291 * - `sec-websocket-version` 146 * - `sec-websocket-version`
292 * - `upgrade` 147 * - `upgrade`
293 * 148 *
294 * If any of these are passed in the `headers` map they will be ignored. 149 * If any of these are passed in the `headers` map they will be ignored.
295 * 150 *
296 * If the `url` contains user information this will be passed as basic 151 * If the `url` contains user information this will be passed as basic
297 * authentication when setting up the connection. 152 * authentication when setting up the connection.
298 */ 153 */
299 static Future<WebSocket> connect(String url, 154 static Future<WebSocket> connect(String url,
300 {Iterable<String> protocols, 155 {Iterable<String> protocols,
301 Map<String, dynamic> headers, 156 Map<String, dynamic> headers}) =>
302 CompressionOptions compression: CompressionOptions.DEFAULT}) => 157 _WebSocketImpl.connect(url, protocols, headers);
303 _WebSocketImpl.connect(url, protocols, headers, compression: compression);
304 158
305 @Deprecated('This constructor will be removed in Dart 2.0. Use `implements`' 159 @Deprecated('This constructor will be removed in Dart 2.0. Use `implements`'
306 ' instead of `extends` if implementing this abstract class.') 160 ' instead of `extends` if implementing this abstract class.')
307 WebSocket(); 161 WebSocket();
308 162
309 /** 163 /**
310 * Creates a WebSocket from an already-upgraded socket. 164 * Creates a WebSocket from an already-upgraded socket.
311 * 165 *
312 * The initial WebSocket handshake must have occurred prior to this call. A 166 * The initial WebSocket handshake must have occurred prior to this call. A
313 * WebSocket client can automatically perform the handshake using 167 * WebSocket client can automatically perform the handshake using
314 * [WebSocket.connect], while a server can do so using 168 * [WebSocket.connect], while a server can do so using
315 * [WebSocketTransformer.upgrade]. To manually upgrade an [HttpRequest], 169 * [WebSocketTransformer.upgrade]. To manually upgrade an [HttpRequest],
316 * [HttpRequest.detachSocket] may be called. 170 * [HttpRequest.detachSocket] may be called.
317 * 171 *
318 * [protocol] should be the protocol negotiated by this handshake, if any. 172 * [protocol] should be the protocol negotiated by this handshake, if any.
319 * 173 *
320 * [serverSide] must be passed explicitly. If it's `false`, the WebSocket will 174 * [serverSide] must be passed explicitly. If it's `false`, the WebSocket will
321 * act as the client and mask the messages it sends. If it's `true`, it will 175 * act as the client and mask the messages it sends. If it's `true`, it will
322 * act as the server and will not mask its messages. 176 * act as the server and will not mask its messages.
323 *
324 * If [compression] is provided, the [WebSocket] created will be configured
325 * to negotiate with the specified [CompressionOptions]. If none is specified
326 * then the [WebSocket] will be created with the default [CompressionOptions].
327 */ 177 */
328 factory WebSocket.fromUpgradedSocket(Socket socket, 178 factory WebSocket.fromUpgradedSocket(Socket socket, {String protocol,
329 {String protocol, 179 bool serverSide}) {
330 bool serverSide,
331 CompressionOptions compression: CompressionOptions.DEFAULT}) {
332 if (serverSide == null) { 180 if (serverSide == null) {
333 throw new ArgumentError("The serverSide argument must be passed " 181 throw new ArgumentError("The serverSide argument must be passed "
334 "explicitly to WebSocket.fromUpgradedSocket."); 182 "explicitly to WebSocket.fromUpgradedSocket.");
335 } 183 }
336 return new _WebSocketImpl._fromSocket( 184 return new _WebSocketImpl._fromSocket(socket, protocol, serverSide);
337 socket, protocol, compression, serverSide);
338 } 185 }
339 186
340 /** 187 /**
341 * Returns the current state of the connection. 188 * Returns the current state of the connection.
342 */ 189 */
343 int get readyState; 190 int get readyState;
344 191
345 /** 192 /**
346 * The extensions property is initially the empty string. After the 193 * The extensions property is initially the empty string. After the
347 * WebSocket connection is established this string reflects the 194 * WebSocket connection is established this string reflects the
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 void add(data); 231 void add(data);
385 232
386 /** 233 /**
387 * Sends data from a stream on WebSocket connection. Each data event from 234 * Sends data from a stream on WebSocket connection. Each data event from
388 * [stream] will be send as a single WebSocket frame. The data from [stream] 235 * [stream] will be send as a single WebSocket frame. The data from [stream]
389 * must be either [:String:]s, or [:List<int>:]s holding bytes. 236 * must be either [:String:]s, or [:List<int>:]s holding bytes.
390 */ 237 */
391 Future addStream(Stream stream); 238 Future addStream(Stream stream);
392 } 239 }
393 240
241
394 class WebSocketException implements IOException { 242 class WebSocketException implements IOException {
395 final String message; 243 final String message;
396
397 const WebSocketException([this.message = ""]); 244 const WebSocketException([this.message = ""]);
398
399 String toString() => "WebSocketException: $message"; 245 String toString() => "WebSocketException: $message";
400 } 246 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http_headers.dart ('k') | sdk/lib/io/websocket_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698