RPCClient.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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 ?? Guid.Empty,
  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. Type = typeof(TEntity),
  115. Filter = filter,
  116. Columns = columns,
  117. Sort = sort
  118. }
  119. }
  120. };
  121. var result = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);
  122. return result.Tables[0].Table;
  123. }
  124. protected override TEntity[] DoLoad(Filter<TEntity>? filter = null, SortOrder<TEntity>? sort = null)
  125. {
  126. return DoQuery(filter, null, sort).ToObjects<TEntity>().ToArray();
  127. }
  128. protected override Dictionary<string, CoreTable> DoQueryMultiple(Dictionary<string, IQueryDef> queries)
  129. {
  130. var result = new Dictionary<string, CoreTable>();
  131. var parameters = new RpcQueryParameters()
  132. {
  133. Queries = queries.Select(kvp =>
  134. new RpcQueryDefinition()
  135. {
  136. Key = kvp.Key,
  137. Type = kvp.Value.Type,
  138. Filter = kvp.Value.Filter,
  139. Columns = kvp.Value.Columns,
  140. Sort = kvp.Value.SortOrder
  141. }
  142. ).ToArray()
  143. };
  144. var response = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);
  145. foreach (var key in response.Tables)
  146. result[key.Key] = key.Table;
  147. return result;
  148. }
  149. protected override void DoSave(TEntity entity, string auditnote)
  150. {
  151. DoSave(new TEntity[] { entity }, auditnote);
  152. }
  153. protected override void DoSave(IEnumerable<TEntity> entities, string auditnote)
  154. {
  155. var items = entities.ToArray();
  156. var parameters = new RpcSaveParameters()
  157. {
  158. Type = typeof(TEntity),
  159. Items = items
  160. };
  161. var result = _transport.Send<RpcSaveCommand, RpcSaveParameters, RpcSaveResult>(parameters);
  162. for (int i = 0; i < result.Deltas.Length; i++)
  163. {
  164. items[i].SetObserving(false);
  165. foreach (var (key, value) in result.Deltas[i])
  166. {
  167. if (CoreUtils.TryGetProperty<TEntity>(key, out var property))
  168. CoreUtils.SetPropertyValue(items[i], key, CoreUtils.ChangeType(value, property.PropertyType));
  169. }
  170. items[i].CommitChanges();
  171. items[i].SetObserving(true);
  172. }
  173. }
  174. protected override void DoDelete(TEntity entity, string auditnote)
  175. {
  176. DoDelete(new TEntity[] { entity }, auditnote);
  177. }
  178. protected override void DoDelete(IList<TEntity> entities, string auditnote)
  179. {
  180. var parameters = new RpcDeleteParameters()
  181. {
  182. Type = typeof(TEntity),
  183. IDs = entities.Select(x => x.ID).ToArray(),
  184. AuditNote = auditnote
  185. };
  186. _transport.Send<RpcDeleteCommand, RpcDeleteParameters, RpcDeleteResult>(parameters);
  187. }
  188. protected override bool DoPing()
  189. {
  190. try
  191. {
  192. _transport.Send<RpcPingCommand, RpcPingParameters, RpcPingResult>(new RpcPingParameters());
  193. return true;
  194. }
  195. catch (Exception)
  196. {
  197. return false;
  198. }
  199. }
  200. #endregion
  201. }
  202. }