using Comal.Classes; using InABox.Core; using InABox.DigitalMatter; using NPOI.HSSF.Record.CF; using PRSServer.Engines; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Media.Media3D; namespace PRSServer { internal class OEMListener { private TcpListener listener; private GPSDeviceCache Cache; private GPSUpdateQueue Queue; private object connectionsLock = new object(); private List Connections = new(); public int Port { get; set; } public OEMListener(int port, GPSDeviceCache cache, GPSUpdateQueue queue) { Port = port; Cache = cache; Queue = queue; } public void Start() { listener = new TcpListener(IPAddress.Any, Port); listener.Start(); AcceptClient(); } private void AcceptClient() { Logger.Send(LogType.Information, "", "Waiting for OEM connection."); listener.AcceptTcpClientAsync().ContinueWith(t => { try { Logger.Send(LogType.Information, "", $"OEM Connection opened; {Connections.Count} connections open."); var connection = new OEMConnection(t.Result, Cache, Queue); lock (connectionsLock) { Connections.Add(connection); } connection.OnCompletion = () => { // When the connection finishes, we should remove it from our list. lock (connectionsLock) { Logger.Send(LogType.Information, "", $"OEM Connection closed; {Connections.Count} connections still open."); Connections.Remove(connection); } }; connection.Run(); // Accept a new client. AcceptClient(); } catch (Exception e) { Logger.Send(LogType.Error, "", CoreUtils.FormatException(e)); } }, TaskContinuationOptions.OnlyOnRanToCompletion); } public void Stop() { listener.Stop(); lock (connectionsLock) { // Running in parallel because each connection can take a second to stop. Parallel.ForEach(Connections, connection => { connection.Stop(); }); Connections.Clear(); } } } }