OLD | NEW |
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 const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 7 const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
8 const String _clientNoContextTakeover = "client_no_context_takeover"; | 8 const String _clientNoContextTakeover = "client_no_context_takeover"; |
9 const String _serverNoContextTakeover = "server_no_context_takeover"; | 9 const String _serverNoContextTakeover = "server_no_context_takeover"; |
10 const String _clientMaxWindowBits = "client_max_window_bits"; | 10 const String _clientMaxWindowBits = "client_max_window_bits"; |
(...skipping 19 matching lines...) Expand all Loading... |
30 static const int PING = 9; | 30 static const int PING = 9; |
31 static const int PONG = 10; | 31 static const int PONG = 10; |
32 static const int RESERVED_B = 11; | 32 static const int RESERVED_B = 11; |
33 static const int RESERVED_C = 12; | 33 static const int RESERVED_C = 12; |
34 static const int RESERVED_D = 13; | 34 static const int RESERVED_D = 13; |
35 static const int RESERVED_E = 14; | 35 static const int RESERVED_E = 14; |
36 static const int RESERVED_F = 15; | 36 static const int RESERVED_F = 15; |
37 } | 37 } |
38 | 38 |
39 /** | 39 /** |
| 40 * Stores the header and integer value derived from negotiation of |
| 41 * client_max_window_bits and server_max_window_bits. headerValue will be |
| 42 * set in the Websocket response headers. |
| 43 */ |
| 44 class _CompressionMaxWindowBits { |
| 45 String headerValue; |
| 46 int maxWindowBits; |
| 47 _CompressionMaxWindowBits([this.headerValue, this.maxWindowBits]); |
| 48 String toString() => headerValue; |
| 49 } |
| 50 |
| 51 /** |
40 * The web socket protocol transformer handles the protocol byte stream | 52 * The web socket protocol transformer handles the protocol byte stream |
41 * which is supplied through the [:handleData:]. As the protocol is processed, | 53 * which is supplied through the [:handleData:]. As the protocol is processed, |
42 * it'll output frame data as either a List<int> or String. | 54 * it'll output frame data as either a List<int> or String. |
43 * | 55 * |
44 * Important information about usage: Be sure you use cancelOnError, so the | 56 * Important information about usage: Be sure you use cancelOnError, so the |
45 * socket will be closed when the processor encounter an error. Not using it | 57 * socket will be closed when the processor encounter an error. Not using it |
46 * will lead to undefined behaviour. | 58 * will lead to undefined behaviour. |
47 */ | 59 */ |
48 // TODO(ajohnsen): make this transformer reusable? | 60 // TODO(ajohnsen): make this transformer reusable? |
49 class _WebSocketProtocolTransformer implements StreamTransformer, EventSink { | 61 class _WebSocketProtocolTransformer implements StreamTransformer, EventSink { |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 }).then(upgrade); | 463 }).then(upgrade); |
452 } else { | 464 } else { |
453 return upgrade(null); | 465 return upgrade(null); |
454 } | 466 } |
455 } | 467 } |
456 | 468 |
457 static _WebSocketPerMessageDeflate _negotiateCompression(HttpRequest request, | 469 static _WebSocketPerMessageDeflate _negotiateCompression(HttpRequest request, |
458 HttpResponse response, CompressionOptions compression) { | 470 HttpResponse response, CompressionOptions compression) { |
459 var extensionHeader = request.headers.value("Sec-WebSocket-Extensions"); | 471 var extensionHeader = request.headers.value("Sec-WebSocket-Extensions"); |
460 | 472 |
461 if (extensionHeader == null) { | 473 extensionHeader ??= ""; |
462 extensionHeader = ""; | |
463 } | |
464 | 474 |
465 var hv = HeaderValue.parse(extensionHeader, valueSeparator: ','); | 475 var hv = HeaderValue.parse(extensionHeader, valueSeparator: ','); |
466 if (compression.enabled && hv.value == _WebSocketImpl.PER_MESSAGE_DEFLATE) { | 476 if (compression.enabled && hv.value == _WebSocketImpl.PER_MESSAGE_DEFLATE) { |
467 var info = compression._createHeader(hv); | 477 var info = compression._createHeader(hv); |
468 | 478 |
469 response.headers.add("Sec-WebSocket-Extensions", info[0]); | 479 response.headers.add("Sec-WebSocket-Extensions", info.headerValue); |
470 var serverNoContextTakeover = | 480 var serverNoContextTakeover = |
471 hv.parameters.containsKey(_serverNoContextTakeover); | 481 hv.parameters.containsKey(_serverNoContextTakeover); |
472 var clientNoContextTakeover = | 482 var clientNoContextTakeover = |
473 hv.parameters.containsKey(_clientNoContextTakeover); | 483 hv.parameters.containsKey(_clientNoContextTakeover); |
474 var deflate = new _WebSocketPerMessageDeflate( | 484 var deflate = new _WebSocketPerMessageDeflate( |
475 serverNoContextTakeover: serverNoContextTakeover, | 485 serverNoContextTakeover: serverNoContextTakeover, |
476 clientNoContextTakeover: clientNoContextTakeover, | 486 clientNoContextTakeover: clientNoContextTakeover, |
477 serverMaxWindowBits: info[1], | 487 serverMaxWindowBits: info.maxWindowBits, |
478 clientMaxWindowBits: info[1], | 488 clientMaxWindowBits: info.maxWindowBits, |
479 serverSide: true); | 489 serverSide: true); |
480 | 490 |
481 return deflate; | 491 return deflate; |
482 } | 492 } |
483 | 493 |
484 return null; | 494 return null; |
485 } | 495 } |
486 | 496 |
487 static bool _isUpgradeRequest(HttpRequest request) { | 497 static bool _isUpgradeRequest(HttpRequest request) { |
488 if (request.method != "GET") { | 498 if (request.method != "GET") { |
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 return code != null && | 1241 return code != null && |
1232 (code < WebSocketStatus.NORMAL_CLOSURE || | 1242 (code < WebSocketStatus.NORMAL_CLOSURE || |
1233 code == WebSocketStatus.RESERVED_1004 || | 1243 code == WebSocketStatus.RESERVED_1004 || |
1234 code == WebSocketStatus.NO_STATUS_RECEIVED || | 1244 code == WebSocketStatus.NO_STATUS_RECEIVED || |
1235 code == WebSocketStatus.ABNORMAL_CLOSURE || | 1245 code == WebSocketStatus.ABNORMAL_CLOSURE || |
1236 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && | 1246 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && |
1237 code < WebSocketStatus.RESERVED_1015) || | 1247 code < WebSocketStatus.RESERVED_1015) || |
1238 (code >= WebSocketStatus.RESERVED_1015 && code < 3000)); | 1248 (code >= WebSocketStatus.RESERVED_1015 && code < 3000)); |
1239 } | 1249 } |
1240 } | 1250 } |
OLD | NEW |