RPCServerTransport.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System.IO.Pipes;
  2. using System.Security.Principal;
  3. using H.Pipes;
  4. using H.Pipes.AccessControl;
  5. using InABox.Core;
  6. namespace InABox.IPC
  7. {
  8. public class RPCServerTransport : IDisposable
  9. {
  10. PipeServer<RPCMessage> Server;
  11. private Dictionary<String, IRPCCommandHandler> _commands = new Dictionary<String, IRPCCommandHandler>();
  12. public void AddCommandHandler<TSender, TCommand, TProperties, TResult>(RPCCommandHandler<TSender,TProperties,TResult> commandHandler)
  13. where TCommand : IRPCCommand<TProperties, TResult>
  14. where TSender : class
  15. {
  16. _commands[typeof(TCommand).Name] = commandHandler;
  17. }
  18. public event LogFunction? OnLog;
  19. private void SetPipeSecurity()
  20. {
  21. #pragma warning disable CA1416
  22. var pipeSecurity = new PipeSecurity();
  23. pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.LocalSid, null), PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow));
  24. pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null), PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow));
  25. pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null), PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow));
  26. Server.SetPipeSecurity(pipeSecurity);
  27. #pragma warning restore CA1416
  28. }
  29. public RPCServerTransport(string name)
  30. {
  31. Server = new PipeServer<RPCMessage>(name);
  32. #if WINDOWS
  33. SetPipeSecurity();
  34. #endif
  35. Server.ClientConnected += Server_ClientConnected;
  36. Server.ClientDisconnected += Server_ClientDisconnected;
  37. Server.MessageReceived += Server_MessageReceived;
  38. Server.ExceptionOccurred += Server_ExceptionOccurred;
  39. }
  40. private void Server_ExceptionOccurred(object? sender, H.Pipes.Args.ExceptionEventArgs e)
  41. {
  42. OnLog?.Invoke(LogType.Error, "", $"Exception Occurred: {e.Exception.Message}");
  43. }
  44. public void Start()
  45. {
  46. Server.StartAsync().Wait();
  47. }
  48. private void Server_MessageReceived(object? sender, H.Pipes.Args.ConnectionMessageEventArgs<RPCMessage?> e)
  49. {
  50. Task.Run(() =>
  51. {
  52. if (e.Message != null)
  53. {
  54. RPCMessage message = new RPCMessage(e.Message.RequestID, e.Message.Command, "");
  55. if (!_commands.TryGetValue(e.Message.Command, out var command))
  56. message.Error = RPCError.COMMANDNOTFOUND;
  57. else
  58. {
  59. try
  60. {
  61. message.Payload = command.Execute(sender!, e.Message.Payload) ?? "";
  62. }
  63. catch (Exception err)
  64. {
  65. OnLog?.Invoke(LogType.Error, "", err.Message);
  66. message.Error = RPCError.SERVERERROR;
  67. }
  68. }
  69. e.Connection.WriteAsync(message);
  70. }
  71. else
  72. OnLog?.Invoke(LogType.Error, "", "Null Message Received");
  73. }
  74. );
  75. }
  76. private void Server_ClientDisconnected(object? sender, H.Pipes.Args.ConnectionEventArgs<RPCMessage> e)
  77. {
  78. OnLog?.Invoke(LogType.Information, "", "Client Disconnected");
  79. e.Connection.DisposeAsync();
  80. }
  81. private void Server_ClientConnected(object? sender, H.Pipes.Args.ConnectionEventArgs<RPCMessage> e)
  82. {
  83. OnLog?.Invoke(LogType.Information, "", "Client Connected");
  84. }
  85. public void Dispose()
  86. {
  87. Server.DisposeAsync().AsTask().Wait();
  88. }
  89. ~RPCServerTransport()
  90. {
  91. Dispose();
  92. }
  93. }
  94. }