|
3 | 3 | // BSD-style license that can be found in the LICENSE file.
|
4 | 4 |
|
5 | 5 | import 'dart:async';
|
6 |
| -import 'dart:io'; |
7 |
| - |
8 |
| -import 'package:async/async.dart'; |
9 |
| -import 'package:stream_channel/stream_channel.dart'; |
| 6 | +import 'dart:io' show HttpClient, WebSocket; |
| 7 | +import 'package:web_socket/io_web_socket.dart' as io_web_socket; |
10 | 8 |
|
11 | 9 | import 'src/channel.dart';
|
12 | 10 | import 'src/exception.dart';
|
13 |
| -import 'src/sink_completer.dart'; |
| 11 | +import 'web_socket_adapter_web_socket_channel.dart'; |
14 | 12 |
|
15 | 13 | /// A [WebSocketChannel] that communicates using a `dart:io` [WebSocket].
|
16 |
| -class IOWebSocketChannel extends StreamChannelMixin |
17 |
| - implements WebSocketChannel { |
18 |
| - /// The underlying `dart:io` [WebSocket]. |
19 |
| - /// |
20 |
| - /// If the channel was constructed with [IOWebSocketChannel.connect], this is |
21 |
| - /// `null` until the [WebSocket.connect] future completes. |
22 |
| - WebSocket? _webSocket; |
23 |
| - |
24 |
| - @override |
25 |
| - String? get protocol => _webSocket?.protocol; |
26 |
| - |
27 |
| - @override |
28 |
| - int? get closeCode => _webSocket?.closeCode; |
29 |
| - |
30 |
| - @override |
31 |
| - String? get closeReason => _webSocket?.closeReason; |
32 |
| - |
33 |
| - @override |
34 |
| - final Stream stream; |
35 |
| - |
36 |
| - @override |
37 |
| - final WebSocketSink sink; |
38 |
| - |
39 |
| - /// Completer for [ready]. |
40 |
| - final Completer<void> _readyCompleter; |
41 |
| - |
42 |
| - @override |
43 |
| - Future<void> get ready => _readyCompleter.future; |
44 |
| - |
45 |
| - /// The underlying [WebSocket], if this channel has connected. |
46 |
| - /// |
47 |
| - /// If the future returned from [WebSocket.connect] has not yet completed, or |
48 |
| - /// completed as an error, this will be null. |
49 |
| - WebSocket? get innerWebSocket => _webSocket; |
50 |
| - |
| 14 | +class IOWebSocketChannel extends WebSocketAdapterWebSocketChannel { |
51 | 15 | /// Creates a new WebSocket connection.
|
52 | 16 | ///
|
53 | 17 | /// Connects to [url] using [WebSocket.connect] and returns a channel that can
|
@@ -76,58 +40,24 @@ class IOWebSocketChannel extends StreamChannelMixin
|
76 | 40 | Duration? connectTimeout,
|
77 | 41 | HttpClient? customClient,
|
78 | 42 | }) {
|
79 |
| - late IOWebSocketChannel channel; |
80 |
| - final sinkCompleter = WebSocketSinkCompleter(); |
81 |
| - var future = WebSocket.connect( |
| 43 | + var webSocketFuture = WebSocket.connect( |
82 | 44 | url.toString(),
|
83 | 45 | headers: headers,
|
84 | 46 | protocols: protocols,
|
85 | 47 | customClient: customClient,
|
86 |
| - ); |
| 48 | + ).then((webSocket) => webSocket..pingInterval = pingInterval); |
| 49 | + |
87 | 50 | if (connectTimeout != null) {
|
88 |
| - future = future.timeout(connectTimeout); |
| 51 | + webSocketFuture = webSocketFuture.timeout(connectTimeout); |
89 | 52 | }
|
90 |
| - final stream = StreamCompleter.fromFuture(future.then((webSocket) { |
91 |
| - webSocket.pingInterval = pingInterval; |
92 |
| - channel._webSocket = webSocket; |
93 |
| - channel._readyCompleter.complete(); |
94 |
| - sinkCompleter.setDestinationSink(_IOWebSocketSink(webSocket)); |
95 |
| - return webSocket; |
96 |
| - }).catchError((Object error, StackTrace stackTrace) { |
97 |
| - channel._readyCompleter.completeError(error, stackTrace); |
98 |
| - throw WebSocketChannelException.from(error); |
99 |
| - })); |
100 |
| - return channel = |
101 |
| - IOWebSocketChannel._withoutSocket(stream, sinkCompleter.sink); |
102 |
| - } |
103 |
| - |
104 |
| - /// Creates a channel wrapping [socket]. |
105 |
| - IOWebSocketChannel(WebSocket socket) |
106 |
| - : _webSocket = socket, |
107 |
| - stream = socket.handleError( |
108 |
| - (Object? error) => throw WebSocketChannelException.from(error)), |
109 |
| - sink = _IOWebSocketSink(socket), |
110 |
| - _readyCompleter = Completer()..complete(); |
111 | 53 |
|
112 |
| - /// Creates a channel without a socket. |
113 |
| - /// |
114 |
| - /// This is used with `connect` to synchronously provide a channel that later |
115 |
| - /// has a socket added. |
116 |
| - IOWebSocketChannel._withoutSocket(Stream stream, this.sink) |
117 |
| - : _webSocket = null, |
118 |
| - stream = stream.handleError( |
119 |
| - (Object? error) => throw WebSocketChannelException.from(error)), |
120 |
| - _readyCompleter = Completer(); |
121 |
| -} |
122 |
| - |
123 |
| -/// A [WebSocketSink] that forwards [close] calls to a `dart:io` [WebSocket]. |
124 |
| -class _IOWebSocketSink extends DelegatingStreamSink implements WebSocketSink { |
125 |
| - /// The underlying socket. |
126 |
| - final WebSocket _webSocket; |
127 |
| - |
128 |
| - _IOWebSocketSink(WebSocket super.webSocket) : _webSocket = webSocket; |
| 54 | + return IOWebSocketChannel(webSocketFuture); |
| 55 | + } |
129 | 56 |
|
130 |
| - @override |
131 |
| - Future close([int? closeCode, String? closeReason]) => |
132 |
| - _webSocket.close(closeCode, closeReason); |
| 57 | + /// Creates a channel wrapping [webSocket]. |
| 58 | + IOWebSocketChannel(FutureOr<WebSocket> webSocket) |
| 59 | + : super(webSocket is Future<WebSocket> |
| 60 | + ? webSocket.then(io_web_socket.IOWebSocket.fromWebSocket) |
| 61 | + as FutureOr<io_web_socket.IOWebSocket> |
| 62 | + : io_web_socket.IOWebSocket.fromWebSocket(webSocket)); |
133 | 63 | }
|
0 commit comments