5
5
using AngleSharp . Dom . Events ;
6
6
using AngleSharp . Io . Extensions ;
7
7
using System ;
8
- using System . IO ;
9
8
using System . Linq ;
10
9
using System . Net . WebSockets ;
11
10
using System . Text ;
@@ -27,6 +26,7 @@ public class WebSocket : EventTarget, IDisposable
27
26
readonly Url _url ;
28
27
readonly CancellationTokenSource _cts ;
29
28
readonly ClientWebSocket _ws ;
29
+ readonly IWindow _window ;
30
30
31
31
WebSocketReadyState _state ;
32
32
@@ -78,14 +78,16 @@ public event DomEventHandler Closed
78
78
/// <summary>
79
79
/// Creates a new WebSocket instance.
80
80
/// </summary>
81
+ /// <param name="window">The parent context.</param>
81
82
/// <param name="url">The URL to connect to.</param>
82
83
/// <param name="protocols">The protocols to allow.</param>
83
84
[ DomConstructor ]
84
- public WebSocket ( String url , params String [ ] protocols )
85
+ public WebSocket ( IWindow window , String url , params String [ ] protocols )
85
86
{
86
87
_url = new Url ( url ) ;
87
88
_state = WebSocketReadyState . Connecting ;
88
89
_cts = new CancellationTokenSource ( ) ;
90
+ _window = window ;
89
91
90
92
if ( _url . IsInvalid || _url . IsRelative )
91
93
throw new DomException ( DomError . Syntax ) ;
@@ -103,8 +105,9 @@ public WebSocket(String url, params String[] protocols)
103
105
async Task ConnectAsync ( String url )
104
106
{
105
107
await _ws . ConnectAsync ( new Uri ( url ) , _cts . Token ) . ConfigureAwait ( false ) ;
108
+ _state = WebSocketReadyState . Open ;
106
109
OnConnected ( ) ;
107
- StartListen ( ) . Forget ( ) ;
110
+ ListenAsync ( ) . Forget ( ) ;
108
111
}
109
112
110
113
#endregion
@@ -178,15 +181,14 @@ public void Close()
178
181
{
179
182
if ( _state != WebSocketReadyState . Closed && _state != WebSocketReadyState . Closing )
180
183
{
181
- _state = WebSocketReadyState . Closing ;
182
- StopListen ( ) ;
183
- OnDisconnected ( ) ;
184
+ CloseAsync ( ) . Forget ( ) ;
184
185
}
185
186
}
186
187
187
188
void IDisposable . Dispose ( )
188
189
{
189
- StopListen ( ) ;
190
+ CancelListener ( ) ;
191
+ _ws . Dispose ( ) ;
190
192
}
191
193
192
194
#endregion
@@ -226,7 +228,15 @@ async Task SendAsync(String message)
226
228
}
227
229
}
228
230
229
- async Task StartListen ( )
231
+ async Task CloseAsync ( )
232
+ {
233
+ _state = WebSocketReadyState . Closing ;
234
+ await _ws . CloseAsync ( WebSocketCloseStatus . NormalClosure , String . Empty , _cts . Token ) . ConfigureAwait ( false ) ;
235
+ CancelListener ( ) ;
236
+ OnDisconnected ( ) ;
237
+ }
238
+
239
+ async Task ListenAsync ( )
230
240
{
231
241
var buffer = new Byte [ ReceiveChunkSize ] ;
232
242
var stringResult = new StringBuilder ( ) ;
@@ -239,11 +249,7 @@ async Task StartListen()
239
249
var result = await _ws . ReceiveAsync ( segment , _cts . Token ) . ConfigureAwait ( false ) ;
240
250
241
251
if ( result . MessageType == WebSocketMessageType . Close )
242
- {
243
- await _ws . CloseAsync ( WebSocketCloseStatus . NormalClosure , String . Empty , _cts . Token ) . ConfigureAwait ( false ) ;
244
- OnDisconnected ( ) ;
245
- return ;
246
- }
252
+ break ;
247
253
248
254
stringResult . Append ( Encoding . UTF8 . GetString ( buffer , 0 , result . Count ) ) ;
249
255
@@ -253,39 +259,50 @@ async Task StartListen()
253
259
stringResult . Clear ( ) ;
254
260
}
255
261
}
262
+
263
+ await CloseAsync ( ) . ConfigureAwait ( false ) ;
256
264
}
257
- catch
265
+ catch ( Exception ex )
258
266
{
267
+ OnError ( ex ) ;
268
+ CancelListener ( ) ;
259
269
OnDisconnected ( ) ;
260
270
}
261
- finally
262
- {
263
- StopListen ( ) ;
264
- }
265
271
}
266
272
267
- void StopListen ( )
273
+ void CancelListener ( )
268
274
{
269
275
_cts . Cancel ( ) ;
270
276
_ws . Abort ( ) ;
271
- _ws . Dispose ( ) ;
277
+ _state = WebSocketReadyState . Closed ;
272
278
}
273
279
274
280
void OnMessage ( String message )
275
281
{
276
- this . Dispatch ( new MessageEvent ( MessageEvent , data : message , origin : _url . Href ) ) ;
282
+ var evt = new MessageEvent ( ) ;
283
+ evt . Init ( MessageEvent , false , false , message , _url . Origin , String . Empty , _window ) ;
284
+ this . Dispatch ( evt ) ;
285
+ }
286
+
287
+ void OnError ( Exception ex )
288
+ {
289
+ var evt = new ErrorEvent ( ) ;
290
+ evt . Init ( ErrorEvent , false , false ) ;
291
+ this . Dispatch ( evt ) ;
277
292
}
278
293
279
294
void OnDisconnected ( )
280
295
{
281
- _state = WebSocketReadyState . Closed ;
282
- this . Dispatch ( new Event ( CloseEvent ) ) ;
296
+ var evt = new Event ( ) ;
297
+ evt . Init ( CloseEvent , false , false ) ;
298
+ this . Dispatch ( evt ) ;
283
299
}
284
300
285
301
void OnConnected ( )
286
302
{
287
- _state = WebSocketReadyState . Open ;
288
- this . Dispatch ( new Event ( OpenEvent ) ) ;
303
+ var evt = new Event ( ) ;
304
+ evt . Init ( OpenEvent , false , false ) ;
305
+ this . Dispatch ( evt ) ;
289
306
}
290
307
291
308
#endregion
0 commit comments