|
|
|
|
using Microsoft.AspNetCore.SignalR.Client;
|
|
|
|
|
|
|
|
|
|
namespace Connected.Net.Server
|
|
|
|
|
{
|
|
|
|
|
public abstract class ServerConnection : IDisposable, IAsyncDisposable, IServerConnection
|
|
|
|
|
{
|
|
|
|
|
private HubConnection? _connection;
|
|
|
|
|
protected ServerConnection(IEndpointServer server)
|
|
|
|
|
{
|
|
|
|
|
if (server is null)
|
|
|
|
|
throw new ArgumentException(null, nameof(server));
|
|
|
|
|
|
|
|
|
|
Server = server;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual async Task Initialize(string hubUrl)
|
|
|
|
|
{
|
|
|
|
|
if (_connection is not null)
|
|
|
|
|
{
|
|
|
|
|
if (_connection.State != HubConnectionState.Disconnected)
|
|
|
|
|
await _connection.StopAsync();
|
|
|
|
|
|
|
|
|
|
await _connection.DisposeAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_connection = new HubConnectionBuilder()
|
|
|
|
|
.WithUrl($"{Server.ServerUrl}/{hubUrl.Trim('/')}")
|
|
|
|
|
.WithAutomaticReconnect()
|
|
|
|
|
.Build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool IsDisposed { get; set; }
|
|
|
|
|
protected HubConnection Connection => _connection;
|
|
|
|
|
|
|
|
|
|
protected IEndpointServer Server { get; }
|
|
|
|
|
|
|
|
|
|
public async Task Connect()
|
|
|
|
|
{
|
|
|
|
|
if (Connection.State != HubConnectionState.Disconnected)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
await Connection.StartAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task Disconnect()
|
|
|
|
|
{
|
|
|
|
|
if (Connection is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (Connection.State == HubConnectionState.Disconnected)
|
|
|
|
|
await Connection.StopAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task Notify<TArgs>(string method, TArgs args)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Buffer message if connection is not opened and send it later.
|
|
|
|
|
if (Connection.State != HubConnectionState.Connected)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (Connection.State == HubConnectionState.Connected)
|
|
|
|
|
await Connection.SendAsync(method, args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Dispose(bool disposing)
|
|
|
|
|
{
|
|
|
|
|
if (!IsDisposed)
|
|
|
|
|
{
|
|
|
|
|
if (disposing)
|
|
|
|
|
{
|
|
|
|
|
if (_connection is not null)
|
|
|
|
|
{
|
|
|
|
|
_connection.DisposeAsync()
|
|
|
|
|
.GetAwaiter()
|
|
|
|
|
.GetResult();
|
|
|
|
|
|
|
|
|
|
_connection = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IsDisposed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
Dispose(true);
|
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async ValueTask DisposeAsync()
|
|
|
|
|
{
|
|
|
|
|
if (_connection is not null)
|
|
|
|
|
{
|
|
|
|
|
await _connection.DisposeAsync();
|
|
|
|
|
_connection = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|