using InABox.Clients; using InABox.Core; using System.Collections.Generic; using System.Linq; using System.Net.NetworkInformation; using System.Text; using System.Threading.Tasks; namespace InABox.IPC { public enum RequestError { NONE, DISCONNECTED, UNKNOWN, TIMEOUT } public enum Method { None, Query, Save, MultiSave, Delete, MultiDelete, QueryMultiple, Validate, Check2FA, Ping, Info, Push, Version, ReleaseNotes, Installer } [Serializable] public class IPCMessage { public Guid RequestID; public Method Method; public string? Type; private string? Data; private byte[]? BinaryData; [NonSerialized] public RequestError ErrorCode; private IPCMessage(Guid requestID, Method method, string? type, string data, RequestError error = RequestError.NONE) { RequestID = requestID; Method = method; Type = type; Data = data; BinaryData = null; ErrorCode = error; } private IPCMessage(Guid requestID, Method method, string? type, byte[] data, RequestError error = RequestError.NONE) { RequestID = requestID; Method = method; Type = type; BinaryData = data; Data = null; ErrorCode = error; } public IPCMessage Respond(TResponse response) where TResponse : Response { return CreateRequest(RequestID, Method.None, Type, response); } private static IPCMessage CreateRequest(Guid requestID, Method method, string? type, object? data) { if (data is ISerializeBinary binary) { return new IPCMessage(requestID, method, type, binary.WriteBinary(BinarySerializationSettings.Latest)); } { return new IPCMessage(requestID, method, type, Serialization.Serialize(data)); } } public TRequest GetRequest() { if (BinaryData is not null) { return (TRequest)Serialization.ReadBinary(typeof(TRequest), BinaryData, BinarySerializationSettings.Latest); } else { return Serialization.Deserialize(Data); } } public object? GetRequest(Type TRequest) { if (BinaryData is not null) { return Serialization.ReadBinary(TRequest, BinaryData, BinarySerializationSettings.Latest); } else if(Data is not null) { return Serialization.Deserialize(TRequest, Data); } else { return null; } } public TResponse GetResponse() where TResponse : Response, new() { var start = DateTime.Now; var response = GetRequest(); response ??= new TResponse(); switch (ErrorCode) { case RequestError.NONE: break; case RequestError.DISCONNECTED: response.Status = StatusCode.Error; response.Messages.Add("Server disconnected"); break; case RequestError.UNKNOWN: response.Status = StatusCode.Error; response.Messages.Add("Unknown Error"); break; case RequestError.TIMEOUT: response.Status = StatusCode.Error; response.Messages.Add("Timeout"); break; } return response; } public static IPCMessage Query(QueryRequest request) where T : Entity, new() { return CreateRequest(Guid.NewGuid(), Method.Query, typeof(T).Name, request); } public static IPCMessage Save(SaveRequest request) where T : Entity, new() { return CreateRequest(Guid.NewGuid(), Method.Save, typeof(T).Name, request); } public static IPCMessage MultiSave(MultiSaveRequest request) where T : Entity, new() { return CreateRequest(Guid.NewGuid(), Method.MultiSave, typeof(T).Name, request); } public static IPCMessage Delete(DeleteRequest request) where T : Entity, new() { return CreateRequest(Guid.NewGuid(), Method.Delete, typeof(T).Name, request); } public static IPCMessage MultiDelete(MultiDeleteRequest request) where T : Entity, new() { return CreateRequest(Guid.NewGuid(), Method.MultiDelete, typeof(T).Name, request); } public static IPCMessage QueryMultiple(MultiQueryRequest request) { return CreateRequest(Guid.NewGuid(), Method.QueryMultiple, null, request); } public static IPCMessage Validate(ValidateRequest request) { return CreateRequest(Guid.NewGuid(), Method.Validate, null, request); } public static IPCMessage Check2FA(Check2FARequest request) { return CreateRequest(Guid.NewGuid(), Method.Check2FA, null, request); } public static IPCMessage Error(RequestError error) { return new IPCMessage(Guid.NewGuid(), Method.None, null, "", error); } public static IPCMessage Ping(PingRequest request) { return CreateRequest(Guid.NewGuid(), Method.Ping, null, request); } public static IPCMessage Info(InfoRequest request) { return CreateRequest(Guid.NewGuid(), Method.Info, null, request); } public static IPCMessage Version(VersionRequest request) { return CreateRequest(Guid.NewGuid(), Method.Version, null, request); } public static IPCMessage ReleaseNotes(ReleaseNotesRequest request) { return CreateRequest(Guid.NewGuid(), Method.ReleaseNotes, null, request); } public static IPCMessage Installer(InstallerRequest request) { return CreateRequest(Guid.NewGuid(), Method.Installer, null, request); } public static IPCMessage Push(TPush push) where TPush : BaseObject => Push(typeof(TPush), push); public static IPCMessage Push(Type TPush, BaseObject push) { return CreateRequest(Guid.NewGuid(), Method.Push, TPush.EntityName(), push); } } }