@@ -50,7 +50,7 @@ public async Task ConnectAsync(Uri serverUri, int timeout = 3)
5050
5151 try
5252 {
53- await TryDisposeResourcesAsync ( WebSocketCloseStatus . NormalClosure ,
53+ await TryCloseAndDisposeAsync ( WebSocketCloseStatus . NormalClosure ,
5454 "Clean up resources before connecting" ) ;
5555 _connectionCts = new CancellationTokenSource ( ) ;
5656
@@ -67,15 +67,15 @@ await TryDisposeResourcesAsync(WebSocketCloseStatus.NormalClosure,
6767
6868 // We handle timeout this way because ConnectAsync was hanging after multiple attempts on Unity 2022.3.29 & Android 14 and cancellation via passed token didn't work
6969 var finishedTask = await Task . WhenAny ( connectTask , timeoutTask ) ;
70-
70+
7171 if ( finishedTask == timeoutTask )
7272 {
7373#if STREAM_DEBUG_ENABLED
7474 _logs . Warning ( "Internal WS Connection attempt timed out." ) ;
7575#endif
7676 throw new TimeoutException ( $ "Connection attempt timed out after { timeout } seconds.") ;
7777 }
78-
78+
7979 if ( _connectionCts == null || _connectionCts . Token . IsCancellationRequested )
8080 {
8181#if STREAM_DEBUG_ENABLED
@@ -90,30 +90,10 @@ await TryDisposeResourcesAsync(WebSocketCloseStatus.NormalClosure,
9090 ws . Stop ( ) ;
9191 _logs . Warning ( $ "Internal WS ConnectAsync COMPLETED in { ws . ElapsedMilliseconds } ms.") ;
9292#endif
93-
94- }
95- catch ( OperationCanceledException e )
96- {
97- LogExceptionIfDebugMode ( e ) ;
98- OnConnectionFailed ( ) ;
99- return ;
100- }
101- catch ( WebSocketException e )
102- {
103- LogExceptionIfDebugMode ( e ) ;
104- OnConnectionFailed ( ) ;
105- return ;
106- }
107- catch ( SocketException e )
108- {
109- LogExceptionIfDebugMode ( e ) ;
110- OnConnectionFailed ( ) ;
111- return ;
11293 }
11394 catch ( Exception e )
11495 {
115- _logs . Exception ( e ) ;
116- OnConnectionFailed ( ) ;
96+ await HandleConnectionFailedAsync ( e ) ;
11797 return ;
11898 }
11999
@@ -135,7 +115,7 @@ public void Update()
135115 {
136116#if STREAM_DEBUG_ENABLED
137117
138- if ( _internalClient != null && _internalClient . State != _lastState )
118+ if ( _internalClient != null && _internalClient . State != _lastState )
139119 {
140120 _logs . Warning ( $ "Internal WS state -> changed from { _lastState } to " + _internalClient . State ) ;
141121 _lastState = _internalClient . State ;
@@ -166,22 +146,22 @@ public void Update()
166146 public async Task DisconnectAsync ( WebSocketCloseStatus closeStatus , string closeMessage )
167147 {
168148 LogInfoIfDebugMode ( "Disconnect" ) ;
169- await TryDisposeResourcesAsync ( closeStatus , closeMessage ) ;
149+ await TryCloseAndDisposeAsync ( closeStatus , closeMessage ) ;
170150
171151 Disconnected ? . Invoke ( ) ;
172152 }
173153
174154 public void Dispose ( )
175155 {
176- LogInfoIfDebugMode ( "Dispose " + Thread . CurrentThread . ManagedThreadId ) ;
177-
178- if ( _internalClient != null && ! _clientClosedStates . Contains ( _internalClient . State ) )
156+ LogInfoIfDebugMode ( "Dispose " + Thread . CurrentThread . ManagedThreadId ) ;
157+
158+ if ( _internalClient != null && ! _clientClosedStates . Contains ( _internalClient . State ) )
179159 {
180160 DisconnectAsync ( WebSocketCloseStatus . NormalClosure , "WebSocket client is disposed" )
181161 . ContinueWith ( t => LogExceptionIfDebugMode ( t . Exception ) , TaskContinuationOptions . OnlyOnFaulted ) ;
182162 }
183163 }
184-
164+
185165 private const int UpdatesPerSecond = 20 ;
186166 private const int UpdatePeriod = 1000 / UpdatesPerSecond ;
187167 private const int UpdatePeriodOffset = UpdatePeriod / 2 ;
@@ -299,22 +279,28 @@ private async void ReceiveMessagesCallback(object state)
299279 }
300280 }
301281
302- private async Task TryDisposeResourcesAsync ( WebSocketCloseStatus closeStatus , string closeMessage )
282+ private async Task TryCloseAndDisposeAsync ( WebSocketCloseStatus closeStatus , string closeMessage )
303283 {
304284 try
305285 {
306- _backgroundReceiveTimer ? . Dispose ( ) ;
307- _backgroundReceiveTimer = null ;
286+ if ( _backgroundReceiveTimer != null )
287+ {
288+ await _backgroundReceiveTimer . DisposeAsync ( ) ;
289+ _backgroundReceiveTimer = null ;
290+ }
308291 }
309292 catch ( Exception e )
310293 {
311294 LogExceptionIfDebugMode ( e ) ;
312295 }
313-
296+
314297 try
315298 {
316- _backgroundSendTimer ? . Dispose ( ) ;
317- _backgroundSendTimer = null ;
299+ if ( _backgroundSendTimer != null )
300+ {
301+ await _backgroundSendTimer . DisposeAsync ( ) ;
302+ _backgroundSendTimer = null ;
303+ }
318304 }
319305 catch ( Exception e )
320306 {
@@ -325,7 +311,11 @@ private async Task TryDisposeResourcesAsync(WebSocketCloseStatus closeStatus, st
325311 {
326312 if ( _connectionCts != null )
327313 {
328- _connectionCts . Cancel ( ) ;
314+ if ( ! _connectionCts . IsCancellationRequested )
315+ {
316+ _connectionCts . Cancel ( ) ;
317+ }
318+
329319 _connectionCts . Dispose ( ) ;
330320 _connectionCts = null ;
331321 }
@@ -342,13 +332,21 @@ private async Task TryDisposeResourcesAsync(WebSocketCloseStatus closeStatus, st
342332
343333 try
344334 {
345- if ( ! _clientClosedStates . Contains ( _internalClient . State ) )
335+ if ( _internalClient . State == WebSocketState . Open )
346336 {
347337#if STREAM_DEBUG_ENABLED
348- _logs . Warning ( "Internal WS - Close in state: " + _internalClient . State ) ;
338+ _logs . Warning ( "Internal WS - Disposing; Is open -> CloseOutputAsync" ) ;
349339#endif
350340 await _internalClient . CloseOutputAsync ( closeStatus , closeMessage , CancellationToken . None ) ;
351341 }
342+
343+ if ( _internalClient . State == WebSocketState . Connecting )
344+ {
345+ #if STREAM_DEBUG_ENABLED
346+ _logs . Warning ( "Internal WS - Disposing; Is Connecting -> Abort" ) ;
347+ #endif
348+ _internalClient . Abort ( ) ;
349+ }
352350 }
353351 catch ( Exception e )
354352 {
@@ -364,7 +362,34 @@ private async Task TryDisposeResourcesAsync(WebSocketCloseStatus closeStatus, st
364362 }
365363 }
366364
367- private void OnConnectionFailed ( ) => ConnectionFailed ? . Invoke ( ) ;
365+ private async Task HandleConnectionFailedAsync ( Exception exception )
366+ {
367+ #if STREAM_DEBUG_ENABLED
368+ _logs . Warning ( "Internal WS - Connection Failed - trigger ConnectionFailed event" ) ;
369+ #endif
370+
371+ try
372+ {
373+ await TryCloseAndDisposeAsync ( WebSocketCloseStatus . ProtocolError ,
374+ "Closing due to exception thrown during connection attempt: " + exception . Message ) ;
375+ }
376+ catch ( Exception e )
377+ {
378+ _logs . Exception ( exception ) ;
379+ }
380+
381+ var isHandledExceptionType = exception is OperationCanceledException || exception is WebSocketException || exception is SocketException ;
382+ if ( isHandledExceptionType )
383+ {
384+ LogExceptionIfDebugMode ( exception ) ;
385+ }
386+ else
387+ {
388+ _logs . Exception ( exception ) ;
389+ }
390+
391+ ConnectionFailed ? . Invoke ( ) ;
392+ }
368393
369394 // Called from a background thread
370395 private void OnReceivedCloseMessage ( )
0 commit comments