| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:io'; | 6 import 'dart:io'; |
| 7 | 7 |
| 8 import 'package:async/async.dart'; | 8 import 'package:async/async.dart'; |
| 9 import 'package:stream_channel/stream_channel.dart'; | 9 import 'package:stream_channel/stream_channel.dart'; |
| 10 | 10 |
| 11 import 'src/channel.dart'; | 11 import 'src/channel.dart'; |
| 12 import 'src/exception.dart'; | 12 import 'src/exception.dart'; |
| 13 import 'src/sink_completer.dart'; | 13 import 'src/sink_completer.dart'; |
| 14 | 14 |
| 15 /// A [WebSocketChannel] that communicates using a `dart:io` [WebSocket]. | 15 /// A [WebSocketChannel] that communicates using a `dart:io` [WebSocket]. |
| 16 class IOWebSocketChannel extends StreamChannelMixin | 16 class IOWebSocketChannel extends StreamChannelMixin |
| 17 implements WebSocketChannel { | 17 implements WebSocketChannel { |
| 18 /// The underlying `dart:io` [WebSocket]. | 18 /// The underlying `dart:io` [WebSocket]. |
| 19 /// | 19 /// |
| 20 /// If the channel was constructed with [IOWebSocketChannel.connect], this is | 20 /// If the channel was constructed with [IOWebSocketChannel.connect], this is |
| 21 /// `null` until the [WebSocket.connect] future completes. | 21 /// `null` until the [WebSocket.connect] future completes. |
| 22 WebSocket _webSocket; | 22 WebSocket _webSocket; |
| 23 | 23 |
| 24 Duration get pingInterval => | |
| 25 _webSocket == null ? _pingInterval : _webSocket.pingInterval; | |
| 26 | |
| 27 set pingInterval(Duration value) { | |
| 28 if (_webSocket == null) { | |
| 29 _pingInterval = value; | |
| 30 } else { | |
| 31 _webSocket.pingInterval = value; | |
| 32 } | |
| 33 } | |
| 34 | |
| 35 /// The ping interval set by the user. | |
| 36 /// | |
| 37 /// This is stored independently of [_webSocket] so that the user can set it | |
| 38 /// prior to [_webSocket] getting a value. | |
| 39 Duration _pingInterval; | |
| 40 | |
| 41 String get protocol => _webSocket?.protocol; | 24 String get protocol => _webSocket?.protocol; |
| 42 int get closeCode => _webSocket?.closeCode; | 25 int get closeCode => _webSocket?.closeCode; |
| 43 String get closeReason => _webSocket?.closeReason; | 26 String get closeReason => _webSocket?.closeReason; |
| 44 | 27 |
| 45 final Stream stream; | 28 final Stream stream; |
| 46 final WebSocketSink sink; | 29 final WebSocketSink sink; |
| 47 | 30 |
| 48 // TODO(nweiz): Add a compression parameter after the initial release. | 31 // TODO(nweiz): Add a compression parameter after the initial release. |
| 49 | 32 |
| 50 /// Creates a new WebSocket connection. | 33 /// Creates a new WebSocket connection. |
| 51 /// | 34 /// |
| 52 /// Connects to [url] using [WebSocket.connect] and returns a channel that can | 35 /// Connects to [url] using [WebSocket.connect] and returns a channel that can |
| 53 /// be used to communicate over the resulting socket. The [url] may be either | 36 /// be used to communicate over the resulting socket. The [url] may be either |
| 54 /// a [String] or a [Uri]; otherwise, the parameters are the same as | 37 /// a [String] or a [Uri]. The [protocols] and [headers] parameters are the |
| 55 /// [WebSocket.connect]. | 38 /// same as [WebSocket.connect]. |
| 39 /// |
| 40 /// [pingInterval] controls the interval for sending ping signals. If a ping |
| 41 /// message is not answered by a pong message from the peer, the WebSocket is |
| 42 /// assumed disconnected and the connection is closed with a |
| 43 /// [WebSocketStatus.GOING_AWAY] close code. When a ping signal is sent, the |
| 44 /// pong message must be received within [pingInterval]. It defaults to |
| 45 /// `null`, indicating that ping messages are disabled. |
| 56 /// | 46 /// |
| 57 /// If there's an error connecting, the channel's stream emits a | 47 /// If there's an error connecting, the channel's stream emits a |
| 58 /// [WebSocketChannelException] wrapping that error and then closes. | 48 /// [WebSocketChannelException] wrapping that error and then closes. |
| 59 factory IOWebSocketChannel.connect(url, {Iterable<String> protocols, | 49 factory IOWebSocketChannel.connect(url, {Iterable<String> protocols, |
| 60 Map<String, dynamic> headers}) { | 50 Map<String, dynamic> headers, Duration pingInterval}) { |
| 61 var channel; | 51 var channel; |
| 62 var sinkCompleter = new WebSocketSinkCompleter(); | 52 var sinkCompleter = new WebSocketSinkCompleter(); |
| 63 var stream = StreamCompleter.fromFuture( | 53 var stream = StreamCompleter.fromFuture( |
| 64 WebSocket.connect(url.toString(), headers: headers).then((webSocket) { | 54 WebSocket.connect(url.toString(), headers: headers).then((webSocket) { |
| 65 channel._setWebSocket(webSocket); | 55 webSocket.pingInterval = pingInterval; |
| 56 channel._webSocket = webSocket; |
| 66 sinkCompleter.setDestinationSink(new _IOWebSocketSink(webSocket)); | 57 sinkCompleter.setDestinationSink(new _IOWebSocketSink(webSocket)); |
| 67 return webSocket; | 58 return webSocket; |
| 68 }).catchError((error) => throw new WebSocketChannelException.from(error))); | 59 }).catchError((error) => throw new WebSocketChannelException.from(error))); |
| 69 | 60 |
| 70 channel = new IOWebSocketChannel._withoutSocket(stream, sinkCompleter.sink); | 61 channel = new IOWebSocketChannel._withoutSocket(stream, sinkCompleter.sink); |
| 71 return channel; | 62 return channel; |
| 72 } | 63 } |
| 73 | 64 |
| 74 /// Creates a channel wrapping [socket]. | 65 /// Creates a channel wrapping [socket]. |
| 75 IOWebSocketChannel(WebSocket socket) | 66 IOWebSocketChannel(WebSocket socket) |
| 76 : _webSocket = socket, | 67 : _webSocket = socket, |
| 77 stream = socket.handleError((error) => | 68 stream = socket.handleError((error) => |
| 78 throw new WebSocketChannelException.from(error)), | 69 throw new WebSocketChannelException.from(error)), |
| 79 sink = new _IOWebSocketSink(socket); | 70 sink = new _IOWebSocketSink(socket); |
| 80 | 71 |
| 81 /// Creates a channel without a socket. | 72 /// Creates a channel without a socket. |
| 82 /// | 73 /// |
| 83 /// This is used with [connect] to synchronously provide a channel that later | 74 /// This is used with [connect] to synchronously provide a channel that later |
| 84 /// has a socket added. | 75 /// has a socket added. |
| 85 IOWebSocketChannel._withoutSocket(Stream stream, this.sink) | 76 IOWebSocketChannel._withoutSocket(Stream stream, this.sink) |
| 86 : _webSocket = null, | 77 : _webSocket = null, |
| 87 stream = stream.handleError((error) => | 78 stream = stream.handleError((error) => |
| 88 throw new WebSocketChannelException.from(error)); | 79 throw new WebSocketChannelException.from(error)); |
| 89 | |
| 90 /// Sets the underlying web socket. | |
| 91 /// | |
| 92 /// This is called by [connect] once the [WebSocket.connect] future has | |
| 93 /// completed. | |
| 94 void _setWebSocket(WebSocket webSocket) { | |
| 95 assert(_webSocket == null); | |
| 96 | |
| 97 _webSocket = webSocket; | |
| 98 if (_pingInterval != null) _webSocket.pingInterval = pingInterval; | |
| 99 } | |
| 100 } | 80 } |
| 101 | 81 |
| 102 /// A [WebSocketSink] that forwards [close] calls to a `dart:io` [WebSocket]. | 82 /// A [WebSocketSink] that forwards [close] calls to a `dart:io` [WebSocket]. |
| 103 class _IOWebSocketSink extends DelegatingStreamSink implements WebSocketSink { | 83 class _IOWebSocketSink extends DelegatingStreamSink implements WebSocketSink { |
| 104 /// The underlying socket. | 84 /// The underlying socket. |
| 105 final WebSocket _webSocket; | 85 final WebSocket _webSocket; |
| 106 | 86 |
| 107 _IOWebSocketSink(WebSocket webSocket) | 87 _IOWebSocketSink(WebSocket webSocket) |
| 108 : super(webSocket), | 88 : super(webSocket), |
| 109 _webSocket = webSocket; | 89 _webSocket = webSocket; |
| 110 | 90 |
| 111 Future close([int closeCode, String closeReason]) => | 91 Future close([int closeCode, String closeReason]) => |
| 112 _webSocket.close(closeCode, closeReason); | 92 _webSocket.close(closeCode, closeReason); |
| 113 } | 93 } |
| OLD | NEW |