using System; using System.Threading.Tasks; using WebSocketSharp; using Socket = WebSocketSharp.WebSocket; using Logger = InABox.Core.Logger; using InABox.Core; using InABox.Clients; using InABox.WebSocket.Shared; namespace InABox.Client.WebSocket { public class WebSocketClient : IDisposable { private Socket Socket; private Guid Session; private bool Closed = false; public WebSocketClient(string url, int port, Guid session) { Session = session; Uri uri = new Uri("http://" + url); Socket = new Socket($"ws://{uri.Host}:{port}/push"); Socket.OnOpen += Socket_OnOpen; Socket.OnError += Socket_OnError; Socket.OnClose += Socket_OnClose; Socket.OnMessage += Socket_OnMessage; Socket.Connect(); // Time to wait before disconnect - the default meant that the client disconnected during debugging, since the ping would fail Socket.WaitTime = TimeSpan.FromMinutes(10); } private void Socket_OnMessage(object? sender, MessageEventArgs e) { var message = SocketMessage.ReadMessage(e.RawData); if(message is PushMessage pushMessage) { var pushType = CoreUtils.GetEntity(pushMessage.EntityType); var pushObject = Serialization.Deserialize(pushType, pushMessage.EntityData); ClientFactory.PushHandlers.Push(pushType, pushObject); } else if(message is InitialMessage) { } } private void Socket_OnOpen(object? sender, EventArgs e) { Logger.Send(LogType.Information, "", "WebSocket connected to server"); var initial = new InitialMessage(Session, ClientFactory.Platform); Socket.Send(initial.WriteToBytes()); } private void Socket_OnClose(object? sender, CloseEventArgs e) { Logger.Send(LogType.Information, "", "WebSocket disconnected from server"); if (!Closed) { Task.Run(() => { if (!Socket.IsAlive) { Task.Delay(30_000).Wait(); // Try to reconnect after 30 seconds Socket.Connect(); } }); } } private void Socket_OnError(object? sender, ErrorEventArgs e) { Logger.Send(LogType.Error, "", $"WebSocket Error: {e.Message}"); } public void Dispose() { Closed = true; if (Socket.IsAlive) { Socket.Close(); } } } }