RPCClient.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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, CoreRange? range = 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. Range = range
  120. }
  121. }
  122. };
  123. var result = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);
  124. return result.Tables[0].Table;
  125. }
  126. protected override TEntity[] DoLoad(Filter<TEntity>? filter = null, SortOrder<TEntity>? sort = null, CoreRange? range = null)
  127. {
  128. return DoQuery(filter, null, sort, range)?.ToArray<TEntity>() ?? new TEntity[] { };
  129. }
  130. protected override Dictionary<string, CoreTable> DoQueryMultiple(Dictionary<string, IQueryDef> queries)
  131. {
  132. var result = new Dictionary<string, CoreTable>();
  133. var parameters = new RpcQueryParameters()
  134. {
  135. Queries = queries.Select(kvp =>
  136. new RpcQueryDefinition()
  137. {
  138. Key = kvp.Key,
  139. Type = kvp.Value.Type,
  140. Filter = kvp.Value.Filter,
  141. Columns = kvp.Value.Columns,
  142. Sort = kvp.Value.SortOrder,
  143. Range = kvp.Value.Range
  144. }
  145. ).ToArray()
  146. };
  147. var response = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);
  148. foreach (var key in response.Tables)
  149. result[key.Key] = key.Table;
  150. return result;
  151. }
  152. protected override void DoSave(TEntity entity, string auditnote)
  153. {
  154. DoSave(new TEntity[] { entity }, auditnote);
  155. }
  156. protected override void DoSave(IEnumerable<TEntity> entities, string auditnote)
  157. {
  158. var items = entities.AsArray();
  159. var parameters = new RpcSaveParameters()
  160. {
  161. Type = typeof(TEntity),
  162. Items = items,
  163. AuditNote = auditnote
  164. };
  165. var result = _transport.Send<RpcSaveCommand, RpcSaveParameters, RpcSaveResult>(parameters);
  166. for (int i = 0; i < result.Deltas.Length; i++)
  167. {
  168. items[i].SetObserving(false);
  169. foreach (var (key, value) in result.Deltas[i])
  170. {
  171. if (CoreUtils.TryGetProperty<TEntity>(key, out var property))
  172. CoreUtils.SetPropertyValue(items[i], key, CoreUtils.ChangeType(value, property.PropertyType));
  173. }
  174. items[i].CommitChanges();
  175. items[i].SetObserving(true);
  176. }
  177. }
  178. protected override void DoDelete(TEntity entity, string auditnote)
  179. {
  180. DoDelete(new TEntity[] { entity }, auditnote);
  181. }
  182. protected override void DoDelete(IEnumerable<TEntity> entities, string auditnote)
  183. {
  184. var parameters = new RpcDeleteParameters()
  185. {
  186. Type = typeof(TEntity),
  187. IDs = entities.Select(x => x.ID).ToArray(),
  188. AuditNote = auditnote
  189. };
  190. _transport.Send<RpcDeleteCommand, RpcDeleteParameters, RpcDeleteResult>(parameters);
  191. }
  192. protected override bool DoPing()
  193. {
  194. try
  195. {
  196. if (!_transport.IsConnected())
  197. _transport.Connect();
  198. if (_transport.IsConnected())
  199. {
  200. _transport.Send<RpcPingCommand, RpcPingParameters, RpcPingResult>(new RpcPingParameters());
  201. return true;
  202. }
  203. return false;
  204. }
  205. catch (Exception)
  206. {
  207. return false;
  208. }
  209. }
  210. public override string Version()
  211. {
  212. return _transport.Send<RpcVersionCommand, RpcVersionParameters, RpcVersionResult>(new RpcVersionParameters()).Version;
  213. }
  214. public override byte[]? Installer()
  215. {
  216. return _transport.Send<RpcInstallerCommand, RpcInstallerParameters, RpcInstallerResult>(new RpcInstallerParameters()).Installer;
  217. }
  218. public override string ReleaseNotes()
  219. {
  220. return _transport.Send<RpcReleaseNotesCommand, RpcReleaseNotesParameters, RpcReleaseNotesResult>(new RpcReleaseNotesParameters()).ReleaseNotes;
  221. }
  222. #endregion
  223. }
  224. }