Skip to content

Commit

Permalink
Read WebSocket state directly from socket type and update default ada…
Browse files Browse the repository at this point in the history
…pter. (#168)
  • Loading branch information
Luke Gehorsam authored Feb 22, 2024
1 parent d719ab2 commit 4a7b6a2
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 28 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a

## [Unreleased]

### Changed
- Nakama: `IsConnected` and `IsConnecting` will now read directly from the underlying .NET socket status. This will allow application code to more quickly and easily detect connectivity loss arising from a lack of internet access.
- Nakama: Default socket adapter changed from `WebSocketAdapter` to `WebSocketStdlibAdapter`. This was done to utilize the native .NET Websocket library for improved stability and maintenance.

## [3.10.0] - 2023-11-21
### Changed
- Nakama: Mark socket as connected before event handler is called.
Expand Down
15 changes: 13 additions & 2 deletions Nakama.Tests/Socket/WebSocketTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,28 @@ public async Task SocketDetectsLossOfInternet()
var session = await _client.AuthenticateCustomAsync($"{Guid.NewGuid()}");
await _socket.ConnectAsync(session, false, 5);
var closeTriggered = false;

_socket.Closed += () =>
{
_testOutputHelper.WriteLine($"Socket was closed");
closeTriggered = true;
};

_testOutputHelper.WriteLine("---Disconnect Internet Now---");
await Task.Delay(TimeSpan.FromSeconds(60));
Assert.False(_socket.IsConnected);
Assert.True(closeTriggered);
}

[Fact]
public async Task SocketCanReconnectAfterClose()
{
var session = await _client.AuthenticateCustomAsync($"{Guid.NewGuid()}");
await _socket.ConnectAsync(session, false, 5);
await _socket.CloseAsync();
await _socket.ConnectAsync(session, false, 5);
var match = await _socket.CreateMatchAsync($"${Guid.NewGuid()}");
Assert.True(match != null);
}
}
}
2 changes: 1 addition & 1 deletion Nakama/Socket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public class Socket : ISocket
/// <summary>
/// A new socket with default options.
/// </summary>
public Socket() : this(Client.DefaultScheme, Client.DefaultHost, Client.DefaultPort, new WebSocketAdapter())
public Socket() : this(Client.DefaultScheme, Client.DefaultHost, Client.DefaultPort, new WebSocketStdlibAdapter())
{
}

Expand Down
32 changes: 7 additions & 25 deletions Nakama/WebSocketStdlibAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ public class WebSocketStdlibAdapter : ISocketAdapter
/// <summary>
/// If the WebSocket is connected.
/// </summary>
public bool IsConnected { get; private set; }
public bool IsConnected => _webSocket != null && _webSocket.State == WebSocketState.Open;

/// <summary>
/// If the WebSocket is connecting.
/// </summary>
public bool IsConnecting { get; private set; }
public bool IsConnecting => _webSocket != null && _webSocket.State == WebSocketState.Connecting;

private CancellationTokenSource _cancellationSource;
private Uri _uri;
Expand Down Expand Up @@ -86,8 +86,6 @@ public async Task CloseAsync()
}

_webSocket = null;
IsConnecting = false;
IsConnected = false;
}

/// <inheritdoc cref="ISocketAdapter.ConnectAsync"/>
Expand All @@ -102,26 +100,12 @@ public async Task ConnectAsync(Uri uri, int timeout)
_cancellationSource = new CancellationTokenSource();
_uri = uri;
_webSocket = new ClientWebSocket();
IsConnecting = true;

try
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeout));
var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_cancellationSource.Token, cts.Token);
await _webSocket.ConnectAsync(_uri, linkedCts.Token).ConfigureAwait(false);
_ = ReceiveLoop(_webSocket, _cancellationSource.Token);
IsConnected = true;
Connected?.Invoke();
}
catch (Exception)
{
IsConnected = false;
throw;
}
finally
{
IsConnecting = false;
}
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeout));
var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_cancellationSource.Token, cts.Token);
await _webSocket.ConnectAsync(_uri, linkedCts.Token).ConfigureAwait(false);
_ = ReceiveLoop(_webSocket, _cancellationSource.Token);
Connected?.Invoke();
}

/// <inheritdoc cref="ISocketAdapter.SendAsync"/>
Expand Down Expand Up @@ -197,8 +181,6 @@ private async Task ReceiveLoop(WebSocket webSocket, CancellationToken canceller)
}
finally
{
IsConnecting = false;
IsConnected = false;
Closed?.Invoke();
}
}
Expand Down

0 comments on commit 4a7b6a2

Please sign in to comment.