RPCClient.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. #region Validate & 2FA
  43. protected override IValidationData DoValidate(string userid, string password, Guid session = default)
  44. {
  45. var parameters = new RpcValidateParameters()
  46. {
  47. UserID = userid,
  48. Password = password,
  49. PIN = "",
  50. UsePIN = false,
  51. SessionID = session,
  52. Platform = ClientFactory.Platform,
  53. Version = ClientFactory.Version
  54. };
  55. return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);
  56. }
  57. protected override IValidationData DoValidate(string pin, Guid session = default)
  58. {
  59. var ticks = DateTime.Now.ToUniversalTime().Ticks.ToString();
  60. var parameters = new RpcValidateParameters()
  61. {
  62. UserID = Encryption.Encrypt(ticks, "wCq9rryEJEuHIifYrxRjxg", true),
  63. Password = Encryption.Encrypt(ticks, "7mhvLnqMwkCAzN+zNGlyyg", true),
  64. PIN = pin,
  65. UsePIN = true,
  66. SessionID = session,
  67. Platform = ClientFactory.Platform,
  68. Version = ClientFactory.Version
  69. };
  70. return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);
  71. }
  72. protected override IValidationData DoValidate(Guid session = default)
  73. {
  74. var parameters = new RpcValidateParameters()
  75. {
  76. UserID = "",
  77. Password = "",
  78. PIN = "",
  79. UsePIN = false,
  80. SessionID = session,
  81. Platform = ClientFactory.Platform,
  82. Version = ClientFactory.Version
  83. };
  84. return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);
  85. }
  86. protected override bool DoCheck2FA(string code, Guid? session)
  87. {
  88. var parameters = new RpcCheck2FAParameters()
  89. {
  90. Code = code,
  91. SessionId = session ?? ClientFactory.SessionID,
  92. };
  93. var result = _transport.Send<RpcCheck2FACommand, RpcCheck2FAParameters, RpcCheck2FAResult>(parameters);
  94. return result.Valid;
  95. }
  96. #endregion
  97. protected override CoreTable DoQuery(Filter<TEntity>? filter, Columns<TEntity>? columns, SortOrder<TEntity>? sort = null)
  98. {
  99. var parameters = new RpcQueryParameters()
  100. {
  101. Queries = new RpcQueryDefinition[]
  102. {
  103. new RpcQueryDefinition()
  104. {
  105. Key = typeof(TEntity).EntityName().Split('.').Last(),
  106. Type = typeof(TEntity),
  107. Filter = filter,
  108. Columns = columns,
  109. Sort = sort
  110. }
  111. }
  112. };
  113. var result = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);
  114. return result.Tables[0].Table;
  115. }
  116. protected override TEntity[] DoLoad(Filter<TEntity>? filter = null, SortOrder<TEntity>? sort = null)
  117. {
  118. return DoQuery(filter, null, sort)?.ToObjects<TEntity>().ToArray() ?? new TEntity[] { };
  119. }
  120. protected override Dictionary<string, CoreTable> DoQueryMultiple(Dictionary<string, IQueryDef> queries)
  121. {
  122. var result = new Dictionary<string, CoreTable>();
  123. var parameters = new RpcQueryParameters()
  124. {
  125. Queries = queries.Select(kvp =>
  126. new RpcQueryDefinition()
  127. {
  128. Key = kvp.Key,
  129. Type = kvp.Value.Type,
  130. Filter = kvp.Value.Filter,
  131. Columns = kvp.Value.Columns,
  132. Sort = kvp.Value.SortOrder
  133. }
  134. ).ToArray()
  135. };
  136. var response = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);
  137. foreach (var key in response.Tables)
  138. result[key.Key] = key.Table;
  139. return result;
  140. }
  141. protected override void DoSave(TEntity entity, string auditnote)
  142. {
  143. DoSave(new TEntity[] { entity }, auditnote);
  144. }
  145. protected override void DoSave(IEnumerable<TEntity> entities, string auditnote)
  146. {
  147. var items = entities.AsArray();
  148. var parameters = new RpcSaveParameters()
  149. {
  150. Type = typeof(TEntity),
  151. Items = items,
  152. AuditNote = auditnote
  153. };
  154. var result = _transport.Send<RpcSaveCommand, RpcSaveParameters, RpcSaveResult>(parameters);
  155. for (int i = 0; i < result.Deltas.Length; i++)
  156. {
  157. items[i].SetObserving(false);
  158. foreach (var (key, value) in result.Deltas[i])
  159. {
  160. if (CoreUtils.TryGetProperty<TEntity>(key, out var property))
  161. CoreUtils.SetPropertyValue(items[i], key, CoreUtils.ChangeType(value, property.PropertyType));
  162. }
  163. items[i].CommitChanges();
  164. items[i].SetObserving(true);
  165. }
  166. }
  167. protected override void DoDelete(TEntity entity, string auditnote)
  168. {
  169. DoDelete(new TEntity[] { entity }, auditnote);
  170. }
  171. protected override void DoDelete(IEnumerable<TEntity> entities, string auditnote)
  172. {
  173. var parameters = new RpcDeleteParameters()
  174. {
  175. Type = typeof(TEntity),
  176. IDs = entities.Select(x => x.ID).ToArray(),
  177. AuditNote = auditnote
  178. };
  179. _transport.Send<RpcDeleteCommand, RpcDeleteParameters, RpcDeleteResult>(parameters);
  180. }
  181. protected override bool DoPing()
  182. {
  183. try
  184. {
  185. if (!_transport.IsConnected())
  186. _transport.Connect();
  187. _transport.Send<RpcPingCommand, RpcPingParameters, RpcPingResult>(new RpcPingParameters());
  188. return true;
  189. }
  190. catch (Exception)
  191. {
  192. return false;
  193. }
  194. }
  195. public override string Version()
  196. {
  197. return _transport.Send<RpcVersionCommand, RpcVersionParameters, RpcVersionResult>(new RpcVersionParameters()).Version;
  198. }
  199. public override byte[]? Installer()
  200. {
  201. return _transport.Send<RpcInstallerCommand, RpcInstallerParameters, RpcInstallerResult>(new RpcInstallerParameters()).Installer;
  202. }
  203. public override string ReleaseNotes()
  204. {
  205. return _transport.Send<RpcReleaseNotesCommand, RpcReleaseNotesParameters, RpcReleaseNotesResult>(new RpcReleaseNotesParameters()).ReleaseNotes;
  206. }
  207. #endregion
  208. }
  209. }