using System.Net; using System.Net.Sockets; using System.Text.Json; using Fleck; using WirelessTextSyncer.Windows.Models; namespace WirelessTextSyncer.Windows.Services; public sealed class WebSocketServerService : IDisposable { private readonly SyncMessageHandler messageHandler; private readonly List clients = []; private WebSocketServer? server; public WebSocketServerService(SyncMessageHandler messageHandler) { this.messageHandler = messageHandler; } public int Port { get; private set; } = 8181; public string LocalIpAddress { get; private set; } = "127.0.0.1"; public bool HasClient => clients.Count > 0; public event EventHandler? StatusChanged; public void Start(int port) { Port = port; LocalIpAddress = ResolveLocalIpAddress(); server = new WebSocketServer($"ws://0.0.0.0:{Port}"); server.Start(socket => { socket.OnOpen = () => { clients.Add(socket); StatusChanged?.Invoke(this, EventArgs.Empty); }; socket.OnClose = () => { clients.Remove(socket); StatusChanged?.Invoke(this, EventArgs.Empty); }; socket.OnMessage = HandleRawMessage; }); } public void Dispose() { foreach (var client in clients.ToArray()) { client.Close(); } clients.Clear(); server?.Dispose(); } private void HandleRawMessage(string rawMessage) { var message = JsonSerializer.Deserialize(rawMessage); if (message is null) { return; } messageHandler.Handle(message); } private static string ResolveLocalIpAddress() { var host = Dns.GetHostEntry(Dns.GetHostName()); var address = host.AddressList.FirstOrDefault( address => address.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(address)); return address?.ToString() ?? "127.0.0.1"; } }