| 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 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 int _readyState = WebSocket.CONNECTING; | 774 int _readyState = WebSocket.CONNECTING; |
| 775 bool _writeClosed = false; | 775 bool _writeClosed = false; |
| 776 int _closeCode; | 776 int _closeCode; |
| 777 String _closeReason; | 777 String _closeReason; |
| 778 Duration _pingInterval; | 778 Duration _pingInterval; |
| 779 Timer _pingTimer; | 779 Timer _pingTimer; |
| 780 _WebSocketConsumer _consumer; | 780 _WebSocketConsumer _consumer; |
| 781 | 781 |
| 782 int _outCloseCode; | 782 int _outCloseCode; |
| 783 String _outCloseReason; | 783 String _outCloseReason; |
| 784 Timer _closeTimer; |
| 784 | 785 |
| 785 static final HttpClient _httpClient = new HttpClient(); | 786 static final HttpClient _httpClient = new HttpClient(); |
| 786 | 787 |
| 787 static Future<WebSocket> connect(String url, List<String> protocols) { | 788 static Future<WebSocket> connect(String url, List<String> protocols) { |
| 788 Uri uri = Uri.parse(url); | 789 Uri uri = Uri.parse(url); |
| 789 if (uri.scheme != "ws" && uri.scheme != "wss") { | 790 if (uri.scheme != "ws" && uri.scheme != "wss") { |
| 790 throw new WebSocketException("Unsupported URL scheme '${uri.scheme}'"); | 791 throw new WebSocketException("Unsupported URL scheme '${uri.scheme}'"); |
| 791 } | 792 } |
| 792 if (uri.userInfo != "") { | 793 if (uri.userInfo != "") { |
| 793 throw new WebSocketException("Unsupported user info '${uri.userInfo}'"); | 794 throw new WebSocketException("Unsupported user info '${uri.userInfo}'"); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 if (data is _WebSocketPing) { | 873 if (data is _WebSocketPing) { |
| 873 if (!_writeClosed) _consumer.add(new _WebSocketPong(data.payload)); | 874 if (!_writeClosed) _consumer.add(new _WebSocketPong(data.payload)); |
| 874 } else if (data is _WebSocketPong) { | 875 } else if (data is _WebSocketPong) { |
| 875 // Simply set pingInterval, as it'll cancel any timers. | 876 // Simply set pingInterval, as it'll cancel any timers. |
| 876 pingInterval = _pingInterval; | 877 pingInterval = _pingInterval; |
| 877 } else { | 878 } else { |
| 878 _controller.add(data); | 879 _controller.add(data); |
| 879 } | 880 } |
| 880 }, | 881 }, |
| 881 onError: (error) { | 882 onError: (error) { |
| 883 if (_closeTimer != null) _closeTimer.cancel(); |
| 882 if (error is FormatException) { | 884 if (error is FormatException) { |
| 883 _close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA); | 885 _close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA); |
| 884 } else { | 886 } else { |
| 885 _close(WebSocketStatus.PROTOCOL_ERROR); | 887 _close(WebSocketStatus.PROTOCOL_ERROR); |
| 886 } | 888 } |
| 887 _controller.close(); | 889 _controller.close(); |
| 888 }, | 890 }, |
| 889 onDone: () { | 891 onDone: () { |
| 892 if (_closeTimer != null) _closeTimer.cancel(); |
| 890 if (_readyState == WebSocket.OPEN) { | 893 if (_readyState == WebSocket.OPEN) { |
| 891 _readyState = WebSocket.CLOSING; | 894 _readyState = WebSocket.CLOSING; |
| 892 if (!_isReservedStatusCode(transformer.closeCode)) { | 895 if (!_isReservedStatusCode(transformer.closeCode)) { |
| 893 _close(transformer.closeCode); | 896 _close(transformer.closeCode); |
| 894 } else { | 897 } else { |
| 895 _close(); | 898 _close(); |
| 896 } | 899 } |
| 897 _readyState = WebSocket.CLOSED; | 900 _readyState = WebSocket.CLOSED; |
| 898 } | 901 } |
| 899 _closeCode = transformer.closeCode; | 902 _closeCode = transformer.closeCode; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 Future get done => _sink.done; | 953 Future get done => _sink.done; |
| 951 | 954 |
| 952 Future close([int code, String reason]) { | 955 Future close([int code, String reason]) { |
| 953 if (_isReservedStatusCode(code)) { | 956 if (_isReservedStatusCode(code)) { |
| 954 throw new WebSocketException("Reserved status code $code"); | 957 throw new WebSocketException("Reserved status code $code"); |
| 955 } | 958 } |
| 956 if (_outCloseCode == null) { | 959 if (_outCloseCode == null) { |
| 957 _outCloseCode = code; | 960 _outCloseCode = code; |
| 958 _outCloseReason = reason; | 961 _outCloseReason = reason; |
| 959 } | 962 } |
| 963 if (_closeTimer == null && !_controller.isClosed) { |
| 964 // When closing the web-socket, we no longer accept data. |
| 965 _closeTimer = new Timer(const Duration(seconds: 5), () { |
| 966 _subscription.cancel(); |
| 967 _controller.close(); |
| 968 }); |
| 969 } |
| 960 return _sink.close(); | 970 return _sink.close(); |
| 961 } | 971 } |
| 962 | 972 |
| 963 void _close([int code, String reason]) { | 973 void _close([int code, String reason]) { |
| 964 if (_writeClosed) return; | 974 if (_writeClosed) return; |
| 965 if (_outCloseCode == null) { | 975 if (_outCloseCode == null) { |
| 966 _outCloseCode = code; | 976 _outCloseCode = code; |
| 967 _outCloseReason = reason; | 977 _outCloseReason = reason; |
| 968 } | 978 } |
| 969 _writeClosed = true; | 979 _writeClosed = true; |
| 970 _consumer.closeSocket(); | 980 _consumer.closeSocket(); |
| 971 } | 981 } |
| 972 | 982 |
| 973 static bool _isReservedStatusCode(int code) { | 983 static bool _isReservedStatusCode(int code) { |
| 974 return code != null && | 984 return code != null && |
| 975 (code < WebSocketStatus.NORMAL_CLOSURE || | 985 (code < WebSocketStatus.NORMAL_CLOSURE || |
| 976 code == WebSocketStatus.RESERVED_1004 || | 986 code == WebSocketStatus.RESERVED_1004 || |
| 977 code == WebSocketStatus.NO_STATUS_RECEIVED || | 987 code == WebSocketStatus.NO_STATUS_RECEIVED || |
| 978 code == WebSocketStatus.ABNORMAL_CLOSURE || | 988 code == WebSocketStatus.ABNORMAL_CLOSURE || |
| 979 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && | 989 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && |
| 980 code < WebSocketStatus.RESERVED_1015) || | 990 code < WebSocketStatus.RESERVED_1015) || |
| 981 (code >= WebSocketStatus.RESERVED_1015 && | 991 (code >= WebSocketStatus.RESERVED_1015 && |
| 982 code < 3000)); | 992 code < 3000)); |
| 983 } | 993 } |
| 984 } | 994 } |
| OLD | NEW |