| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 | using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Linq;using System.Threading;using InABox.Clients;using InABox.Core;namespace InABox.Rpc{        public class RpcClient<TEntity> : BaseClient<TEntity> where TEntity : Entity, new()    {        private IRpcClientTransport _transport;        private ConcurrentDictionary<Guid, ManualResetEventSlim> _events = new ConcurrentDictionary<Guid, ManualResetEventSlim>();        private ConcurrentDictionary<Guid, RpcMessage> _responses = new ConcurrentDictionary<Guid, RpcMessage>();        private const int DefaultRequestTimeout = 5 * 60 * 1000; // 5 minutes                public RpcClient(IRpcClientTransport transport)        {            _transport = transport;            _transport.OnMessage += Transport_Message;        }        ~RpcClient()        {            _transport.OnMessage -= Transport_Message;                    }                #region TransportManagement        public override bool IsConnected() => _transport?.IsConnected() == true;                private void Transport_Message(IRpcTransport transport, RpcTransportMessageArgs e)        {            if (e.Message != null && e.Message.Command == "Push")            {                var push = Serialization.ReadBinary<RpcPush>(e.Message.Payload, BinarySerializationSettings.Latest);                ClientFactory.PushHandlers.Push(push.Type, push.Object);            }        }        #endregion        #region Client Interface        public override DatabaseInfo Info()        {            var result = _transport.Send<RpcInfoCommand, RpcInfoParameters, RpcInfoResult>(new RpcInfoParameters());            return result.Info;        }        private static string[]? _types;        public override IEnumerable<string> SupportedTypes()        {            _types ??= CoreUtils.Entities                .Where(x => x.GetInterfaces().Contains(typeof(IPersistent)))                .Select(x => x.EntityName().Replace(".", "_"))                .ToArray();            return _types;        }                #region Validate & 2FA        protected override IValidationData DoValidate(string userid, string password, Guid session = default)        {            var parameters = new RpcValidateParameters()            {                UserID = userid,                Password = password,                PIN = "",                UsePIN = false,                SessionID = session,                Platform = ClientFactory.Platform,                Version = ClientFactory.Version            };            return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);        }        protected override IValidationData DoValidate(string pin, Guid session = default)        {            var ticks = DateTime.Now.ToUniversalTime().Ticks.ToString();            var parameters = new RpcValidateParameters()            {                UserID = Encryption.Encrypt(ticks, "wCq9rryEJEuHIifYrxRjxg", true),                Password = Encryption.Encrypt(ticks, "7mhvLnqMwkCAzN+zNGlyyg", true),                PIN = pin,                UsePIN = true,                SessionID = session,                Platform = ClientFactory.Platform,                Version = ClientFactory.Version            };            return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);        }        protected override IValidationData DoValidate(Guid session = default)        {            var parameters = new RpcValidateParameters()            {                UserID = "",                Password = "",                PIN = "",                UsePIN = false,                SessionID = session,                Platform = ClientFactory.Platform,                Version = ClientFactory.Version            };            return _transport.Send<RpcValidateCommand, RpcValidateParameters, RpcValidateResult>(parameters);        }                protected override bool DoCheck2FA(string code, Guid? session)        {            var parameters = new RpcCheck2FAParameters()            {                Code = code,                SessionId = session ?? ClientFactory.SessionID,            };            var result = _transport.Send<RpcCheck2FACommand, RpcCheck2FAParameters, RpcCheck2FAResult>(parameters);            return result.Valid;        }                #endregion        protected override CoreTable DoQuery(Filter<TEntity>? filter, Columns<TEntity>? columns, SortOrder<TEntity>? sort = null, CoreRange? range = null)        {            var parameters = new RpcQueryParameters()            {                Queries = new RpcQueryDefinition[]                {                    new RpcQueryDefinition()                    {                        Key = typeof(TEntity).EntityName().Split('.').Last(),                        Type = typeof(TEntity),                        Filter = filter,                        Columns = columns,                        Sort = sort,                        Range = range                    }                }            };            var result = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);            return result.Tables[0].Table;        }        protected override TEntity[] DoLoad(Filter<TEntity>? filter = null, SortOrder<TEntity>? sort = null, CoreRange? range = null)        {            return DoQuery(filter, null, sort, range)?.ToArray<TEntity>() ?? new TEntity[] { };        }                        protected override Dictionary<string, CoreTable> DoQueryMultiple(Dictionary<string, IQueryDef> queries)        {            var result = new Dictionary<string, CoreTable>();                        var parameters = new RpcQueryParameters()            {                Queries = queries.Select(kvp =>                    new RpcQueryDefinition()                    {                        Key = kvp.Key,                        Type = kvp.Value.Type,                        Filter = kvp.Value.Filter,                        Columns = kvp.Value.Columns,                        Sort = kvp.Value.SortOrder,                        Range = kvp.Value.Range                    }                ).ToArray()            };            var response = _transport.Send<RpcQueryCommand, RpcQueryParameters, RpcQueryResult>(parameters);            foreach (var key in response.Tables)                result[key.Key] = key.Table;            return result;        }        protected override void DoSave(TEntity entity, string auditnote)        {            DoSave(new TEntity[] { entity }, auditnote);        }        protected override void DoSave(IEnumerable<TEntity> entities, string auditnote)        {            var items = entities.AsArray();            var parameters = new RpcSaveParameters()            {                Type = typeof(TEntity),                Items = items,                AuditNote = auditnote,                ExcludeCustomProperties = this.ExcludeCustomProperties            };            var result = _transport.Send<RpcSaveCommand, RpcSaveParameters, RpcSaveResult>(parameters);            for (int i = 0; i < result.Deltas.Length; i++)            {                items[i].SetObserving(false);                foreach (var (key, value) in result.Deltas[i])                {                    if (CoreUtils.TryGetProperty<TEntity>(key, out var property))                        CoreUtils.SetPropertyValue(items[i], key, CoreUtils.ChangeType(value, property.PropertyType));                }                items[i].CommitChanges();                items[i].SetObserving(true);            }        }        protected override void DoDelete(TEntity entity, string auditnote)        {            DoDelete(new TEntity[] { entity }, auditnote);        }        protected override void DoDelete(IEnumerable<TEntity> entities, string auditnote)        {            var parameters = new RpcDeleteParameters()            {                Type = typeof(TEntity),                IDs = entities.Select(x => x.ID).ToArray(),                AuditNote = auditnote            };            _transport.Send<RpcDeleteCommand, RpcDeleteParameters, RpcDeleteResult>(parameters);        }                protected override bool DoPing()        {            try            {                if (!_transport.IsConnected())                    _transport.Connect();                if (_transport.IsConnected())                {                    _transport.Send<RpcPingCommand, RpcPingParameters, RpcPingResult>(new RpcPingParameters());                    return true;                }                return false;            }            catch (Exception)            {                return false;            }                    }        public override string Version()        {            return _transport.Send<RpcVersionCommand, RpcVersionParameters, RpcVersionResult>(new RpcVersionParameters()).Version;        }        public override byte[]? Installer()        {            return _transport.Send<RpcInstallerCommand, RpcInstallerParameters, RpcInstallerResult>(new RpcInstallerParameters()).Installer;        }        public override string ReleaseNotes()        {            return _transport.Send<RpcReleaseNotesCommand, RpcReleaseNotesParameters, RpcReleaseNotesResult>(new RpcReleaseNotesParameters()).ReleaseNotes;        }        #endregion    }}
 |