RPCServerTransport.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. using InABox.Core;
  2. namespace InABox.Rpc
  3. {
  4. public abstract class RpcServerTransport<TConnection> : IPusher, IRpcServerTransport where TConnection : notnull
  5. {
  6. public abstract bool IsSecure();
  7. private Dictionary<TConnection, RpcServerSession> _sessions = new Dictionary<TConnection, RpcServerSession>();
  8. protected RpcServerSession CreateSession(TConnection connection)
  9. {
  10. var result = new RpcServerSession();
  11. _sessions[connection] = result;
  12. return result;
  13. }
  14. public RpcServerSession? GetSession(TConnection? connection)
  15. {
  16. if (connection == null)
  17. return null;
  18. _sessions.TryGetValue(connection, out RpcServerSession? result);
  19. return result;
  20. }
  21. protected RpcServerSession? DeleteSession(TConnection connection)
  22. {
  23. _sessions.Remove(connection, out RpcServerSession? session);
  24. return session;
  25. }
  26. private Dictionary<string, IRpcCommandHandler> _handlers = new Dictionary<string, IRpcCommandHandler>();
  27. public void AddHandler<TSender, TCommand, TProperties, TResult>(RpcCommandHandler<TSender, TCommand, TProperties, TResult> handler)
  28. where TSender : class
  29. where TCommand : IRpcCommand<TProperties, TResult>
  30. where TProperties : IRpcCommandParameters, new()
  31. where TResult : IRpcCommandResult, new()
  32. {
  33. _handlers[typeof(TCommand).Name] = handler;
  34. }
  35. public abstract void Start();
  36. public abstract void Stop();
  37. public event RpcTransportOpenEvent? OnOpen;
  38. protected void DoOpen(TConnection connection)
  39. {
  40. var session = CreateSession(connection);
  41. OnOpen?.Invoke(this, new RpcTransportOpenArgs(session) );
  42. }
  43. public event RpcTransportCloseEvent? OnClose;
  44. protected void DoClose(TConnection connection, RpcTransportCloseEventType type)
  45. {
  46. var session = DeleteSession(connection);
  47. OnClose?.Invoke(this, new RpcTransportCloseArgs(session, type));
  48. }
  49. public event RpcTransportExceptionEvent? OnException;
  50. protected void DoException(TConnection? connection, Exception e)
  51. {
  52. var session = GetSession(connection);
  53. OnException?.Invoke(this, new RpcTransportExceptionArgs(session, e));
  54. }
  55. public event RpcTransportMessageEvent? BeforeMessage;
  56. protected void DoBeforeMessage(RpcServerSession? session, RpcMessage? message)
  57. {
  58. BeforeMessage?.Invoke(this, new RpcTransportMessageArgs(session,message));
  59. }
  60. public event RpcTransportMessageEvent? AfterMessage;
  61. protected void DoAfterMessage(RpcServerSession? session, RpcMessage? message)
  62. {
  63. AfterMessage?.Invoke(this, new RpcTransportMessageArgs(session,message));
  64. }
  65. /// <summary>
  66. /// Handle a message from a client.
  67. /// </summary>
  68. /// <param name="connection">The client connection.</param>
  69. /// <param name="message">The message to be handled.</param>
  70. /// <returns>The response to be sent back to the client.</returns>
  71. public RpcMessage? DoMessage(TConnection? connection, RpcMessage? message)
  72. {
  73. if(message is null)
  74. {
  75. DoException(connection, new Exception("NULL Message Received"));
  76. return null;
  77. }
  78. var response = new RpcMessage() { Id = message.Id, Command = message.Command };
  79. try
  80. {
  81. var session = GetSession(connection);
  82. DoBeforeMessage(session, message);
  83. if (session != null)
  84. {
  85. response = new RpcMessage() { Id = message.Id, Command = message.Command };
  86. if (_handlers.TryGetValue(message.Command, out var command))
  87. {
  88. try
  89. {
  90. response.Payload = command.Execute(session, message.Payload);
  91. }
  92. catch (RpcException err)
  93. {
  94. response.Error = err.Error;
  95. }
  96. }
  97. else
  98. {
  99. DoException(connection, new Exception("Command Not Found"));
  100. response.Error = RpcError.COMMANDNOTFOUND;
  101. }
  102. DoAfterMessage(session, response);
  103. }
  104. else
  105. {
  106. DoException(connection, new Exception("Session not Found"));
  107. response.Error = RpcError.SESSIONNOTFOUND;
  108. }
  109. }
  110. catch(Exception e)
  111. {
  112. DoException(connection, e);
  113. response.Error = RpcError.SERVERERROR;
  114. }
  115. return response;
  116. }
  117. /// <summary>
  118. /// Send a message to a particular client connection.
  119. /// </summary>
  120. /// <param name="connection">The connection to send to.</param>
  121. /// <param name="message">The message to send.</param>
  122. public abstract void Send(TConnection connection, RpcMessage message);
  123. #region Pusher Stuff
  124. public void PushToAll<TPush>(TPush push) where TPush : BaseObject
  125. {
  126. var message = new RpcMessage(Guid.NewGuid(), "Push", RpcPush.Create(push).WriteBinary(BinarySerializationSettings.Latest));
  127. foreach (var connection in _sessions.Keys)
  128. {
  129. Send(connection, message);
  130. }
  131. }
  132. public void PushToSession<TPush>(Guid session, TPush push) where TPush : BaseObject
  133. {
  134. var message = new RpcMessage(Guid.NewGuid(), "Push", RpcPush.Create(push).WriteBinary(BinarySerializationSettings.Latest));
  135. var sessionConnection = _sessions.FirstOrDefault(x => x.Value.ID == session).Key;
  136. if(sessionConnection is not null)
  137. {
  138. Send(sessionConnection, message);
  139. }
  140. }
  141. public void PushToSession(Guid session, Type TPush, BaseObject push)
  142. {
  143. var message = new RpcMessage(Guid.NewGuid(), "Push", new RpcPush
  144. {
  145. Object = push,
  146. Type = TPush
  147. }.WriteBinary(BinarySerializationSettings.Latest));
  148. var sessionConnection = _sessions.FirstOrDefault(x => x.Value.ID == session).Key;
  149. if (sessionConnection is not null)
  150. {
  151. Send(sessionConnection, message);
  152. }
  153. }
  154. public IEnumerable<Guid> GetUserSessions(Guid user) =>
  155. _sessions.Values.Where(x => x.UserGuid == user).Select(x => x.ID);
  156. public IEnumerable<Guid> GetSessions(Platform platform) =>
  157. _sessions.Values.Where(x => x.Platform == platform).Select(x => x.ID);
  158. #endregion
  159. }
  160. }