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 | 8 |
9 // Matches _WebSocketOpcode. | 9 // Matches _WebSocketOpcode. |
10 class _WebSocketMessageType { | 10 class _WebSocketMessageType { |
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 _controller.add(data); | 858 _controller.add(data); |
859 } | 859 } |
860 }, | 860 }, |
861 onError: (error) { | 861 onError: (error) { |
862 if (_closeTimer != null) _closeTimer.cancel(); | 862 if (_closeTimer != null) _closeTimer.cancel(); |
863 if (error is FormatException) { | 863 if (error is FormatException) { |
864 _close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA); | 864 _close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA); |
865 } else { | 865 } else { |
866 _close(WebSocketStatus.PROTOCOL_ERROR); | 866 _close(WebSocketStatus.PROTOCOL_ERROR); |
867 } | 867 } |
| 868 // An error happened, set the close code set above. |
| 869 _closeCode = _outCloseCode; |
| 870 _closeReason = _outCloseReason; |
868 _controller.close(); | 871 _controller.close(); |
869 }, | 872 }, |
870 onDone: () { | 873 onDone: () { |
871 if (_closeTimer != null) _closeTimer.cancel(); | 874 if (_closeTimer != null) _closeTimer.cancel(); |
872 if (_readyState == WebSocket.OPEN) { | 875 if (_readyState == WebSocket.OPEN) { |
873 _readyState = WebSocket.CLOSING; | 876 _readyState = WebSocket.CLOSING; |
874 if (!_isReservedStatusCode(transformer.closeCode)) { | 877 if (!_isReservedStatusCode(transformer.closeCode)) { |
875 _close(transformer.closeCode); | 878 _close(transformer.closeCode); |
876 } else { | 879 } else { |
877 _close(); | 880 _close(); |
878 } | 881 } |
879 _readyState = WebSocket.CLOSED; | 882 _readyState = WebSocket.CLOSED; |
880 } | 883 } |
| 884 // Protocol close, use close code from transformer. |
881 _closeCode = transformer.closeCode; | 885 _closeCode = transformer.closeCode; |
882 _closeReason = transformer.closeReason; | 886 _closeReason = transformer.closeReason; |
883 _controller.close(); | 887 _controller.close(); |
884 }, | 888 }, |
885 cancelOnError: true); | 889 cancelOnError: true); |
886 _subscription.pause(); | 890 _subscription.pause(); |
887 _controller = new StreamController(sync: true, | 891 _controller = new StreamController(sync: true, |
888 onListen: _subscription.resume, | 892 onListen: _subscription.resume, |
889 onPause: _subscription.pause, | 893 onPause: _subscription.pause, |
890 onResume: _subscription.resume); | 894 onResume: _subscription.resume); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 if (_isReservedStatusCode(code)) { | 939 if (_isReservedStatusCode(code)) { |
936 throw new WebSocketException("Reserved status code $code"); | 940 throw new WebSocketException("Reserved status code $code"); |
937 } | 941 } |
938 if (_outCloseCode == null) { | 942 if (_outCloseCode == null) { |
939 _outCloseCode = code; | 943 _outCloseCode = code; |
940 _outCloseReason = reason; | 944 _outCloseReason = reason; |
941 } | 945 } |
942 if (_closeTimer == null && !_controller.isClosed) { | 946 if (_closeTimer == null && !_controller.isClosed) { |
943 // When closing the web-socket, we no longer accept data. | 947 // When closing the web-socket, we no longer accept data. |
944 _closeTimer = new Timer(const Duration(seconds: 5), () { | 948 _closeTimer = new Timer(const Duration(seconds: 5), () { |
| 949 // Reuse code and reason from the local close. |
| 950 _closeCode = _outCloseCode; |
| 951 _closeReason = _outCloseReason; |
945 _subscription.cancel(); | 952 _subscription.cancel(); |
946 _controller.close(); | 953 _controller.close(); |
947 }); | 954 }); |
948 } | 955 } |
949 return _sink.close(); | 956 return _sink.close(); |
950 } | 957 } |
951 | 958 |
952 void _close([int code, String reason]) { | 959 void _close([int code, String reason]) { |
953 if (_writeClosed) return; | 960 if (_writeClosed) return; |
954 if (_outCloseCode == null) { | 961 if (_outCloseCode == null) { |
955 _outCloseCode = code; | 962 _outCloseCode = code; |
956 _outCloseReason = reason; | 963 _outCloseReason = reason; |
957 } | 964 } |
958 _writeClosed = true; | 965 _writeClosed = true; |
959 _consumer.closeSocket(); | 966 _consumer.closeSocket(); |
960 } | 967 } |
961 | 968 |
962 static bool _isReservedStatusCode(int code) { | 969 static bool _isReservedStatusCode(int code) { |
963 return code != null && | 970 return code != null && |
964 (code < WebSocketStatus.NORMAL_CLOSURE || | 971 (code < WebSocketStatus.NORMAL_CLOSURE || |
965 code == WebSocketStatus.RESERVED_1004 || | 972 code == WebSocketStatus.RESERVED_1004 || |
966 code == WebSocketStatus.NO_STATUS_RECEIVED || | 973 code == WebSocketStatus.NO_STATUS_RECEIVED || |
967 code == WebSocketStatus.ABNORMAL_CLOSURE || | 974 code == WebSocketStatus.ABNORMAL_CLOSURE || |
968 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && | 975 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && |
969 code < WebSocketStatus.RESERVED_1015) || | 976 code < WebSocketStatus.RESERVED_1015) || |
970 (code >= WebSocketStatus.RESERVED_1015 && | 977 (code >= WebSocketStatus.RESERVED_1015 && |
971 code < 3000)); | 978 code < 3000)); |
972 } | 979 } |
973 } | 980 } |
OLD | NEW |