214 lines
9.3 KiB
C#
214 lines
9.3 KiB
C#
using Microsoft.AspNetCore.SignalR.Client;
|
|
using Microsoft.Extensions.Logging;
|
|
using QtCNETAPI.Dtos.User;
|
|
using QtCNETAPI.Events;
|
|
using QtCNETAPI.Models;
|
|
using QtCNETAPI.Services.ApiService;
|
|
|
|
namespace QtCNETAPI.Services.GatewayService
|
|
{
|
|
public class GatewayService(string GWUrl, IApiService apiService, LoggingService loggingService) : IGatewayService, IAsyncDisposable
|
|
{
|
|
internal string gwBaseUri = GWUrl;
|
|
|
|
public Room? CurrentRoom { get; private set; }
|
|
public bool InLobby { get; private set; }
|
|
public HubConnection? HubConnection { get; private set; }
|
|
|
|
|
|
public event EventHandler? OnRoomMessageReceived;
|
|
public event EventHandler? OnRoomUserListReceived;
|
|
public event EventHandler? OnGuestUserJoin;
|
|
public event EventHandler? OnRefreshUserListsReceived;
|
|
public event EventHandler? OnRefreshRoomListReceived;
|
|
public event EventHandler? OnRoomDeleted;
|
|
public event EventHandler? OnRefreshContactsListReceived;
|
|
public event EventHandler? OnClientFunctionReceived;
|
|
public event EventHandler? OnDirectMessageReceived;
|
|
public event EventHandler? OnServerConfigReceived;
|
|
public event EventHandler? OnServerDisconnect;
|
|
public event EventHandler? OnServerReconnecting;
|
|
public event EventHandler? OnServerReconnected;
|
|
public event EventHandler? OnUserForceLogout;
|
|
|
|
private IApiService _apiService = apiService;
|
|
private LoggingService _loggingService = loggingService;
|
|
|
|
public async Task StartAsync()
|
|
{
|
|
// build connection
|
|
var gwConBuilder = new HubConnectionBuilder()
|
|
.WithAutomaticReconnect()
|
|
.ConfigureLogging((builder) =>
|
|
{
|
|
builder.AddProvider(new LoggingServiceProvider(_loggingService));
|
|
|
|
if (System.Diagnostics.Debugger.IsAttached) builder.SetMinimumLevel(LogLevel.Debug);
|
|
else builder.SetMinimumLevel(LogLevel.Error);
|
|
})
|
|
.WithUrl(gwBaseUri, options =>
|
|
{
|
|
options.AccessTokenProvider = async () =>
|
|
{
|
|
// this should hopefully refresh the session every time the gateway connection is used to prevent connection aborts
|
|
await _apiService.RefreshSessionIfInvalid();
|
|
return _apiService.SessionToken;
|
|
};
|
|
})
|
|
.WithStatefulReconnect()
|
|
.WithServerTimeout(TimeSpan.FromMinutes(1))
|
|
.WithKeepAliveInterval(TimeSpan.FromMinutes(1));
|
|
HubConnection = gwConBuilder.Build();
|
|
|
|
// register events
|
|
HubConnection.On<string>("RoomMessage", (serverMessage) => OnRoomMessageReceived?.Invoke(this, new ServerMessageEventArgs { Message = serverMessage }));
|
|
HubConnection.On<string>("cf", (function) => OnClientFunctionReceived?.Invoke(this, new ClientFunctionEventArgs { Function = function }));
|
|
HubConnection.On<Message, UserInformationDto>("ReceiveDirectMessage", (message, user) => OnDirectMessageReceived?.Invoke(this, new DirectMessageEventArgs { Message = message, User = user }));
|
|
HubConnection.On("RefreshUserLists", () => OnRefreshUserListsReceived?.Invoke(this, EventArgs.Empty));
|
|
HubConnection.On("RefreshRoomList", () => OnRefreshRoomListReceived?.Invoke(this, EventArgs.Empty));
|
|
HubConnection.On("RefreshContactsList", () => OnRefreshContactsListReceived?.Invoke(this, EventArgs.Empty));
|
|
HubConnection.On<ServerConfig>("ReceiveServerConfig", (serverConfig) => OnServerConfigReceived?.Invoke(this, new ServerConfigEventArgs { ServerConfig = serverConfig }));
|
|
HubConnection.On<List<User>>("RoomUserList", (userList) => OnRoomUserListReceived?.Invoke(this, new RoomListEventArgs { UserList = userList }));
|
|
HubConnection.On<string>("GuestJoin", (username) => OnGuestUserJoin?.Invoke(this, new GuestUserJoinEventArgs { Username = username }));
|
|
HubConnection.On("RoomDeleted", () => OnRoomDeleted?.Invoke(this, EventArgs.Empty));
|
|
HubConnection.On("ForceSignOut", () => OnUserForceLogout?.Invoke(this, EventArgs.Empty));
|
|
|
|
HubConnection.Closed += HubConnection_Closed;
|
|
HubConnection.Reconnecting += HubConnection_Reconnecting;
|
|
HubConnection.Reconnected += HubConnection_Reconnected;
|
|
|
|
// start connection
|
|
try
|
|
{
|
|
await HubConnection.StartAsync();
|
|
}
|
|
catch (HttpRequestException ex)
|
|
{
|
|
_loggingService.LogString($"Unable To Connect To SignalR.\n{ex.Message}\n{ex.StackTrace}");
|
|
return;
|
|
}
|
|
|
|
// ensure current user is up to date (particularly status)
|
|
await _apiService.SetCurrentUser();
|
|
}
|
|
|
|
public async Task StopAsync()
|
|
{
|
|
if (HubConnection != null && HubConnection.State == HubConnectionState.Connected)
|
|
{
|
|
await HubConnection.StopAsync();
|
|
}
|
|
}
|
|
|
|
async ValueTask IAsyncDisposable.DisposeAsync()
|
|
{
|
|
if (HubConnection != null && HubConnection.State == HubConnectionState.Disconnected)
|
|
{
|
|
await HubConnection.DisposeAsync();
|
|
|
|
HubConnection = null;
|
|
CurrentRoom = null;
|
|
}
|
|
}
|
|
|
|
public async Task DisposeAsync()
|
|
{
|
|
if (HubConnection != null && HubConnection.State == HubConnectionState.Disconnected)
|
|
{
|
|
await HubConnection.DisposeAsync();
|
|
|
|
HubConnection = null;
|
|
CurrentRoom = null;
|
|
}
|
|
}
|
|
|
|
public async Task JoinLobbyAsync()
|
|
{
|
|
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
|
|
|
|
await HubConnection.SendAsync("JoinLobby", _apiService.CurrentUser);
|
|
InLobby = true;
|
|
CurrentRoom = null;
|
|
}
|
|
|
|
public async Task JoinRoomAsync(Room room)
|
|
{
|
|
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
|
|
|
|
if (InLobby == true)
|
|
{
|
|
await HubConnection.SendAsync("LeaveLobby", _apiService.CurrentUser);
|
|
InLobby = false;
|
|
}
|
|
else if (CurrentRoom != null)
|
|
{
|
|
await HubConnection.SendAsync("LeaveRoom", _apiService.CurrentUser, CurrentRoom);
|
|
}
|
|
|
|
await HubConnection.SendAsync("JoinRoom", _apiService.CurrentUser, room);
|
|
CurrentRoom = room;
|
|
}
|
|
|
|
public async Task LeaveRoomAsync()
|
|
{
|
|
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
|
|
|
|
if (InLobby)
|
|
{
|
|
await HubConnection.SendAsync("LeaveLobby", _apiService.CurrentUser);
|
|
InLobby = false;
|
|
}
|
|
else
|
|
{
|
|
await HubConnection.SendAsync("LeaveRoom", _apiService.CurrentUser, CurrentRoom);
|
|
CurrentRoom = null;
|
|
}
|
|
}
|
|
|
|
public async Task PostMessageAsync(Message message)
|
|
{
|
|
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
|
|
|
|
await HubConnection.SendAsync("SendMessage", _apiService.CurrentUser, message, InLobby, CurrentRoom);
|
|
}
|
|
|
|
public async Task SendDirectMessageAsync(UserInformationDto user, Message message)
|
|
{
|
|
await _apiService.RefreshSessionIfInvalid();
|
|
|
|
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
|
|
|
|
await HubConnection.SendAsync("SendDirectMessage", _apiService.CurrentUser, user, message);
|
|
}
|
|
|
|
public async Task UpdateStatus(int status)
|
|
{
|
|
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
|
|
|
|
await HubConnection.SendAsync("UpdateStatus", _apiService.CurrentUser, status);
|
|
|
|
// anything that changes the user should tell the api service to set it again
|
|
await _apiService.SetCurrentUser();
|
|
}
|
|
|
|
|
|
private Task HubConnection_Closed(Exception? arg)
|
|
{
|
|
OnServerDisconnect?.Invoke(this, new ServerConnectionClosedEventArgs { Error = arg });
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task HubConnection_Reconnecting(Exception? arg)
|
|
{
|
|
OnServerReconnecting?.Invoke(this, new ServerConnectionReconnectingEventArgs { Error = arg });
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task HubConnection_Reconnected(string? arg)
|
|
{
|
|
OnServerReconnected?.Invoke(this, EventArgs.Empty);
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
}
|