From 61a1683c26314ad7de80d745f141d7c13e8d2817 Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Sun, 26 Jan 2020 14:30:39 +0300 Subject: [PATCH] 1.4 --- .../Esyur.Stores.MongoDB.csproj | 2 +- Esyur.Stores.MongoDB/MongoDBStore.cs | 268 +++++++----------- Esyur/Core/AsyncReply.cs | 7 +- Esyur/Core/ExceptionCode.cs | 2 + Esyur/Data/Codec.cs | 109 ++++--- Esyur/Data/DataConverter.cs | 65 +++-- Esyur/Data/IUserType.cs | 12 + Esyur/Data/Structure.cs | 26 +- Esyur/Esyur.csproj | 2 +- Esyur/Misc/Global.cs | 2 +- Esyur/Net/HTTP/HTTPConnection.cs | 3 +- Esyur/Net/HTTP/HTTPServer.cs | 19 +- Esyur/Net/IIP/DistributedConnection.cs | 25 +- .../Net/IIP/DistributedConnectionProtocol.cs | 45 ++- Esyur/Net/NetworkConnection.cs | 4 +- Esyur/Net/Sockets/ISocket.cs | 1 + Esyur/Net/Sockets/TCPSocket.cs | 113 ++++---- Esyur/Resource/IStore.cs | 2 +- Esyur/Resource/Instance.cs | 1 + Esyur/Resource/Warehouse.cs | 37 ++- Esyur/Stores/MemoryStore.cs | 2 +- Esyur/Stores/TemporaryStore.cs | 8 +- 22 files changed, 409 insertions(+), 346 deletions(-) create mode 100644 Esyur/Data/IUserType.cs diff --git a/Esyur.Stores.MongoDB/Esyur.Stores.MongoDB.csproj b/Esyur.Stores.MongoDB/Esyur.Stores.MongoDB.csproj index 58dc39b..29b678e 100644 --- a/Esyur.Stores.MongoDB/Esyur.Stores.MongoDB.csproj +++ b/Esyur.Stores.MongoDB/Esyur.Stores.MongoDB.csproj @@ -11,7 +11,7 @@ http://www.esyur.com https://github.com/esyur/esyur-dotnet/ True - 1.3.0 + 1.3.2 diff --git a/Esyur.Stores.MongoDB/MongoDBStore.cs b/Esyur.Stores.MongoDB/MongoDBStore.cs index 8aa940a..54d9a31 100644 --- a/Esyur.Stores.MongoDB/MongoDBStore.cs +++ b/Esyur.Stores.MongoDB/MongoDBStore.cs @@ -24,7 +24,6 @@ namespace Esyur.Stores.MongoDB IMongoDatabase database; IMongoCollection resourcesCollection; - Dictionary resources = new Dictionary(); @@ -52,6 +51,13 @@ namespace Esyur.Stores.MongoDB } + /* + public IResource[] Query(string json) + { + //var json = "{ SendId: 4, 'Events.Code' : { $all : [2], $nin : [3] } }"; + resourcesCollection.Find(new QueryDocument(BsonDocument.Parse(json))); + + }*/ public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime date) { @@ -98,29 +104,27 @@ namespace Esyur.Stores.MongoDB return true; } - - - AsyncReply Fetch(string id) where T : IResource + async AsyncReply Fetch(string id) where T : IResource { if (resources.ContainsKey(id) && resources[id].IsAlive) { if (resources[id].Target is T) - return new AsyncReply((T)resources[id].Target); + return (T)resources[id].Target;// new AsyncReply((T)resources[id].Target); else - return new AsyncReply(default(T)); ; + return default(T);// new AsyncReply(default(T)); ; } var filter = Builders.Filter.Eq("_id", new BsonObjectId(new ObjectId(id))); var list = resourcesCollection.Find(filter).ToList(); if (list.Count == 0) - return new AsyncReply(default(T)); + return default(T);// new AsyncReply(default(T)); var document = list[0]; var type = Type.GetType(document["classname"].AsString); if (type == null) - return new AsyncReply(default(T)); + return default(T);// new AsyncReply(default(T)); IResource resource = (IResource)Activator.CreateInstance(ResourceProxy.GetProxy(type)); @@ -142,32 +146,7 @@ namespace Esyur.Stores.MongoDB resource.Instance.SetAttributes(x as Structure); }); - var bag = new AsyncBag(); - - /* - foreach (var p in parents) - { - var ap = Warehouse.Get(p.AsString); - bag.Add(ap); - ap.Then((x) => - { - if (!resource.Instance.Parents.Contains(x)) - resource.Instance.Parents.Add(x); - }); - } - - foreach (var c in children) - { - - var ac = Warehouse.Get(c.AsString); - bag.Add(ac); - ac.Then((x) => - { - if (!resource.Instance.Children.Contains(x)) - resource.Instance.Children.Add(x); - }); - } - */ + // var bag = new AsyncBag(); resource.Instance.Attributes.Add("children", children.Select(x => x.AsString).ToArray()); resource.Instance.Attributes.Add("parents", parents.Select(x => x.AsString).ToArray()); @@ -199,34 +178,19 @@ namespace Esyur.Stores.MongoDB { var valueInfo = v.Value as BsonDocument; - var av = Parse(valueInfo["value"]); - av.Then((x) => - { - resource.Instance.LoadProperty(v.Name, - (ulong)valueInfo["age"].AsInt64, - valueInfo["modification"].ToUniversalTime(), - x); - }); + var x = await Parse(valueInfo["value"]); + resource.Instance.LoadProperty(v.Name, + (ulong)valueInfo["age"].AsInt64, + valueInfo["modification"].ToUniversalTime(), + x); - - bag.Add(av); + //bag.Add(av); } - var rt = new AsyncReply(); - - bag.Then((x) => - { - if (resource is T) - rt.Trigger(resource); - else - rt.Trigger(null); - }); - - bag.Seal(); - - - - return rt; + if (resource is T) + return (T)resource; + else + return default(T); } AsyncReply Parse(BsonValue value) @@ -314,133 +278,121 @@ namespace Esyur.Stores.MongoDB return this.Instance.Name + "/id/" + (string)resource.Instance.Attributes["objectId"]; } - public bool Put(IResource resource) + public async AsyncReply Put(IResource resource) { - if (resource == this) - return true; - - PutResource(resource).Wait(); - - ResourceAdded?.Invoke(resource); - - count++; - - Instance.Modified("Count"); - - return true; - } - - private async Task PutResource(IResource resource) - { - var attrs = resource.Instance.GetAttributes(); - - foreach (var kv in resources) - if (kv.Value.Target == resource) - { - resource.Instance.Attributes.Add("objectId", kv.Key); + try + { + if (resource == this) return true; - } - var type = ResourceProxy.GetBaseType(resource); - // insert the document - var document = new BsonDocument + var attrs = resource.Instance.GetAttributes(); + + foreach (var kv in resources) + if (kv.Value.Target == resource) + { + resource.Instance.Attributes.Add("objectId", kv.Key); + return true; + } + + count++; + + Instance.Modified("Count"); + + var type = ResourceProxy.GetBaseType(resource); + + // insert the document + var document = new BsonDocument { { "classname", type.FullName + "," + type.GetTypeInfo().Assembly.GetName().Name }, { "name", resource.Instance.Name }, }; - resourcesCollection.InsertOne(document); - resource.Instance.Attributes["objectId"] = document["_id"].ToString(); + resourcesCollection.InsertOne(document); + resource.Instance.Attributes["objectId"] = document["_id"].ToString(); - // now update the document - // * insert first to get the object id, update values, attributes, children and parents after in case the same resource has a property references self + // now update the document + // * insert first to get the object id, update values, attributes, children and parents after in case the same resource has a property references self - var parents = new BsonArray(); - var children = new BsonArray(); + var parents = new BsonArray(); + var children = new BsonArray(); - var template = resource.Instance.Template; + var template = resource.Instance.Template; - // setup attributes - resource.Instance.Attributes["children"] = new string[0]; - resource.Instance.Attributes["parents"] = new string[] { this.Instance.Link }; + // setup attributes + resource.Instance.Attributes["children"] = new string[0]; + resource.Instance.Attributes["parents"] = new string[] { this.Instance.Link }; - // copy old children (in case we are moving a resource from a store to another. - if (resource.Instance.Store != this) - { - var resourceChildren = await resource.Instance.Children(); - - if (resourceChildren != null) - foreach (IResource c in resourceChildren) - children.Add(c.Instance.Link); - - var resourceParents = await resource.Instance.Parents(); - - if (resourceParents == null) + // copy old children (in case we are moving a resource from a store to another. + if (resource.Instance.Store != this) { - parents.Add(this.Instance.Link); + var resourceChildren = await resource.Instance.Children(); + + if (resourceChildren != null) + foreach (IResource c in resourceChildren) + children.Add(c.Instance.Link); + + var resourceParents = await resource.Instance.Parents(); + + if (resourceParents == null) + { + parents.Add(this.Instance.Link); + } + else + { + foreach (IResource p in resourceParents) + parents.Add(p.Instance.Link); + } } else { - foreach (IResource p in resourceParents) - parents.Add(p.Instance.Link); + // just add self + parents.Add(this.Instance.Link); } - } - else - { - // just add self - parents.Add(this.Instance.Link); - } - var attrsDoc = ComposeStructure(attrs); + var attrsDoc = ComposeStructure(attrs); - var values = new BsonDocument(); + var values = new BsonDocument(); - foreach (var pt in template.Properties) - { - var rt = pt.Info.GetValue(resource, null); + foreach (var pt in template.Properties) + { + var rt = pt.Info.GetValue(resource, null); - values.Add(pt.Name, - new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) }, + values.Add(pt.Name, + new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) }, { "modification", resource.Instance.GetModificationDate(pt.Index) }, { "value", Compose(rt) } }); + } + + + var filter = Builders.Filter.Eq("_id", document["_id"]); + var update = Builders.Update + .Set("values", values).Set("parents", parents).Set("children", children).Set("attributes", attrsDoc); + resourcesCollection.UpdateOne(filter, update); + + + resources.Add(document["_id"].AsObjectId.ToString(), new WeakReference(resource)); + + //resource.Instance.Attributes["objectId"] = document["_id"].ToString(); + + ResourceAdded?.Invoke(resource); + + return true; + } - - - // var filter = Builders.Filter.Eq("_id", document["_id"]); - // var update = Builders.Update - // .Set("values", values); - // col.UpdateOne(filter, update); - - - /* - var document = new BsonDocument + catch(Exception ex) { - { "parents", parents }, - { "children", children }, - { "attributes", attrsDoc }, - { "classname", resource.GetType().FullName + "," + resource.GetType().GetTypeInfo().Assembly.GetName().Name }, - { "name", resource.Instance.Name }, - { "values", values } - }; - */ - - var filter = Builders.Filter.Eq("_id", document["_id"]); - var update = Builders.Update - .Set("values", values).Set("parents", parents).Set("children", children).Set("attributes", attrsDoc); - resourcesCollection.UpdateOne(filter, update); - - - //resource.Instance.Attributes["objectId"] = document["_id"].ToString(); - - - return true; + Console.WriteLine(ex); + return false; + } } + + public BsonDocument ComposeStructure(Structure value) { var rt = new BsonDocument { { "type", 1 } }; @@ -453,12 +405,12 @@ namespace Esyur.Stores.MongoDB return rt; } - public BsonArray ComposeVarArray(object[] array) + public BsonArray ComposeVarArray(Array array) { var rt = new BsonArray(); for (var i = 0; i < array.Length; i++) - rt.Add(Compose(array[i])); + rt.Add(Compose(array.GetValue(i)));// [i])); return rt; } @@ -491,9 +443,9 @@ namespace Esyur.Stores.MongoDB return rt; } - private BsonValue Compose(object value) + private BsonValue Compose(object valueObj) { - var type = Codec.GetDataType(value, null); + var (type, value) = Codec.GetDataType(valueObj, null); switch (type) { @@ -515,7 +467,7 @@ namespace Esyur.Stores.MongoDB return ComposeStructure((Structure)value); case DataType.VarArray: - return ComposeVarArray((object[])value); + return ComposeVarArray((Array)value); case DataType.ResourceArray: if (value is IResource[]) diff --git a/Esyur/Core/AsyncReply.cs b/Esyur/Core/AsyncReply.cs index 3a26d5f..c820788 100644 --- a/Esyur/Core/AsyncReply.cs +++ b/Esyur/Core/AsyncReply.cs @@ -227,9 +227,6 @@ namespace Esyur.Core { //timeout?.Dispose(); - if (resultReady) - return; - //lock (callbacksLock) //{ foreach (var cb in progressCallbacks) @@ -244,9 +241,7 @@ namespace Esyur.Core //timeout?.Dispose(); - if (resultReady) - return; - + //lock (callbacksLock) //{ foreach (var cb in chunkCallbacks) diff --git a/Esyur/Core/ExceptionCode.cs b/Esyur/Core/ExceptionCode.cs index 94bda40..61d28ae 100644 --- a/Esyur/Core/ExceptionCode.cs +++ b/Esyur/Core/ExceptionCode.cs @@ -8,6 +8,8 @@ namespace Esyur.Core { HostNotReachable, AccessDenied, + UserNotFound, + ChallengeFailed, ResourceNotFound, AttachDenied, InvalidMethod, diff --git a/Esyur/Data/Codec.cs b/Esyur/Data/Codec.cs index a838565..3ec1dd7 100644 --- a/Esyur/Data/Codec.cs +++ b/Esyur/Data/Codec.cs @@ -73,7 +73,9 @@ namespace Esyur.Data var types = new DataType[keys.Length]; for (var i = 0; i < keys.Length; i++) - types[i] = Codec.GetDataType(structure[keys[i]], connection); + { + types[i] = Codec.GetDataType(structure[keys[i]], connection).type; + } return types; } @@ -125,7 +127,7 @@ namespace Esyur.Data { if (structures == null || structures?.Length == 0) return prependLength ? new byte[] { 0, 0, 0, 0 } : new byte[0]; - + var rt = new BinaryList(); var comparsion = StructureComparisonResult.Structure; @@ -173,8 +175,8 @@ namespace Esyur.Data var result = (StructureComparisonResult)data[offset++]; AsyncReply previous = null; - // string[] previousKeys = null; - // DataType[] previousTypes = null; + // string[] previousKeys = null; + // DataType[] previousTypes = null; Structure.StructureMetadata metadata = new Structure.StructureMetadata(); @@ -188,7 +190,7 @@ namespace Esyur.Data previous = ParseStructure(data, offset, cs, connection, out metadata); offset += cs; } - + reply.Add(previous); @@ -382,7 +384,7 @@ namespace Esyur.Data /// Value public static AsyncReply Parse(byte[] data, uint offset, out uint size, DistributedConnection connection, DataType dataType = DataType.Unspecified) { - + bool isArray; DataType t; @@ -434,7 +436,7 @@ namespace Esyur.Data return new AsyncReply(data.GetCharArray(offset, contentLength)); case DataType.Int16: - return new AsyncReply(data.GetInt16Array( offset, contentLength)); + return new AsyncReply(data.GetInt16Array(offset, contentLength)); case DataType.UInt16: return new AsyncReply(data.GetUInt16Array(offset, contentLength)); @@ -595,7 +597,7 @@ namespace Esyur.Data if (resource is DistributedResource) if ((resource as DistributedResource).Connection == connection) return true; - + return false; } @@ -658,7 +660,7 @@ namespace Esyur.Data rt.AddUInt32((resources[0] as DistributedResource).Id); else if (comparsion == ResourceComparisonResult.Distributed) rt.AddUInt32(resources[0].Instance.Id); - + for (var i = 1; i < resources.Length; i++) { comparsion = Compare(resources[i - 1], resources[i], connection); @@ -756,12 +758,12 @@ namespace Esyur.Data /// DistributedConnection is required to check locality. /// If True, prepend the length as UInt32 at the beginning of the output. /// Array of bytes in the network byte order. - public static byte[] ComposeVarArray(object[] array, DistributedConnection connection, bool prependLength = false) + public static byte[] ComposeVarArray(Array array, DistributedConnection connection, bool prependLength = false) { var rt = new List(); for (var i = 0; i < array.Length; i++) - rt.AddRange(Compose(array[i], connection)); + rt.AddRange(Compose(array.GetValue(i), connection)); if (prependLength) rt.InsertRange(0, DC.ToBytes(rt.Count)); return rt.ToArray(); @@ -844,9 +846,9 @@ namespace Esyur.Data // age, date, value //if (includeAge) - // return BinaryList.ToBytes(propertyValue.Age, propertyValue.Date, Compose(propertyValue.Value, connection)); + // return BinaryList.ToBytes(propertyValue.Age, propertyValue.Date, Compose(propertyValue.Value, connection)); //else - // return BinaryList.ToBytes(propertyValue.Date, Compose(propertyValue.Value, connection)); + // return BinaryList.ToBytes(propertyValue.Date, Compose(propertyValue.Value, connection)); } @@ -858,14 +860,14 @@ namespace Esyur.Data /// Zero-indexed offset. /// DistributedConnection is required to fetch resources. /// Output content size. - /// PropertyValue. + /// PropertyValue. public static AsyncReply ParsePropertyValue(byte[] data, uint offset, out uint cs, DistributedConnection connection)//, bool ageIncluded = true) { var reply = new AsyncReply(); var age = data.GetUInt64(offset); offset += 8; - + DateTime date = data.GetDateTime(offset); offset += 8; @@ -928,14 +930,14 @@ namespace Esyur.Data bagOfBags.Then(x => { - for(var i = 0; i < list.Count; i++) + for (var i = 0; i < list.Count; i++) list[list.Keys.ElementAt(i)] = x[i]; reply.Trigger(list); }); return reply; - + } /// @@ -945,7 +947,7 @@ namespace Esyur.Data /// DistributedConnection is required to fetch resources. /// public static byte[] ComposeHistory(KeyList history, - DistributedConnection connection, bool prependLength = false) + DistributedConnection connection, bool prependLength = false) { var rt = new BinaryList(); @@ -954,7 +956,7 @@ namespace Esyur.Data .AddUInt8Array(ComposePropertyValueArray(history.Values.ElementAt(i), connection, true)); // rt.Append((byte)history.Keys.ElementAt(i).Index, - // ComposePropertyValueArray(history.Values.ElementAt(i), connection, true)); + // ComposePropertyValueArray(history.Values.ElementAt(i), connection, true)); if (prependLength) rt.InsertInt32(0, rt.Length); @@ -1001,15 +1003,10 @@ namespace Esyur.Data /// DistributedConnection is required to check locality. /// If True, prepend the DataType at the beginning of the output. /// Array of bytes in the network byte order. - public static byte[] Compose(object value, DistributedConnection connection, bool prependType = true) + public static byte[] Compose(object valueOrSource, DistributedConnection connection, bool prependType = true) { - if (value is Func) - value = (value as Func)(connection); - else if (value is DistributedPropertyContext) - value = (value as DistributedPropertyContext).Method(connection); - - var type = GetDataType(value, connection); + var (type, value) = GetDataType(valueOrSource, connection); var rt = new BinaryList(); switch (type) @@ -1038,7 +1035,7 @@ namespace Esyur.Data break; case DataType.VarArray: - rt.AddUInt8Array(ComposeVarArray((object[])value, connection, true)); + rt.AddUInt8Array(ComposeVarArray((Array)value, connection, true)); break; case DataType.ResourceArray: @@ -1115,22 +1112,22 @@ namespace Esyur.Data */ //{ - while (type != null) - { - if (type == iface) - return true; + while (type != null) + { + if (type == iface) + return true; #if NETSTANDARD - if (type.GetTypeInfo().GetInterfaces().Contains(iface)) - return true; + if (type.GetTypeInfo().GetInterfaces().Contains(iface)) + return true; - type = type.GetTypeInfo().BaseType; + type = type.GetTypeInfo().BaseType; #else if (type.GetInterfaces().Contains(iface)) return true; type = type.BaseType; #endif - } + } //} return false; @@ -1165,16 +1162,36 @@ namespace Esyur.Data /// Value to find its DataType. /// DistributedConnection is required to check locality of resources. /// DataType. - public static DataType GetDataType(object value, DistributedConnection connection) + public static (DataType type, object value) GetDataType(object value, DistributedConnection connection) { + if (value == null) - return DataType.Void; + return (DataType.Void, null); + + if (value is IUserType) + value = (value as IUserType).Get(); + + + if (value is Func) + //if (connection != null) + value = (value as Func)(connection); + //else + // return (DataType.Void, null); + else if (value is DistributedPropertyContext) + //if (connection != null) + value = (value as DistributedPropertyContext).Method(connection); + //else + // return (DataType.Void, null); + + if (value == null) + return (DataType.Void, null); + var t = value.GetType(); - + var isArray = t.IsArray; if (isArray) - t = t.GetElementType(); + t = t.GetElementType(); DataType type; @@ -1208,27 +1225,27 @@ namespace Esyur.Data type = DataType.String; else if (t == typeof(DateTime)) type = DataType.DateTime; - else if (t == typeof(Structure)) + else if (typeof(Structure).IsAssignableFrom(t)) type = DataType.Structure; //else if (t == typeof(DistributedResource)) - // type = DataType.DistributedResource; + // type = DataType.DistributedResource; else if (ImplementsInterface(t, typeof(IResource))) { if (isArray) - return DataType.ResourceArray; + return (DataType.ResourceArray, value); else { - return IsLocalResource((IResource)value, connection) ? DataType.Resource : DataType.DistributedResource; + return (IsLocalResource((IResource)value, connection) ? DataType.Resource : DataType.DistributedResource, value); } } else type = DataType.Void; - + if (isArray) - return (DataType)((byte)type | 0x80); + return ((DataType)((byte)type | 0x80), value); else - return type; + return (type, value); } diff --git a/Esyur/Data/DataConverter.cs b/Esyur/Data/DataConverter.cs index 6a4b23f..c1fe1d7 100644 --- a/Esyur/Data/DataConverter.cs +++ b/Esyur/Data/DataConverter.cs @@ -43,9 +43,13 @@ namespace Esyur.Data { public static object CastConvert(object value, Type destinationType) { + if (value == null) return null; + //if (destinationType.IsArray && destinationType.GetElementType().IsArray) + // Console.Beep(); + var sourceType = value.GetType(); if (destinationType == sourceType) @@ -54,10 +58,9 @@ namespace Esyur.Data } else { - if (sourceType.IsArray) + if (sourceType.IsArray && (destinationType.IsArray || destinationType == typeof(object))) { - if (destinationType.IsArray) - destinationType = destinationType.GetElementType(); + destinationType = destinationType.GetElementType(); var v = value as Array; @@ -65,29 +68,34 @@ namespace Esyur.Data for (var i = 0; i < rt.Length; i++) { - try - { -#if NETSTANDARD - if (destinationType.GetTypeInfo().IsInstanceOfType(v.GetValue(i))) -#else - if (destinationType.IsInstanceOfType(v.GetValue(i))) -#endif - rt.SetValue(v.GetValue(i), i); - else - rt.SetValue(Convert.ChangeType(v.GetValue(i), destinationType), i); - } - catch - { - rt.SetValue(null, i); - } + rt.SetValue(CastConvert(v.GetValue(i), destinationType), i); + + // try + // { + //#if NETSTANDARD + // if (destinationType.GetTypeInfo().IsInstanceOfType(v.GetValue(i))) + //#else + // if (destinationType.IsInstanceOfType(v.GetValue(i))) + //#endif + // rt.SetValue(v.GetValue(i), i); + // else + // rt.SetValue(Convert.ChangeType(v.GetValue(i), destinationType), i); + // } + // catch + // { + // rt.SetValue(null, i); + // } } return rt; + } else { try { + + var underType = Nullable.GetUnderlyingType(destinationType); if (underType != null) { @@ -96,15 +104,26 @@ namespace Esyur.Data else destinationType = underType; } - -#if NETSTANDARD - if (destinationType.GetTypeInfo().IsInstanceOfType(value)) -#else + + if (destinationType.IsInstanceOfType(value)) -#endif + { return value; + } + else if (typeof(IUserType).IsAssignableFrom(destinationType)) + { + var rt = Activator.CreateInstance(destinationType) as IUserType; + rt.Set(value); + return rt; + } + else if (sourceType == typeof(Structure) && sourceType.IsAssignableFrom(destinationType)) + { + return Structure.FromStructure((Structure)value, destinationType); + } else + { return Convert.ChangeType(value, destinationType); + } } catch { diff --git a/Esyur/Data/IUserType.cs b/Esyur/Data/IUserType.cs new file mode 100644 index 0000000..5c9cdf0 --- /dev/null +++ b/Esyur/Data/IUserType.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Esyur.Data +{ + public interface IUserType + { + object Get(); + void Set(object value); + } +} diff --git a/Esyur/Data/Structure.cs b/Esyur/Data/Structure.cs index 628547b..f75ac90 100644 --- a/Esyur/Data/Structure.cs +++ b/Esyur/Data/Structure.cs @@ -47,7 +47,7 @@ namespace Esyur.Data private Dictionary dic = new Dictionary(StringComparer.OrdinalIgnoreCase); private object syncRoot = new object(); - + public bool ContainsKey(string key) { return dic.ContainsKey(key); @@ -57,11 +57,33 @@ namespace Esyur.Data { var rt = ""; foreach (var kv in dic) - rt += kv.Key + ": " + kv.Value.ToString() + "\r\n"; + rt += kv.Key + ": " + kv.Value.ToString() + " \r\n"; return rt.TrimEnd('\r', '\n'); } + public Structure(Structure source) + { + dic = source.dic; + } + public Structure() + { + + } + + public static Structure FromStructure(Structure source, Type destinationType) + { + var rt = Activator.CreateInstance(destinationType) as Structure; + rt.dic = source.dic; + return rt; + } + + public static T FromStructure(Structure source) where T : Structure + { + var rt = Activator.CreateInstance(); + rt.dic = source.dic; + return rt; + } public static Structure FromObject(object obj) { diff --git a/Esyur/Esyur.csproj b/Esyur/Esyur.csproj index 6afb314..28f0b20 100644 --- a/Esyur/Esyur.csproj +++ b/Esyur/Esyur.csproj @@ -7,7 +7,7 @@ https://github.com/Esyur/Esyur-dotnet/blob/master/LICENSE http://www.esyur.com true - 1.4.5 + 1.4.7 https://github.com/esyur/esyur-dotnet Ahmed Kh. Zamil 1.3.1.0 diff --git a/Esyur/Misc/Global.cs b/Esyur/Misc/Global.cs index b3616d3..166a48e 100644 --- a/Esyur/Misc/Global.cs +++ b/Esyur/Misc/Global.cs @@ -410,7 +410,7 @@ namespace Esyur.Misc public static string GenerateCode(int length) { - return GenerateCode(length, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_-+=\\?/"); + return GenerateCode(length, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");// ~!@#$%^&*()_-+=\\?/"); } public static string GenerateCode(int length, string chars) diff --git a/Esyur/Net/HTTP/HTTPConnection.cs b/Esyur/Net/HTTP/HTTPConnection.cs index 51a3861..abde4d5 100644 --- a/Esyur/Net/HTTP/HTTPConnection.cs +++ b/Esyur/Net/HTTP/HTTPConnection.cs @@ -225,7 +225,6 @@ namespace Esyur.Net.HTTP } } - bool bb; public void SendFile(string filename) { @@ -299,7 +298,7 @@ namespace Esyur.Net.HTTP if (n <= 0) break; - + Thread.Sleep(50); base.Send(buffer, 0, n); } diff --git a/Esyur/Net/HTTP/HTTPServer.cs b/Esyur/Net/HTTP/HTTPServer.cs index 3984d0e..8872180 100644 --- a/Esyur/Net/HTTP/HTTPServer.cs +++ b/Esyur/Net/HTTP/HTTPServer.cs @@ -53,48 +53,48 @@ namespace Esyur.Net.HTTP } [Storable] - string ip + public virtual string ip { get; set; } [Storable] - ushort port + public virtual ushort port { get; set; } [Storable] - uint timeout + public virtual uint timeout { get; set; } [Storable] - uint clock + public virtual uint clock { get; set; } [Storable] - uint maxPost + public virtual uint maxPost { get; set; } [Storable] - bool ssl + public virtual bool ssl { get; set; } [Storable] - string certificate + public virtual string certificate { get; set; @@ -380,6 +380,11 @@ namespace Esyur.Net.HTTP sender.SetParent(this); //Console.WriteLine("IN: " + this.Connections.Count); + if (filters == null) + { + sender.Close(); + return; + } foreach (var resource in filters) { diff --git a/Esyur/Net/IIP/DistributedConnection.cs b/Esyur/Net/IIP/DistributedConnection.cs index 24cf069..c35ef28 100644 --- a/Esyur/Net/IIP/DistributedConnection.cs +++ b/Esyur/Net/IIP/DistributedConnection.cs @@ -610,8 +610,10 @@ namespace Esyur.Net.IIP else { //Console.WriteLine("User not found"); - //SendParams((byte)0xc0, (byte)1, (ushort)14, DC.ToBytes("User not found")); - SendParams().AddUInt8(0xc0).AddUInt8(1).AddUInt16(14).AddString("User not found").Done(); + SendParams().AddUInt8(0xc0) + .AddUInt8((byte)ExceptionCode.UserNotFound) + .AddUInt16(14) + .AddString("User not found").Done(); } }); @@ -649,9 +651,11 @@ namespace Esyur.Net.IIP else { //Global.Log("auth", LogType.Warning, "U:" + RemoteUsername + " IP:" + Socket.RemoteEndPoint.Address.ToString() + " S:DENIED"); - //Console.WriteLine("Incorrect password"); - //SendParams((byte)0xc0, (byte)1, (ushort)5, DC.ToBytes("Error")); - SendParams().AddUInt8(0xc0).AddUInt8(1).AddUInt16(5).AddString("Error").Done(); + SendParams().AddUInt8(0xc0) + .AddUInt8((byte)ExceptionCode.AccessDenied) + .AddUInt16(13) + .AddString("Access Denied") + .Done(); } } }); @@ -729,9 +733,9 @@ namespace Esyur.Net.IIP { SendParams() .AddUInt8(0xc0) - .AddUInt8(1) - .AddUInt16(5) - .AddString("Error") + .AddUInt8((byte)ExceptionCode.ChallengeFailed) + .AddUInt16(16) + .AddString("Challenge Failed") .Done(); //SendParams((byte)0xc0, 1, (ushort)5, DC.ToBytes("Error")); @@ -789,7 +793,6 @@ namespace Esyur.Net.IIP catch (Exception ex) { Console.WriteLine(ex); - Console.Beep(); } finally { @@ -830,7 +833,7 @@ namespace Esyur.Net.IIP var sock = new TCPSocket(); - sock.Connect(domain, port).Then((x)=> { + sock.Connect(address, port).Then((x)=> { Assign(sock); //rt.trigger(true); }).Error((x) => @@ -849,7 +852,7 @@ namespace Esyur.Net.IIP /// /// Resource. /// - public bool Put(IResource resource) + public async AsyncReply Put(IResource resource) { if (Codec.IsLocalResource(resource, this)) resources.Add((resource as DistributedResource).Id, (DistributedResource)resource); diff --git a/Esyur/Net/IIP/DistributedConnectionProtocol.cs b/Esyur/Net/IIP/DistributedConnectionProtocol.cs index a543178..a88e296 100644 --- a/Esyur/Net/IIP/DistributedConnectionProtocol.cs +++ b/Esyur/Net/IIP/DistributedConnectionProtocol.cs @@ -1097,6 +1097,10 @@ namespace Esyur.Net.IIP var ft = r.Instance.Template.GetFunctionTemplateByIndex(index); if (ft != null) { + + // un hold the socket to send data immediately + this.Socket.Unhold(); + if (r is DistributedResource) { var rt = (r as DistributedResource)._InvokeByArrayArguments(index, arguments); @@ -1163,7 +1167,8 @@ namespace Esyur.Net.IIP } catch (Exception ex) { - SendError(ErrorType.Exception, callback, 0, ex.InnerException.ToString()); + SendError(ErrorType.Exception, callback, 0, + ex.InnerException != null ? ex.InnerException.ToString() : ex.ToString()); return; } @@ -1171,12 +1176,18 @@ namespace Esyur.Net.IIP { var enu = rt as System.Collections.IEnumerable; - foreach (var v in enu) - SendChunk(callback, v); - - SendReply(IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments, callback) - .AddUInt8((byte)DataType.Void) - .Done(); + try + { + foreach (var v in enu) + SendChunk(callback, v); + SendReply(IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments, callback) + .AddUInt8((byte)DataType.Void) + .Done(); + } + catch(Exception ex) + { + SendError(ErrorType.Exception, callback, 0, ex.ToString()); + } } else if (rt is Task) @@ -1254,6 +1265,9 @@ namespace Esyur.Net.IIP var ft = r.Instance.Template.GetFunctionTemplateByIndex(index); if (ft != null) { + // un hold the socket to send data immediately + this.Socket.Unhold(); + if (r is DistributedResource) { var rt = (r as DistributedResource)._InvokeByNamedArguments(index, namedArgs); @@ -1323,12 +1337,19 @@ namespace Esyur.Net.IIP { var enu = rt as System.Collections.IEnumerable; - foreach (var v in enu) - SendChunk(callback, v); + try + { + foreach (var v in enu) + SendChunk(callback, v); - SendReply(IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments, callback) - .AddUInt8((byte)DataType.Void) - .Done(); + SendReply(IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments, callback) + .AddUInt8((byte)DataType.Void) + .Done(); + } + catch (Exception ex) + { + SendError(ErrorType.Exception, callback, 0, ex.ToString()); + } } else if (rt is Task) { diff --git a/Esyur/Net/NetworkConnection.cs b/Esyur/Net/NetworkConnection.cs index 248f0c6..df785a8 100644 --- a/Esyur/Net/NetworkConnection.cs +++ b/Esyur/Net/NetworkConnection.cs @@ -284,9 +284,9 @@ namespace Esyur.Net sock.Send(msg, offset, length); } } - catch + catch (Exception ex) { - + Console.WriteLine(ex); } } diff --git a/Esyur/Net/Sockets/ISocket.cs b/Esyur/Net/Sockets/ISocket.cs index 6b53865..827c4a7 100644 --- a/Esyur/Net/Sockets/ISocket.cs +++ b/Esyur/Net/Sockets/ISocket.cs @@ -50,6 +50,7 @@ namespace Esyur.Net.Sockets event ISocketConnectEvent OnConnect; event ISocketCloseEvent OnClose; + void Send(byte[] message); void Send(byte[] message, int offset, int size); void Close(); diff --git a/Esyur/Net/Sockets/TCPSocket.cs b/Esyur/Net/Sockets/TCPSocket.cs index 7bad65b..1b78db3 100644 --- a/Esyur/Net/Sockets/TCPSocket.cs +++ b/Esyur/Net/Sockets/TCPSocket.cs @@ -48,11 +48,11 @@ namespace Esyur.Net.Sockets NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); - object sendLock = new object(); + readonly object sendLock = new object(); Queue sendBufferQueue = new Queue(); - bool asyncSending; + bool asyncSending; bool began = false; @@ -176,7 +176,7 @@ namespace Esyur.Net.Sockets //lock (receiveNetworkBuffer.SyncLock) - // Console.WriteLine(e. + " " + e.BytesTransferred); + // Console.WriteLine(e. + " " + e.BytesTransferred); receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)e.BytesTransferred); @@ -238,39 +238,39 @@ namespace Esyur.Net.Sockets } - private void DataSent(Task task) - { - try - { - lock (sendLock) - { + //private void DataSent(Task task) + //{ + // try + // { + // lock (sendLock) + // { - if (sendBufferQueue.Count > 0) - { - byte[] data = sendBufferQueue.Dequeue(); - //Console.WriteLine(Encoding.UTF8.GetString(data)); - sock.SendAsync(new ArraySegment(data), SocketFlags.None).ContinueWith(DataSent); - } + // if (sendBufferQueue.Count > 0) + // { + // byte[] data = sendBufferQueue.Dequeue(); + // //Console.WriteLine(Encoding.UTF8.GetString(data)); + // sock.SendAsync(new ArraySegment(data), SocketFlags.None).ContinueWith(DataSent); + // } - else - { - asyncSending = false; - } - } - } - catch (Exception ex) - { - if (state != SocketState.Closed && !sock.Connected) - { - state = SocketState.Terminated; - Close(); - } + // else + // { + // asyncSending = false; + // } + // } + // } + // catch (Exception ex) + // { + // if (state != SocketState.Closed && !sock.Connected) + // { + // state = SocketState.Terminated; + // Close(); + // } - asyncSending = false; + // asyncSending = false; - Global.Log("TCPSocket", LogType.Error, ex.ToString()); - } - } + // Global.Log("TCPSocket", LogType.Error, ex.ToString()); + // } + //} public TCPSocket(IPEndPoint localEndPoint) { @@ -348,42 +348,44 @@ namespace Esyur.Net.Sockets public void Send(byte[] message, int offset, int size) { - //sock.Blocking = - //sock.Send(message, offset, size, SocketFlags.None); - //return; - if (sock.Connected) - lock (sendLock) - { - if (asyncSending || held) - { - sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size)); - } - else - { - asyncSending = true; - sock.BeginSend(message, offset, size, SocketFlags.None, PacketSent, null); - //sock.SendAsync(new ArraySegment(msg), SocketFlags.None).ContinueWith(DataSent); - } + var msg = message.Clip((uint)offset, (uint)size); + + lock (sendLock) + { + if (!sock.Connected) + return; + + if (asyncSending || held) + { + sendBufferQueue.Enqueue(msg); } + else + { + asyncSending = true; + sock.BeginSend(msg, 0, size, SocketFlags.None, PacketSent, null); + //sock.SendAsync(new ArraySegment(msg), SocketFlags.None).ContinueWith(DataSent); + } + } + } private void PacketSent(IAsyncResult ar) { try { - if (sendBufferQueue.Count > 0) + lock (sendLock) { - lock (sendLock) + if (sendBufferQueue.Count > 0) { byte[] data = sendBufferQueue.Dequeue(); sock.BeginSend(data, 0, data.Length, SocketFlags.None, PacketSent, null); } - } - else - { - asyncSending = false; + else + { + asyncSending = false; + } } } catch (Exception ex) @@ -447,12 +449,11 @@ namespace Esyur.Net.Sockets { try { - DataSent(null); + PacketSent(null); } catch (Exception ex) { Console.WriteLine(ex); - Console.Beep(); } finally { diff --git a/Esyur/Resource/IStore.cs b/Esyur/Resource/IStore.cs index 6af67f2..281720b 100644 --- a/Esyur/Resource/IStore.cs +++ b/Esyur/Resource/IStore.cs @@ -37,7 +37,7 @@ namespace Esyur.Resource { AsyncReply Get(string path);//, Func filter = null); //AsyncReply Retrieve(uint iid); - bool Put(IResource resource); + AsyncReply Put(IResource resource); string Link(IResource resource); bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime); bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime); diff --git a/Esyur/Resource/Instance.cs b/Esyur/Resource/Instance.cs index 08f3717..4d1a196 100644 --- a/Esyur/Resource/Instance.cs +++ b/Esyur/Resource/Instance.cs @@ -394,6 +394,7 @@ namespace Esyur.Resource if (resource.TryGetTarget(out res)) { var rt = pt.Serilize ? pt.Info.GetValue(res, null) : null; + props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index])); } //} diff --git a/Esyur/Resource/Warehouse.cs b/Esyur/Resource/Warehouse.cs index aa0e11e..75c0bf8 100644 --- a/Esyur/Resource/Warehouse.cs +++ b/Esyur/Resource/Warehouse.cs @@ -111,30 +111,38 @@ namespace Esyur.Resource /// True, if no problem occurred. public static async AsyncReply Open() { + warehouseIsOpen = true; - foreach (var rk in resources) + var resSnap = resources.Select(x => { + IResource r; + if (x.Value.TryGetTarget(out r)) + return r; + else + return null; + }).Where(r=>r!=null).ToArray(); + + foreach (var r in resSnap) { - IResource r; - if (rk.Value.TryGetTarget(out r)) - { + //IResource r; + //if (rk.Value.TryGetTarget(out r)) + //{ var rt = await r.Trigger(ResourceTrigger.Initialize); if (!rt) return false; - } + //} } - foreach (var rk in resources) + foreach (var r in resSnap) { - IResource r; - if (rk.Value.TryGetTarget(out r)) - { + //IResource r; + //if (rk.Value.TryGetTarget(out r)) + //{ var rt = await r.Trigger(ResourceTrigger.SystemInitialized); if (!rt) return false; - } + //} } - warehouseIsOpen = true; return true; @@ -422,6 +430,8 @@ namespace Esyur.Resource /// Parent resource. if not presented the store becomes the parent for the resource. public static void Put(IResource resource, string name, IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) { + if (resource.Instance != null) + throw new Exception("Resource has a store."); if (store == null) { @@ -467,6 +477,8 @@ namespace Esyur.Resource if (resource is IStore) StoreConnected?.Invoke(resource as IStore, name); //else + + store.Put(resource); @@ -481,7 +493,8 @@ namespace Esyur.Resource var t = resource.GetType(); Global.Counters["T-" + t.Namespace + "." + t.Name]++; - resources.Add(resource.Instance.Id, new WeakReference(resource)); + lock (resourcesLock) + resources.Add(resource.Instance.Id, new WeakReference(resource)); if (warehouseIsOpen) resource.Trigger(ResourceTrigger.Initialize); diff --git a/Esyur/Stores/MemoryStore.cs b/Esyur/Stores/MemoryStore.cs index a7287cc..25b847b 100644 --- a/Esyur/Stores/MemoryStore.cs +++ b/Esyur/Stores/MemoryStore.cs @@ -41,7 +41,7 @@ namespace Esyur.Stores return new AsyncReply(null); } - public bool Put(IResource resource) + public async AsyncReply Put(IResource resource) { resources.Add(resource.Instance.Id, resource);// new WeakReference(resource)); diff --git a/Esyur/Stores/TemporaryStore.cs b/Esyur/Stores/TemporaryStore.cs index 894db67..77d5a81 100644 --- a/Esyur/Stores/TemporaryStore.cs +++ b/Esyur/Stores/TemporaryStore.cs @@ -31,16 +31,16 @@ namespace Esyur.Stores return null; } - public AsyncReply Get(string path) + public async AsyncReply Get(string path) { foreach (var r in resources) if (r.Value.IsAlive && (r.Value.Target as IResource).Instance.Name == path) - return new AsyncReply(r.Value.Target as IResource); + return r.Value.Target as IResource; - return new AsyncReply(null); + return null; } - public bool Put(IResource resource) + public async AsyncReply Put(IResource resource) { resources.Add(resource.Instance.Id, new WeakReference( resource));// new WeakReference(resource)); return true;