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

Side by Side Diff: lib/src/copy/web_socket_impl.dart

Issue 1225403008: Bring in latest dart:io WebSocket code. (Closed) Base URL: git@github.com:dart-lang/http_parser@master
Patch Set: pubspec + changelog 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 | « lib/src/copy/web_socket.dart ('k') | lib/src/web_socket.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 library http_parser.web_socket; 5 // The following code is copied from sdk/lib/io/websocket_impl.dart. The
6 // "dart:io" implementation isn't used directly to support non-"dart:io"
7 // applications.
8 //
9 // Because it's copied directly, only modifications necessary to support the
10 // desired public API and to remove "dart:io" dependencies have been made.
11 //
12 // This is up-to-date as of sdk revision
13 // 86227840d75d974feb238f8b3c59c038b99c05cf.
14 library http_parser.copy.web_socket_impl;
6 15
7 import 'dart:async'; 16 import 'dart:async';
8 import 'dart:convert'; 17 import 'dart:convert';
9 import 'dart:math'; 18 import 'dart:math';
10 import 'dart:typed_data'; 19 import 'dart:typed_data';
11 20
12 import 'package:crypto/crypto.dart'; 21 import '../web_socket.dart';
22 import 'bytes_builder.dart';
23 import 'io_sink.dart';
24 import 'web_socket.dart';
13 25
14 import 'bytes_builder.dart'; 26 const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
15
16 /// An implementation of the WebSocket protocol that's not specific to "dart:io"
17 /// or to any particular HTTP API.
18 ///
19 /// Because this is HTTP-API-agnostic, it doesn't handle the initial [WebSocket
20 /// handshake][]. This needs to be handled manually by the user of the code.
21 /// Once that's been done, [new CompatibleWebSocket] can be called with the
22 /// underlying socket and it will handle the remainder of the protocol.
23 ///
24 /// [WebSocket handshake]: https://tools.ietf.org/html/rfc6455#section-4
25 abstract class CompatibleWebSocket implements Stream, StreamSink {
26 /// The interval for sending ping signals.
27 ///
28 /// If a ping message is not answered by a pong message from the peer, the
29 /// `WebSocket` is assumed disconnected and the connection is closed with a
30 /// [WebSocketStatus.GOING_AWAY] close code. When a ping signal is sent, the
31 /// pong message must be received within [pingInterval].
32 ///
33 /// There are never two outstanding pings at any given time, and the next ping
34 /// timer starts when the pong is received.
35 ///
36 /// By default, the [pingInterval] is `null`, indicating that ping messages
37 /// are disabled.
38 Duration pingInterval;
39
40 /// The [close code][] set when the WebSocket connection is closed.
41 ///
42 /// [close code]: https://tools.ietf.org/html/rfc6455#section-7.1.5
43 ///
44 /// Before the connection has been closed, this will be `null`.
45 int get closeCode;
46
47 /// The [close reason][] set when the WebSocket connection is closed.
48 ///
49 /// [close reason]: https://tools.ietf.org/html/rfc6455#section-7.1.6
50 ///
51 /// Before the connection has been closed, this will be `null`.
52 String get closeReason;
53
54 /// Signs a `Sec-WebSocket-Key` header sent by a WebSocket client as part of
55 /// the [initial handshake].
56 ///
57 /// The return value should be sent back to the client in a
58 /// `Sec-WebSocket-Accept` header.
59 ///
60 /// [initial handshake]: https://tools.ietf.org/html/rfc6455#section-4.2.2
61 static String signKey(String key) {
62 var hash = new SHA1();
63 // We use [codeUnits] here rather than UTF-8-decoding the string because
64 // [key] is expected to be base64 encoded, and so will be pure ASCII.
65 hash.add((key + _webSocketGUID).codeUnits);
66 return CryptoUtils.bytesToBase64(hash.close());
67 }
68
69 /// Creates a new WebSocket handling messaging across an existing socket.
70 ///
71 /// Because this is HTTP-API-agnostic, the initial [WebSocket handshake][]
72 /// must have already been completed on the socket before this is called.
73 ///
74 /// If [stream] is also a [StreamSink] (for example, if it's a "dart:io"
75 /// `Socket`), it will be used for both sending and receiving data. Otherwise,
76 /// it will be used for receiving data and [sink] will be used for sending it.
77 ///
78 /// If this is a WebSocket server, [serverSide] should be `true` (the
79 /// default); if it's a client, [serverSide] should be `false`.
80 ///
81 /// [WebSocket handshake]: https://tools.ietf.org/html/rfc6455#section-4
82 factory CompatibleWebSocket(Stream<List<int>> stream,
83 {StreamSink<List<int>> sink, bool serverSide: true}) {
84 if (sink == null) {
85 if (stream is! StreamSink) {
86 throw new ArgumentError("If stream isn't also a StreamSink, sink must "
87 "be passed explicitly.");
88 }
89 sink = stream as StreamSink;
90 }
91
92 return new _WebSocketImpl._fromSocket(stream, sink, serverSide);
93 }
94
95 /// Closes the web socket connection.
96 ///
97 /// [closeCode] and [closeReason] are the [close code][] and [reason][] sent
98 /// to the remote peer, respectively. If they are omitted, the peer will see
99 /// a "no status received" code with no reason.
100 ///
101 /// [close code]: https://tools.ietf.org/html/rfc6455#section-7.1.5
102 /// [reason]: https://tools.ietf.org/html/rfc6455#section-7.1.6
103 Future close([int closeCode, String closeReason]);
104 }
105
106 /// An exception thrown by [CompatibleWebSocket].
107 class CompatibleWebSocketException implements Exception {
108 final String message;
109
110 CompatibleWebSocketException([this.message]);
111
112 String toString() => message == null
113 ? "CompatibleWebSocketException" :
114 "CompatibleWebSocketException: $message";
115 }
116
117 // The following code is copied from sdk/lib/io/websocket_impl.dart. The
118 // "dart:io" implementation isn't used directly both to support non-"dart:io"
119 // applications, and because it's incompatible with non-"dart:io" HTTP requests
120 // (issue 18172).
121 //
122 // Because it's copied directly, only modifications necessary to support the
123 // desired public API and to remove "dart:io" dependencies have been made.
124
125 /**
126 * Web socket status codes used when closing a web socket connection.
127 */
128 abstract class _WebSocketStatus {
129 static const int NORMAL_CLOSURE = 1000;
130 static const int GOING_AWAY = 1001;
131 static const int PROTOCOL_ERROR = 1002;
132 static const int UNSUPPORTED_DATA = 1003;
133 static const int RESERVED_1004 = 1004;
134 static const int NO_STATUS_RECEIVED = 1005;
135 static const int ABNORMAL_CLOSURE = 1006;
136 static const int INVALID_FRAME_PAYLOAD_DATA = 1007;
137 static const int POLICY_VIOLATION = 1008;
138 static const int MESSAGE_TOO_BIG = 1009;
139 static const int MISSING_MANDATORY_EXTENSION = 1010;
140 static const int INTERNAL_SERVER_ERROR = 1011;
141 static const int RESERVED_1015 = 1015;
142 }
143
144 abstract class _WebSocketState {
145 static const int CONNECTING = 0;
146 static const int OPEN = 1;
147 static const int CLOSING = 2;
148 static const int CLOSED = 3;
149 }
150
151 const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
152 27
153 final _random = new Random(); 28 final _random = new Random();
154 29
155 // Matches _WebSocketOpcode. 30 // Matches _WebSocketOpcode.
156 class _WebSocketMessageType { 31 class _WebSocketMessageType {
157 static const int NONE = 0; 32 static const int NONE = 0;
158 static const int TEXT = 1; 33 static const int TEXT = 1;
159 static const int BINARY = 2; 34 static const int BINARY = 2;
160 } 35 }
161 36
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 int _state = START; 76 int _state = START;
202 bool _fin = false; 77 bool _fin = false;
203 int _opcode = -1; 78 int _opcode = -1;
204 int _len = -1; 79 int _len = -1;
205 bool _masked = false; 80 bool _masked = false;
206 int _remainingLenBytes = -1; 81 int _remainingLenBytes = -1;
207 int _remainingMaskingKeyBytes = 4; 82 int _remainingMaskingKeyBytes = 4;
208 int _remainingPayloadBytes = -1; 83 int _remainingPayloadBytes = -1;
209 int _unmaskingIndex = 0; 84 int _unmaskingIndex = 0;
210 int _currentMessageType = _WebSocketMessageType.NONE; 85 int _currentMessageType = _WebSocketMessageType.NONE;
211 int closeCode = _WebSocketStatus.NO_STATUS_RECEIVED; 86 int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
212 String closeReason = ""; 87 String closeReason = "";
213 88
214 EventSink _eventSink; 89 EventSink _eventSink;
215 90
216 final bool _serverSide; 91 final bool _serverSide;
217 final List _maskingBytes = new List(4); 92 final List _maskingBytes = new List(4);
218 final BytesBuilder _payload = new BytesBuilder(copy: false); 93 final BytesBuilder _payload = new BytesBuilder(copy: false);
219 94
220 _WebSocketProtocolTransformer([this._serverSide = false]); 95 _WebSocketProtocolTransformer([this._serverSide = false]);
221 96
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 break; 316 break;
442 } 317 }
443 _currentMessageType = _WebSocketMessageType.NONE; 318 _currentMessageType = _WebSocketMessageType.NONE;
444 } 319 }
445 _prepareForNextFrame(); 320 _prepareForNextFrame();
446 } 321 }
447 322
448 void _controlFrameEnd() { 323 void _controlFrameEnd() {
449 switch (_opcode) { 324 switch (_opcode) {
450 case _WebSocketOpcode.CLOSE: 325 case _WebSocketOpcode.CLOSE:
451 closeCode = _WebSocketStatus.NO_STATUS_RECEIVED; 326 closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
452 var payload = _payload.takeBytes(); 327 var payload = _payload.takeBytes();
453 if (payload.length > 0) { 328 if (payload.length > 0) {
454 if (payload.length == 1) { 329 if (payload.length == 1) {
455 throw new CompatibleWebSocketException("Protocol error"); 330 throw new CompatibleWebSocketException("Protocol error");
456 } 331 }
457 closeCode = payload[0] << 8 | payload[1]; 332 closeCode = payload[0] << 8 | payload[1];
458 if (closeCode == _WebSocketStatus.NO_STATUS_RECEIVED) { 333 if (closeCode == WebSocketStatus.NO_STATUS_RECEIVED) {
459 throw new CompatibleWebSocketException("Protocol error"); 334 throw new CompatibleWebSocketException("Protocol error");
460 } 335 }
461 if (payload.length > 2) { 336 if (payload.length > 2) {
462 closeReason = UTF8.decode(payload.sublist(2)); 337 closeReason = UTF8.decode(payload.sublist(2));
463 } 338 }
464 } 339 }
465 _state = CLOSED; 340 _state = CLOSED;
466 _eventSink.close(); 341 _eventSink.close();
467 break; 342 break;
468 343
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 } 377 }
503 378
504 379
505 class _WebSocketPong { 380 class _WebSocketPong {
506 final List<int> payload; 381 final List<int> payload;
507 _WebSocketPong([this.payload = null]); 382 _WebSocketPong([this.payload = null]);
508 } 383 }
509 384
510 // TODO(ajohnsen): Make this transformer reusable. 385 // TODO(ajohnsen): Make this transformer reusable.
511 class _WebSocketOutgoingTransformer implements StreamTransformer, EventSink { 386 class _WebSocketOutgoingTransformer implements StreamTransformer, EventSink {
512 final _WebSocketImpl webSocket; 387 final WebSocketImpl webSocket;
513 EventSink _eventSink; 388 EventSink _eventSink;
514 389
515 _WebSocketOutgoingTransformer(this.webSocket); 390 _WebSocketOutgoingTransformer(this.webSocket);
516 391
517 Stream bind(Stream stream) { 392 Stream bind(Stream stream) {
518 return new Stream.eventTransformed( 393 return new Stream.eventTransformed(
519 stream, 394 stream,
520 (EventSink eventSink) { 395 (EventSink eventSink) {
521 if (_eventSink != null) { 396 if (_eventSink != null) {
522 throw new StateError("WebSocket transformer already used"); 397 throw new StateError("WebSocket transformer already used");
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 if (data == null) { 531 if (data == null) {
657 return [header]; 532 return [header];
658 } else { 533 } else {
659 return [header, data]; 534 return [header, data];
660 } 535 }
661 } 536 }
662 } 537 }
663 538
664 539
665 class _WebSocketConsumer implements StreamConsumer { 540 class _WebSocketConsumer implements StreamConsumer {
666 final _WebSocketImpl webSocket; 541 final WebSocketImpl webSocket;
667 final StreamSink<List<int>> sink; 542 final StreamSink<List<int>> sink;
668 StreamController _controller; 543 StreamController _controller;
669 StreamSubscription _subscription; 544 StreamSubscription _subscription;
670 bool _issuedPause = false; 545 bool _issuedPause = false;
671 bool _closed = false; 546 bool _closed = false;
672 Completer _closeCompleter = new Completer(); 547 Completer _closeCompleter = new Completer();
673 Completer _completer; 548 Completer _completer;
674 549
675 _WebSocketConsumer(this.webSocket, this.sink); 550 _WebSocketConsumer(this.webSocket, this.sink);
676 551
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 } 653 }
779 654
780 void closeSocket() { 655 void closeSocket() {
781 _closed = true; 656 _closed = true;
782 _cancel(); 657 _cancel();
783 close(); 658 close();
784 } 659 }
785 } 660 }
786 661
787 662
788 class _WebSocketImpl extends Stream implements CompatibleWebSocket { 663 class WebSocketImpl extends Stream with _ServiceObject
664 implements CompatibleWebSocket {
665 // Use default Map so we keep order.
666 static Map<int, WebSocketImpl> _webSockets = new Map<int, WebSocketImpl>();
667
668 final String protocol;
669
789 StreamController _controller; 670 StreamController _controller;
790 StreamSubscription _subscription; 671 StreamSubscription _subscription;
791 StreamController _sink; 672 StreamSink _sink;
792 673
793 final bool _serverSide; 674 final bool _serverSide;
794 int _readyState = _WebSocketState.CONNECTING; 675 int _readyState = WebSocket.CONNECTING;
795 bool _writeClosed = false; 676 bool _writeClosed = false;
796 int _closeCode; 677 int _closeCode;
797 String _closeReason; 678 String _closeReason;
798 Duration _pingInterval; 679 Duration _pingInterval;
799 Timer _pingTimer; 680 Timer _pingTimer;
800 _WebSocketConsumer _consumer; 681 _WebSocketConsumer _consumer;
801 682
802 int _outCloseCode; 683 int _outCloseCode;
803 String _outCloseReason; 684 String _outCloseReason;
804 Timer _closeTimer; 685 Timer _closeTimer;
805 686
806 _WebSocketImpl._fromSocket(Stream<List<int>> stream, 687 WebSocketImpl.fromSocket(Stream<List<int>> stream,
807 StreamSink<List<int>> sink, [this._serverSide = false]) { 688 StreamSink<List<int>> sink, this.protocol, [this._serverSide = false]) {
808 _consumer = new _WebSocketConsumer(this, sink); 689 _consumer = new _WebSocketConsumer(this, sink);
809 _sink = new StreamController(); 690 _sink = new StreamSinkImpl(_consumer);
810 _sink.stream.pipe(_consumer); 691 _readyState = WebSocket.OPEN;
811 _readyState = _WebSocketState.OPEN;
812 692
813 var transformer = new _WebSocketProtocolTransformer(_serverSide); 693 var transformer = new _WebSocketProtocolTransformer(_serverSide);
814 _subscription = stream.transform(transformer).listen( 694 _subscription = stream.transform(transformer).listen(
815 (data) { 695 (data) {
816 if (data is _WebSocketPing) { 696 if (data is _WebSocketPing) {
817 if (!_writeClosed) _consumer.add(new _WebSocketPong(data.payload)); 697 if (!_writeClosed) _consumer.add(new _WebSocketPong(data.payload));
818 } else if (data is _WebSocketPong) { 698 } else if (data is _WebSocketPong) {
819 // Simply set pingInterval, as it'll cancel any timers. 699 // Simply set pingInterval, as it'll cancel any timers.
820 pingInterval = _pingInterval; 700 pingInterval = _pingInterval;
821 } else { 701 } else {
822 _controller.add(data); 702 _controller.add(data);
823 } 703 }
824 }, 704 },
825 onError: (error) { 705 onError: (error) {
826 if (_closeTimer != null) _closeTimer.cancel(); 706 if (_closeTimer != null) _closeTimer.cancel();
827 if (error is FormatException) { 707 if (error is FormatException) {
828 _close(_WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA); 708 _close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA);
829 } else { 709 } else {
830 _close(_WebSocketStatus.PROTOCOL_ERROR); 710 _close(WebSocketStatus.PROTOCOL_ERROR);
831 } 711 }
712 // An error happened, set the close code set above.
713 _closeCode = _outCloseCode;
714 _closeReason = _outCloseReason;
832 _controller.close(); 715 _controller.close();
833 }, 716 },
834 onDone: () { 717 onDone: () {
835 if (_closeTimer != null) _closeTimer.cancel(); 718 if (_closeTimer != null) _closeTimer.cancel();
836 if (_readyState == _WebSocketState.OPEN) { 719 if (_readyState == WebSocket.OPEN) {
837 _readyState = _WebSocketState.CLOSING; 720 _readyState = WebSocket.CLOSING;
838 if (!_isReservedStatusCode(transformer.closeCode)) { 721 if (!_isReservedStatusCode(transformer.closeCode)) {
839 _close(transformer.closeCode); 722 _close(transformer.closeCode);
840 } else { 723 } else {
841 _close(); 724 _close();
842 } 725 }
843 _readyState = _WebSocketState.CLOSED; 726 _readyState = WebSocket.CLOSED;
844 } 727 }
728 // Protocol close, use close code from transformer.
845 _closeCode = transformer.closeCode; 729 _closeCode = transformer.closeCode;
846 _closeReason = transformer.closeReason; 730 _closeReason = transformer.closeReason;
847 _controller.close(); 731 _controller.close();
848 }, 732 },
849 cancelOnError: true); 733 cancelOnError: true);
850 _subscription.pause(); 734 _subscription.pause();
851 _controller = new StreamController(sync: true, 735 _controller = new StreamController(sync: true,
852 onListen: _subscription.resume, 736 onListen: () => _subscription.resume(),
737 onCancel: () {
738 _subscription.cancel();
739 _subscription = null;
740 },
853 onPause: _subscription.pause, 741 onPause: _subscription.pause,
854 onResume: _subscription.resume); 742 onResume: _subscription.resume);
743
744 _webSockets[_serviceId] = this;
855 } 745 }
856 746
857 StreamSubscription listen(void onData(message), 747 StreamSubscription listen(void onData(message),
858 {Function onError, 748 {Function onError,
859 void onDone(), 749 void onDone(),
860 bool cancelOnError}) { 750 bool cancelOnError}) {
861 return _controller.stream.listen(onData, 751 return _controller.stream.listen(onData,
862 onError: onError, 752 onError: onError,
863 onDone: onDone, 753 onDone: onDone,
864 cancelOnError: cancelOnError); 754 cancelOnError: cancelOnError);
865 } 755 }
866 756
867 Duration get pingInterval => _pingInterval; 757 Duration get pingInterval => _pingInterval;
868 758
869 void set pingInterval(Duration interval) { 759 void set pingInterval(Duration interval) {
870 if (_writeClosed) return; 760 if (_writeClosed) return;
871 if (_pingTimer != null) _pingTimer.cancel(); 761 if (_pingTimer != null) _pingTimer.cancel();
872 _pingInterval = interval; 762 _pingInterval = interval;
873 763
874 if (_pingInterval == null) return; 764 if (_pingInterval == null) return;
875 765
876 _pingTimer = new Timer(_pingInterval, () { 766 _pingTimer = new Timer(_pingInterval, () {
877 if (_writeClosed) return; 767 if (_writeClosed) return;
878 _consumer.add(new _WebSocketPing()); 768 _consumer.add(new _WebSocketPing());
879 _pingTimer = new Timer(_pingInterval, () { 769 _pingTimer = new Timer(_pingInterval, () {
880 // No pong received. 770 // No pong received.
881 _close(_WebSocketStatus.GOING_AWAY); 771 _close(WebSocketStatus.GOING_AWAY);
882 }); 772 });
883 }); 773 });
884 } 774 }
885 775
776 int get readyState => _readyState;
777
778 String get extensions => null;
886 int get closeCode => _closeCode; 779 int get closeCode => _closeCode;
887 String get closeReason => _closeReason; 780 String get closeReason => _closeReason;
888 781
889 void add(data) => _sink.add(data); 782 void add(data) => _sink.add(data);
890 void addError(error, [StackTrace stackTrace]) => 783 void addError(error, [StackTrace stackTrace]) =>
891 _sink.addError(error, stackTrace); 784 _sink.addError(error, stackTrace);
892 Future addStream(Stream stream) => _sink.addStream(stream); 785 Future addStream(Stream stream) => _sink.addStream(stream);
893 Future get done => _sink.done; 786 Future get done => _sink.done;
894 787
895 Future close([int code, String reason]) { 788 Future close([int code, String reason]) {
896 if (_isReservedStatusCode(code)) { 789 if (_isReservedStatusCode(code)) {
897 throw new CompatibleWebSocketException("Reserved status code $code"); 790 throw new CompatibleWebSocketException("Reserved status code $code");
898 } 791 }
899 if (_outCloseCode == null) { 792 if (_outCloseCode == null) {
900 _outCloseCode = code; 793 _outCloseCode = code;
901 _outCloseReason = reason; 794 _outCloseReason = reason;
902 } 795 }
903 if (_closeTimer == null && !_controller.isClosed) { 796 if (!_controller.isClosed) {
904 // When closing the web-socket, we no longer accept data. 797 // If a close has not yet been received from the other end then
905 _closeTimer = new Timer(const Duration(seconds: 5), () { 798 // 1) make sure to listen on the stream so the close frame will be
906 _subscription.cancel(); 799 // processed if received.
907 _controller.close(); 800 // 2) set a timer terminate the connection if a close frame is
908 }); 801 // not received.
802 if (!_controller.hasListener && _subscription != null) {
803 _controller.stream.drain().catchError((_) => {});
804 }
805 if (_closeTimer == null) {
806 // When closing the web-socket, we no longer accept data.
807 _closeTimer = new Timer(const Duration(seconds: 5), () {
808 // Reuse code and reason from the local close.
809 _closeCode = _outCloseCode;
810 _closeReason = _outCloseReason;
811 if (_subscription != null) _subscription.cancel();
812 _controller.close();
813 _webSockets.remove(_serviceId);
814 });
815 }
909 } 816 }
910 return _sink.close(); 817 return _sink.close();
911 } 818 }
912 819
913 void _close([int code, String reason]) { 820 void _close([int code, String reason]) {
914 if (_writeClosed) return; 821 if (_writeClosed) return;
915 if (_outCloseCode == null) { 822 if (_outCloseCode == null) {
916 _outCloseCode = code; 823 _outCloseCode = code;
917 _outCloseReason = reason; 824 _outCloseReason = reason;
918 } 825 }
919 _writeClosed = true; 826 _writeClosed = true;
920 _consumer.closeSocket(); 827 _consumer.closeSocket();
828 _webSockets.remove(_serviceId);
921 } 829 }
922 830
831 // The _toJSON, _serviceTypePath, and _serviceTypeName methods
832 // have been deleted for http_parser. The methods were unused in WebSocket
833 // code and produced warnings.
834
923 static bool _isReservedStatusCode(int code) { 835 static bool _isReservedStatusCode(int code) {
924 return code != null && 836 return code != null &&
925 (code < _WebSocketStatus.NORMAL_CLOSURE || 837 (code < WebSocketStatus.NORMAL_CLOSURE ||
926 code == _WebSocketStatus.RESERVED_1004 || 838 code == WebSocketStatus.RESERVED_1004 ||
927 code == _WebSocketStatus.NO_STATUS_RECEIVED || 839 code == WebSocketStatus.NO_STATUS_RECEIVED ||
928 code == _WebSocketStatus.ABNORMAL_CLOSURE || 840 code == WebSocketStatus.ABNORMAL_CLOSURE ||
929 (code > _WebSocketStatus.INTERNAL_SERVER_ERROR && 841 (code > WebSocketStatus.INTERNAL_SERVER_ERROR &&
930 code < _WebSocketStatus.RESERVED_1015) || 842 code < WebSocketStatus.RESERVED_1015) ||
931 (code >= _WebSocketStatus.RESERVED_1015 && 843 (code >= WebSocketStatus.RESERVED_1015 &&
932 code < 3000)); 844 code < 3000));
933 } 845 }
934 } 846 }
935 847
848 // The following code is from sdk/lib/io/service_object.dart.
849
850 int _nextServiceId = 1;
851
852 // TODO(ajohnsen): Use other way of getting a uniq id.
853 abstract class _ServiceObject {
854 int __serviceId = 0;
855 int get _serviceId {
856 if (__serviceId == 0) __serviceId = _nextServiceId++;
857 return __serviceId;
858 }
859
860 // The _toJSON, _servicePath, _serviceTypePath, _serviceTypeName, and
861 // _serviceType methods have been deleted for http_parser. The methods were
862 // unused in WebSocket code and produced warnings.
863 }
OLDNEW
« no previous file with comments | « lib/src/copy/web_socket.dart ('k') | lib/src/web_socket.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698