RPCClient.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading;
  6. using InABox.Clients;
  7. using InABox.Core;
  8. namespace InABox.Rpc
  9. {
  10. public class RpcClient<TEntity> : BaseClient<TEntity> where TEntity : Entity, new()
  11. {
  12. private IRpcClientTransport _transport;
  13. private ConcurrentDictionary<Guid, ManualResetEventSlim> _events = new ConcurrentDictionary<Guid, ManualResetEventSlim>();
  14. private ConcurrentDictionary<Guid, RpcMessage> _responses = new ConcurrentDictionary<Guid, RpcMessage>();
  15. private const int DefaultRequestTimeout = 5 * 60 * 1000; // 5 minutes
  16. public RpcClient(IRpcClientTransport transport)
  17. {
  18. _transport = transport;
  19. _transport.OnMessage += Transport_Message;
  20. }
  21. ~RpcClient()
  22. {
  23. _transport.OnMessage -= Transport_Message;
  24. }
  25. #region TransportManagement
  26. public override bool IsConnected() => _transport?.IsConnected() == true;
  27. private void Transport_Message(IRpcTransport transport, RpcTransportMessageArgs e)
  28. {
  29. if (e.Message != null && e.Message.Command == "Push")
  30. {
  31. var push = Serialization.ReadBinary<RpcPush>(e.Message.Payload, BinarySerializationSettings.Latest);
  32. ClientFactory.PushHandlers.Push(push.Type, push.Object);
  33. }
  34. }
  35. #endregion
  36. #region Client Interface
  37. public override DatabaseInfo Info()
  38. {
  39. var result = _transport.Send<RpcInfoCommand, RpcInfoParameters, RpcInfoResult>(new RpcInfoParameters());
  40. return result.Info;
  41. }
  42. private static string[]? _types;
  43. public override IEnumerable<string> SupportedTypes()
  44. {
  45. _types ??= CoreUtils.Entities
  46. .Where(x => x.GetInterfaces().Contains(typeof(IPersistent)))
  47. .Select(x => x.EntityName().Replace(".", "_"))
  48. .ToArray();
  49. return _types;
  50. }
  51. #region Validate & 2FA
  52. protected override IValidationData DoValidate(string userid, string password, Guid session = default)
  53. {
  54. var parameters = new RpcValidateParameters()
  55. {
  56. UserID = userid,
  57. Password = password,
  58. PIN = "",
  59. UsePIN = false,
  60. SessionID = session,
  61. Platform = ClientFactory.Platform,
  62. Version = ClientFactory.Version
  63. };
  64. return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);
  65. }
  66. protected override IValidationData DoValidate(string pin, Guid session = default)
  67. {
  68. var ticks = DateTime.Now.ToUniversalTime().Ticks.ToString();
  69. var parameters = new RpcValidateParameters()
  70. {
  71. UserID = Encryption.Encrypt(ticks, "wCq9rryEJEuHIifYrxRjxg", true),
  72. Password = Encryption.Encrypt(ticks, "7mhvLnqMwkCAzN+zNGlyyg", true),
  73. PIN = pin,
  74. UsePIN = true,
  75. SessionID = session,
  76. Platform = ClientFactory.Platform,
  77. Version = ClientFactory.Version
  78. };
  79. return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);
  80. }
  81. protected override IValidationData DoValidate(Guid session = default)
  82. {
  83. var parameters = new RpcValidateParameters()
  84. {
  85. UserID = "",
  86. Password = "",
  87. PIN = "",
  88. UsePIN = false,
  89. SessionID = session,
  90. Platform = ClientFactory.Platform,
  91. Version = ClientFactory.Version
  92. };
  93. return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);
  94. }
  95. protected override bool DoCheck2FA(string code, Guid? session)
  96. {
  97. var parameters = new RpcCheck2FAParameters()
  98. {
  99. Code = code,
  100. SessionId = session ?? ClientFactory.SessionID,
  101. };
  102. var result = _transport.Send<RpcCheck2FACommand, RpcCheck2FAParameters, RpcCheck2FAResult>(parameters);
  103. return result.Valid;
  104. }
  105. #endregion
  106. protected override CoreTable DoQuery(Filter<TEntity>? filter, Columns<TEntity>? columns, SortOrder<TEntity>? sort = null)
  107. {
  108. var parameters = new RpcQueryParameters()
  109. {
  110. Queries = new RpcQueryDefinition[]
  111. {
  112. new RpcQueryDefinition()
  113. {
  114. Key = typeof(TEntity).EntityName().Split('.').Last(),
  115. Type = typeof(TEntity),
  116. Filter = filter,
  117. Columns = columns,
  118. Sort = sort
  119. }
  120. }
  121. };
  122. var result = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);
  123. return result.Tables[0].Table;
  124. }
  125. protected override TEntity[] DoLoad(Filter<TEntity>? filter = null, SortOrder<TEntity>? sort = null)
  126. {
  127. return DoQuery(filter, null, sort).ToObjects<TEntity>().ToArray();
  128. }
  129. protected override Dictionary<string, CoreTable> DoQueryMultiple(Dictionary<string, IQueryDef> queries)
  130. {
  131. var result = new Dictionary<string, CoreTable>();
  132. var parameters = new RpcQueryParameters()
  133. {
  134. Queries = queries.Select(kvp =>
  135. new RpcQueryDefinition()
  136. {
  137. Key = kvp.Key,
  138. Type = kvp.Value.Type,
  139. Filter = kvp.Value.Filter,
  140. Columns = kvp.Value.Columns,
  141. Sort = kvp.Value.SortOrder
  142. }
  143. ).ToArray()
  144. };
  145. var response = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);
  146. foreach (var key in response.Tables)
  147. result[key.Key] = key.Table;
  148. return result;
  149. }
  150. protected override void DoSave(TEntity entity, string auditnote)
  151. {
  152. DoSave(new TEntity[] { entity }, auditnote);
  153. }
  154. protected override void DoSave(IEnumerable<TEntity> entities, string auditnote)
  155. {
  156. var items = entities.ToArray();
  157. var parameters = new RpcSaveParameters()
  158. {
  159. Type = typeof(TEntity),
  160. Items = items
  161. };
  162. var result = _transport.Send<RpcSaveCommand, RpcSaveParameters, RpcSaveResult>(parameters);
  163. for (int i = 0; i < result.Deltas.Length; i++)
  164. {
  165. items[i].SetObserving(false);
  166. foreach (var (key, value) in result.Deltas[i])
  167. {
  168. if (CoreUtils.TryGetProperty<TEntity>(key, out var property))
  169. CoreUtils.SetPropertyValue(items[i], key, CoreUtils.ChangeType(value, property.PropertyType));
  170. }
  171. items[i].CommitChanges();
  172. items[i].SetObserving(true);
  173. }
  174. }
  175. protected override void DoDelete(TEntity entity, string auditnote)
  176. {
  177. DoDelete(new TEntity[] { entity }, auditnote);
  178. }
  179. protected override void DoDelete(IList<TEntity> entities, string auditnote)
  180. {
  181. var parameters = new RpcDeleteParameters()
  182. {
  183. Type = typeof(TEntity),
  184. IDs = entities.Select(x => x.ID).ToArray(),
  185. AuditNote = auditnote
  186. };
  187. _transport.Send<RpcDeleteCommand, RpcDeleteParameters, RpcDeleteResult>(parameters);
  188. }
  189. protected override bool DoPing()
  190. {
  191. try
  192. {
  193. if (!_transport.IsConnected())
  194. _transport.Connect();
  195. _transport.Send<RpcPingCommand, RpcPingParameters, RpcPingResult>(new RpcPingParameters());
  196. return true;
  197. }
  198. catch (Exception)
  199. {
  200. return false;
  201. }
  202. }
  203. #endregion
  204. }
  205. }