Chromium Code Reviews| Index: lib/io.dart |
| diff --git a/lib/io.dart b/lib/io.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4c06c07a0d29ec68d081b36928672c77b8d77d30 |
| --- /dev/null |
| +++ b/lib/io.dart |
| @@ -0,0 +1,113 @@ |
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +import 'dart:async'; |
| +import 'dart:io'; |
| + |
| +import 'package:async/async.dart'; |
| +import 'package:stream_channel/stream_channel.dart'; |
| + |
| +import 'src/channel.dart'; |
| +import 'src/exception.dart'; |
| +import 'src/sink_completer.dart'; |
| + |
| +/// A [WebSocketChannel] that communicates using a `dart:io` [WebSocket]. |
| +class IOWebSocketChannel extends StreamChannelMixin |
| + implements WebSocketChannel { |
| + /// The underlying `dart:io` [WebSocket]. |
| + /// |
| + /// If the channel was constructed with [IOWebSocketChannel.connect], this is |
| + /// `null` until the [WebSocket.connect] future completes. |
| + WebSocket _webSocket; |
| + |
| + Duration get pingInterval => |
| + _webSocket == null ? _pingInterval : _webSocket.pingInterval; |
| + |
| + set pingInterval(Duration value) { |
| + if (_webSocket == null) { |
| + _pingInterval = value; |
| + } else { |
| + _webSocket.pingInterval = value; |
| + } |
| + } |
| + |
| + /// The ping interval set by the user. |
| + /// |
| + /// This is stored independently of [_webSocket] so that the user can set it |
| + /// prior to [_webSocket] getting a value. |
| + Duration _pingInterval; |
| + |
| + String get protocol => _webSocket?.protocol; |
|
kevmoo
2016/03/01 23:24:46
document that these can be null if not connected?
nweiz
2016/03/02 00:10:20
That's documented in the superclass.
|
| + int get closeCode => _webSocket?.closeCode; |
| + String get closeReason => _webSocket?.closeReason; |
| + |
| + final Stream stream; |
| + final WebSocketSink sink; |
| + |
| + // TODO(nweiz): Add a compression parameter after the initial release. |
| + |
| + /// Creates a new WebSocket connection. |
| + /// |
| + /// Connects to [url] using [WebSocket.connect] and returns a channel that can |
| + /// be used to communicate over the resulting socket. The [url] may be either |
| + /// a [String] or a [Uri]; otherwise, the parameters are the same as |
| + /// [WebSocket.connect]. |
| + /// |
| + /// If there's an error connecting, the channel's stream emits a |
| + /// [WebSocketChannelException] wrapping that error and then closes. |
| + factory IOWebSocketChannel.connect(url, {Iterable<String> protocols, |
| + Map<String, dynamic> headers}) { |
| + var channel; |
| + var sinkCompleter = new WebSocketSinkCompleter(); |
| + var stream = StreamCompleter.fromFuture( |
| + WebSocket.connect(url.toString(), headers: headers).then((webSocket) { |
| + channel._setWebSocket(webSocket); |
| + sinkCompleter.setDestinationSink(new _IOWebSocketSink(webSocket)); |
| + return webSocket; |
| + }).catchError((error) => throw new WebSocketChannelException.from(error))); |
| + |
| + channel = new IOWebSocketChannel._withoutSocket(stream, sinkCompleter.sink); |
| + return channel; |
| + } |
| + |
| + /// Creates a channel wrapping [socket]. |
| + IOWebSocketChannel(WebSocket socket) |
| + : _webSocket = socket, |
| + stream = socket.handleError((error) => |
| + throw new WebSocketChannelException.from(error)), |
| + sink = new _IOWebSocketSink(socket); |
| + |
| + /// Creates a channel without a socket. |
| + /// |
| + /// This is used with [connect] to synchronously provide a channel that later |
| + /// has a socket added. |
| + IOWebSocketChannel._withoutSocket(Stream stream, this.sink) |
| + : _webSocket = null, |
| + stream = stream.handleError((error) => |
| + throw new WebSocketChannelException.from(error)); |
| + |
| + /// Sets the underlying web socket. |
| + /// |
| + /// This is called by [connect] once the [WebSocket.connect] future has |
| + /// completed. |
| + void _setWebSocket(WebSocket webSocket) { |
| + assert(_webSocket == null); |
| + |
| + _webSocket = webSocket; |
| + if (_pingInterval != null) _webSocket.pingInterval = pingInterval; |
| + } |
| +} |
| + |
| +/// A [WebSocketSink] that forwards [close] calls to a `dart:io` [WebSocket]. |
| +class _IOWebSocketSink extends DelegatingStreamSink implements WebSocketSink { |
| + /// The underlying socket. |
| + final WebSocket _webSocket; |
| + |
| + _IOWebSocketSink(WebSocket webSocket) |
| + : super(webSocket), |
| + _webSocket = webSocket; |
| + |
| + Future close([int closeCode, String closeReason]) => |
| + _webSocket.close(closeCode, closeReason); |
| +} |