namespace InABox.IPC { public abstract class RPCServerTransport : IRPCServerTransport where TConnection : notnull { private Dictionary _sessions = new Dictionary(); protected RPCServerSession CreateSession(TConnection connection) { var session = new RPCServerSession(); _sessions[connection] = session; return session; } protected RPCServerSession? GetSession(TConnection? connection) { if (connection == null) return null; _sessions.TryGetValue(connection, out RPCServerSession? session); return session; } protected RPCServerSession? DeleteSession(TConnection connection) { _sessions.Remove(connection, out RPCServerSession? session); return session; } private Dictionary _handlers = new Dictionary(); public void AddHandler(RPCCommandHandler handler) where TCommand : IRPCCommand where TSender : class { _handlers[typeof(TCommand).Name] = handler; } public abstract void Start(); public abstract void Stop(); public event RPCTransportOpenEvent? OnOpen; protected void DoOpen(TConnection connection) { var session = CreateSession(connection); OnOpen?.Invoke(this, new RPCTransportOpenArgs(session) ); } public event RPCTransportCloseEvent? OnClose; protected void DoClose(TConnection connection , RPCTransportCloseEventType type) { var session = GetSession(connection); OnClose?.Invoke(this, new RPCTransportCloseArgs(session, type)); } public event RPCTransportExceptionEvent? OnException; protected void DoException(TConnection? connection, Exception e) { var session = GetSession(connection); OnException?.Invoke(this, new RPCTransportExceptionArgs(session, e)); } public event RPCTransportMessageEvent? BeforeMessage; protected void DoBeforeMessage(RPCServerSession? session, RPCMessage? message) { BeforeMessage?.Invoke(this, new RPCTransportMessageArgs(session,message)); } public event RPCTransportMessageEvent? AfterMessage; protected void DoAfterMessage(RPCServerSession? session, RPCMessage? message) { AfterMessage?.Invoke(this, new RPCTransportMessageArgs(session,message)); } public RPCMessage? DoMessage(TConnection? connection, RPCMessage? message) { var session = GetSession(connection); DoBeforeMessage(session,message); RPCMessage? response = null; if (session != null) { if (message != null) { response = new RPCMessage(message.ID, message.Command, ""); if (_handlers.TryGetValue(message.Command, out var command)) { try { response.Payload = command.Execute(message.Payload) ?? ""; } catch (Exception err) { DoException(connection, err); response.Error = RPCError.SERVERERROR; } } else { DoException(connection, new Exception("Command Not Found")); response.Error = RPCError.COMMANDNOTFOUND; } DoAfterMessage(session, response); } else DoException(connection, new Exception("NULL Message Received")); } else DoException(connection, new Exception("Session not Found")); return response; } } }