using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; using H.Formatters; using H.Pipes; using InABox.Core; using InABox.IPC; using InABox.Logikal; using java.lang; using Exception = System.Exception; using Process = System.Diagnostics.Process; namespace PRSDesktop; public class LogikalClient : IDisposable, ILogikalApp { private readonly PipeClient _client; private ConcurrentDictionary Events = new(); private ConcurrentDictionary Responses = new(); private const int DefaultRequestTimeout = 5 * 60 * 1000; // 5 minutes public LogikalClient() { var _basedirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) ?? ""; var _logikalapp = System.IO.Path.Combine(_basedirectory, "PRSLogikal", "PRSLogikal.exe"); Process.Start(_logikalapp); _client = new PipeClient("$logikal", formatter: new NewtonsoftJsonFormatter()); _client.Connected += Client_Connected; _client.Disconnected += Client_Disconnected; _client.MessageReceived += Client_MessageReceived; _client.ExceptionOccurred += Client_ExceptionOccurred; _client.ConnectAsync(); } public void Dispose() { _client.DisposeAsync().AsTask().Wait(); } private void Client_Connected(object? sender, H.Pipes.Args.ConnectionEventArgs e) { Logger.Send(LogType.Information, "", $"Connected to Pipe: {e.Connection.PipeName}"); //Disconnected = false; // Here we will register a Licence "Hit" for the Logikal interface } private void Client_Disconnected(object? sender, H.Pipes.Args.ConnectionEventArgs e) { Logger.Send(LogType.Information, "", $"Disconnected from Pipe: {e.Connection.PipeName}"); foreach (var ev in Events) { Responses.TryAdd(ev.Key, LogikalMessage.Error("Disconnected")); ev.Value.Set(); } //Disconnected = true; } private void Client_ExceptionOccurred(object? sender, H.Pipes.Args.ExceptionEventArgs e) { Logger.Send(LogType.Error, "", $"Exception occured: {e.Exception.Message}"); } public LogikalResponse Send(LogikalRequest request, int timeout = DefaultRequestTimeout) { var message = new LogikalMessage() { ID = Guid.NewGuid(), Method = request.Method(), Payload = Serialization.Serialize(request), }; var ev = Queue(message.ID); _client.WriteAsync(message); var result = GetResult(message.ID, ev, timeout); return LogikalResponse.FromMessage(result); } public ManualResetEventSlim Queue(Guid id) { var ev = new ManualResetEventSlim(); Events[id] = ev; return ev; } public LogikalMessage GetResult(Guid id, ManualResetEventSlim ev, int timeout) { if (Responses.TryRemove(id, out var result)) { Events.TryRemove(id, out ev); return result; } try { if (!ev.Wait(timeout)) { return LogikalMessage.Error("Timeout"); } } catch (Exception e) { Console.WriteLine(e); throw; } Responses.TryRemove(id, out result); Events.TryRemove(id, out ev); return result ?? LogikalMessage.Error("Unknown"); } private void Client_MessageReceived(object? sender, H.Pipes.Args.ConnectionMessageEventArgs e) { if (Events.TryGetValue(e.Message.ID, out var ev)) { Responses[e.Message.ID] = e.Message; ev.Set(); } } ~LogikalClient() { Dispose(); } public LogikalStatus Connect(string path) { var request = new LogikalConnectRequest() { Path = path }; var result = Send(request); return result.Status; } public LogikalStatus Disconnect() { var request = new LogikalDisconnectRequest(); var result = Send(request); return result.Status; } public LogikalStatus Login(string username, string password) { var request = new LogikalLoginRequest() { UserID = username, Password = password }; var result = Send(request); return result.Status; } public LogikalStatus Logout() { var request = new LogikalLogoutRequest(); var result = Send(request); return result.Status; } }