using InABox.Clients; using InABox.Core; using InABox.Formatters; 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 } public class IPCMessage : ISerializeBinary, ICoreFormattable { public Guid RequestID { get; set; } public Method Method { get; set; } public string? Type { get; set; } public string? Data { get; set; } public byte[]? BinaryData { get; set; } public RequestError ErrorCode; public IPCMessage() { RequestID = Guid.Empty; Method = Method.None; Type = ""; Data = ""; BinaryData = []; ErrorCode = RequestError.UNKNOWN; } private IPCMessage(Guid requestID, Method method, string type, string data, RequestError error = RequestError.NONE) : this() { RequestID = requestID; Method = method; Type = type; Data = data; BinaryData = []; ErrorCode = error; } private IPCMessage(Guid requestID, Method method, string type, byte[] data, RequestError error = RequestError.NONE) : this() { RequestID = requestID; Method = method; Type = type; BinaryData = data; Data = ""; 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: response.Status = StatusCode.OK; 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); } public void SerializeBinary(CoreBinaryWriter writer) => Write(writer); public void DeserializeBinary(CoreBinaryReader reader) => Read(reader); public void Write(BinaryWriter writer) { writer.Write(RequestID); writer.Write((Int32)Method); writer.Write(Type ?? ""); writer.Write(Data ?? ""); writer.Write(BinaryData?.Length ?? 0); if (BinaryData != null) writer.Write(BinaryData); writer.Write((Int32)ErrorCode); } public void Read(BinaryReader reader) { RequestID = reader.ReadGuid(); Method = (Method)reader.ReadInt32(); Type = reader.ReadString(); Data = reader.ReadString(); var _length = reader.ReadInt32(); BinaryData = reader.ReadBytes(_length); ErrorCode = (RequestError)reader.ReadInt32(); } } }