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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/lib/io/websocket.dart

Issue 2698353003: unfork DDC's copy of most SDK libraries (Closed)
Patch Set: revert core_patch Created 3 years, 9 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart.io;
6
7 /**
8 * WebSocket status codes used when closing a WebSocket connection.
9 */
10 abstract class WebSocketStatus {
11 static const int NORMAL_CLOSURE = 1000;
12 static const int GOING_AWAY = 1001;
13 static const int PROTOCOL_ERROR = 1002;
14 static const int UNSUPPORTED_DATA = 1003;
15 static const int RESERVED_1004 = 1004;
16 static const int NO_STATUS_RECEIVED = 1005;
17 static const int ABNORMAL_CLOSURE = 1006;
18 static const int INVALID_FRAME_PAYLOAD_DATA = 1007;
19 static const int POLICY_VIOLATION = 1008;
20 static const int MESSAGE_TOO_BIG = 1009;
21 static const int MISSING_MANDATORY_EXTENSION = 1010;
22 static const int INTERNAL_SERVER_ERROR = 1011;
23 static const int RESERVED_1015 = 1015;
24 }
25
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,
76 this.serverMaxWindowBits,
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]. Returns a [_CompressionMaxWindowBits]
83 /// object which contains the response headers and negotiated max window bits.
84 _CompressionMaxWindowBits _createServerResponseHeader(HeaderValue requested) {
85 var info = new _CompressionMaxWindowBits();
86
87 int mwb;
88 String part;
89 if (requested?.parameters != null) {
90 part = requested.parameters[_serverMaxWindowBits];
91 }
92 if (part != null) {
93 if (part.length >= 2 && part.startsWith('0')) {
94 throw new ArgumentError("Illegal 0 padding on value.");
95 } else {
96 mwb = serverMaxWindowBits == null
97 ? int.parse(part,
98 onError: (source) => _WebSocketImpl.DEFAULT_WINDOW_BITS)
99 : serverMaxWindowBits;
100 info.headerValue = "; server_max_window_bits=${mwb}";
101 info.maxWindowBits = mwb;
102 }
103 } else {
104 info.headerValue = "";
105 info.maxWindowBits = _WebSocketImpl.DEFAULT_WINDOW_BITS;
106 }
107 return info;
108 }
109
110 /// Returns default values for client compression request headers.
111 String _createClientRequestHeader(HeaderValue requested, int size) {
112 var info = "";
113
114 // If responding to a valid request, specify size
115 if (requested != null) {
116 info = "; client_max_window_bits=$size";
117 } else {
118 // Client request. Specify default
119 if (clientMaxWindowBits == null) {
120 info = "; client_max_window_bits";
121 } else {
122 info = "; client_max_window_bits=$clientMaxWindowBits";
123 }
124 if (serverMaxWindowBits != null) {
125 info += "; server_max_window_bits=$serverMaxWindowBits";
126 }
127 }
128
129 return info;
130 }
131
132 /// Create a Compression Header. If [requested] is null or contains
133 /// client request headers, returns Client compression request headers with
134 /// default settings for `client_max_window_bits` header value.
135 /// If [requested] contains server response headers this method returns
136 /// a Server compression response header negotiating the max window bits
137 /// for both client and server as requested server_max_window_bits value.
138 /// This method returns a [_CompressionMaxWindowBits] object with the
139 /// response headers and negotiated maxWindowBits value.
140 _CompressionMaxWindowBits _createHeader([HeaderValue requested]) {
141 var info = new _CompressionMaxWindowBits("", 0);
142 if (!enabled) {
143 return info;
144 }
145
146 info.headerValue = _WebSocketImpl.PER_MESSAGE_DEFLATE;
147
148 if (clientNoContextTakeover &&
149 (requested == null || (requested != null &&
150 requested.parameters.containsKey(_clientNoContextTakeover)))) {
151 info.headerValue += "; client_no_context_takeover";
152 }
153
154 if (serverNoContextTakeover &&
155 (requested == null || (requested != null &&
156 requested.parameters.containsKey(_serverNoContextTakeover)))) {
157 info.headerValue += "; server_no_context_takeover";
158 }
159
160 var headerList = _createServerResponseHeader(requested);
161 info.headerValue += headerList.headerValue;
162 info.maxWindowBits = headerList.maxWindowBits;
163
164 info.headerValue +=
165 _createClientRequestHeader(requested, info.maxWindowBits);
166
167 return info;
168 }
169 }
170
171 /**
172 * The [WebSocketTransformer] provides the ability to upgrade a
173 * [HttpRequest] to a [WebSocket] connection. It supports both
174 * upgrading a single [HttpRequest] and upgrading a stream of
175 * [HttpRequest]s.
176 *
177 * To upgrade a single [HttpRequest] use the static [upgrade] method.
178 *
179 * HttpServer server;
180 * server.listen((request) {
181 * if (...) {
182 * WebSocketTransformer.upgrade(request).then((websocket) {
183 * ...
184 * });
185 * } else {
186 * // Do normal HTTP request processing.
187 * }
188 * });
189 *
190 * To transform a stream of [HttpRequest] events as it implements a
191 * stream transformer that transforms a stream of HttpRequest into a
192 * stream of WebSockets by upgrading each HttpRequest from the HTTP or
193 * HTTPS server, to the WebSocket protocol.
194 *
195 * server.transform(new WebSocketTransformer()).listen((webSocket) => ...);
196 *
197 * This transformer strives to implement WebSockets as specified by RFC6455.
198 */
199 abstract class WebSocketTransformer
200 implements StreamTransformer<HttpRequest, WebSocket> {
201 /**
202 * Create a new [WebSocketTransformer].
203 *
204 * If [protocolSelector] is provided, [protocolSelector] will be called to
205 * select what protocol to use, if any were provided by the client.
206 * [protocolSelector] is should return either a [String] or a [Future]
207 * completing with a [String]. The [String] must exist in the list of
208 * protocols.
209 *
210 * If [compression] is provided, the [WebSocket] created will be configured
211 * to negotiate with the specified [CompressionOptions]. If none is specified
212 * then the [WebSocket] will be created with the default [CompressionOptions].
213 */
214 factory WebSocketTransformer(
215 {protocolSelector(List<String> protocols),
216 CompressionOptions compression: CompressionOptions.DEFAULT}) =>
217 new _WebSocketTransformerImpl(protocolSelector, compression);
218
219 /**
220 * Upgrades a [HttpRequest] to a [WebSocket] connection. If the
221 * request is not a valid WebSocket upgrade request an HTTP response
222 * with status code 500 will be returned. Otherwise the returned
223 * future will complete with the [WebSocket] when the upgrade pocess
224 * is complete.
225 *
226 * If [protocolSelector] is provided, [protocolSelector] will be called to
227 * select what protocol to use, if any were provided by the client.
228 * [protocolSelector] is should return either a [String] or a [Future]
229 * completing with a [String]. The [String] must exist in the list of
230 * protocols.
231 *
232 * If [compression] is provided, the [WebSocket] created will be configured
233 * to negotiate with the specified [CompressionOptions]. If none is specified
234 * then the [WebSocket] will be created with the default [CompressionOptions].
235 */
236 static Future<WebSocket> upgrade(HttpRequest request,
237 {protocolSelector(List<String> protocols),
238 CompressionOptions compression: CompressionOptions.DEFAULT}) {
239 return _WebSocketTransformerImpl._upgrade(
240 request, protocolSelector, compression);
241 }
242
243 /**
244 * Checks whether the request is a valid WebSocket upgrade request.
245 */
246 static bool isUpgradeRequest(HttpRequest request) {
247 return _WebSocketTransformerImpl._isUpgradeRequest(request);
248 }
249 }
250
251 /**
252 * A two-way HTTP communication object for client or server applications.
253 *
254 * The stream exposes the messages received. A text message will be of type
255 * [:String:] and a binary message will be of type [:List<int>:].
256 */
257 abstract class WebSocket implements Stream, StreamSink {
258 /**
259 * Possible states of the connection.
260 */
261 static const int CONNECTING = 0;
262 static const int OPEN = 1;
263 static const int CLOSING = 2;
264 static const int CLOSED = 3;
265
266 /**
267 * Set and get the interval for sending ping signals. If a ping message is not
268 * answered by a pong message from the peer, the `WebSocket` is assumed
269 * disconnected and the connection is closed with a
270 * [WebSocketStatus.GOING_AWAY] close code. When a ping signal is sent, the
271 * pong message must be received within [pingInterval].
272 *
273 * There are never two outstanding pings at any given time, and the next ping
274 * timer starts when the pong is received.
275 *
276 * Set the [pingInterval] to `null` to disable sending ping messages.
277 *
278 * The default value is `null`.
279 */
280 Duration pingInterval;
281
282 /**
283 * Create a new WebSocket connection. The URL supplied in [url]
284 * must use the scheme `ws` or `wss`.
285 *
286 * The [protocols] argument is specifying the subprotocols the
287 * client is willing to speak.
288 *
289 * The [headers] argument is specifying additional HTTP headers for
290 * setting up the connection. This would typically be the `Origin`
291 * header and potentially cookies. The keys of the map are the header
292 * fields and the values are either String or List<String>.
293 *
294 * If [headers] is provided, there are a number of headers
295 * which are controlled by the WebSocket connection process. These
296 * headers are:
297 *
298 * - `connection`
299 * - `sec-websocket-key`
300 * - `sec-websocket-protocol`
301 * - `sec-websocket-version`
302 * - `upgrade`
303 *
304 * If any of these are passed in the `headers` map they will be ignored.
305 *
306 * If the `url` contains user information this will be passed as basic
307 * authentication when setting up the connection.
308 */
309 static Future<WebSocket> connect(String url,
310 {Iterable<String> protocols,
311 Map<String, dynamic> headers,
312 CompressionOptions compression: CompressionOptions.DEFAULT}) =>
313 _WebSocketImpl.connect(url, protocols, headers, compression: compression);
314
315 @Deprecated('This constructor will be removed in Dart 2.0. Use `implements`'
316 ' instead of `extends` if implementing this abstract class.')
317 WebSocket();
318
319 /**
320 * Creates a WebSocket from an already-upgraded socket.
321 *
322 * The initial WebSocket handshake must have occurred prior to this call. A
323 * WebSocket client can automatically perform the handshake using
324 * [WebSocket.connect], while a server can do so using
325 * [WebSocketTransformer.upgrade]. To manually upgrade an [HttpRequest],
326 * [HttpRequest.detachSocket] may be called.
327 *
328 * [protocol] should be the protocol negotiated by this handshake, if any.
329 *
330 * [serverSide] must be passed explicitly. If it's `false`, the WebSocket will
331 * act as the client and mask the messages it sends. If it's `true`, it will
332 * act as the server and will not mask its messages.
333 *
334 * If [compression] is provided, the [WebSocket] created will be configured
335 * to negotiate with the specified [CompressionOptions]. If none is specified
336 * then the [WebSocket] will be created with the default [CompressionOptions].
337 */
338 factory WebSocket.fromUpgradedSocket(Socket socket,
339 {String protocol,
340 bool serverSide,
341 CompressionOptions compression: CompressionOptions.DEFAULT}) {
342 if (serverSide == null) {
343 throw new ArgumentError("The serverSide argument must be passed "
344 "explicitly to WebSocket.fromUpgradedSocket.");
345 }
346 return new _WebSocketImpl._fromSocket(
347 socket, protocol, compression, serverSide);
348 }
349
350 /**
351 * Returns the current state of the connection.
352 */
353 int get readyState;
354
355 /**
356 * The extensions property is initially the empty string. After the
357 * WebSocket connection is established this string reflects the
358 * extensions used by the server.
359 */
360 String get extensions;
361
362 /**
363 * The protocol property is initially the empty string. After the
364 * WebSocket connection is established the value is the subprotocol
365 * selected by the server. If no subprotocol is negotiated the
366 * value will remain [:null:].
367 */
368 String get protocol;
369
370 /**
371 * The close code set when the WebSocket connection is closed. If
372 * there is no close code available this property will be [:null:]
373 */
374 int get closeCode;
375
376 /**
377 * The close reason set when the WebSocket connection is closed. If
378 * there is no close reason available this property will be [:null:]
379 */
380 String get closeReason;
381
382 /**
383 * Closes the WebSocket connection. Set the optional [code] and [reason]
384 * arguments to send close information to the remote peer. If they are
385 * omitted, the peer will see [WebSocketStatus.NO_STATUS_RECEIVED] code
386 * with no reason.
387 */
388 Future close([int code, String reason]);
389
390 /**
391 * Sends data on the WebSocket connection. The data in [data] must
392 * be either a [:String:], or a [:List<int>:] holding bytes.
393 */
394 void add(data);
395
396 /**
397 * Sends data from a stream on WebSocket connection. Each data event from
398 * [stream] will be send as a single WebSocket frame. The data from [stream]
399 * must be either [:String:]s, or [:List<int>:]s holding bytes.
400 */
401 Future addStream(Stream stream);
402 }
403
404 class WebSocketException implements IOException {
405 final String message;
406
407 const WebSocketException([this.message = ""]);
408
409 String toString() => "WebSocketException: $message";
410 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698