2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-06-26 13:03:13 +00:00

Updated to support IIP v3.3

This commit is contained in:
2019-05-24 05:38:53 +03:00
parent d215e48761
commit 08e95bd4dc
106 changed files with 6643 additions and 1179 deletions

View File

@ -7,6 +7,10 @@ using MongoDB.Bson;
using Esiur.Data; using Esiur.Data;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using Esiur.Resource.Template;
using System.Linq;
using Esiur.Security.Permissions;
namespace Esiur.Stores.MongoDB namespace Esiur.Stores.MongoDB
{ {
@ -17,6 +21,7 @@ namespace Esiur.Stores.MongoDB
public event DestroyedEvent OnDestroy; public event DestroyedEvent OnDestroy;
MongoClient client; MongoClient client;
IMongoDatabase database; IMongoDatabase database;
IMongoCollection<BsonDocument> resourcesCollection;
Dictionary<string, IResource> resources = new Dictionary<string, IResource>(); Dictionary<string, IResource> resources = new Dictionary<string, IResource>();
@ -25,28 +30,70 @@ namespace Esiur.Stores.MongoDB
{ {
get { return resources.Count; } get { return resources.Count; }
} }
public void Destroy() public void Destroy()
{ {
} }
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime date)
{
var objectId = resource.Instance.Attributes["objectId"].ToString();
//var bsonObjectId = new BsonObjectId(new ObjectId(objectId));
var record = this.database.GetCollection<BsonDocument>("record_" + objectId);
record.InsertOne(new BsonDocument()
{
{"property", propertyName}, {"age", BsonValue.Create(age) }, {"date", date}, {"value", Compose(value) }
});
var col = this.database.GetCollection<BsonDocument>("resources");
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(objectId)));
var update = Builders<BsonDocument>.Update
.Set("values." + propertyName, new BsonDocument { { "age", BsonValue.Create(age) },
{ "modification", date },
{ "value", Compose(value) } });
col.UpdateOne(filter, update);
return true;
}
public MongoDBStore() public MongoDBStore()
{ {
client = new MongoClient(); client = new MongoClient();
this.database = client.GetDatabase("esiur"); this.database = client.GetDatabase("esiur");
this.resourcesCollection = this.database.GetCollection<BsonDocument>("resources");
} }
public MongoDBStore(string connectionString, string database) public MongoDBStore(string connectionString, string database)
{ {
client = new MongoClient(connectionString); client = new MongoClient(connectionString);
this.database = client.GetDatabase(database); this.database = client.GetDatabase(database);
this.resourcesCollection = this.database.GetCollection<BsonDocument>("resources");
} }
public bool Remove(IResource resource)
{
var objectId = resource.Instance.Attributes["objectId"].ToString();
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(objectId)));
this.database.DropCollection("record_" + objectId);
resourcesCollection.DeleteOne(filter);
return true;
}
AsyncReply<IResource> Fetch(string id) AsyncReply<IResource> Fetch(string id)
{ {
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(id))); var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(id)));
var list = this.database.GetCollection<BsonDocument>("resources").Find(filter).ToList(); var list = resourcesCollection.Find(filter).ToList();
if (list.Count == 0) if (list.Count == 0)
return new AsyncReply<IResource>(null); return new AsyncReply<IResource>(null);
var document = list[0]; var document = list[0];
@ -60,6 +107,11 @@ namespace Esiur.Stores.MongoDB
var parents = document["parents"].AsBsonArray; var parents = document["parents"].AsBsonArray;
var children = document["children"].AsBsonArray; var children = document["children"].AsBsonArray;
//var managers = document["managers"].AsBsonArray;
var attributes = Parse(document["attributes"]).Then(x=> {
resource.Instance.SetAttributes(x as Structure);
});
var bag = new AsyncBag<object>(); var bag = new AsyncBag<object>();
@ -69,7 +121,8 @@ namespace Esiur.Stores.MongoDB
bag.Add(ap); bag.Add(ap);
ap.Then((x) => ap.Then((x) =>
{ {
resource.Instance.Parents.Add(x); if (!resource.Instance.Parents.Contains(x))
resource.Instance.Parents.Add(x);
}); });
} }
@ -80,28 +133,41 @@ namespace Esiur.Stores.MongoDB
bag.Add(ac); bag.Add(ac);
ac.Then((x) => ac.Then((x) =>
{ {
resource.Instance.Children.Add(x); if (!resource.Instance.Children.Contains(x))
resource.Instance.Children.Add(x);
}); });
} }
/*
// load managers
foreach(var m in managers)
{
IPermissionsManager pm = (IPermissionsManager)Activator.CreateInstance(Type.GetType(m["classname"].AsString));
var sr = Parse(m["settings"]);
bag.Add(sr);
sr.Then((x) =>
{
pm.Initialize((Structure)x, resource);
resource.Instance.Managers.Add(pm);
});
}
*/
// Load values // Load values
var values = document["values"].AsBsonDocument; var values = document["values"].AsBsonDocument;
foreach (var v in values) foreach (var v in values)
{ {
#if NETSTANDARD1_5
var pi = resource.GetType().GetTypeInfo().GetProperty(v.Name);
#else
var pi = resource.GetType().GetProperty(pt.Name);
#endif
var av = Parse(v.Value); var valueInfo = v.Value as BsonDocument;
var av = Parse(valueInfo["value"]);
bag.Add(av); bag.Add(av);
av.Then((x) => av.Then((x) =>
{ {
if (pi.CanWrite) resource.Instance.LoadProperty(v.Name, (ulong)valueInfo["age"].AsInt64, valueInfo["modification"].ToUniversalTime(), x);
pi.SetValue(resource, DC.CastConvert(x, pi.PropertyType));
}); });
} }
@ -163,8 +229,13 @@ namespace Esiur.Stores.MongoDB
return bag; return bag;
} }
else if (value.BsonType == BsonType.DateTime)
{
return new AsyncReply(value.ToUniversalTime());
}
else else
{ {
return new AsyncReply(value.RawValue); return new AsyncReply(value.RawValue);
} }
} }
@ -194,6 +265,8 @@ namespace Esiur.Stores.MongoDB
public bool Put(IResource resource) public bool Put(IResource resource)
{ {
var attrs = resource.Instance.GetAttributes();
foreach (var kv in resources) foreach (var kv in resources)
if (kv.Value == resource) if (kv.Value == resource)
{ {
@ -203,6 +276,7 @@ namespace Esiur.Stores.MongoDB
var parents = new BsonArray(); var parents = new BsonArray();
var children = new BsonArray(); var children = new BsonArray();
var template = resource.Instance.Template; var template = resource.Instance.Template;
foreach (IResource c in resource.Instance.Children) foreach (IResource c in resource.Instance.Children)
@ -210,22 +284,13 @@ namespace Esiur.Stores.MongoDB
foreach (IResource p in resource.Instance.Parents) foreach (IResource p in resource.Instance.Parents)
parents.Add(p.Instance.Link); parents.Add(p.Instance.Link);
var document = new BsonDocument var attrsDoc = ComposeStructure(attrs);
{
{ "parents", parents },
{ "children", children },
{ "classname", resource.GetType().AssemblyQualifiedName },
{ "name", resource.Instance.Name }
};
var col = this.database.GetCollection<BsonDocument>("resources");
col.InsertOne(document);
resource.Instance.Attributes["objectId"] = document["_id"].ToString();
var values = new BsonDocument(); var values = new BsonDocument();
foreach (var pt in template.Properties) foreach (var pt in template.Properties)
@ -236,19 +301,34 @@ namespace Esiur.Stores.MongoDB
var pi = resource.GetType().GetProperty(pt.Name); var pi = resource.GetType().GetProperty(pt.Name);
#endif #endif
var rt = pi.GetValue(resource, null); var rt = pi.GetValue(resource, null);
values.Add(pt.Name, Compose(rt)); 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<BsonDocument>.Filter.Eq("_id", document["_id"]); // var filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]);
var update = Builders<BsonDocument>.Update // var update = Builders<BsonDocument>.Update
.Set("values", values); // .Set("values", values);
// col.UpdateOne(filter, update);
col.UpdateOne(filter, update);
//document.Add("values", values); var document = new BsonDocument
{
{ "parents", parents },
{ "children", children },
{ "attributes", attrsDoc },
{ "classname", resource.GetType().FullName + "," + resource.GetType().GetTypeInfo().Assembly.GetName().Name },
{ "name", resource.Instance.Name },
{ "values", values }
};
resourcesCollection.InsertOne(document);
resource.Instance.Attributes["objectId"] = document["_id"].ToString();
//col.ReplaceOne(document, document);
return true; return true;
} }
@ -356,17 +436,19 @@ namespace Esiur.Stores.MongoDB
{ {
var filter = new BsonDocument(); var filter = new BsonDocument();
var list = this.database.GetCollection<BsonDocument>("resources").Find(filter).ToList(); var list = resourcesCollection.Find(filter).ToList();
Console.WriteLine(list.Count);
// if (list.Count == 0) // if (list.Count == 0)
// return new AsyncBag<IResource>(new IResource[0]); // return new AsyncBag<IResource>(new IResource[0]);
var bag = new AsyncBag<IResource>(); var bag = new AsyncBag<IResource>();
foreach (var r in list) for(var i = 0; i < list.Count; i++)
{ {
bag.Add(Get("id/" + r["_id"].AsObjectId.ToString())); Console.WriteLine("Loading {0}/{1}", i, list.Count);
bag.Add(Get("id/" + list[i]["_id"].AsObjectId.ToString()));
} }
bag.Seal(); bag.Seal();
@ -392,6 +474,8 @@ namespace Esiur.Stores.MongoDB
public void SaveResource(IResource resource) public void SaveResource(IResource resource)
{ {
var attrs = resource.Instance.GetAttributes();
var parents = new BsonArray(); var parents = new BsonArray();
var children = new BsonArray(); var children = new BsonArray();
var template = resource.Instance.Template; var template = resource.Instance.Template;
@ -401,6 +485,7 @@ namespace Esiur.Stores.MongoDB
foreach (IResource p in resource.Instance.Parents) foreach (IResource p in resource.Instance.Parents)
parents.Add(p.Instance.Link); parents.Add(p.Instance.Link);
var values = new BsonDocument(); var values = new BsonDocument();
@ -413,27 +498,181 @@ namespace Esiur.Stores.MongoDB
#endif #endif
var rt = pi.GetValue(resource, null); var rt = pi.GetValue(resource, null);
values.Add(pt.Name, Compose(rt)); values.Add(pt.Name,
new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) },
{ "modification", resource.Instance.GetModificationDate(pt.Index) },
{ "value", Compose(rt) } });
} }
var attrsDoc = ComposeStructure(attrs);
var document = new BsonDocument var document = new BsonDocument
{ {
{ "parents", parents }, { "parents", parents },
{ "children", children }, { "children", children },
{ "classname", resource.GetType().AssemblyQualifiedName }, {"attributes", attrsDoc },
{ "classname", resource.GetType().FullName + "," + resource.GetType().GetTypeInfo().Assembly.GetName().Name },
{ "name", resource.Instance.Name }, { "name", resource.Instance.Name },
{ "_id", new BsonObjectId(new ObjectId(resource.Instance.Attributes["objectId"].ToString())) }, { "_id", new BsonObjectId(new ObjectId(resource.Instance.Attributes["objectId"].ToString())) },
{"values", values } {"values", values }
}; };
var col = this.database.GetCollection<BsonDocument>("resources");
var filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]); var filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]);
/*
var update = Builders<BsonDocument>.Update var update = Builders<BsonDocument>.Update
.Set("values", values); .Set("values", values);
col.UpdateOne(filter, update); var update = Builders<BsonDocument>.Update.Set("values", values).Set("parents", parents;
col.UpdateOne(filter, update);
*/
resourcesCollection.ReplaceOne(filter, document);
}
public AsyncReply<PropertyValue[]> GetPropertyRecordByAge(IResource resource, string propertyName, ulong fromAge, ulong toAge)
{
var objectId = resource.Instance.Attributes["objectId"].ToString();
var record = this.database.GetCollection<BsonDocument>("record_" + objectId);
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Gte("age", fromAge) & builder.Lte("age", toAge) & builder.Eq("property", propertyName);
var reply = new AsyncReply<PropertyValue[]>();
record.FindAsync(filter).ContinueWith((x) =>
{
var values = ((Task<IAsyncCursor<BsonDocument>>)x).Result.ToList();
var bag = new AsyncBag<object>();
foreach(var v in values)
bag.Add(Parse(v["value"]));
bag.Seal();
bag.Then((results) =>
{
var list = new List<PropertyValue>();
for(var i = 0; i < results.Length; i++)
list.Add(new PropertyValue(results[i], (ulong)values[i]["age"].AsInt64, values[i]["date"].ToUniversalTime()));
reply.Trigger(list.ToArray());
});
});
return reply;
}
public AsyncReply<PropertyValue[]> GetPropertyRecordByDate(IResource resource, string propertyName, DateTime fromDate, DateTime toDate)
{
var objectId = resource.Instance.Attributes["objectId"].ToString();
var record = this.database.GetCollection<BsonDocument>("record_" + objectId);
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Gte("date", fromDate) & builder.Lte("date", toDate) & builder.Eq("property", propertyName);
var reply = new AsyncReply<PropertyValue[]>();
record.FindAsync(filter).ContinueWith((x) =>
{
var values = ((Task<IAsyncCursor<BsonDocument>>)x).Result.ToList();
var bag = new AsyncBag<object>();
foreach (var v in values)
bag.Add(Parse(v["value"]));
bag.Seal();
bag.Then((results) =>
{
var list = new List<PropertyValue>();
for (var i = 0; i < results.Length; i++)
list.Add(new PropertyValue(results[i], (ulong)values[i]["age"].AsInt64, values[i]["date"].ToUniversalTime()));
reply.Trigger(list.ToArray());
});
});
return reply;
}
AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecordByAge(IResource resource, ulong fromAge, ulong toAge)
{
var properties = resource.Instance.Template.Properties.Where(x => x.Storage == StorageMode.Recordable).ToList();
var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();
AsyncBag<PropertyValue> bag = new AsyncBag<PropertyValue>();
foreach (var p in properties)
bag.Add(GetPropertyRecordByAge(resource, p.Name, fromAge, toAge));
bag.Seal();
bag.Then(x =>
{
var list = new KeyList<PropertyTemplate, PropertyValue>();
for (var i = 0; i < x.Length; i++)
list.Add(properties[i], x[i]);
reply.Trigger(list);
});
return reply;
}
public AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, DateTime fromDate, DateTime toDate)
{
var properties = resource.Instance.Template.Properties.Where(x => x.Storage == StorageMode.Recordable).ToList();
var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();
AsyncBag<PropertyValue[]> bag = new AsyncBag<PropertyValue[]>();
foreach (var p in properties)
bag.Add(GetPropertyRecordByDate(resource, p.Name, fromDate, toDate));
bag.Seal();
bag.Then(x =>
{
var list = new KeyList<PropertyTemplate, PropertyValue[]>();
for (var i = 0; i < x.Length; i++)
list.Add(properties[i], x[i]);
reply.Trigger(list);
});
return reply;
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
{
var objectId = resource.Instance.Attributes["objectId"].ToString();
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(objectId)));
var update = Builders<BsonDocument>.Update
.Set("values." + propertyName, new BsonDocument { { "age", BsonValue.Create(age) },
{ "modification", dateTime },
{ "value", Compose(value) } });
resourcesCollection.UpdateOne(filter, update);
return true;
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,7 +32,7 @@ using System.Reflection;
namespace Esiur.Data namespace Esiur.Data
{ {
public class AutoList<T, ST> : IEnumerable public class AutoList<T, ST> : IEnumerable<T>
{ {
private readonly object syncRoot = new object(); private readonly object syncRoot = new object();
@ -45,6 +69,10 @@ namespace Esiur.Data
list.Sort(comparer); list.Sort(comparer);
} }
public void Sort(Comparison<T> comparison)
{
list.Sort(comparison);
}
public IEnumerable<T> Where(Func<T, bool> predicate) public IEnumerable<T> Where(Func<T, bool> predicate)
{ {
@ -80,9 +108,9 @@ namespace Esiur.Data
/// </summary> /// </summary>
/// <param name="values">Populate the list with items</param> /// <param name="values">Populate the list with items</param>
/// <returns></returns> /// <returns></returns>
public AutoList(T[] values) public AutoList(ST state, T[] values)
{ {
this.state = state;
#if NETSTANDARD1_5 #if NETSTANDARD1_5
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())); removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
#else #else
@ -167,12 +195,7 @@ namespace Esiur.Data
{ {
Remove((T)sender); Remove((T)sender);
} }
public IEnumerator GetEnumerator()
{
return list.GetEnumerator();
}
/// <summary> /// <summary>
/// Clear the list /// Clear the list
/// </summary> /// </summary>
@ -249,5 +272,15 @@ namespace Esiur.Data
return true; return true;
return false; return false;
} }
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)list).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<T>)list).GetEnumerator();
}
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using Esiur.Misc; using Esiur.Misc;
@ -9,6 +33,7 @@ using Esiur.Net.IIP;
using Esiur.Resource; using Esiur.Resource;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Esiur.Resource.Template;
namespace Esiur.Data namespace Esiur.Data
{ {
@ -98,13 +123,13 @@ namespace Esiur.Data
public static byte[] ComposeStructureArray(Structure[] structures, DistributedConnection connection, bool prependLength = false) public static byte[] ComposeStructureArray(Structure[] structures, DistributedConnection connection, bool prependLength = false)
{ {
if (structures == null || structures?.Length == 0) if (structures == null || structures?.Length == 0)
return new byte[0]; return prependLength ? new byte[] { 0, 0, 0, 0 } : new byte[0];
var rt = new BinaryList(); var rt = new BinaryList();
var comparsion = StructureComparisonResult.Structure; var comparsion = StructureComparisonResult.Structure;
rt.Append((byte)comparsion); rt.Append((byte)comparsion);
rt.Append(ComposeStructure(structures[0], connection)); rt.Append(ComposeStructure(structures[0], connection, true, true, true));
for (var i = 1; i < structures.Length; i++) for (var i = 1; i < structures.Length; i++)
{ {
@ -112,11 +137,11 @@ namespace Esiur.Data
rt.Append((byte)comparsion); rt.Append((byte)comparsion);
if (comparsion == StructureComparisonResult.Structure) if (comparsion == StructureComparisonResult.Structure)
rt.Append(ComposeStructure(structures[i], connection)); rt.Append(ComposeStructure(structures[i], connection, true, true, true));
else if (comparsion == StructureComparisonResult.StructureSameKeys) else if (comparsion == StructureComparisonResult.StructureSameKeys)
rt.Append(ComposeStructure(structures[i], connection, false)); rt.Append(ComposeStructure(structures[i], connection, false, true, true));
else if (comparsion == StructureComparisonResult.StructureSameTypes) else if (comparsion == StructureComparisonResult.StructureSameTypes)
rt.Append(ComposeStructure(structures[i], connection, false, false)); rt.Append(ComposeStructure(structures[i], connection, false, false, true));
} }
if (prependLength) if (prependLength)
@ -147,18 +172,19 @@ namespace Esiur.Data
var result = (StructureComparisonResult)data[offset++]; var result = (StructureComparisonResult)data[offset++];
AsyncReply previous = null; AsyncReply previous = null;
string[] previousKeys = null; // string[] previousKeys = null;
DataType[] previousTypes = null; // DataType[] previousTypes = null;
Structure.StructureMetadata metadata = new Structure.StructureMetadata();
if (result == StructureComparisonResult.Null) if (result == StructureComparisonResult.Null)
previous = new AsyncReply<Structure>(null); previous = new AsyncReply<Structure>(null);
else if (result == StructureComparisonResult.Structure) else if (result == StructureComparisonResult.Structure)
{ {
uint cs = data.GetUInt32(offset); uint cs = data.GetUInt32(offset);
cs += 4; offset += 4;
previous = ParseStructure(data, offset, cs, connection, out previousKeys, out previousTypes); previous = ParseStructure(data, offset, cs, connection, out metadata);
offset += cs; offset += cs;
} }
@ -174,22 +200,22 @@ namespace Esiur.Data
else if (result == StructureComparisonResult.Structure) else if (result == StructureComparisonResult.Structure)
{ {
uint cs = data.GetUInt32(offset); uint cs = data.GetUInt32(offset);
cs += 4; offset += 4;
previous = ParseStructure(data, offset, cs, connection, out previousKeys, out previousTypes); previous = ParseStructure(data, offset, cs, connection, out metadata);// out previousKeys, out previousTypes);
offset += cs; offset += cs;
} }
else if (result == StructureComparisonResult.StructureSameKeys) else if (result == StructureComparisonResult.StructureSameKeys)
{ {
uint cs = data.GetUInt32(offset); uint cs = data.GetUInt32(offset);
cs += 4; offset += 4;
previous = ParseStructure(data, offset, cs, connection, out previousKeys, out previousTypes, previousKeys); previous = ParseStructure(data, offset, cs, connection, out metadata, metadata.Keys);
offset += cs; offset += cs;
} }
else if (result == StructureComparisonResult.StructureSameTypes) else if (result == StructureComparisonResult.StructureSameTypes)
{ {
uint cs = data.GetUInt32(offset); uint cs = data.GetUInt32(offset);
cs += 4; offset += 4;
previous = ParseStructure(data, offset, cs, connection, out previousKeys, out previousTypes, previousKeys, previousTypes); previous = ParseStructure(data, offset, cs, connection, out metadata, metadata.Keys, metadata.Types);
offset += cs; offset += cs;
} }
@ -243,9 +269,8 @@ namespace Esiur.Data
/// <returns>Value</returns> /// <returns>Value</returns>
public static AsyncReply<Structure> ParseStructure(byte[] data, uint offset, uint contentLength, DistributedConnection connection) public static AsyncReply<Structure> ParseStructure(byte[] data, uint offset, uint contentLength, DistributedConnection connection)
{ {
string[] pk; Structure.StructureMetadata metadata;
DataType[] pt; return ParseStructure(data, offset, contentLength, connection, out metadata);
return ParseStructure(data, offset, contentLength, connection, out pk, out pt);
} }
/// <summary> /// <summary>
@ -260,7 +285,7 @@ namespace Esiur.Data
/// <param name="keys">Array of keys, in case the data doesn't include keys</param> /// <param name="keys">Array of keys, in case the data doesn't include keys</param>
/// <param name="types">Array of DataTypes, in case the data doesn't include DataTypes</param> /// <param name="types">Array of DataTypes, in case the data doesn't include DataTypes</param>
/// <returns>Structure</returns> /// <returns>Structure</returns>
public static AsyncReply<Structure> ParseStructure(byte[] data, uint offset, uint length, DistributedConnection connection, out string[] parsedKeys, out DataType[] parsedTypes, string[] keys = null, DataType[] types = null) public static AsyncReply<Structure> ParseStructure(byte[] data, uint offset, uint length, DistributedConnection connection, out Structure.StructureMetadata metadata, string[] keys = null, DataType[] types = null)// out string[] parsedKeys, out DataType[] parsedTypes, string[] keys = null, DataType[] types = null)
{ {
var reply = new AsyncReply<Structure>(); var reply = new AsyncReply<Structure>();
var bag = new AsyncBag<object>(); var bag = new AsyncBag<object>();
@ -293,8 +318,8 @@ namespace Esiur.Data
uint rt; uint rt;
bag.Add(Codec.Parse(data, offset, out rt, connection)); bag.Add(Codec.Parse(data, offset, out rt, connection));
length -= rt + 1; length -= rt;
offset += rt + 1; offset += rt;
} }
} }
else else
@ -324,8 +349,8 @@ namespace Esiur.Data
reply.Trigger(s); reply.Trigger(s);
}); });
parsedKeys = keylist.ToArray(); metadata = new Structure.StructureMetadata() { Keys = keylist.ToArray(), Types = typelist.ToArray() };
parsedTypes = typelist.ToArray();
return reply; return reply;
} }
@ -544,7 +569,6 @@ namespace Esiur.Data
{ {
Null, Null,
Distributed, Distributed,
DistributedSameClass,
Local, Local,
Same Same
} }
@ -585,21 +609,12 @@ namespace Esiur.Data
{ {
if (next == null) if (next == null)
return ResourceComparisonResult.Null; return ResourceComparisonResult.Null;
else if (next == initial)
if (next == initial)
return ResourceComparisonResult.Same; return ResourceComparisonResult.Same;
else if (IsLocalResource(next, connection))
if (IsLocalResource(next, connection))
return ResourceComparisonResult.Local; return ResourceComparisonResult.Local;
else
if (initial == null)
return ResourceComparisonResult.Distributed; return ResourceComparisonResult.Distributed;
if (initial.Instance.Template.ClassId == next.Instance.Template.ClassId)
return ResourceComparisonResult.DistributedSameClass;
return ResourceComparisonResult.Distributed;
} }
/// <summary> /// <summary>
@ -629,7 +644,7 @@ namespace Esiur.Data
public static byte[] ComposeResourceArray(IResource[] resources, DistributedConnection connection, bool prependLength = false) public static byte[] ComposeResourceArray(IResource[] resources, DistributedConnection connection, bool prependLength = false)
{ {
if (resources == null || resources?.Length == 0) if (resources == null || resources?.Length == 0)
return new byte[0]; return prependLength ? new byte[] { 0, 0, 0, 0 } : new byte[0];
var rt = new BinaryList(); var rt = new BinaryList();
var comparsion = Compare(null, resources[0], connection); var comparsion = Compare(null, resources[0], connection);
@ -639,26 +654,16 @@ namespace Esiur.Data
if (comparsion == ResourceComparisonResult.Local) if (comparsion == ResourceComparisonResult.Local)
rt.Append((resources[0] as DistributedResource).Id); rt.Append((resources[0] as DistributedResource).Id);
else if (comparsion == ResourceComparisonResult.Distributed) else if (comparsion == ResourceComparisonResult.Distributed)
{
rt.Append(resources[0].Instance.Template.ClassId);
rt.Append(resources[0].Instance.Id); rt.Append(resources[0].Instance.Id);
}
for (var i = 1; i < resources.Length; i++) for (var i = 1; i < resources.Length; i++)
{ {
comparsion = Compare(resources[i - 1], resources[i], connection); comparsion = Compare(resources[i - 1], resources[i], connection);
rt.Append((byte)comparsion); rt.Append((byte)comparsion);
if (comparsion == ResourceComparisonResult.Local) if (comparsion == ResourceComparisonResult.Local)
rt.Append((resources[0] as DistributedResource).Id); rt.Append((resources[i] as DistributedResource).Id);
else if (comparsion == ResourceComparisonResult.Distributed) else if (comparsion == ResourceComparisonResult.Distributed)
{ rt.Append(resources[i].Instance.Id);
rt.Append(resources[0].Instance.Template.ClassId);
rt.Append(resources[0].Instance.Id);
}
else if (comparsion == ResourceComparisonResult.DistributedSameClass)
{
rt.Append(resources[0].Instance.Id);
}
} }
if (prependLength) if (prependLength)
@ -690,7 +695,6 @@ namespace Esiur.Data
var result = (ResourceComparisonResult)data[offset++]; var result = (ResourceComparisonResult)data[offset++];
AsyncReply previous = null; AsyncReply previous = null;
Guid previousGuid = Guid.Empty;
if (result == ResourceComparisonResult.Null) if (result == ResourceComparisonResult.Null)
previous = new AsyncReply<IResource>(null); previous = new AsyncReply<IResource>(null);
@ -701,9 +705,7 @@ namespace Esiur.Data
} }
else if (result == ResourceComparisonResult.Distributed) else if (result == ResourceComparisonResult.Distributed)
{ {
previousGuid = data.GetGuid(offset); previous = connection.Fetch(data.GetUInt32(offset));
offset += 16;
//previous = connection.Fetch(previousGuid, data.GetUInt32(offset));
offset += 4; offset += 4;
} }
@ -714,32 +716,30 @@ namespace Esiur.Data
{ {
result = (ResourceComparisonResult)data[offset++]; result = (ResourceComparisonResult)data[offset++];
AsyncReply current = null;
if (result == ResourceComparisonResult.Null) if (result == ResourceComparisonResult.Null)
previous = new AsyncReply<IResource>(null); {
//else if (result == ResourceComparisonResult.Same) current = new AsyncReply<IResource>(null);
// reply.Add(previous); }
else if (result == ResourceComparisonResult.Same)
{
current = previous;
}
else if (result == ResourceComparisonResult.Local) else if (result == ResourceComparisonResult.Local)
{ {
// overwrite previous current = Warehouse.Get(data.GetUInt32(offset));
previous = Warehouse.Get(data.GetUInt32(offset));
offset += 4; offset += 4;
} }
else if (result == ResourceComparisonResult.Distributed) else if (result == ResourceComparisonResult.Distributed)
{ {
// overwrite previous current = connection.Fetch(data.GetUInt32(offset));
previousGuid = data.GetGuid(offset);
offset += 16;
//previous = connection.Fetch(previousGuid, data.GetUInt32(offset));
offset += 4;
}
else if (result == ResourceComparisonResult.DistributedSameClass)
{
// overwrite previous
//previous = connection.Fetch(previousGuid, data.GetUInt32(offset));
offset += 4; offset += 4;
} }
reply.Add(previous); reply.Add(current);
previous = current;
} }
reply.Seal(); reply.Seal();
@ -763,7 +763,12 @@ namespace Esiur.Data
rt.InsertRange(0, DC.ToBytes(rt.Count)); rt.InsertRange(0, DC.ToBytes(rt.Count));
return rt.ToArray(); return rt.ToArray();
} }
/// <summary>
/// Parse an array of variables.
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <returns>Array of variables.</returns>
public static AsyncBag<object> ParseVarArray(byte[] data, DistributedConnection connection) public static AsyncBag<object> ParseVarArray(byte[] data, DistributedConnection connection)
{ {
return ParseVarArray(data, 0, (uint)data.Length, connection); return ParseVarArray(data, 0, (uint)data.Length, connection);
@ -801,6 +806,180 @@ namespace Esiur.Data
return rt; return rt;
} }
/// <summary>
/// Compose an array of property values.
/// </summary>
/// <param name="array">PropertyValue array.</param>
/// <param name="connection">DistributedConnection is required to check locality.</param>
/// <param name="prependLength">If True, prepend the length as UInt32 at the beginning of the output.</param>
/// <returns>Array of bytes in the network byte order.</returns>
/// //, bool includeAge = true
public static byte[] ComposePropertyValueArray(PropertyValue[] array, DistributedConnection connection, bool prependLength = false)
{
var rt = new List<byte>();
for (var i = 0; i < array.Length; i++)
rt.AddRange(ComposePropertyValue(array[i], connection));
if (prependLength)
rt.InsertRange(0, DC.ToBytes(rt.Count));
return rt.ToArray();
}
/// <summary>
/// Compose a property value.
/// </summary>
/// <param name="propertyValue">Property value</param>
/// <param name="connection">DistributedConnection is required to check locality.</param>
/// <returns>Array of bytes in the network byte order.</returns>
public static byte[] ComposePropertyValue(PropertyValue propertyValue, DistributedConnection connection)//, bool includeAge = true)
{
// age, date, value
//if (includeAge)
return BinaryList.ToBytes(propertyValue.Age, propertyValue.Date, Compose(propertyValue.Value, connection));
//else
// return BinaryList.ToBytes(propertyValue.Date, Compose(propertyValue.Value, connection));
}
/// <summary>
/// Parse property value.
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="offset">Zero-indexed offset.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <param name="cs">Output content size.</param>
/// <returns>PropertyValue.</returns>
public static AsyncReply<PropertyValue> ParsePropertyValue(byte[] data, uint offset, out uint cs, DistributedConnection connection)//, bool ageIncluded = true)
{
var reply = new AsyncReply<PropertyValue>();
var age = data.GetUInt64(offset);
offset += 8;
DateTime date = data.GetDateTime(offset);
offset += 8;
uint valueSize;
Parse(data, offset, out valueSize, connection).Then(value =>
{
reply.Trigger(new PropertyValue(value, age, date));
});
cs = 16 + valueSize;
return reply;
}
/// <summary>
/// Parse an array of PropertyValue.
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <returns>Array of variables.</returns>
public static AsyncBag<PropertyValue> ParsePropertyValueArray(byte[] data, DistributedConnection connection)
{
return ParsePropertyValueArray(data, 0, (uint)data.Length, connection);
}
/// <summary>
/// Parse resource history
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="offset">Zero-indexed offset.</param>
/// <param name="length">Number of bytes to parse.</param>
/// <param name="resource">Resource</param>
/// <param name="fromAge">Starting age.</param>
/// <param name="toAge">Ending age.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <returns></returns>
public static AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> ParseHistory(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection)
{
//var count = (int)toAge - (int)fromAge;
var list = new KeyList<PropertyTemplate, PropertyValue[]>();
var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();
var bagOfBags = new AsyncBag<PropertyValue[]>();
var ends = offset + length;
while (offset < ends)
{
var index = data[offset++];
var pt = resource.Instance.Template.GetPropertyTemplate(index);
list.Add(pt, null);
var cs = DC.GetUInt32(data, offset);
offset += 4;
bagOfBags.Add(ParsePropertyValueArray(data, offset, cs, connection));
offset += cs;
}
bagOfBags.Seal();
bagOfBags.Then(x =>
{
for(var i = 0; i < list.Count; i++)
list[list.Keys.ElementAt(i)] = x[i];
reply.Trigger(list);
});
return reply;
}
/// <summary>
/// Compose resource history
/// </summary>
/// <param name="history">History</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <returns></returns>
public static byte[] ComposeHistory(KeyList<PropertyTemplate, PropertyValue[]> history, DistributedConnection connection, bool prependLength = false)
{
var rt = new BinaryList();
for (var i = 0; i < history.Count; i++)
rt.Append((byte)history.Keys.ElementAt(i).Index,
ComposePropertyValueArray(history.Values.ElementAt(i), connection, true));
if (prependLength)
rt.Insert(0, (uint)rt.Length);
return rt.ToArray();
}
/// <summary>
/// Parse an array of PropertyValue.
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="offset">Zero-indexed offset.</param>
/// <param name="length">Number of bytes to parse.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <param name="ageIncluded">Whether property age is represented in the data.</param>
/// <returns></returns>
public static AsyncBag<PropertyValue> ParsePropertyValueArray(byte[] data, uint offset, uint length, DistributedConnection connection)//, bool ageIncluded = true)
{
var rt = new AsyncBag<PropertyValue>();
while (length > 0)
{
uint cs;
rt.Add(ParsePropertyValue(data, offset, out cs, connection));//, ageIncluded));
if (cs > 0)
{
offset += (uint)cs;
length -= (uint)cs;
}
else
throw new Exception("Error while parsing ValueInfo structured data");
}
rt.Seal();
return rt;
}
/// <summary> /// <summary>
/// Compose a variable /// Compose a variable
/// </summary> /// </summary>
@ -810,6 +989,11 @@ namespace Esiur.Data
/// <returns>Array of bytes in the network byte order.</returns> /// <returns>Array of bytes in the network byte order.</returns>
public static byte[] Compose(object value, DistributedConnection connection, bool prependType = true) public static byte[] Compose(object value, DistributedConnection connection, bool prependType = true)
{ {
if (value is Func<DistributedConnection, object>)
value = (value as Func<DistributedConnection, object>)(connection);
else if (value is DistributedPropertyContext)
value = (value as DistributedPropertyContext).Method(connection);
var type = GetDataType(value, connection); var type = GetDataType(value, connection);
var rt = new BinaryList(); var rt = new BinaryList();
@ -873,11 +1057,15 @@ namespace Esiur.Data
/// <param name="type">Sub-class type.</param> /// <param name="type">Sub-class type.</param>
/// <param name="iface">Super-interface type.</param> /// <param name="iface">Super-interface type.</param>
/// <returns>True, if <paramref name="type"/> implements <paramref name="iface"/>.</returns> /// <returns>True, if <paramref name="type"/> implements <paramref name="iface"/>.</returns>
private static bool ImplementsInterface(Type type, Type iface) public static bool ImplementsInterface(Type type, Type iface)
{ {
while (type != null) while (type != null)
{ {
if (type == iface)
return true;
#if NETSTANDARD1_5 #if NETSTANDARD1_5
if (type.GetTypeInfo().GetInterfaces().Contains(iface)) if (type.GetTypeInfo().GetInterfaces().Contains(iface))
return true; return true;
@ -977,7 +1165,7 @@ namespace Esiur.Data
} }
} }
else else
return DataType.Void; type = DataType.Void;
if (isArray) if (isArray)

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -225,14 +249,14 @@ namespace Esiur.Data
UInt64 rt = 0; UInt64 rt = 0;
byte* p = (byte*)&rt; byte* p = (byte*)&rt;
*(p + 7) = data[0]; *(p + 7) = data[offset++];
*(p + 6) = data[1]; *(p + 6) = data[offset++];
*(p + 5) = data[2]; *(p + 5) = data[offset++];
*(p + 4) = data[3]; *(p + 4) = data[offset++];
*(p + 3) = data[4]; *(p + 3) = data[offset++];
*(p + 2) = data[5]; *(p + 2) = data[offset++];
*(p + 1) = data[6]; *(p + 1) = data[offset++];
*(p) = data[7]; *(p) = data[offset++];
return rt; return rt;
@ -252,14 +276,14 @@ namespace Esiur.Data
Int64 rt = 0; Int64 rt = 0;
byte* p = (byte*)&rt; byte* p = (byte*)&rt;
*(p + 7) = data[0]; *(p + 7) = data[offset++];
*(p + 6) = data[1]; *(p + 6) = data[offset++];
*(p + 5) = data[2]; *(p + 5) = data[offset++];
*(p + 4) = data[3]; *(p + 4) = data[offset++];
*(p + 3) = data[4]; *(p + 3) = data[offset++];
*(p + 2) = data[5]; *(p + 2) = data[offset++];
*(p + 1) = data[6]; *(p + 1) = data[offset++];
*(p) = data[7]; *(p) = data[offset++];
return rt; return rt;
@ -311,14 +335,14 @@ namespace Esiur.Data
double rt = 0; double rt = 0;
byte* p = (byte*)&rt; byte* p = (byte*)&rt;
*(p + 7) = data[0]; *(p + 7) = data[offset++];
*(p + 6) = data[1]; *(p + 6) = data[offset++];
*(p + 5) = data[2]; *(p + 5) = data[offset++];
*(p + 4) = data[3]; *(p + 4) = data[offset++];
*(p + 3) = data[4]; *(p + 3) = data[offset++];
*(p + 2) = data[5]; *(p + 2) = data[offset++];
*(p + 1) = data[6]; *(p + 1) = data[offset++];
*(p) = data[7]; *(p) = data[offset++];
return rt; return rt;
} }
@ -792,33 +816,48 @@ namespace Esiur.Data
return rt.ToArray(); return rt.ToArray();
} }
public static byte[] ToBytes(int value) public static unsafe byte[] ToBytes(int value)
{ {
byte[] ret = BitConverter.GetBytes(value); var rt = new byte[4];
byte* p = (byte*)&value;
Array.Reverse(ret); rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p + 0);
return ret; return rt;
} }
public static byte[] ToBytes(short value) public static unsafe byte[] ToBytes(short value)
{ {
byte[] ret = BitConverter.GetBytes(value); var rt = new byte[2];
byte* p = (byte*)&value;
Array.Reverse(ret); rt[0] = *(p + 1);
rt[1] = *(p + 0);
return ret; return rt;
} }
public static byte[] ToBytes(float value) public static unsafe byte[] ToBytes(float value)
{ {
byte[] ret = BitConverter.GetBytes(value); var rt = new byte[4];
Array.Reverse(ret); //float rt = 0;
byte* p = (byte*)&value;
rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p);
return ret; return rt;
} }
/* /*
public static byte[] ToBytes(Structure[] values) public static byte[] ToBytes(Structure[] values)
{ {
@ -888,58 +927,108 @@ namespace Esiur.Data
return Encoding.UTF8.GetBytes(value); return Encoding.UTF8.GetBytes(value);
} }
public static byte[] ToBytes(double value) public unsafe static byte[] ToBytes(double value)
{ {
byte[] ret = BitConverter.GetBytes(value); var rt = new byte[8];
Array.Reverse(ret); byte* p = (byte*)&value;
return ret; rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
return rt;
} }
public static byte[] ToBytes(long value) public static unsafe byte[] ToBytes(long value)
{ {
byte[] ret = BitConverter.GetBytes(value); var rt = new byte[8];
Array.Reverse(ret); byte* p = (byte*)&value;
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
return rt;
return ret;
} }
public static byte[] ToBytes(DateTime value) public static unsafe byte[] ToBytes(DateTime value)
{ {
byte[] ret = BitConverter.GetBytes(value.ToUniversalTime().Ticks);
Array.Reverse(ret); var rt = new byte[8];
return ret; var v = value.ToUniversalTime().Ticks;
byte* p = (byte*)&v;
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
return rt;
} }
public static byte[] ToBytes(ulong value) public static unsafe byte[] ToBytes(ulong value)
{ {
byte[] ret = BitConverter.GetBytes(value); var rt = new byte[8];
Array.Reverse(ret); byte* p = (byte*)&value;
return ret; rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
return rt;
} }
public static byte[] ToBytes(uint value) public static unsafe byte[] ToBytes(uint value)
{ {
byte[] ret = BitConverter.GetBytes(value); var rt = new byte[4];
Array.Reverse(ret); byte* p = (byte*)&value;
return ret; rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p + 0);
return rt;
} }
public static byte[] ToBytes(ushort value) public static unsafe byte[] ToBytes(ushort value)
{ {
byte[] ret = BitConverter.GetBytes(value); var rt = new byte[2];
Array.Reverse(ret); byte* p = (byte*)&value;
return ret; rt[0] = *(p + 1);
rt[1] = *(p);
return rt;
} }
public static byte[] ToBytes(decimal value) public static byte[] ToBytes(decimal value)

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.IO; using System.IO;
using System.Collections; using System.Collections;
using System.Security.Cryptography; using System.Security.Cryptography;
@ -17,10 +41,10 @@ namespace Esiur.Data
private readonly object syncRoot = new object(); private readonly object syncRoot = new object();
private Dictionary<KT, T> dic; private Dictionary<KT, T> dic;
public delegate void Modified(KT key, T oldValue, T newValue); public delegate void Modified(KT key, T oldValue, T newValue, KeyList<KT, T> sender);
public delegate void Added(T value); public delegate void Added(T value, KeyList<KT, T> sender);
public delegate void Removed(KT key, T value); public delegate void Removed(KT key, T value, KeyList<KT, T> sender);
public delegate void Cleared(); public delegate void Cleared(KeyList<KT, T> sender);
public event Modified OnModified; public event Modified OnModified;
public event Removed OnRemoved; public event Removed OnRemoved;
@ -77,14 +101,14 @@ namespace Esiur.Data
((IDestructible)oldValue).OnDestroy -= ItemDestroyed; ((IDestructible)oldValue).OnDestroy -= ItemDestroyed;
dic[key] = value; dic[key] = value;
if (OnModified != null) if (OnModified != null)
OnModified(key, oldValue, value); OnModified(key, oldValue, value, this);
} }
else else
{ {
dic.Add(key, value); dic.Add(key, value);
if (OnAdd != null) if (OnAdd != null)
OnAdd(value); OnAdd(value, this);
} }
} }
} }
@ -136,7 +160,7 @@ namespace Esiur.Data
dic.Clear(); dic.Clear();
if (OnCleared != null) if (OnCleared != null)
OnCleared(); OnCleared(this);
} }
public Dictionary<KT, T>.KeyCollection Keys public Dictionary<KT, T>.KeyCollection Keys
@ -167,7 +191,13 @@ namespace Esiur.Data
dic.Remove(key); dic.Remove(key);
if (OnRemoved != null) if (OnRemoved != null)
OnRemoved(key, value); OnRemoved(key, value, this);
}
public object Owner
{
get;
set;
} }
public int Count public int Count
@ -187,13 +217,16 @@ namespace Esiur.Data
return dic.ContainsValue(Value); return dic.ContainsValue(Value);
} }
public KeyList()
public KeyList(object owner = null)
{ {
#if NETSTANDARD1_5 #if NETSTANDARD1_5
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())); removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
#else #else
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T))); removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
#endif #endif
this.Owner = owner;
if (typeof(KT) == typeof(string)) if (typeof(KT) == typeof(string))
dic = (Dictionary<KT, T>)(object)new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase); dic = (Dictionary<KT, T>)(object)new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Data
{
public class PropertyValue
{
/// <summary>
/// Get or set the value.
/// </summary>
public object Value { get; set; }
/// <summary>
/// Get or set date of modification or occurrence.
/// </summary>
public DateTime Date { get; set; }
/// <summary>
/// Get or set property age.
/// </summary>
public ulong Age { get; set; }
/// <summary>
/// Create an instance of PropertyValue.
/// </summary>
/// <param name="value">Value.</param>
/// <param name="age">Age.</param>
/// <param name="date">Date.</param>
public PropertyValue(object value, ulong age, DateTime date)
{
Value = value;
Age = age;
Date = date;
}
}
}

View File

@ -1,10 +1,35 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.IO; using System.IO;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Reflection; using System.Reflection;
using System.Linq;
namespace Esiur.Data namespace Esiur.Data
{ {
@ -64,15 +89,16 @@ namespace Esiur.Data
{ {
var key = Key.ToLower(); var key = Key.ToLower();
if (OnModified != null) var toRemove = m_Variables.Where(x => x.Key.ToLower() == key);
OnModified(Key, value);
foreach (var item in toRemove)
m_Variables.Remove(item);
foreach (var kv in m_Variables)
if (kv.Key.ToLower() == key)
m_Variables.Remove(kv);
m_Variables.Add(new KeyValuePair<string, string>(Key, value)); m_Variables.Add(new KeyValuePair<string, string>(Key, value));
OnModified?.Invoke(Key, value);
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -13,6 +37,12 @@ namespace Esiur.Data
public class Structure : IEnumerable<KeyValuePair<string, object>> public class Structure : IEnumerable<KeyValuePair<string, object>>
{ {
public struct StructureMetadata
{
public string[] Keys;
public DataType[] Types;
}
private Dictionary<string, object> dic = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); private Dictionary<string, object> dic = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
private object syncRoot = new object(); private object syncRoot = new object();
@ -56,11 +86,11 @@ namespace Esiur.Data
get { return syncRoot; } get { return syncRoot; }
} }
public string[] GetKeys() public string[] GetKeys() => dic.Keys.ToArray();//GetKeys()
{ //{
return dic.Keys.ToArray(); // return dic.Keys.ToArray();
} //}
public object this[string index] public object this[string index]
{ {
get get

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,36 +32,54 @@ namespace Esiur.Engine
{ {
public class AsyncBag<T>:AsyncReply public class AsyncBag<T>:AsyncReply
{ {
Dictionary<AsyncReply, T> results = new Dictionary<AsyncReply, T>(); //Dictionary<AsyncReply, T> results = new Dictionary<AsyncReply, T>();
List<AsyncReply> replies = new List<AsyncReply>();
List<T> results = new List<T>();
int count = 0; int count = 0;
bool sealedBag = false; bool sealedBag = false;
public void Then(Action<T[]> callback) public AsyncBag<T> Then(Action<T[]> callback)
{ {
base.Then(new Action<object>(o => callback((T[])o))); base.Then(new Action<object>(o => callback((T[])o)));
return this;
} }
public void Seal() public void Seal()
{ {
if (sealedBag)
return;
sealedBag = true; sealedBag = true;
if (results.Count == 0) if (results.Count == 0)
Trigger(new T[0]); Trigger(new T[0]);
for(var i = 0; i < results.Count; i++) for (var i = 0; i < results.Count; i++)
//foreach(var reply in results.Keys) //foreach(var reply in results.Keys)
results.Keys.ElementAt(i).Then((r) => { {
results[results.Keys.ElementAt(i)] = (T)r; var k = replies[i];// results.Keys.ElementAt(i);
var index = i;
k.Then((r) =>
{
results[index] = (T)r;
count++; count++;
if (count == results.Count) if (count == results.Count)
Trigger(results.Values.ToArray()); Trigger(results.ToArray());
}); });
}
} }
public void Add(AsyncReply reply) public void Add(AsyncReply reply)
{ {
if (!sealedBag) if (!sealedBag)
results.Add(reply, default(T)); {
results.Add(default(T));
replies.Add(reply);
}
//results.Add(reply, default(T));
} }
public AsyncBag() public AsyncBag()

View File

@ -0,0 +1,85 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Engine
{
public enum ExceptionCode : ushort
{
HostNotReachable,
AccessDenied,
ResourceNotFound,
AttachDenied,
InvalidMethod,
InvokeDenied,
CreateDenied,
AddParentDenied,
AddChildDenied,
ViewAttributeDenied,
UpdateAttributeDenied,
StoreNotFound,
ParentNotFound,
ChildNotFound,
ResourceIsNotStore,
DeleteDenied,
DeleteFailed,
UpdateAttributeFailed,
GetAttributesFailed,
ClearAttributesFailed,
TemplateNotFound,
RenameDenied,
ClassNotFound,
MethodNotFound,
PropertyNotFound,
SetPropertyDenied,
ReadOnlyProperty
}
public class AsyncException: Exception
{
AsyncReply.ErrorType type;
ExceptionCode code;
public AsyncReply.ErrorType Type => type;
public ExceptionCode Code => code;
public AsyncException(AsyncReply.ErrorType type, ushort code, string message)
: base(type == AsyncReply.ErrorType.Management ? ((ExceptionCode)code).ToString() : message)
{
this.type = type;
this.code = (ExceptionCode)code;
}
public override string ToString()
{
return code.ToString() + ": " + Message;
}
}
}

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -12,9 +36,11 @@ namespace Esiur.Engine
//Action<T> callback; //Action<T> callback;
object queueLock = new object(); object queueLock = new object();
public void Then(Action<T> callback) public AsyncQueue<T> Then(Action<T> callback)
{ {
base.Then(new Action<object>(o => callback((T)o))); base.Then(new Action<object>(o => callback((T)o)));
return this;
} }
public void Add(AsyncReply<T> reply) public void Add(AsyncReply<T> reply)

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,12 +32,34 @@ namespace Esiur.Engine
{ {
public class AsyncReply public class AsyncReply
{ {
public enum ErrorType
{
Management,
Exception
}
public enum ProgressType
{
Execution,
Network,
}
protected List<Action<object>> callbacks = new List<Action<object>>(); protected List<Action<object>> callbacks = new List<Action<object>>();
protected object result; protected object result;
protected List<Action<AsyncException>> errorCallbacks = new List<Action<AsyncException>>();
protected List<Action<ProgressType, int, int>> progressCallbacks = new List<Action<ProgressType, int, int>>();
protected List<Action<object>> chunkCallbacks = new List<Action<object>>();
object callbacksLock = new object(); object callbacksLock = new object();
//bool fired = false;
protected bool resultReady = false; protected bool resultReady = false;
AsyncException exception;
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
public bool Ready public bool Ready
{ {
@ -25,40 +71,111 @@ namespace Esiur.Engine
get { return result; } get { return result; }
} }
public void Then(Action<object> callback) public AsyncReply Then(Action<object> callback)
{ {
callbacks.Add(callback); callbacks.Add(callback);
if (resultReady) if (resultReady)
callback(result); callback(result);
// Trigger(this.result);
return this;
}
public AsyncReply Error(Action<AsyncException> callback)
{
errorCallbacks.Add(callback);
if (exception != null)
{
callback(exception);
tcs.SetException(exception);
}
return this;
}
public AsyncReply Progress(Action<ProgressType, int, int> callback)
{
progressCallbacks.Add(callback);
return this;
}
public AsyncReply Chunk(Action<object> callback)
{
chunkCallbacks.Add(callback);
return this;
} }
public void Trigger(object result) public void Trigger(object result)
{ {
//if (!fired)
//{
this.result = result;
resultReady = true;
lock (callbacksLock) lock (callbacksLock)
{ {
if (resultReady)
return;
this.result = result;
resultReady = true;
foreach (var cb in callbacks) foreach (var cb in callbacks)
cb(result); cb(result);
//callbacks.Clear();
tcs.TrySetResult(result);
}
}
public void TriggerError(AsyncException exception)
{
if (resultReady)
return;
this.exception = exception;
lock (callbacksLock)
{
foreach (var cb in errorCallbacks)
cb(exception);
}
tcs.TrySetException(exception);
}
public void TriggerProgress(ProgressType type, int value, int max)
{
if (resultReady)
return;
lock (callbacksLock)
{
foreach (var cb in progressCallbacks)
cb(type, value, max);
}
}
public void TriggerChunk(object value)
{
if (resultReady)
return;
lock (callbacksLock)
{
foreach (var cb in chunkCallbacks)
cb(value);
}
}
public Task Task
{
get
{
return tcs.Task;
} }
/*
if (callback == null)
{
fireAtChance = true;
}
else
{
callback(result);
fired = true;
}
*/
//}
} }
public AsyncReply() public AsyncReply()
@ -69,6 +186,7 @@ namespace Esiur.Engine
public AsyncReply(object result) public AsyncReply(object result)
{ {
resultReady = true; resultReady = true;
tcs.SetResult(result);
this.result = result; this.result = result;
} }
} }

View File

@ -1,17 +1,44 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Esiur.Resource; using Esiur.Resource;
using System.Reflection;
namespace Esiur.Engine namespace Esiur.Engine
{ {
public class AsyncReply<T>: AsyncReply public class AsyncReply<T>: AsyncReply
{ {
public void Then(Action<T> callback)
public AsyncReply<T> Then(Action<T> callback)
{ {
base.Then(new Action<object>(o => callback((T)o))); base.Then(new Action<object>(o => callback((T)o)));
return this;
} }
public void Trigger(T result) public void Trigger(T result)
@ -24,6 +51,22 @@ namespace Esiur.Engine
} }
public new Task<T> Task
{
get
{
return base.Task.ContinueWith<T>((t) =>
{
#if NETSTANDARD1_5
return (T)t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t);
#else
return (T)t.GetType().GetProperty("Result").GetValue(t);
#endif
});
}
}
public AsyncReply(T result) public AsyncReply(T result)
: base(result) : base(result)
{ {

View File

@ -1,4 +1,27 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,29 @@
using System; 
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -6,7 +6,7 @@
<Copyright>Ahmed Kh. Zamil</Copyright> <Copyright>Ahmed Kh. Zamil</Copyright>
<PackageLicenseUrl>https://github.com/esiur/esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://github.com/esiur/esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl> <PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<Version>1.0.0</Version> <Version>1.0.0</Version>
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl> <RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
<Authors>Ahmed Kh. Zamil</Authors> <Authors>Ahmed Kh. Zamil</Authors>

View File

@ -1,3 +1,27 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System; using System;
using System.IO; using System.IO;
using System.Collections; using System.Collections;
@ -31,7 +55,7 @@ namespace Esiur.Misc
public delegate void LogEvent(string service, LogType type, string message); public delegate void LogEvent(string service, LogType type, string message);
public static LogEvent SystemLog; public static event LogEvent SystemLog;
static Random random = new Random(); static Random random = new Random();
@ -88,8 +112,7 @@ namespace Esiur.Misc
//if (type != LogType.Debug) //if (type != LogType.Debug)
Console.WriteLine(service + " " + message); Console.WriteLine(service + " " + message);
if (SystemLog != null) SystemLog?.Invoke(service, type, message);
SystemLog(service, type, message);
} }
/* /*
@ -398,8 +421,8 @@ namespace Esiur.Misc
Enumerable.Repeat(chars, length) Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]) .Select(s => s[random.Next(s.Length)])
.ToArray()); .ToArray());
if (result.Length < length) //if (result.Length < length)
Console.WriteLine(); // Console.WriteLine();
return result; return result;
/* /*
int len = 0; int len = 0;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using Esiur.Net.Packets; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Net.Packets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net.Sockets; using System.Net.Sockets;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net.Sockets; using System.Net.Sockets;

View File

@ -1,3 +1,27 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -157,7 +181,7 @@ namespace Esiur.Net.HTTP
protected override void ClientDisconnected(HTTPConnection sender) protected override void ClientDisconnected(HTTPConnection sender)
{ {
Console.WriteLine("OUT: " + this.Connections.Count); //Console.WriteLine("OUT: " + this.Connections.Count);
foreach (IResource resource in Instance.Children) foreach (IResource resource in Instance.Children)
{ {
@ -369,7 +393,7 @@ namespace Esiur.Net.HTTP
//sender.SessionEnded += SessionExpired; //sender.SessionEnded += SessionExpired;
sender.SetParent(this); sender.SetParent(this);
Console.WriteLine("IN: " + this.Connections.Count); //Console.WriteLine("IN: " + this.Connections.Count);
foreach (IResource resource in Instance.Children) foreach (IResource resource in Instance.Children)
{ {

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net.Sockets; using System.Net.Sockets;
@ -61,7 +85,7 @@ namespace Esiur.Net.HTTP
OnEnd?.Invoke(this); OnEnd?.Invoke(this);
} }
void VariablesModified(string key, object oldValue, object newValue) void VariablesModified(string key, object oldValue, object newValue, KeyList<string, object> sender)
{ {
OnModify?.Invoke(this, key, oldValue, newValue); OnModify?.Invoke(this, key, oldValue, newValue);
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -27,11 +51,21 @@ namespace Esiur.Net.HTTP
var httpServer = sender.Parent; var httpServer = sender.Parent;
var iipServer = r as DistributedServer; var iipServer = r as DistributedServer;
var tcpSocket = sender.Unassign(); var tcpSocket = sender.Unassign();
if (tcpSocket == null)
return;
var wsSocket = new WSSocket(tcpSocket); var wsSocket = new WSSocket(tcpSocket);
httpServer.Connections.Remove(sender); httpServer.RemoveConnection(sender);
//httpServer.Connections.Remove(sender);
var iipConnection = new DistributedConnection(); var iipConnection = new DistributedConnection();
iipConnection.Server = iipServer; // iipConnection.OnReady += IipConnection_OnReady;
// iipConnection.Server = iipServer;
// iipConnection.Assign(wsSocket);
iipServer.AddConnection(iipConnection);
iipConnection.Assign(wsSocket); iipConnection.Assign(wsSocket);
wsSocket.Begin();
} }
}); });
@ -41,6 +75,11 @@ namespace Esiur.Net.HTTP
return false; return false;
} }
private void IipConnection_OnReady(DistributedConnection sender)
{
Warehouse.Put(sender, sender.RemoteUsername, null, sender.Server);
}
public override AsyncReply<bool> Trigger(ResourceTrigger trigger) public override AsyncReply<bool> Trigger(ResourceTrigger trigger)
{ {
return new AsyncReply<bool>(true); return new AsyncReply<bool>(true);

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Net; using System.Net;
@ -14,6 +38,7 @@ using Esiur.Security.Authority;
using Esiur.Resource.Template; using Esiur.Resource.Template;
using System.Linq; using System.Linq;
using System.Diagnostics; using System.Diagnostics;
using static Esiur.Net.Packets.IIPPacket;
namespace Esiur.Net.IIP namespace Esiur.Net.IIP
{ {
@ -35,35 +60,36 @@ namespace Esiur.Net.IIP
IIPPacket packet = new IIPPacket(); IIPPacket packet = new IIPPacket();
IIPAuthPacket authPacket = new IIPAuthPacket(); IIPAuthPacket authPacket = new IIPAuthPacket();
byte[] sessionId; Session session;
AuthenticationType hostType;
string domain;
string localUsername, remoteUsername;
byte[] localPassword;
byte[] localPassword;
byte[] localNonce, remoteNonce; byte[] localNonce, remoteNonce;
bool ready, readyToEstablish; bool ready, readyToEstablish;
DateTime loginDate; DateTime loginDate;
KeyList<string, object> variables = new KeyList<string, object>();
/// <summary> /// <summary>
/// Local username to authenticate ourselves. /// Local username to authenticate ourselves.
/// </summary> /// </summary>
public string LocalUsername { get; set; } public string LocalUsername => session.LocalAuthentication.Username;// { get; set; }
/// <summary> /// <summary>
/// Peer's username. /// Peer's username.
/// </summary> /// </summary>
public string RemoteUsername { get; set; } public string RemoteUsername => session.RemoteAuthentication.Username;// { get; set; }
/// <summary> /// <summary>
/// Working domain. /// Working domain.
/// </summary> /// </summary>
public string Domain { get { return domain; } } //public string Domain { get { return domain; } }
/// <summary>
/// The session related to this connection.
/// </summary>
public Session Session => session;
/// <summary> /// <summary>
/// Distributed server responsible for this connection, usually for incoming connections. /// Distributed server responsible for this connection, usually for incoming connections.
/// </summary> /// </summary>
@ -73,14 +99,50 @@ namespace Esiur.Net.IIP
set; set;
} }
public bool Remove(IResource resource)
{
// nothing to do
return true;
}
/// <summary> /// <summary>
/// Send data to the other end as parameters /// Send data to the other end as parameters
/// </summary> /// </summary>
/// <param name="values">Values will be converted to bytes then sent.</param> /// <param name="values">Values will be converted to bytes then sent.</param>
internal void SendParams(params object[] values) internal void SendParams(params object[] values)
{ {
var ar = BinaryList.ToBytes(values); var data = BinaryList.ToBytes(values);
Send(ar);
if (ready)
{
var cmd = (IIPPacketCommand)(data[0] >> 6);
if (cmd == IIPPacketCommand.Event)
{
var evt = (IIPPacketEvent)(data[0] & 0x3f);
//Console.Write("Sent: " + cmd.ToString() + " " + evt.ToString());
}
else if (cmd == IIPPacketCommand.Report)
{
var r = (IIPPacketReport)(data[0] & 0x3f);
//Console.Write("Sent: " + cmd.ToString() + " " + r.ToString());
}
else
{
var act = (IIPPacketAction)(data[0] & 0x3f);
//Console.Write("Sent: " + cmd.ToString() + " " + act.ToString());
}
//foreach (var param in values)
// Console.Write(", " + param);
//Console.WriteLine();
}
Send(data);
//StackTrace stackTrace = new StackTrace(; //StackTrace stackTrace = new StackTrace(;
@ -104,13 +166,7 @@ namespace Esiur.Net.IIP
/// <summary> /// <summary>
/// KeyList to store user variables related to this connection. /// KeyList to store user variables related to this connection.
/// </summary> /// </summary>
public KeyList<string, object> Variables public KeyList<string, object> Variables { get; } = new KeyList<string, object>();
{
get
{
return variables;
}
}
/// <summary> /// <summary>
/// IResource interface. /// IResource interface.
@ -129,12 +185,17 @@ namespace Esiur.Net.IIP
{ {
base.Assign(socket); base.Assign(socket);
session.RemoteAuthentication.Source.Attributes.Add(SourceAttributeType.IPv4, socket.RemoteEndPoint.Address);
session.RemoteAuthentication.Source.Attributes.Add(SourceAttributeType.Port, socket.RemoteEndPoint.Port);
session.LocalAuthentication.Source.Attributes.Add(SourceAttributeType.IPv4, socket.LocalEndPoint.Address);
session.LocalAuthentication.Source.Attributes.Add(SourceAttributeType.Port, socket.LocalEndPoint.Port);
if (hostType == AuthenticationType.Client) if (session.LocalAuthentication.Type == AuthenticationType.Client)
{ {
// declare (Credentials -> No Auth, No Enctypt) // declare (Credentials -> No Auth, No Enctypt)
var un = DC.ToBytes(localUsername);
var dmn = DC.ToBytes(domain); var un = DC.ToBytes(session.LocalAuthentication.Username);
var dmn = DC.ToBytes(session.LocalAuthentication.Domain);// domain);
if (socket.State == SocketState.Established) if (socket.State == SocketState.Established)
{ {
@ -160,10 +221,14 @@ namespace Esiur.Net.IIP
/// <param name="password">Password.</param> /// <param name="password">Password.</param>
public DistributedConnection(ISocket socket, string domain, string username, string password) public DistributedConnection(ISocket socket, string domain, string username, string password)
{ {
this.session = new Session( new ClientAuthentication()
, new HostAuthentication());
//Instance.Name = Global.GenerateCode(12); //Instance.Name = Global.GenerateCode(12);
this.hostType = AuthenticationType.Client; //this.hostType = AuthenticationType.Client;
this.domain = domain; //this.domain = domain;
this.localUsername = username; //this.localUsername = username;
session.LocalAuthentication.Domain = domain;
session.LocalAuthentication.Username = username;
this.localPassword = DC.ToBytes(password); this.localPassword = DC.ToBytes(password);
init(); init();
@ -178,6 +243,7 @@ namespace Esiur.Net.IIP
{ {
//myId = Global.GenerateCode(12); //myId = Global.GenerateCode(12);
// localParams.Host = DistributedParameters.HostType.Host; // localParams.Host = DistributedParameters.HostType.Host;
session = new Session(new HostAuthentication(), new ClientAuthentication());
init(); init();
} }
@ -185,7 +251,7 @@ namespace Esiur.Net.IIP
public string Link(IResource resource) public string Link(IResource resource)
{ {
if (resource is DistributedConnection) if (resource is DistributedResource)
{ {
var r = resource as DistributedResource; var r = resource as DistributedResource;
if (r.Instance.Store == this) if (r.Instance.Store == this)
@ -203,7 +269,7 @@ namespace Esiur.Net.IIP
if (x.Type == DistributedResourceQueueItem.DistributedResourceQueueItemType.Event) if (x.Type == DistributedResourceQueueItem.DistributedResourceQueueItemType.Event)
x.Resource._EmitEventByIndex(x.Index, (object[])x.Value); x.Resource._EmitEventByIndex(x.Index, (object[])x.Value);
else else
x.Resource.UpdatePropertyByIndex(x.Index, x.Value); x.Resource._UpdatePropertyByIndex(x.Index, x.Value);
}); });
var r = new Random(); var r = new Random();
@ -213,279 +279,420 @@ namespace Esiur.Net.IIP
private uint processPacket(byte[] msg, uint offset, uint ends, NetworkBuffer data, int chunkId)
{
var packet = new IIPPacket();
// packets++;
if (ready)
{
var rt = packet.Parse(msg, offset, ends);
//Console.WriteLine("Rec: " + chunkId + " " + packet.ToString());
/*
if (packet.Command == IIPPacketCommand.Event)
Console.WriteLine("Rec: " + packet.Command.ToString() + " " + packet.Event.ToString());
else if (packet.Command == IIPPacketCommand.Report)
Console.WriteLine("Rec: " + packet.Command.ToString() + " " + packet.Report.ToString());
else
Console.WriteLine("Rec: " + packet.Command.ToString() + " " + packet.Action.ToString() + " " + packet.ResourceId + " " + offset + "/" + ends);
*/
//packs.Add(packet.Command.ToString() + " " + packet.Action.ToString() + " " + packet.Event.ToString());
//if (packs.Count > 1)
// Console.WriteLine("P2");
if (rt <= 0)
{
var size = ends - offset;
data.HoldFor(msg, offset, size, size + (uint)(-rt));
return ends;
}
else
{
offset += (uint)rt;
if (packet.Command == IIPPacket.IIPPacketCommand.Event)
{
switch (packet.Event)
{
case IIPPacket.IIPPacketEvent.ResourceReassigned:
IIPEventResourceReassigned(packet.ResourceId, packet.NewResourceId);
break;
case IIPPacket.IIPPacketEvent.ResourceDestroyed:
IIPEventResourceDestroyed(packet.ResourceId);
break;
case IIPPacket.IIPPacketEvent.PropertyUpdated:
IIPEventPropertyUpdated(packet.ResourceId, packet.MethodIndex, packet.Content);
break;
case IIPPacket.IIPPacketEvent.EventOccurred:
IIPEventEventOccurred(packet.ResourceId, packet.MethodIndex, packet.Content);
break;
case IIPPacketEvent.ChildAdded:
IIPEventChildAdded(packet.ResourceId, packet.ChildId);
break;
case IIPPacketEvent.ChildRemoved:
IIPEventChildRemoved(packet.ResourceId, packet.ChildId);
break;
case IIPPacketEvent.Renamed:
IIPEventRenamed(packet.ResourceId, packet.Content);
break;
case IIPPacketEvent.AttributesUpdated:
IIPEventAttributesUpdated(packet.ResourceId, packet.Content);
break;
}
}
else if (packet.Command == IIPPacket.IIPPacketCommand.Request)
{
switch (packet.Action)
{
// Manage
case IIPPacket.IIPPacketAction.AttachResource:
IIPRequestAttachResource(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.ReattachResource:
IIPRequestReattachResource(packet.CallbackId, packet.ResourceId, packet.ResourceAge);
break;
case IIPPacket.IIPPacketAction.DetachResource:
IIPRequestDetachResource(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.CreateResource:
IIPRequestCreateResource(packet.CallbackId, packet.StoreId, packet.ResourceId, packet.Content);
break;
case IIPPacket.IIPPacketAction.DeleteResource:
IIPRequestDeleteResource(packet.CallbackId, packet.ResourceId);
break;
case IIPPacketAction.AddChild:
IIPRequestAddChild(packet.CallbackId, packet.ResourceId, packet.ChildId);
break;
case IIPPacketAction.RemoveChild:
IIPRequestRemoveChild(packet.CallbackId, packet.ResourceId, packet.ChildId);
break;
case IIPPacketAction.RenameResource:
IIPRequestRenameResource(packet.CallbackId, packet.ResourceId, packet.Content);
break;
// Inquire
case IIPPacket.IIPPacketAction.TemplateFromClassName:
IIPRequestTemplateFromClassName(packet.CallbackId, packet.ClassName);
break;
case IIPPacket.IIPPacketAction.TemplateFromClassId:
IIPRequestTemplateFromClassId(packet.CallbackId, packet.ClassId);
break;
case IIPPacket.IIPPacketAction.TemplateFromResourceId:
IIPRequestTemplateFromResourceId(packet.CallbackId, packet.ResourceId);
break;
case IIPPacketAction.QueryLink:
IIPRequestQueryResources(packet.CallbackId, packet.ResourceLink);
break;
case IIPPacketAction.ResourceChildren:
IIPRequestResourceChildren(packet.CallbackId, packet.ResourceId);
break;
case IIPPacketAction.ResourceParents:
IIPRequestResourceParents(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.ResourceHistory:
IIPRequestInquireResourceHistory(packet.CallbackId, packet.ResourceId, packet.FromDate, packet.ToDate);
break;
// Invoke
case IIPPacket.IIPPacketAction.InvokeFunction:
IIPRequestInvokeFunction(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
break;
case IIPPacket.IIPPacketAction.GetProperty:
IIPRequestGetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
break;
case IIPPacket.IIPPacketAction.GetPropertyIfModified:
IIPRequestGetPropertyIfModifiedSince(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.ResourceAge);
break;
case IIPPacket.IIPPacketAction.SetProperty:
IIPRequestSetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
break;
// Attribute
case IIPPacketAction.GetAllAttributes:
IIPRequestGetAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
break;
case IIPPacketAction.UpdateAllAttributes:
IIPRequestUpdateAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
break;
case IIPPacketAction.ClearAllAttributes:
IIPRequestClearAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
break;
case IIPPacketAction.GetAttributes:
IIPRequestGetAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
break;
case IIPPacketAction.UpdateAttributes:
IIPRequestUpdateAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
break;
case IIPPacketAction.ClearAttributes:
IIPRequestClearAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
break;
}
}
else if (packet.Command == IIPPacket.IIPPacketCommand.Reply)
{
switch (packet.Action)
{
// Manage
case IIPPacket.IIPPacketAction.AttachResource:
IIPReply(packet.CallbackId, packet.ClassId, packet.ResourceAge, packet.ResourceLink, packet.Content);
break;
case IIPPacket.IIPPacketAction.ReattachResource:
IIPReply(packet.CallbackId, packet.ResourceAge, packet.Content);
break;
case IIPPacket.IIPPacketAction.DetachResource:
IIPReply(packet.CallbackId);
break;
case IIPPacket.IIPPacketAction.CreateResource:
IIPReply(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.DeleteResource:
case IIPPacketAction.AddChild:
case IIPPacketAction.RemoveChild:
case IIPPacketAction.RenameResource:
IIPReply(packet.CallbackId);
break;
// Inquire
case IIPPacket.IIPPacketAction.TemplateFromClassName:
case IIPPacket.IIPPacketAction.TemplateFromClassId:
case IIPPacket.IIPPacketAction.TemplateFromResourceId:
IIPReply(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
break;
case IIPPacketAction.QueryLink:
case IIPPacketAction.ResourceChildren:
case IIPPacketAction.ResourceParents:
case IIPPacketAction.ResourceHistory:
IIPReply(packet.CallbackId, packet.Content);
break;
// Invoke
case IIPPacket.IIPPacketAction.InvokeFunction:
IIPReplyInvoke(packet.CallbackId, packet.Content);
break;
case IIPPacket.IIPPacketAction.GetProperty:
IIPReply(packet.CallbackId, packet.Content);
break;
case IIPPacket.IIPPacketAction.GetPropertyIfModified:
IIPReply(packet.CallbackId, packet.Content);
break;
case IIPPacket.IIPPacketAction.SetProperty:
IIPReply(packet.CallbackId);
break;
// Attribute
case IIPPacketAction.GetAllAttributes:
case IIPPacketAction.GetAttributes:
IIPReply(packet.CallbackId, packet.Content);
break;
case IIPPacketAction.UpdateAllAttributes:
case IIPPacketAction.UpdateAttributes:
case IIPPacketAction.ClearAllAttributes:
case IIPPacketAction.ClearAttributes:
IIPReply(packet.CallbackId);
break;
}
}
else if (packet.Command == IIPPacketCommand.Report)
{
switch (packet.Report)
{
case IIPPacketReport.ManagementError:
IIPReportError(packet.CallbackId, AsyncReply.ErrorType.Management, packet.ErrorCode, null);
break;
case IIPPacketReport.ExecutionError:
IIPReportError(packet.CallbackId, AsyncReply.ErrorType.Exception, packet.ErrorCode, packet.ErrorMessage);
break;
case IIPPacketReport.ProgressReport:
IIPReportProgress(packet.CallbackId, AsyncReply.ProgressType.Execution, packet.ProgressValue, packet.ProgressMax);
break;
case IIPPacketReport.ChunkStream:
IIPReportChunk(packet.CallbackId, packet.Content);
break;
}
}
}
}
else
{
var rt = authPacket.Parse(msg, offset, ends);
//Console.WriteLine(session.LocalAuthentication.Type.ToString() + " " + offset + " " + ends + " " + rt + " " + authPacket.ToString());
if (rt <= 0)
{
data.HoldFor(msg, ends + (uint)(-rt));
return ends;
}
else
{
offset += (uint)rt;
if (session.LocalAuthentication.Type == AuthenticationType.Host)
{
if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Declare)
{
if (authPacket.RemoteMethod == IIPAuthPacket.IIPAuthPacketMethod.Credentials && authPacket.LocalMethod == IIPAuthPacket.IIPAuthPacketMethod.None)
{
Server.Membership.UserExists(authPacket.RemoteUsername, authPacket.Domain).Then(x =>
{
if (x)
{
session.RemoteAuthentication.Username = authPacket.RemoteUsername;
remoteNonce = authPacket.RemoteNonce;
session.RemoteAuthentication.Domain = authPacket.Domain;
SendParams((byte)0xa0, localNonce);
}
else
{
//Console.WriteLine("User not found");
SendParams((byte)0xc0, (byte)1, (ushort)14, DC.ToBytes("User not found"));
}
});
}
}
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Action)
{
if (authPacket.Action == IIPAuthPacket.IIPAuthPacketAction.AuthenticateHash)
{
var remoteHash = authPacket.Hash;
Server.Membership.GetPassword(session.RemoteAuthentication.Username,
session.RemoteAuthentication.Domain).Then((pw) =>
{
if (pw != null)
{
var hashFunc = SHA256.Create();
var hash = hashFunc.ComputeHash(BinaryList.ToBytes(pw, remoteNonce, localNonce));
if (hash.SequenceEqual(remoteHash))
{
// send our hash
var localHash = hashFunc.ComputeHash(BinaryList.ToBytes(localNonce, remoteNonce, pw));
SendParams((byte)0, localHash);
readyToEstablish = true;
}
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"));
}
}
});
}
else if (authPacket.Action == IIPAuthPacket.IIPAuthPacketAction.NewConnection)
{
if (readyToEstablish)
{
var r = new Random();
session.Id = new byte[32];
r.NextBytes(session.Id);
SendParams((byte)0x28, session.Id);
ready = true;
OnReady?.Invoke(this);
Server.Membership.Login(session);
Global.Log("auth", LogType.Warning, "U:" + RemoteUsername + " IP:" + Socket.RemoteEndPoint.Address.ToString() + " S:AUTH");
}
}
}
}
else if (session.LocalAuthentication.Type == AuthenticationType.Client)
{
if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Acknowledge)
{
remoteNonce = authPacket.RemoteNonce;
// send our hash
var hashFunc = SHA256.Create();
var localHash = hashFunc.ComputeHash(BinaryList.ToBytes(localPassword, localNonce, remoteNonce));
SendParams((byte)0, localHash);
}
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Action)
{
if (authPacket.Action == IIPAuthPacket.IIPAuthPacketAction.AuthenticateHash)
{
// check if the server knows my password
var hashFunc = SHA256.Create();
var remoteHash = hashFunc.ComputeHash(BinaryList.ToBytes(remoteNonce, localNonce, localPassword));
if (remoteHash.SequenceEqual(authPacket.Hash))
{
// send establish request
SendParams((byte)0x20, (ushort)0);
}
else
{
SendParams((byte)0xc0, 1, (ushort)5, DC.ToBytes("Error"));
}
}
else if (authPacket.Action == IIPAuthPacket.IIPAuthPacketAction.ConnectionEstablished)
{
session.Id = authPacket.SessionId;
ready = true;
OnReady?.Invoke(this);
}
}
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Error)
{
OnError?.Invoke(this, authPacket.ErrorCode, authPacket.ErrorMessage);
Close();
}
}
}
}
return offset;
//if (offset < ends)
// processPacket(msg, offset, ends, data, chunkId);
}
protected override void DataReceived(NetworkBuffer data) protected override void DataReceived(NetworkBuffer data)
{ {
// Console.WriteLine("DR " + hostType + " " + data.Available + " " + RemoteEndPoint.ToString()); // Console.WriteLine("DR " + hostType + " " + data.Available + " " + RemoteEndPoint.ToString());
var msg = data.Read(); var msg = data.Read();
uint offset = 0; uint offset = 0;
uint ends = (uint)msg.Length; uint ends = (uint)msg.Length;
var packs = new List<string>();
var chunkId = (new Random()).Next(1000, 1000000);
while (offset < ends) while (offset < ends)
{ {
offset = processPacket(msg, offset, ends, data, chunkId);
if (ready)
{
var rt = packet.Parse(msg, offset, ends);
if (rt <= 0)
{
data.HoldFor(msg, offset, ends - offset, (uint)(-rt));
return;
}
else
{
offset += (uint)rt;
if (packet.Command == IIPPacket.IIPPacketCommand.Event)
{
switch (packet.Event)
{
case IIPPacket.IIPPacketEvent.ResourceReassigned:
IIPEventResourceReassigned(packet.ResourceId, packet.NewResourceId);
break;
case IIPPacket.IIPPacketEvent.ResourceDestroyed:
IIPEventResourceDestroyed(packet.ResourceId);
break;
case IIPPacket.IIPPacketEvent.PropertyUpdated:
IIPEventPropertyUpdated(packet.ResourceId, packet.MethodIndex, packet.Content);
break;
case IIPPacket.IIPPacketEvent.EventOccured:
IIPEventEventOccured(packet.ResourceId, packet.MethodIndex, packet.Content);
break;
}
}
else if (packet.Command == IIPPacket.IIPPacketCommand.Request)
{
switch (packet.Action)
{
case IIPPacket.IIPPacketAction.AttachResource:
IIPRequestAttachResource(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.ReattachResource:
IIPRequestReattachResource(packet.CallbackId, packet.ResourceId, packet.ResourceAge);
break;
case IIPPacket.IIPPacketAction.DetachResource:
IIPRequestDetachResource(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.CreateResource:
IIPRequestCreateResource(packet.CallbackId, packet.ClassName);
break;
case IIPPacket.IIPPacketAction.DeleteResource:
IIPRequestDeleteResource(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.TemplateFromClassName:
IIPRequestTemplateFromClassName(packet.CallbackId, packet.ClassName);
break;
case IIPPacket.IIPPacketAction.TemplateFromClassId:
IIPRequestTemplateFromClassId(packet.CallbackId, packet.ClassId);
break;
case IIPPacket.IIPPacketAction.TemplateFromResourceLink:
IIPRequestTemplateFromResourceLink(packet.CallbackId, packet.ResourceLink);
break;
case IIPPacket.IIPPacketAction.TemplateFromResourceId:
IIPRequestTemplateFromResourceId(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.ResourceIdFromResourceLink:
IIPRequestResourceIdFromResourceLink(packet.CallbackId, packet.ResourceLink);
break;
case IIPPacket.IIPPacketAction.InvokeFunction:
IIPRequestInvokeFunction(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
break;
case IIPPacket.IIPPacketAction.GetProperty:
IIPRequestGetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
break;
case IIPPacket.IIPPacketAction.GetPropertyIfModified:
IIPRequestGetPropertyIfModifiedSince(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.ResourceAge);
break;
case IIPPacket.IIPPacketAction.SetProperty:
IIPRequestSetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
break;
}
}
else if (packet.Command == IIPPacket.IIPPacketCommand.Reply)
{
switch (packet.Action)
{
case IIPPacket.IIPPacketAction.AttachResource:
IIPReply(packet.CallbackId, packet.ClassId, packet.ResourceAge, packet.ResourceLink, packet.Content);
//IIPReplyAttachResource(packet.CallbackId, packet.ResourceAge, Codec.ParseValues(packet.Content));
break;
case IIPPacket.IIPPacketAction.ReattachResource:
//IIPReplyReattachResource(packet.CallbackId, packet.ResourceAge, Codec.ParseValues(packet.Content));
IIPReply(packet.CallbackId, packet.ResourceAge, packet.Content);
break;
case IIPPacket.IIPPacketAction.DetachResource:
//IIPReplyDetachResource(packet.CallbackId);
IIPReply(packet.CallbackId);
break;
case IIPPacket.IIPPacketAction.CreateResource:
//IIPReplyCreateResource(packet.CallbackId, packet.ClassId, packet.ResourceId);
IIPReply(packet.CallbackId, packet.ClassId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.DeleteResource:
//IIPReplyDeleteResource(packet.CallbackId);
IIPReply(packet.CallbackId);
break;
case IIPPacket.IIPPacketAction.TemplateFromClassName:
//IIPReplyTemplateFromClassName(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
IIPReply(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
break;
case IIPPacket.IIPPacketAction.TemplateFromClassId:
//IIPReplyTemplateFromClassId(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
IIPReply(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
break;
case IIPPacket.IIPPacketAction.TemplateFromResourceLink:
//IIPReplyTemplateFromResourceLink(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
IIPReply(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
break;
case IIPPacket.IIPPacketAction.TemplateFromResourceId:
//IIPReplyTemplateFromResourceId(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
IIPReply(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
break;
case IIPPacket.IIPPacketAction.ResourceIdFromResourceLink:
//IIPReplyResourceIdFromResourceLink(packet.CallbackId, packet.ClassId, packet.ResourceId, packet.ResourceAge);
IIPReply(packet.CallbackId, packet.ClassId, packet.ResourceId, packet.ResourceAge);
break;
case IIPPacket.IIPPacketAction.InvokeFunction:
//IIPReplyInvokeFunction(packet.CallbackId, Codec.Parse(packet.Content, 0));
IIPReply(packet.CallbackId, packet.Content);
break;
case IIPPacket.IIPPacketAction.GetProperty:
//IIPReplyGetProperty(packet.CallbackId, Codec.Parse(packet.Content, 0));
IIPReply(packet.CallbackId, packet.Content);
break;
case IIPPacket.IIPPacketAction.GetPropertyIfModified:
//IIPReplyGetPropertyIfModifiedSince(packet.CallbackId, Codec.Parse(packet.Content, 0));
IIPReply(packet.CallbackId, packet.Content);
break;
case IIPPacket.IIPPacketAction.SetProperty:
//IIPReplySetProperty(packet.CallbackId);
IIPReply(packet.CallbackId);
break;
}
}
}
}
else
{
var rt = authPacket.Parse(msg, offset, ends);
Console.WriteLine(hostType.ToString() + " " + offset + " " + ends + " " + rt + " " + authPacket.ToString());
if (rt <= 0)
{
data.HoldFor(msg, ends + (uint)(-rt));
return;
}
else
{
offset += (uint)rt;
if (hostType == AuthenticationType.Host)
{
if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Declare)
{
if (authPacket.RemoteMethod == IIPAuthPacket.IIPAuthPacketMethod.Credentials && authPacket.LocalMethod == IIPAuthPacket.IIPAuthPacketMethod.None)
{
remoteUsername = authPacket.RemoteUsername;
remoteNonce = authPacket.RemoteNonce;
domain = authPacket.Domain;
SendParams((byte)0xa0, localNonce);
}
}
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Action)
{
if (authPacket.Action == IIPAuthPacket.IIPAuthPacketAction.AuthenticateHash)
{
var remoteHash = authPacket.Hash;
Server.Membership.GetPassword(remoteUsername, domain).Then((pw) =>
{
if (pw != null)
{
var hashFunc = SHA256.Create();
var hash = hashFunc.ComputeHash(BinaryList.ToBytes(pw, remoteNonce, localNonce));
if (hash.SequenceEqual(remoteHash))
{
// send our hash
var localHash = hashFunc.ComputeHash(BinaryList.ToBytes(localNonce, remoteNonce, pw));
SendParams((byte)0, localHash);
readyToEstablish = true;
}
else
{
Console.WriteLine("Incorrect password");
SendParams((byte)0xc0, (byte)1, (ushort)5, DC.ToBytes("Error"));
}
}
});
}
else if (authPacket.Action == IIPAuthPacket.IIPAuthPacketAction.NewConnection)
{
if (readyToEstablish)
{
var r = new Random();
sessionId = new byte[32];
r.NextBytes(sessionId);
SendParams((byte)0x28, sessionId);
ready = true;
OnReady?.Invoke(this);
}
}
}
}
else if (hostType == AuthenticationType.Client)
{
if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Acknowledge)
{
remoteNonce = authPacket.RemoteNonce;
// send our hash
var hashFunc = SHA256.Create();
var localHash = hashFunc.ComputeHash(BinaryList.ToBytes(localPassword, localNonce, remoteNonce));
SendParams((byte)0, localHash);
}
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Action)
{
if (authPacket.Action == IIPAuthPacket.IIPAuthPacketAction.AuthenticateHash)
{
// check if the server knows my password
var hashFunc = SHA256.Create();
var remoteHash = hashFunc.ComputeHash(BinaryList.ToBytes(remoteNonce, localNonce, localPassword));
if (remoteHash.SequenceEqual(authPacket.Hash))
{
// send establish request
SendParams((byte)0x20, (ushort)0);
}
else
{
SendParams((byte)0xc0, 1, (ushort)5, DC.ToBytes("Error"));
}
}
else if (authPacket.Action == IIPAuthPacket.IIPAuthPacketAction.ConnectionEstablished)
{
sessionId = authPacket.SessionId;
ready = true;
OnReady?.Invoke(this);
}
}
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Error)
{
OnError?.Invoke(this, authPacket.ErrorCode, authPacket.ErrorMessage);
Close();
}
}
}
}
} }
} }
@ -510,5 +717,17 @@ namespace Esiur.Net.IIP
resources.Add(Convert.ToUInt32(resource.Instance.Name), (DistributedResource)resource); resources.Add(Convert.ToUInt32(resource.Instance.Name), (DistributedResource)resource);
return true; return true;
} }
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
{
// nothing to do
return true;
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
{
// nothing to do
return true;
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Net.IIP
{
public class DistributedPropertyContext
{
public object Value { get; private set; }
public DistributedConnection Connection { get; private set; }
public Func<DistributedConnection, object> Method { get; private set; }
public DistributedPropertyContext(DistributedConnection connection, object value)
{
this.Value = value;
this.Connection = connection;
}
public DistributedPropertyContext(Func<DistributedConnection, object> method)
{
this.Method = method;
}
}
}

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Reflection; using System.Reflection;
@ -41,12 +65,12 @@ namespace Esiur.Net.IIP
//Structure properties = new Structure(); //Structure properties = new Structure();
string link; string link;
uint age; //ulong age;
uint[] ages; //ulong[] ages;
object[] properties; object[] properties;
DistributedResourceEvent[] events; DistributedResourceEvent[] events;
ResourceTemplate template; //ResourceTemplate template;
//DistributedResourceStack stack; //DistributedResourceStack stack;
@ -54,13 +78,23 @@ namespace Esiur.Net.IIP
bool destroyed; bool destroyed;
/*
Dictionary<AsyncReply, object> afterAttachmentTriggers = new Dictionary<AsyncReply, object>();
internal void AddAfterAttachement(AsyncReply trigger, object value)
{
afterAttachmentTriggers.Add(trigger, value);
}
*/
/// <summary> /// <summary>
/// Resource template for the remotely located resource. /// Resource template for the remotely located resource.
/// </summary> /// </summary>
public ResourceTemplate Template //public ResourceTemplate Template
{ //{
get { return template; } // get { return template; }
} //}
/// <summary> /// <summary>
@ -132,40 +166,72 @@ namespace Esiur.Net.IIP
/// <param name="template">Resource template.</param> /// <param name="template">Resource template.</param>
/// <param name="instanceId">Instance Id given by the other end.</param> /// <param name="instanceId">Instance Id given by the other end.</param>
/// <param name="age">Resource age.</param> /// <param name="age">Resource age.</param>
public DistributedResource(DistributedConnection connection, ResourceTemplate template, uint instanceId, uint age, string link) public DistributedResource(DistributedConnection connection, uint instanceId, ulong age, string link)
{ {
this.link = link; this.link = link;
this.connection = connection; this.connection = connection;
this.instanceId = instanceId; this.instanceId = instanceId;
this.template = template; //this.Instance.Template = template;
this.age = age; //this.Instance.Age = age;
//this.template = template;
//this.age = age;
} }
internal void _Ready() internal void _Ready()
{ {
isReady = true; isReady = true;
} }
internal bool _Attached(object[] properties) /// <summary>
/// Export all properties with ResourceProperty attributed as bytes array.
/// </summary>
/// <returns></returns>
internal PropertyValue[] _Serialize()
{
var props = new PropertyValue[properties.Length];
for (byte i = 0; i < properties.Length; i++)
props[i] = new PropertyValue(properties[i], Instance.GetAge(i), Instance.GetModificationDate(i));
return props;
}
internal bool _Attached(PropertyValue[] properties)
{ {
if (isAttached) if (isAttached)
return false; return false;
else else
{ {
this.properties = properties; this.properties = new object[properties.Length];
ages = new uint[properties.Length];
this.events = new DistributedResourceEvent[template.Events.Length]; this.events = new DistributedResourceEvent[Instance.Template.Events.Length];
for (byte i = 0; i < properties.Length; i++)
{
Instance.SetAge(i, properties[i].Age);
Instance.SetModificationDate(i, properties[i].Date);
this.properties[i] = properties[i].Value;
}
// trigger holded events/property updates.
//foreach (var r in afterAttachmentTriggers)
// r.Key.Trigger(r.Value);
//afterAttachmentTriggers.Clear();
isAttached = true; isAttached = true;
} }
return true; return true;
} }
internal void _EmitEventByIndex(byte index, object[] args) internal void _EmitEventByIndex(byte index, object[] args)
{ {
var et = template.GetEventTemplate(index); var et = Instance.Template.GetEventTemplate(index);
events[index]?.Invoke(this, args); events[index]?.Invoke(this, args);
Instance.EmitResourceEvent(et.Name, null, args); Instance.EmitResourceEvent(null, null, et.Name, args);
} }
public AsyncReply _Invoke(byte index, object[] args) public AsyncReply _Invoke(byte index, object[] args)
@ -173,29 +239,37 @@ namespace Esiur.Net.IIP
if (destroyed) if (destroyed)
throw new Exception("Trying to access destroyed object"); throw new Exception("Trying to access destroyed object");
if (index >= template.Functions.Length) if (index >= Instance.Template.Functions.Length)
throw new Exception("Function index is incorrect"); throw new Exception("Function index is incorrect");
var reply = new AsyncReply(); // var reply = new AsyncReply();
var parameters = Codec.ComposeVarArray(args, connection, true); return connection.SendInvoke(instanceId, index, args);
connection.SendRequest(Packets.IIPPacket.IIPPacketAction.InvokeFunction, instanceId, index, parameters).Then((res) =>
//var parameters = Codec.ComposeVarArray(args, connection, true);
//return connection.SendRequest(Packets.IIPPacket.IIPPacketAction.InvokeFunction, instanceId, index, parameters);
/*.Then((res) =>
{ {
Codec.Parse((byte[])res[0], 0, connection).Then((rt) => Codec.Parse((byte[])res[0], 0, connection).Then((rt) =>
{ {
reply.Trigger(rt); reply.Trigger(rt);
}); });
}); }).Error((ex) => {
reply.TriggerError(ex);
}).Progress((t, pv, pm)=> {
reply.TriggerProgress(t, pv, pm);
}).Chunk(v => reply.TriggerChunk(v));
return reply; return reply;
*/
} }
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{ {
var ft = template.GetFunctionTemplate(binder.Name); var ft = Instance.Template.GetFunctionTemplate(binder.Name);
var reply = new AsyncReply(); var reply = new AsyncReply();
@ -233,7 +307,7 @@ namespace Esiur.Net.IIP
if (!isAttached) if (!isAttached)
return false; return false;
var pt = template.GetPropertyTemplate(binder.Name); var pt = Instance.Template.GetPropertyTemplate(binder.Name);
if (pt != null) if (pt != null)
{ {
@ -242,7 +316,7 @@ namespace Esiur.Net.IIP
} }
else else
{ {
var et = template.GetEventTemplate(binder.Name); var et = Instance.Template.GetEventTemplate(binder.Name);
if (et == null) if (et == null)
return false; return false;
@ -253,11 +327,11 @@ namespace Esiur.Net.IIP
} }
internal void UpdatePropertyByIndex(byte index, object value) internal void _UpdatePropertyByIndex(byte index, object value)
{ {
var pt = template.GetPropertyTemplate(index); var pt = Instance.Template.GetPropertyTemplate(index);
properties[index] = value; properties[index] = value;
Instance.Modified(pt.Name, value); Instance.EmitModification(pt, value);
} }
/// <summary> /// <summary>
@ -277,9 +351,8 @@ namespace Esiur.Net.IIP
connection.SendRequest(Packets.IIPPacket.IIPPacketAction.SetProperty, instanceId, index, parameters).Then((res) => connection.SendRequest(Packets.IIPPacket.IIPPacketAction.SetProperty, instanceId, index, parameters).Then((res) =>
{ {
// not really needed, server will always send property modified, this only happens if the programmer forgot to emit in property setter // not really needed, server will always send property modified, this only happens if the programmer forgot to emit in property setter
//Update(index, value); properties[index] = value;
reply.Trigger(null); reply.Trigger(null);
// nothing to do here
}); });
return reply; return reply;
@ -293,8 +366,7 @@ namespace Esiur.Net.IIP
if (!isAttached) if (!isAttached)
return false; return false;
var pt = template.GetPropertyTemplate(binder.Name); var pt = Instance.Template.GetPropertyTemplate(binder.Name);
if (pt != null) if (pt != null)
{ {
@ -303,7 +375,7 @@ namespace Esiur.Net.IIP
} }
else else
{ {
var et = template.GetEventTemplate(binder.Name); var et = Instance.Template.GetEventTemplate(binder.Name);
if (et == null) if (et == null)
return false; return false;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -16,39 +40,40 @@ namespace Esiur.Net.IIP
public class DistributedServer : NetworkServer<DistributedConnection>, IResource public class DistributedServer : NetworkServer<DistributedConnection>, IResource
{ {
[Storable] //[Storable]
[ResourceProperty] //[ResourceProperty]
public string ip public string ip
{ {
get; get;
set; set;
} }
[Storable] //[Storable]
[ResourceProperty] //[ResourceProperty]
public IMembership Membership public IMembership Membership
{ {
get; get;
set; set;
} }
[Storable]
[ResourceProperty] //[Storable]
//[ResourceProperty]
public ushort port public ushort port
{ {
get; get;
set; set;
} }
[Storable] //[Storable]
[ResourceProperty] //[ResourceProperty]
public uint timeout public uint timeout
{ {
get; get;
set; set;
} }
[Storable] //[Storable]
[ResourceProperty] //[ResourceProperty]
public uint clock public uint clock
{ {
get; get;
@ -94,24 +119,45 @@ namespace Esiur.Net.IIP
{ {
//throw new NotImplementedException(); //throw new NotImplementedException();
} }
private void SessionModified(DistributedConnection Session, string Key, object NewValue) private void SessionModified(DistributedConnection Session, string Key, object NewValue)
{ {
} }
protected override void ClientConnected(DistributedConnection sender) protected override void ClientConnected(DistributedConnection sender)
{ {
Console.WriteLine("DistributedConnection Client Connected"); //Console.WriteLine("DistributedConnection Client Connected");
sender.Server = this;
} }
private void Sender_OnReady(DistributedConnection sender)
{
Warehouse.Put(sender, sender.LocalUsername, null, this);
}
public override void RemoveConnection(DistributedConnection connection)
{
connection.OnReady -= Sender_OnReady;
//connection.Server = null;
base.RemoveConnection(connection);
}
public override void AddConnection(DistributedConnection connection)
{
connection.OnReady += Sender_OnReady;
connection.Server = this;
base.AddConnection(connection);
}
protected override void ClientDisconnected(DistributedConnection sender) protected override void ClientDisconnected(DistributedConnection sender)
{ {
Console.WriteLine("DistributedConnection Client Disconnected"); sender.Destroy();
Warehouse.Remove(sender);
//Console.WriteLine("DistributedConnection Client Disconnected");
} }
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using Esiur.Net.Sockets; using Esiur.Net.Sockets;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -14,6 +38,13 @@ namespace Esiur.Net
uint neededDataLength = 0; uint neededDataLength = 0;
//bool trim; //bool trim;
object syncLock = new object();
//public object SyncLock
//{
// get { return syncLock; }
//}
public NetworkBuffer() public NetworkBuffer()
{ {
data = new byte[0]; data = new byte[0];
@ -62,16 +93,19 @@ namespace Esiur.Net
public void HoldFor(byte[] src, uint offset, uint size, uint needed) public void HoldFor(byte[] src, uint offset, uint size, uint needed)
{ {
if (size >= needed) lock (syncLock)
throw new Exception("Size >= Needed !"); {
if (size >= needed)
throw new Exception("Size >= Needed !");
//trim = true; //trim = true;
data = DC.Combine(src, offset, size, data, 0, (uint)data.Length); data = DC.Combine(src, offset, size, data, 0, (uint)data.Length);
neededDataLength = needed; neededDataLength = needed;
// Console.WriteLine("Hold StackTrace: '{0}'", Environment.StackTrace); // Console.WriteLine("Hold StackTrace: '{0}'", Environment.StackTrace);
Console.WriteLine("Holded {0} {1} {2} {3} - {4}", offset, size, needed, data.Length, GetHashCode()); //Console.WriteLine("Holded {0} {1} {2} {3} - {4}", offset, size, needed, data.Length, GetHashCode());
}
} }
public void HoldFor(byte[] src, uint needed) public void HoldFor(byte[] src, uint needed)
@ -104,7 +138,11 @@ namespace Esiur.Net
public void Write(byte[] src, uint offset, uint length) public void Write(byte[] src, uint offset, uint length)
{ {
DC.Append(ref data, src, offset, length); //if (data.Length > 0)
// Console.WriteLine();
lock(syncLock)
DC.Append(ref data, src, offset, length);
} }
public bool CanRead public bool CanRead
@ -122,46 +160,49 @@ namespace Esiur.Net
public byte[] Read() public byte[] Read()
{ {
if (data.Length == 0) lock (syncLock)
return null;
byte[] rt = null;
if (neededDataLength == 0)
{ {
rt = data; if (data.Length == 0)
data = new byte[0]; return null;
}
else
{
//Console.WriteLine("P STATE:" + data.Length + " " + neededDataLength);
if (data.Length >= neededDataLength) byte[] rt = null;
if (neededDataLength == 0)
{ {
//Console.WriteLine("data.Length >= neededDataLength " + data.Length + " >= " + neededDataLength + " " + trim);
//if (trim)
//{
// rt = DC.Clip(data, 0, neededDataLength);
// data = DC.Clip(data, neededDataLength, (uint)data.Length - neededDataLength);
//}
//else
//{
// return all data
rt = data; rt = data;
data = new byte[0]; data = new byte[0];
//}
neededDataLength = 0;
return rt;
} }
else else
{ {
return null; //Console.WriteLine("P STATE:" + data.Length + " " + neededDataLength);
}
}
return rt; if (data.Length >= neededDataLength)
{
//Console.WriteLine("data.Length >= neededDataLength " + data.Length + " >= " + neededDataLength + " " + trim);
//if (trim)
//{
// rt = DC.Clip(data, 0, neededDataLength);
// data = DC.Clip(data, neededDataLength, (uint)data.Length - neededDataLength);
//}
//else
//{
// return all data
rt = data;
data = new byte[0];
//}
neededDataLength = 0;
return rt;
}
else
{
return null;
}
}
return rt;
}
} }
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.IO; using System.IO;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
@ -29,9 +53,11 @@ namespace Esiur.Net
public event DataReceivedEvent OnDataReceived; public event DataReceivedEvent OnDataReceived;
public event ConnectionClosedEvent OnClose; public event ConnectionClosedEvent OnClose;
public event DestroyedEvent OnDestroy; public event DestroyedEvent OnDestroy;
object receivingLock = new object();
bool processing = false;
public void Destroy() public void Destroy()
{ {
// if (connected) // if (connected)
@ -62,8 +88,8 @@ namespace Esiur.Net
socket.OnReceive += Socket_OnReceive; socket.OnReceive += Socket_OnReceive;
socket.OnClose += Socket_OnClose; socket.OnClose += Socket_OnClose;
socket.OnConnect += Socket_OnConnect; socket.OnConnect += Socket_OnConnect;
if (socket.State == SocketState.Established) //if (socket.State == SocketState.Established)
socket.Begin(); // socket.Begin();
} }
private void Socket_OnConnect() private void Socket_OnConnect()
@ -90,8 +116,23 @@ namespace Esiur.Net
lastAction = DateTime.Now; lastAction = DateTime.Now;
while (buffer.Available > 0 && !buffer.Protected) if (!processing)
DataReceived(buffer); {
processing = true;
try
{
//lock(buffer.SyncLock)
while (buffer.Available > 0 && !buffer.Protected)
DataReceived(buffer);
}
catch
{
}
processing = false;
}
} }
catch (Exception ex) catch (Exception ex)
@ -234,9 +275,9 @@ namespace Esiur.Net
sock.Send(msg); sock.Send(msg);
} }
} }
catch catch (Exception ex)
{ {
Console.WriteLine(ex.ToString());
} }
} }

View File

@ -1,3 +1,27 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System; using System;
using System.Threading; using System.Threading;
using System.Collections.Generic; using System.Collections.Generic;
@ -10,7 +34,6 @@ using System.Threading.Tasks;
namespace Esiur.Net namespace Esiur.Net
{ {
//public abstract class NetworkServer<TConnection, TSession> : IResource where TSession : NetworkSession, new() where TConnection : NetworkConnection<TSession>, new()
public abstract class NetworkServer<TConnection>: IDestructible where TConnection : NetworkConnection, new() public abstract class NetworkServer<TConnection>: IDestructible where TConnection : NetworkConnection, new()
{ {
@ -25,8 +48,6 @@ namespace Esiur.Net
protected abstract void ClientConnected(TConnection sender); protected abstract void ClientConnected(TConnection sender);
protected abstract void ClientDisconnected(TConnection sender); protected abstract void ClientDisconnected(TConnection sender);
// private int port;
// private IPAddress ip = null;
private uint timeout; private uint timeout;
private Timer timer; private Timer timer;
@ -201,7 +222,7 @@ namespace Esiur.Net
// Thread.Sleep(100); // Thread.Sleep(100);
//} //}
Console.WriteLine("Listener stopped"); //Console.WriteLine("Listener stopped");
var cons = connections.ToArray(); var cons = connections.ToArray();
@ -211,14 +232,13 @@ namespace Esiur.Net
con.Close(); con.Close();
//} //}
Console.WriteLine("Sockets Closed"); //Console.WriteLine("Sockets Closed");
while (connections.Count > 0) //while (connections.Count > 0)
{ //{
Console.WriteLine("Waiting... " + connections.Count); // Console.WriteLine("Waiting... " + connections.Count);
// Thread.Sleep(1000);
//Thread.Sleep(1000); //}
}
} }
finally finally
@ -228,6 +248,21 @@ namespace Esiur.Net
} }
public virtual void RemoveConnection(TConnection connection)
{
connection.OnDataReceived -= OnDataReceived;
connection.OnConnect -= OnClientConnect;
connection.OnClose -= OnClientClose;
connections.Remove(connection);
}
public virtual void AddConnection(TConnection connection)
{
connection.OnDataReceived += OnDataReceived;
connection.OnConnect += OnClientConnect;
connection.OnClose += OnClientClose;
connections.Add(connection);
}
private void NewConnection(ISocket sock) private void NewConnection(ISocket sock)
{ {
@ -246,20 +281,17 @@ namespace Esiur.Net
if (sock == null) if (sock == null)
{ {
Console.Write("sock == null"); //Console.Write("sock == null");
return; return;
} }
//sock.ReceiveBufferSize = 102400; //sock.ReceiveBufferSize = 102400;
//sock.SendBufferSize = 102400; //sock.SendBufferSize = 102400;
TConnection c = new TConnection(); TConnection c = new TConnection();
c.OnDataReceived += OnDataReceived; AddConnection(c);
c.OnConnect += OnClientConnect;
c.OnClose += OnClientClose;
connections.Add(c);
c.Assign(sock); c.Assign(sock);
ClientConnected(c); ClientConnected(c);
@ -267,13 +299,14 @@ namespace Esiur.Net
// Accept more // Accept more
listener.Accept().Then(NewConnection); listener.Accept().Then(NewConnection);
sock.Begin();
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine("TSERVER " + ex.ToString()); //Console.WriteLine("TSERVER " + ex.ToString());
Global.Log("TServer", LogType.Error, ex.ToString()); Global.Log("NetworkServer", LogType.Error, ex.ToString());
} }
//isRunning = false; //isRunning = false;
@ -317,6 +350,7 @@ namespace Esiur.Net
try try
{ {
sender.Destroy(); sender.Destroy();
RemoveConnection((TConnection)sender);
ClientDisconnected((TConnection)sender); ClientDisconnected((TConnection)sender);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net.Sockets; using System.Net.Sockets;
@ -61,7 +85,7 @@ namespace Esiur.Net
OnEnd?.Invoke(this); OnEnd?.Invoke(this);
} }
void VariablesModified(string key, object oldValue, object newValue) void VariablesModified(string key, object oldValue, object newValue, KeyList<string, object> sender)
{ {
OnModify?.Invoke(this, key, oldValue, newValue); OnModify?.Invoke(this, key, oldValue, newValue);
} }

View File

@ -1,4 +1,29 @@
using System; 
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -218,7 +243,7 @@ namespace Esiur.Net.Packets
return postSize - (data.Length - headerSize); return postSize - (data.Length - headerSize);
if (Headers["content-type"] == "application/x-www-form-urlencoded" if (Headers["content-type"].StartsWith("application/x-www-form-urlencoded")
|| Headers["content-type"] == "" || Headers["content-type"] == ""
|| Headers["content-type"] == null) || Headers["content-type"] == null)
{ {

View File

@ -1,4 +1,27 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
 using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,4 +1,28 @@
 using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine; using Esiur.Engine;
using Esiur.Misc; using Esiur.Misc;
using Esiur.Net.Packets; using Esiur.Net.Packets;
@ -12,12 +36,39 @@ namespace Esiur.Net.Packets
{ {
class IIPPacket : Packet class IIPPacket : Packet
{ {
public override string ToString()
{
var rt = Command.ToString();
if (Command == IIPPacketCommand.Event)
{
rt += " " + Event.ToString();
//if (Event == IIPPacketEvent.AttributesUpdated)
// rt +=
}
else if (Command == IIPPacketCommand.Request)
{
rt += " " + Action.ToString();
if (Action == IIPPacketAction.AttachResource)
{
rt += " CID: " + CallbackId + " RID: " + ResourceId;
}
}
else if (Command == IIPPacketCommand.Reply)
rt += " " + Action.ToString();
else if (Command == IIPPacketCommand.Report)
rt += " " + Report.ToString();
return rt;
}
public enum IIPPacketCommand : byte public enum IIPPacketCommand : byte
{ {
Event = 0, Event = 0,
Request, Request,
Reply, Reply,
Error, Report,
} }
public enum IIPPacketEvent: byte public enum IIPPacketEvent: byte
@ -25,10 +76,15 @@ namespace Esiur.Net.Packets
// Event Manage // Event Manage
ResourceReassigned = 0, ResourceReassigned = 0,
ResourceDestroyed, ResourceDestroyed,
ChildAdded,
ChildRemoved,
Renamed,
// Event Invoke // Event Invoke
PropertyUpdated = 0x10, PropertyUpdated = 0x10,
EventOccured, EventOccurred,
// Attribute
AttributesUpdated = 0x18
} }
public enum IIPPacketAction : byte public enum IIPPacketAction : byte
@ -39,22 +95,49 @@ namespace Esiur.Net.Packets
DetachResource, DetachResource,
CreateResource, CreateResource,
DeleteResource, DeleteResource,
AddChild,
RemoveChild,
RenameResource,
// Request Inquire // Request Inquire
TemplateFromClassName = 0x8, TemplateFromClassName = 0x8,
TemplateFromClassId, TemplateFromClassId,
TemplateFromResourceLink,
TemplateFromResourceId, TemplateFromResourceId,
ResourceIdFromResourceLink, QueryLink,
ResourceHistory,
ResourceChildren,
ResourceParents,
// Request Invoke // Request Invoke
InvokeFunction = 0x10, InvokeFunction = 0x10,
GetProperty, GetProperty,
GetPropertyIfModified, GetPropertyIfModified,
SetProperty, SetProperty,
// Request Attribute
GetAllAttributes = 0x18,
UpdateAllAttributes,
ClearAllAttributes,
GetAttributes,
UpdateAttributes,
ClearAttributes
}
public enum IIPPacketReport: byte
{
ManagementError,
ExecutionError,
ProgressReport = 0x8,
ChunkStream = 0x9
}
public IIPPacketReport Report
{
get;
set;
} }
public IIPPacketCommand Command public IIPPacketCommand Command
{ {
get; get;
@ -72,13 +155,33 @@ namespace Esiur.Net.Packets
set; set;
} }
public IIPPacketCommand PreviousCommand
{
get;
set;
}
public IIPPacketAction PreviousAction
{
get;
set;
}
public IIPPacketEvent PreviousEvent
{
get;
set;
}
public uint ResourceId { get; set; } public uint ResourceId { get; set; }
public uint NewResourceId { get; set; } public uint NewResourceId { get; set; }
//public uint ParentId { get; set; }
public uint ChildId { get; set; }
public uint StoreId { get; set; }
public uint ResourceAge { get; set; } public ulong ResourceAge { get; set; }
public byte[] Content { get; set; } public byte[] Content { get; set; }
public byte ErrorCode { get; set; } public ushort ErrorCode { get; set; }
public string ErrorMessage { get; set; } public string ErrorMessage { get; set; }
public string ClassName { get; set; } public string ClassName { get; set; }
public string ResourceLink { get; set; } public string ResourceLink { get; set; }
@ -86,8 +189,15 @@ namespace Esiur.Net.Packets
public byte MethodIndex { get; set; } public byte MethodIndex { get; set; }
public string MethodName { get; set; } public string MethodName { get; set; }
public uint CallbackId { get; set; } public uint CallbackId { get; set; }
public int ProgressValue { get; set; }
public int ProgressMax { get; set; }
public DateTime FromDate { get; set; }
public DateTime ToDate { get; set; }
public ulong FromAge { get; set; }
public ulong ToAge { get; set; }
private uint dataLengthNeeded; private uint dataLengthNeeded;
private uint originalOffset;
public override bool Compose() public override bool Compose()
{ {
@ -98,7 +208,9 @@ namespace Esiur.Net.Packets
{ {
if (offset + needed > ends) if (offset + needed > ends)
{ {
dataLengthNeeded = needed - (ends - offset); //dataLengthNeeded = needed - (ends - offset);
dataLengthNeeded = needed - (ends - originalOffset);
return true; return true;
} }
else else
@ -107,13 +219,15 @@ namespace Esiur.Net.Packets
public override long Parse(byte[] data, uint offset, uint ends) public override long Parse(byte[] data, uint offset, uint ends)
{ {
var oOffset = offset; originalOffset = offset;
if (NotEnough(offset, ends, 1)) if (NotEnough(offset, ends, 1))
return -dataLengthNeeded; return -dataLengthNeeded;
Command = (IIPPacketCommand)(data[offset] >> 6); PreviousCommand = Command;
Command = (IIPPacketCommand)(data[offset] >> 6);
if (Command == IIPPacketCommand.Event) if (Command == IIPPacketCommand.Event)
{ {
Event = (IIPPacketEvent)(data[offset++] & 0x3f); Event = (IIPPacketEvent)(data[offset++] & 0x3f);
@ -124,8 +238,19 @@ namespace Esiur.Net.Packets
ResourceId = data.GetUInt32(offset); ResourceId = data.GetUInt32(offset);
offset += 4; offset += 4;
} }
else if (Command == IIPPacketCommand.Report)
{
Report = (IIPPacketReport)(data[offset++] & 0x3f);
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
CallbackId = data.GetUInt32(offset);
offset += 4;
}
else else
{ {
PreviousAction = Action;
Action = (IIPPacketAction)(data[offset++] & 0x3f); Action = (IIPPacketAction)(data[offset++] & 0x3f);
if (NotEnough(offset, ends, 4)) if (NotEnough(offset, ends, 4))
@ -150,6 +275,30 @@ namespace Esiur.Net.Packets
{ {
// nothing to parse // nothing to parse
} }
else if (Event == IIPPacketEvent.ChildAdded
|| Event == IIPPacketEvent.ChildRemoved)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ChildId = data.GetUInt32(offset);
offset += 4;
}
else if(Event == IIPPacketEvent.Renamed)
{
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var cl = data.GetUInt16(offset);
offset += 2;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset, cl);
offset += cl;
}
else if (Event == IIPPacketEvent.PropertyUpdated) else if (Event == IIPPacketEvent.PropertyUpdated)
{ {
if (NotEnough(offset, ends, 2)) if (NotEnough(offset, ends, 2))
@ -183,7 +332,7 @@ namespace Esiur.Net.Packets
offset += (uint)size; offset += (uint)size;
} }
} }
else if (Event == IIPPacketEvent.EventOccured) else if (Event == IIPPacketEvent.EventOccurred)
{ {
if (NotEnough(offset, ends, 5)) if (NotEnough(offset, ends, 5))
return -dataLengthNeeded; return -dataLengthNeeded;
@ -197,6 +346,22 @@ namespace Esiur.Net.Packets
offset += cl; offset += cl;
} }
// Attribute
else if (Event == IIPPacketEvent.AttributesUpdated)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
var cl = data.GetUInt32(offset);
offset += 4;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset, cl);
offset += cl;
}
} }
else if (Command == IIPPacketCommand.Request) else if (Command == IIPPacketCommand.Request)
{ {
@ -210,14 +375,14 @@ namespace Esiur.Net.Packets
} }
else if (Action == IIPPacketAction.ReattachResource) else if (Action == IIPPacketAction.ReattachResource)
{ {
if (NotEnough(offset, ends, 8)) if (NotEnough(offset, ends, 12))
return -dataLengthNeeded; return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset); ResourceId = data.GetUInt32(offset);
offset += 4; offset += 4;
ResourceAge = data.GetUInt32(offset); ResourceAge = data.GetUInt64(offset);
offset += 4; offset += 8;
} }
else if (Action == IIPPacketAction.DetachResource) else if (Action == IIPPacketAction.DetachResource)
@ -231,16 +396,21 @@ namespace Esiur.Net.Packets
} }
else if (Action == IIPPacketAction.CreateResource) else if (Action == IIPPacketAction.CreateResource)
{ {
if (NotEnough(offset, ends, 1)) if (NotEnough(offset, ends, 12))
return -dataLengthNeeded; return -dataLengthNeeded;
var cl = data[offset++]; StoreId = data.GetUInt32(offset);
offset += 4;
ResourceId = data.GetUInt32(offset);
offset += 4;
var cl = data.GetUInt32(offset);
offset += 4;
if (NotEnough(offset, ends, cl)) if (NotEnough(offset, ends, cl))
return -dataLengthNeeded; return -dataLengthNeeded;
ClassName = data.GetString(offset, cl); this.Content = data.Clip(offset, cl);
offset += cl;
} }
else if (Action == IIPPacketAction.DeleteResource) else if (Action == IIPPacketAction.DeleteResource)
{ {
@ -251,6 +421,33 @@ namespace Esiur.Net.Packets
offset += 4; offset += 4;
} }
else if (Action == IIPPacketAction.AddChild
|| Action == IIPPacketAction.RemoveChild)
{
if (NotEnough(offset, ends, 8))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
offset += 4;
ChildId = data.GetUInt32(offset);
offset += 4;
}
else if (Action == IIPPacketAction.RenameResource)
{
if (NotEnough(offset, ends, 6))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
offset += 4;
var cl = data.GetUInt16(offset);
offset += 2;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset, cl);
offset += cl;
}
else if (Action == IIPPacketAction.TemplateFromClassName) else if (Action == IIPPacketAction.TemplateFromClassName)
{ {
if (NotEnough(offset, ends, 1)) if (NotEnough(offset, ends, 1))
@ -274,20 +471,6 @@ namespace Esiur.Net.Packets
offset += 16; offset += 16;
} }
else if (Action == IIPPacketAction.TemplateFromResourceLink)
{
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var cl = data.GetUInt16(offset);
offset += 2;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
ResourceLink = data.GetString(offset, cl);
offset += cl;
}
else if (Action == IIPPacketAction.TemplateFromResourceId) else if (Action == IIPPacketAction.TemplateFromResourceId)
{ {
if (NotEnough(offset, ends, 4)) if (NotEnough(offset, ends, 4))
@ -296,7 +479,7 @@ namespace Esiur.Net.Packets
ResourceId = data.GetUInt32(offset); ResourceId = data.GetUInt32(offset);
offset += 4; offset += 4;
} }
else if (Action == IIPPacketAction.ResourceIdFromResourceLink) else if (Action == IIPPacketAction.QueryLink)
{ {
if (NotEnough(offset, ends, 2)) if (NotEnough(offset, ends, 2))
return -dataLengthNeeded; return -dataLengthNeeded;
@ -310,6 +493,30 @@ namespace Esiur.Net.Packets
ResourceLink = data.GetString(offset, cl); ResourceLink = data.GetString(offset, cl);
offset += cl; offset += cl;
} }
else if (Action == IIPPacketAction.ResourceChildren
|| Action == IIPPacketAction.ResourceParents)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
offset += 4;
}
else if (Action == IIPPacketAction.ResourceHistory)
{
if (NotEnough(offset, ends, 20))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
offset += 4;
FromDate = data.GetDateTime(offset);
offset += 8;
ToDate = data.GetDateTime(offset);
offset += 8;
}
else if (Action == IIPPacketAction.InvokeFunction) else if (Action == IIPPacketAction.InvokeFunction)
{ {
if (NotEnough(offset, ends, 9)) if (NotEnough(offset, ends, 9))
@ -351,8 +558,8 @@ namespace Esiur.Net.Packets
MethodIndex = data[offset++]; MethodIndex = data[offset++];
ResourceAge = data.GetUInt32(offset); ResourceAge = data.GetUInt64(offset);
offset += 4; offset += 8;
} }
else if (Action == IIPPacketAction.SetProperty) else if (Action == IIPPacketAction.SetProperty)
@ -392,6 +599,26 @@ namespace Esiur.Net.Packets
offset += (uint)size; offset += (uint)size;
} }
} }
// Attributes
else if (Action == IIPPacketAction.UpdateAllAttributes
|| Action == IIPPacketAction.GetAttributes
|| Action == IIPPacketAction.UpdateAttributes
|| Action == IIPPacketAction.ClearAttributes)
{
if (NotEnough(offset, ends, 8))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
offset += 4;
var cl = data.GetUInt32(offset);
offset += 4;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset, cl);
offset += cl;
}
} }
else if (Command == IIPPacketCommand.Reply) else if (Command == IIPPacketCommand.Reply)
{ {
@ -405,8 +632,8 @@ namespace Esiur.Net.Packets
ClassId = data.GetGuid(offset); ClassId = data.GetGuid(offset);
offset += 16; offset += 16;
ResourceAge = data.GetUInt32(offset); ResourceAge = data.GetUInt64(offset);
offset += 4; offset += 8;
uint cl = data.GetUInt16(offset); uint cl = data.GetUInt16(offset);
offset += 2; offset += 2;
@ -438,8 +665,8 @@ namespace Esiur.Net.Packets
if (NotEnough(offset, ends, 20)) if (NotEnough(offset, ends, 20))
return -dataLengthNeeded; return -dataLengthNeeded;
ClassId = data.GetGuid(offset); //ClassId = data.GetGuid(offset);
offset += 16; //offset += 16;
ResourceId = data.GetUInt32(offset); ResourceId = data.GetUInt32(offset);
offset += 4; offset += 4;
@ -449,10 +676,17 @@ namespace Esiur.Net.Packets
{ {
// nothing to do // nothing to do
} }
// Inquire
else if (Action == IIPPacketAction.TemplateFromClassName else if (Action == IIPPacketAction.TemplateFromClassName
|| Action == IIPPacketAction.TemplateFromClassId || Action == IIPPacketAction.TemplateFromClassId
|| Action == IIPPacketAction.TemplateFromResourceLink || Action == IIPPacketAction.TemplateFromResourceId
|| Action == IIPPacketAction.TemplateFromResourceId) || Action == IIPPacketAction.QueryLink
|| Action == IIPPacketAction.ResourceChildren
|| Action == IIPPacketAction.ResourceParents
|| Action == IIPPacketAction.ResourceHistory
// Attribute
|| Action == IIPPacketAction.GetAllAttributes
|| Action == IIPPacketAction.GetAttributes)
{ {
if (NotEnough(offset, ends, 4)) if (NotEnough(offset, ends, 4))
return -dataLengthNeeded; return -dataLengthNeeded;
@ -466,20 +700,6 @@ namespace Esiur.Net.Packets
Content = data.Clip(offset, cl); Content = data.Clip(offset, cl);
offset += cl; offset += cl;
} }
else if (Action == IIPPacketAction.ResourceIdFromResourceLink)
{
if (NotEnough(offset, ends, 24))
return -dataLengthNeeded;
ClassId = data.GetGuid(offset);
offset += 16;
ResourceId = data.GetUInt32(offset);
offset += 4;
ResourceAge = data.GetUInt32(offset);
offset += 4;
}
else if (Action == IIPPacketAction.InvokeFunction else if (Action == IIPPacketAction.InvokeFunction
|| Action == IIPPacketAction.GetProperty || Action == IIPPacketAction.GetProperty
|| Action == IIPPacketAction.GetPropertyIfModified) || Action == IIPPacketAction.GetPropertyIfModified)
@ -518,33 +738,80 @@ namespace Esiur.Net.Packets
// nothing to do // nothing to do
} }
} }
else if (Command == IIPPacketCommand.Error) else if (Command == IIPPacketCommand.Report)
{ {
// Error if (Report == IIPPacketReport.ManagementError)
if (NotEnough(offset, ends, 4)) {
return -dataLengthNeeded; if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
CallbackId = data.GetUInt32(offset); ErrorCode = data.GetUInt16(offset);
offset += 2;
}
else if (Report == IIPPacketReport.ExecutionError)
{
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
if (NotEnough(offset, ends, 1)) ErrorCode = data.GetUInt16(offset);
return -dataLengthNeeded; offset += 2;
ErrorCode = data[offset++]; if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
if (NotEnough(offset, ends, 4)) var cl = data.GetUInt16(offset);
return -dataLengthNeeded; offset += 2;
var cl = data.GetUInt32(offset); if (NotEnough(offset, ends, cl))
offset += 4; return -dataLengthNeeded;
if (NotEnough(offset, ends, cl)) ErrorMessage = data.GetString(offset, cl);
return -dataLengthNeeded; offset += cl;
}
else if (Report == IIPPacketReport.ProgressReport)
{
if (NotEnough(offset, ends, 8))
return -dataLengthNeeded;
ErrorMessage = data.GetString(offset, cl); ProgressValue = data.GetInt32(offset);
offset += cl; offset += 4;
ProgressMax = data.GetInt32(offset);
offset += 4;
}
else if (Report == IIPPacketReport.ChunkStream)
{
if (NotEnough(offset, ends, 1))
return -dataLengthNeeded;
var dt = (DataType)data[offset++];
var size = dt.Size();// Codec.SizeOf(dt);
if (size < 0)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
var cl = data.GetUInt32(offset);
offset += 4;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset - 5, cl + 5);
offset += cl;
}
else
{
if (NotEnough(offset, ends, (uint)size))
return -dataLengthNeeded;
Content = data.Clip(offset - 1, (uint)size + 1);
offset += (uint)size;
}
}
} }
return offset - oOffset; return offset - originalOffset;
} }
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -138,9 +162,10 @@ namespace Esiur.Net.Packets
offset += 8; offset += 8;
} }
/*
if (Mask) if (Mask)
{ {
MaskKey = new byte[4]; MaskKey = new byte[4];
MaskKey[0] = data[offset++]; MaskKey[0] = data[offset++];
MaskKey[1] = data[offset++]; MaskKey[1] = data[offset++];
MaskKey[2] = data[offset++]; MaskKey[2] = data[offset++];
@ -149,6 +174,7 @@ namespace Esiur.Net.Packets
//MaskKey = DC.GetUInt32(data, offset); //MaskKey = DC.GetUInt32(data, offset);
//offset += 4; //offset += 4;
} }
*/
needed += PayloadLength; needed += PayloadLength;
if (length < needed) if (length < needed)
@ -156,23 +182,26 @@ namespace Esiur.Net.Packets
//Console.WriteLine("stage 4"); //Console.WriteLine("stage 4");
return length - needed; return length - needed;
} }
// if ((int)PayloadLength > (ends - offset))
// {
// return -((int)PayloadLength - (ends - offset));
// }
else else
{ {
Message = DC.Clip(data, offset, (uint)PayloadLength);
if (Mask) if (Mask)
{ {
MaskKey = new byte[4];
MaskKey[0] = data[offset++];
MaskKey[1] = data[offset++];
MaskKey[2] = data[offset++];
MaskKey[3] = data[offset++];
Message = DC.Clip(data, offset, (uint)PayloadLength);
//var aMask = BitConverter.GetBytes(MaskKey); //var aMask = BitConverter.GetBytes(MaskKey);
for (int i = 0; i < Message.Length; i++) for (int i = 0; i < Message.Length; i++)
{
Message[i] = (byte)(Message[i] ^ MaskKey[i % 4]); Message[i] = (byte)(Message[i] ^ MaskKey[i % 4]);
}
} }
else
Message = DC.Clip(data, offset, (uint)PayloadLength);
return (offset - oOffset) + (int)PayloadLength; return (offset - oOffset) + (int)PayloadLength;
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.IO; using System.IO;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -27,7 +51,7 @@ namespace Esiur.Net.Sockets
Queue<byte[]> sendBufferQueue = new Queue<byte[]>(); Queue<byte[]> sendBufferQueue = new Queue<byte[]>();
bool asyncSending; bool asyncSending;
bool began = false;
SocketState state = SocketState.Initial; SocketState state = SocketState.Initial;
@ -36,6 +60,7 @@ namespace Esiur.Net.Sockets
public event ISocketCloseEvent OnClose; public event ISocketCloseEvent OnClose;
public event DestroyedEvent OnDestroy; public event DestroyedEvent OnDestroy;
SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs();
private void Connected(Task t) private void Connected(Task t)
{ {
@ -46,7 +71,18 @@ namespace Esiur.Net.Sockets
public bool Begin() public bool Begin()
{ {
sock.ReceiveAsync(receiveBufferSegment, SocketFlags.None).ContinueWith(DataReceived); if (began)
return false;
began = true;
socketArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
socketArgs.Completed += SocketArgs_Completed;
if (!sock.ReceiveAsync(socketArgs))
SocketArgs_Completed(null, socketArgs);
//sock.ReceiveAsync(receiveBufferSegment, SocketFlags.None).ContinueWith(DataReceived);
return true; return true;
} }
@ -80,11 +116,21 @@ namespace Esiur.Net.Sockets
return; return;
} }
//if (receiveNetworkBuffer.Protected)
// Console.WriteLine();
//lock (receiveNetworkBuffer.SyncLock)
receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)task.Result); receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)task.Result);
//Console.WriteLine("TC IN: " + (uint)task.Result + " " + DC.ToHex(receiveBuffer, 0, (uint)task.Result));
OnReceive?.Invoke(receiveNetworkBuffer); OnReceive?.Invoke(receiveNetworkBuffer);
if (state == SocketState.Established) if (state == SocketState.Established)
{
sock.ReceiveAsync(receiveBufferSegment, SocketFlags.None).ContinueWith(DataReceived); sock.ReceiveAsync(receiveBufferSegment, SocketFlags.None).ContinueWith(DataReceived);
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -98,6 +144,56 @@ namespace Esiur.Net.Sockets
} }
} }
private void SocketArgs_Completed(object sender, SocketAsyncEventArgs e)
{
try
{
// SocketError err;
if (state == SocketState.Closed || state == SocketState.Terminated)
return;
if (e.BytesTransferred == 0)
{
Close();
return;
}
//if (receiveNetworkBuffer.Protected)
// Console.WriteLine();
//lock (receiveNetworkBuffer.SyncLock)
receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)e.BytesTransferred);
//Console.WriteLine("TC IN: " + (uint)e.BytesTransferred + " " + DC.ToHex(receiveBuffer, 0, (uint)e.BytesTransferred));
OnReceive?.Invoke(receiveNetworkBuffer);
if (state == SocketState.Established)
{
if (!sock.ReceiveAsync(socketArgs))
{
//Console.WriteLine("Sync");
SocketArgs_Completed(sender, e);
}
}
}
catch (Exception ex)
{
if (state != SocketState.Closed && !sock.Connected)
{
state = SocketState.Terminated;
Close();
}
Global.Log("TCPSocket", LogType.Error, ex.ToString());
}
}
public IPEndPoint LocalEndPoint public IPEndPoint LocalEndPoint
{ {
@ -234,18 +330,19 @@ namespace Esiur.Net.Sockets
public void Send(byte[] message, int offset, int size) public void Send(byte[] message, int offset, int size)
{ {
lock (sendLock) if (sock.Connected)
{ lock (sendLock)
if (asyncSending)
{ {
sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size)); if (asyncSending)
{
sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size));
}
else
{
asyncSending = true;
sock.SendAsync(new ArraySegment<byte>(message, offset, size), SocketFlags.None).ContinueWith(DataSent);
}
} }
else
{
asyncSending = true;
sock.SendAsync(new ArraySegment<byte>(message, offset, size), SocketFlags.None).ContinueWith(DataSent);
}
}
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -9,6 +33,7 @@ using Esiur.Misc;
using System.IO; using System.IO;
using Esiur.Engine; using Esiur.Engine;
using Esiur.Resource; using Esiur.Resource;
using Esiur.Data;
namespace Esiur.Net.Sockets namespace Esiur.Net.Sockets
{ {
@ -28,6 +53,8 @@ namespace Esiur.Net.Sockets
long totalSent, totalReceived; long totalSent, totalReceived;
bool processing = false;
public IPEndPoint LocalEndPoint public IPEndPoint LocalEndPoint
{ {
get { return (IPEndPoint)sock.LocalEndPoint; } get { return (IPEndPoint)sock.LocalEndPoint; }
@ -70,9 +97,17 @@ namespace Esiur.Net.Sockets
if (buffer.Protected) if (buffer.Protected)
return; return;
if (processing)
return;
var msg = buffer.Read(); var msg = buffer.Read();
if (msg == null)
return;
var wsPacketLength = pkt_receive.Parse(msg, 0, (uint)msg.Length); var wsPacketLength = pkt_receive.Parse(msg, 0, (uint)msg.Length);
//Console.WriteLine("WSP: " + wsPacketLength);
if (wsPacketLength < 0) if (wsPacketLength < 0)
{ {
@ -114,12 +149,16 @@ namespace Esiur.Net.Sockets
receiveNetworkBuffer.Write(pkt_receive.Message); receiveNetworkBuffer.Write(pkt_receive.Message);
offset += (uint)wsPacketLength; offset += (uint)wsPacketLength;
//Console.WriteLine("WS IN: " + pkt_receive.Opcode.ToString() + " " + pkt_receive.Message.Length + " | " + offset + " " + string.Join(" ", pkt_receive.Message));// DC.ToHex(pkt_receive.Message));
} }
else else
Console.WriteLine("Unknown WS opcode:" + pkt_receive.Opcode); Console.WriteLine("Unknown WS opcode:" + pkt_receive.Opcode);
if (offset == msg.Length) if (offset == msg.Length)
{ {
// Console.WriteLine("WS IN: " + receiveNetworkBuffer.Available);
OnReceive?.Invoke(receiveNetworkBuffer); OnReceive?.Invoke(receiveNetworkBuffer);
return; return;
} }
@ -132,11 +171,18 @@ namespace Esiur.Net.Sockets
//receiveNetworkBuffer.HoldFor(msg, offset, (uint)(msg.Length - offset), (uint)msg.Length + (uint)-wsPacketLength); //receiveNetworkBuffer.HoldFor(msg, offset, (uint)(msg.Length - offset), (uint)msg.Length + (uint)-wsPacketLength);
// save the incomplete packet to the heldBuffer queue // save the incomplete packet to the heldBuffer queue
receiveNetworkBuffer.HoldFor(msg, offset, (uint)(msg.Length - offset), (uint)(msg.Length - offset) + (uint)-wsPacketLength); buffer.HoldFor(msg, offset, (uint)(msg.Length - offset), (uint)(msg.Length - offset) + (uint)-wsPacketLength);
} }
//Console.WriteLine("WS IN: " + receiveNetworkBuffer.Available);
OnReceive?.Invoke(receiveNetworkBuffer); OnReceive?.Invoke(receiveNetworkBuffer);
processing = false;
if (buffer.Available > 0 && !buffer.Protected)
Sock_OnReceive(buffer);
} }
private void Sock_OnConnect() private void Sock_OnConnect()

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,3 +1,27 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System; using System;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Release</Configuration>
<TargetFramework>netstandard1.5</TargetFramework>
<PublishDir>M:\opt\esiur</PublishDir>
<Platform>Any CPU</Platform>
</PropertyGroup>
</Project>

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,30 @@
using Esiur.Engine; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine;
using Esiur.Resource.Template;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -13,5 +39,15 @@ namespace Esiur.Resource
AsyncReply<IResource> Retrieve(uint iid); AsyncReply<IResource> Retrieve(uint iid);
bool Put(IResource resource); bool Put(IResource resource);
string Link(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);
bool Remove(IResource resource);
//AsyncReply<PropertyValue[]> GetPropertyRecord(IResource resource, string propertyName, ulong fromAge, ulong toAge);
//AsyncReply<PropertyValue[]> GetPropertyRecordByDate(IResource resource, string propertyName, DateTime fromDate, DateTime toDate);
//AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, ulong fromAge, ulong toAge);
// AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecordByDate(IResource resource, DateTime fromDate, DateTime toDate);
AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, DateTime fromDate, DateTime toDate);
} }
} }

View File

@ -10,6 +10,7 @@ using Esiur.Net.IIP;
using Esiur.Misc; using Esiur.Misc;
using Esiur.Security.Permissions; using Esiur.Security.Permissions;
using Esiur.Resource.Template; using Esiur.Resource.Template;
using Esiur.Security.Authority;
namespace Esiur.Resource namespace Esiur.Resource
{ {
@ -21,27 +22,33 @@ namespace Esiur.Resource
IResource resource; IResource resource;
IStore store; IStore store;
AutoList<IResource, Instance> parents;// = new AutoList<IResource>(); AutoList<IResource, Instance> parents;// = new AutoList<IResource>();
bool inherit; //bool inherit;
ResourceTemplate template; ResourceTemplate template;
AutoList<IPermissionManager, Instance> managers;// = new AutoList<IPermissionManager, Instance>(); AutoList<IPermissionsManager, Instance> managers;// = new AutoList<IPermissionManager, Instance>();
public delegate void ResourceModifiedEvent(IResource resource, string propertyName, object newValue);
//public delegate void ResourceEventOccurredEvent(IResource resource, string eventName, string[] users, DistributedConnection[] connections, object[] args);
public delegate void ResourceEventOccurredEvent(IResource resource, object issuer, Session[] receivers, string eventName, object[] args);
public delegate void ResourceModifiedEvent(IResource resource, string propertyName, object newValue, object oldValue);
public delegate void ResourceEventOccurredEvent(IResource resource, string eventName, string[] receivers, object[] args);
public delegate void ResourceDestroyedEvent(IResource resource); public delegate void ResourceDestroyedEvent(IResource resource);
public event ResourceModifiedEvent ResourceModified; public event ResourceModifiedEvent ResourceModified;
public event ResourceEventOccurredEvent ResourceEventOccured; public event ResourceEventOccurredEvent ResourceEventOccurred;
public event ResourceDestroyedEvent ResourceDestroyed; public event ResourceDestroyedEvent ResourceDestroyed;
KeyList<string, object> attributes = new KeyList<string, object>(); KeyList<string, object> attributes;
List<uint> ages = new List<uint>(); List<ulong> ages = new List<ulong>();
private uint age; List<DateTime> modificationDates = new List<DateTime>();
private ulong instanceAge;
private DateTime instanceModificationDate;
uint id; uint id;
/// <summary> /// <summary>
/// Instance attributes are custom properties associated with the instance, a place to store information by IStore. /// Instance attributes are custom properties associated with the instance, a place to store information by IStore.
/// </summary> /// </summary>
@ -53,12 +60,151 @@ namespace Esiur.Resource
} }
} }
public override string ToString()
{
return name + " (" + Link + ")";
}
public bool RemoveAttributes(string[] attributes = null)
{
if (attributes == null)
this.attributes.Clear();
else
{
foreach (var attr in attributes)
this.attributes.Remove(attr);
}
return true;
}
public Structure GetAttributes(string[] attributes = null)
{
var st = new Structure();
if (attributes == null)
{
var clone = this.attributes.Keys.ToList();
clone.Add("managers");
attributes = clone.ToArray();// this.attributes.Keys.ToList().Add("managers");
}
foreach(var attr in attributes)
{
if (attr == "name")
st["name"] = this.name;
else if (attr == "managers")
{
var mngrs = new List<Structure>();
foreach (var manager in this.managers)
mngrs.Add(new Structure()
{
["type"] = manager.GetType().FullName + "," + manager.GetType().GetTypeInfo().Assembly.GetName().Name,
["settings"] = manager.Settings
});
st["managers"] = mngrs.ToArray();
}
else if (attr == "parents")
{
st["parents"] = parents.ToArray();
}
else if (attr == "children")
{
st["children"] = children.ToArray();
}
else if (attr == "childrenCount")
{
st["childrenCount"] = children.Count;
}
else if (attr == "type")
{
st["type"] = resource.GetType().FullName;
}
else
st[attr] = this.attributes[attr];
}
return st;
}
public bool SetAttributes(Structure attributes, bool clearAttributes = false)
{
try
{
if (clearAttributes)
this.attributes.Clear();
foreach (var attr in attributes)
if (attr.Key == "name")
this.name = attr.Value as string;
else if (attr.Key == "managers")
{
this.managers.Clear();
var mngrs = attr.Value as object[];
foreach (var mngr in mngrs)
{
var m = mngr as Structure;
var type = Type.GetType(m["type"] as string);
if (Codec.ImplementsInterface(type, typeof(IPermissionsManager)))
{
var settings = m["settings"] as Structure;
var manager = Activator.CreateInstance(type) as IPermissionsManager;
manager.Initialize(settings, this.resource);
this.managers.Add(manager);
}
else
return false;
}
}
else
{
this.attributes[attr.Key] = attr.Value;
}
}
catch
{
return false;
}
return true;
}
/*
public Structure GetAttributes()
{
var st = new Structure();
foreach (var a in attributes.Keys)
st[a] = attributes[a];
st["name"] = name;
var mngrs = new List<Structure>();
foreach (var manager in managers)
{
var mngr = new Structure();
mngr["settings"] = manager.Settings;
mngr["type"] = manager.GetType().FullName;
mngrs.Add(mngr);
}
st["managers"] = mngrs;
return st;
}*/
/// <summary> /// <summary>
/// Get the age of a given property index. /// Get the age of a given property index.
/// </summary> /// </summary>
/// <param name="index">Zero-based property index.</param> /// <param name="index">Zero-based property index.</param>
/// <returns>Age.</returns> /// <returns>Age.</returns>
public uint GetAge(byte index) public ulong GetAge(byte index)
{ {
if (index < ages.Count) if (index < ages.Count)
return ages[index]; return ages[index];
@ -67,12 +213,107 @@ namespace Esiur.Resource
} }
/// <summary> /// <summary>
/// Age of the instance, increments by 1 in every modification. /// Set the age of a property.
/// </summary> /// </summary>
public uint Age /// <param name="index">Zero-based property index.</param>
/// <param name="value">Age.</param>
public void SetAge(byte index, ulong value)
{ {
get { return age; } if (index < ages.Count)
internal set { age = value; } {
ages[index] = value;
if (value > instanceAge)
instanceAge = value;
}
}
/// <summary>
/// Set the modification date of a property.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Modification date.</param>
public void SetModificationDate(byte index, DateTime value)
{
if (index < modificationDates.Count)
{
modificationDates[index] = value;
if (value > instanceModificationDate)
instanceModificationDate = value;
}
}
/// <summary>
/// Get modification date of a specific property.
/// </summary>
/// <param name="index">Zero-based property index</param>
/// <returns>Modification date.</returns>
public DateTime GetModificationDate(byte index)
{
if (index < modificationDates.Count)
return modificationDates[index];
else
return DateTime.MinValue;
}
/// <summary>
/// Load property value (used by stores)
/// </summary>
/// <param name="name">Property name</param>
/// <param name="age">Property age</param>
/// <param name="value">Property value</param>
/// <returns></returns>
public bool LoadProperty(string name, ulong age, DateTime modificationDate, object value)
{
var pt = template.GetPropertyTemplate(name);
if (pt == null)
return false;
#if NETSTANDARD1_5
var pi = resource.GetType().GetTypeInfo().GetProperty(name);
#else
var pi = resource.GetType().GetProperty(pt.Name);
#endif
if (pi.PropertyType == typeof(DistributedPropertyContext))
return false;
try
{
if (pi.CanWrite)
pi.SetValue(resource, DC.CastConvert(value, pi.PropertyType));
}
catch(Exception ex)
{
//Console.WriteLine(resource.ToString() + " " + name);
Global.Log(ex);
}
SetAge(pt.Index, age);
SetModificationDate(pt.Index, modificationDate);
return true;
}
/// <summary>
/// Age of the instance, incremented by 1 in every modification.
/// </summary>
public ulong Age
{
get { return instanceAge; }
internal set { instanceAge = value; }
}
/// <summary>
/// Last modification date.
/// </summary>
public DateTime ModificationDate
{
get
{
return instanceModificationDate;
}
} }
/// <summary> /// <summary>
@ -88,18 +329,18 @@ namespace Esiur.Resource
/// </summary> /// </summary>
/// <param name="properties"></param> /// <param name="properties"></param>
/// <returns></returns> /// <returns></returns>
public bool Deserialize(object[] properties) public bool Deserialize(PropertyValue[] properties)
{ {
foreach (var pt in template.Properties) for (byte i = 0; i < properties.Length; i++)
{ {
#if NETSTANDARD1_5 var pt = this.template.GetPropertyTemplate(i);
var pi = resource.GetType().GetTypeInfo().GetProperty(pt.Name); if (pt != null)
#else {
var pi = resource.GetType().GetProperty(pt.Name); var pv = properties[i];
#endif LoadProperty(pt.Name, pv.Age, pv.Date, pv.Value);
if (!(properties[pt.Index] is NotModified)) }
pi.SetValue(resource, properties[pt.Index]);
} }
return true; return true;
} }
@ -107,9 +348,9 @@ namespace Esiur.Resource
/// Export all properties with ResourceProperty attributed as bytes array. /// Export all properties with ResourceProperty attributed as bytes array.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public object[] Serialize() public PropertyValue[] Serialize()
{ {
List<object> props = new List<object>(); List<PropertyValue> props = new List<PropertyValue>();
foreach (var pt in template.Properties) foreach (var pt in template.Properties)
{ {
@ -119,7 +360,7 @@ namespace Esiur.Resource
var pi = resource.GetType().GetProperty(pt.Name); var pi = resource.GetType().GetProperty(pt.Name);
#endif #endif
var rt = pi.GetValue(resource, null); var rt = pi.GetValue(resource, null);
props.Add(rt); props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
} }
return props.ToArray(); return props.ToArray();
@ -191,10 +432,10 @@ namespace Esiur.Resource
} }
*/ */
/// <summary> /// <summary>
/// If True, the instance can be stored to disk. /// If True, the instance can be stored to disk.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public bool IsStorable() public bool IsStorable()
{ {
#if NETSTANDARD1_5 #if NETSTANDARD1_5
@ -207,27 +448,47 @@ namespace Esiur.Resource
} }
internal void EmitModification(PropertyTemplate pt, object value)
{
instanceAge++;
var now = DateTime.UtcNow;
ages[pt.Index] = instanceAge;
modificationDates[pt.Index] = now;
if (pt.Storage == StorageMode.NonVolatile)
{
store.Modify(resource, pt.Name, value, ages[pt.Index], now);
}
else if (pt.Storage == StorageMode.Recordable)
{
store.Record(resource, pt.Name, value, ages[pt.Index], now);
}
ResourceModified?.Invoke(resource, pt.Name, value);
}
/// <summary> /// <summary>
/// Notify listeners that a property was modified. /// Notify listeners that a property was modified.
/// </summary> /// </summary>
/// <param name="propertyName"></param> /// <param name="propertyName"></param>
/// <param name="newValue"></param> /// <param name="newValue"></param>
/// <param name="oldValue"></param> /// <param name="oldValue"></param>
public void Modified([CallerMemberName] string propertyName = "", object newValue = null, object oldValue = null) public void Modified([CallerMemberName] string propertyName = "")//, object newValue = null)//, object oldValue = null)
{ {
if (newValue == null) object value;
if (GetPropertyValue(propertyName, out value))
{ {
object val; var pt = template.GetPropertyTemplate(propertyName);
if (GetPropertyValue(propertyName, out val)) EmitModification(pt, value);
ResourceModified?.Invoke(resource, propertyName, val, oldValue);
} }
else
ResourceModified?.Invoke(resource, propertyName, newValue, oldValue);
} }
internal void EmitResourceEvent(string name, string[] receivers, object[] args) // internal void EmitResourceEvent(string name, string[] users, DistributedConnection[] connections, object[] args)
internal void EmitResourceEvent(object issuer, Session[] receivers, string name, object[] args)
{ {
ResourceEventOccured?.Invoke(resource, name, receivers, args); ResourceEventOccurred?.Invoke(resource, issuer, receivers, name, args);
} }
/// <summary> /// <summary>
@ -259,7 +520,7 @@ namespace Esiur.Resource
{ {
value = pi.GetValue(resource, null); value = pi.GetValue(resource, null);
//if (value is Func<IManager, object>) //if (value is Func<IManager, object>)
// value = (value as Func<IManager, object>)(sender); // value = (value as Func<IManager, object>)(sender);
return true; return true;
} }
} }
@ -269,10 +530,11 @@ namespace Esiur.Resource
} }
/*
public bool Inherit public bool Inherit
{ {
get { return inherit; } get { return inherit; }
} }*/
/// <summary> /// <summary>
/// List of parents. /// List of parents.
@ -289,7 +551,7 @@ namespace Esiur.Resource
{ {
get { return store; } get { return store; }
} }
/// <summary> /// <summary>
/// List of children. /// List of children.
/// </summary> /// </summary>
@ -335,6 +597,7 @@ namespace Esiur.Resource
public string Name public string Name
{ {
get { return name; } get { return name; }
set { name = value; }
} }
@ -352,38 +615,86 @@ namespace Esiur.Resource
public ResourceTemplate Template public ResourceTemplate Template
{ {
get { return template; } get { return template; }
/*
internal set
{
template = Warehouse.GetTemplate(resource.GetType());
// set ages
for (byte i = 0; i < template.Properties.Length; i++)
{
ages.Add(0);
modificationDates.Add(DateTime.MinValue);
}
}
*/
} }
/// <summary> /// <summary>
/// Create new instance. /// Check for permission.
/// </summary> /// </summary>
/// <param name="id">Instance Id.</param> /// <param name="session">Caller sessions.</param>
/// <param name="name">Name of the instance.</param> /// <param name="action">Action type</param>
/// <param name="resource">Resource to manage.</param> /// <param name="member">Function, property or event to check for permission.</param>
/// <param name="store">Store responsible for the resource.</param> /// <param name="inquirer">Permission inquirer.</param>
public Instance(uint id, string name, IResource resource, IStore store) /// <returns>Ruling.</returns>
public Ruling Applicable(Session session, ActionType action, MemberTemplate member, object inquirer = null)
{
foreach (IPermissionsManager manager in managers)
{
var r = manager.Applicable(this.resource, session, action, member, inquirer);
if (r != Ruling.DontCare)
return r;
}
return Ruling.DontCare;
}
/// <summary>
/// Execution managers.
/// </summary>
public AutoList<IPermissionsManager, Instance> Managers => managers;
/// <summary>
/// Create new instance.
/// </summary>
/// <param name="id">Instance Id.</param>
/// <param name="name">Name of the instance.</param>
/// <param name="resource">Resource to manage.</param>
/// <param name="store">Store responsible for the resource.</param>
public Instance(uint id, string name, IResource resource, IStore store, ResourceTemplate customTemplate = null, ulong age = 0)
{ {
this.store = store; this.store = store;
this.resource = resource; this.resource = resource;
this.id = id; this.id = id;
this.name = name; this.name = name;
this.instanceAge = age;
this.attributes = new KeyList<string, object>(this);
children = new AutoList<IResource, Instance>(this); children = new AutoList<IResource, Instance>(this);
parents = new AutoList<IResource, Instance>(this); parents = new AutoList<IResource, Instance>(this);
managers = new AutoList<IPermissionManager, Instance>(this); managers = new AutoList<IPermissionsManager, Instance>(this);
children.OnAdd += Children_OnAdd; children.OnAdd += Children_OnAdd;
children.OnRemoved += Children_OnRemoved; children.OnRemoved += Children_OnRemoved;
parents.OnAdd += Parents_OnAdd;
parents.OnRemoved += Parents_OnRemoved;
resource.OnDestroy += Resource_OnDestroy; resource.OnDestroy += Resource_OnDestroy;
template = Warehouse.GetTemplate(resource.GetType()); if (customTemplate != null)
this.template = customTemplate;
else
// set ages this.template = Warehouse.GetTemplate(resource.GetType());
// set ages
for (byte i = 0; i < template.Properties.Length; i++) for (byte i = 0; i < template.Properties.Length; i++)
{
ages.Add(0); ages.Add(0);
modificationDates.Add(DateTime.MinValue);
}
// connect events // connect events
Type t = resource.GetType(); Type t = resource.GetType();
@ -396,16 +707,62 @@ namespace Esiur.Resource
foreach (var evt in events) foreach (var evt in events)
{ {
if (evt.EventHandlerType != typeof(ResourceEventHanlder)) //if (evt.EventHandlerType != typeof(ResourceEventHanlder))
continue; // continue;
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0) if (evt.EventHandlerType == typeof(ResourceEventHanlder))
continue; {
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
ResourceEventHanlder proxyDelegate = (args) => EmitResourceEvent(null, null, evt.Name, args);
evt.AddEventHandler(resource, proxyDelegate);
}
else if (evt.EventHandlerType == typeof(CustomResourceEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
CustomResourceEventHanlder proxyDelegate = (issuer, receivers, args) => EmitResourceEvent(issuer, receivers, evt.Name, args);
evt.AddEventHandler(resource, proxyDelegate);
}
/*
else if (evt.EventHandlerType == typeof(CustomUsersEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
CustomUsersEventHanlder proxyDelegate = (users, args) => EmitResourceEvent(evt.Name, users, null, args);
evt.AddEventHandler(resource, proxyDelegate);
}
else if (evt.EventHandlerType == typeof(CustomConnectionsEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
CustomConnectionsEventHanlder proxyDelegate = (connections, args) => EmitResourceEvent(evt.Name, null, connections, args);
evt.AddEventHandler(resource, proxyDelegate);
}
else if (evt.EventHandlerType == typeof(CustomReceiversEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
CustomReceiversEventHanlder proxyDelegate = (users, connections, args) => EmitResourceEvent(evt.Name, users, connections, args);
evt.AddEventHandler(resource, proxyDelegate);
}
*/
ResourceEventHanlder proxyDelegate = (receivers, args) => EmitResourceEvent(evt.Name, receivers, args);
evt.AddEventHandler(resource, proxyDelegate);
} }
} }
@ -416,9 +773,22 @@ namespace Esiur.Resource
private void Children_OnAdd(Instance parent, IResource value) private void Children_OnAdd(Instance parent, IResource value)
{ {
value.Instance.parents.Add(resource); if (!value.Instance.parents.Contains(resource))
value.Instance.parents.Add(resource);
} }
private void Parents_OnRemoved(Instance parent, IResource value)
{
value.Instance.children.Remove(resource);
}
private void Parents_OnAdd(Instance parent, IResource value)
{
if (!value.Instance.children.Contains(resource))
value.Instance.children.Add(resource);
}
private void Resource_OnDestroy(object sender) private void Resource_OnDestroy(object sender)
{ {
ResourceDestroyed?.Invoke((IResource)sender); ResourceDestroyed?.Invoke((IResource)sender);

View File

@ -0,0 +1,47 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using Esiur.Engine;
namespace Esiur.Resource
{
public class Resource : IResource
{
public Instance Instance { get; set; }
public event DestroyedEvent OnDestroy;
public virtual void Destroy()
{
}
public virtual AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
return new AsyncReply<bool>(true);
}
}
}

View File

@ -1,4 +1,27 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,5 +1,30 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine; using Esiur.Engine;
using Esiur.Net.IIP;
using Esiur.Security.Authority;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -8,6 +33,13 @@ using System.Threading.Tasks;
namespace Esiur.Resource namespace Esiur.Resource
{ {
public delegate void ResourceEventHanlder(string[] receivers, params object[] args); public delegate void ResourceEventHanlder(params object[] args);
// public delegate void CustomUsersEventHanlder(string[] usernames, params object[] args);
//public delegate void CustomReceiversEventHanlder(DistributedConnection[] connections, params object[] args);
//public delegate void CustomInquirerEventHanlder(object inquirer, params object[] args);
public delegate void CustomResourceEventHanlder(object issuer, Session[] receivers, params object[] args);
// public delegate void CustomReceiversEventHanlder(string[] usernames, DistributedConnection[] connections, params object[] args);
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,29 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Resource.Template;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -12,7 +37,15 @@ namespace Esiur.Resource
{ {
string readExpansion; string readExpansion;
string writeExpansion; string writeExpansion;
// bool recordable;
//bool storable;
//public bool Recordable => recordable;
//public bool Storable => storable;
StorageMode storage;
public StorageMode Storage => storage;
public string ReadExpansion public string ReadExpansion
{ {
@ -30,10 +63,11 @@ namespace Esiur.Resource
} }
} }
public ResourceProperty(string readExpansion = null, string writeExpansion = null) public ResourceProperty(StorageMode storage = StorageMode.Volatile, string readExpansion = null, string writeExpansion = null)
{ {
this.readExpansion = readExpansion; this.readExpansion = readExpansion;
this.writeExpansion = writeExpansion; this.writeExpansion = writeExpansion;
this.storage = storage;
} }
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine; using Esiur.Engine;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Resource
{
public enum StorageMode : byte
{
Volatile = 0,
NonVolatile,
Recordable
}
}

View File

@ -28,6 +28,11 @@ namespace Esiur.Resource.Template
return BinaryList.ToBytes((byte)0x40, (byte)name.Length, name); return BinaryList.ToBytes((byte)0x40, (byte)name.Length, name);
} }
public EventTemplate() { Type = MemberType.Event; }
public EventTemplate(ResourceTemplate template, byte index, string name, string expansion)
:base(template, MemberType.Property, index, name)
{
this.Expansion = expansion;
}
} }
} }

View File

@ -37,6 +37,11 @@ namespace Esiur.Resource.Template
} }
public FunctionTemplate() { Type = MemberType.Function; } public FunctionTemplate(ResourceTemplate template, byte index, string name,bool isVoid, string expansion)
:base(template, MemberType.Property, index, name)
{
this.IsVoid = isVoid;
this.Expansion = expansion;
}
} }
} }

View File

@ -16,9 +16,26 @@ namespace Esiur.Resource.Template
Event = 2, Event = 2,
} }
public byte Index { get; set; } public byte Index => index;
public string Name { get; set; } public string Name => name;
public MemberType Type { get; set; } public MemberType Type => type;
ResourceTemplate template;
string name;
MemberType type;
byte index;
public ResourceTemplate Template => template;
public MemberTemplate(ResourceTemplate template, MemberType type, byte index, string name)
{
this.template = template;
this.type = type;
this.index = index;
this.name = name;
}
public string Fullname => template.ClassName + "." + Name;
public virtual byte[] Compose() public virtual byte[] Compose()
{ {

View File

@ -16,13 +16,27 @@ namespace Esiur.Resource.Template
ReadWrite ReadWrite
} }
//bool ReadOnly; //bool ReadOnly;
//IIPTypes::DataType ReturnType; //IIPTypes::DataType ReturnType;
public PropertyPermission Permission { public PropertyPermission Permission {
get; get;
set; set;
} }
/*
public bool Recordable
{
get;
set;
}*/
public StorageMode Storage
{
get;
set;
}
public string ReadExpansion public string ReadExpansion
{ {
get; get;
@ -35,37 +49,46 @@ namespace Esiur.Resource.Template
set; set;
} }
/*
public bool Storable public bool Storable
{ {
get; get;
set; set;
} }*/
public override byte[] Compose() public override byte[] Compose()
{ {
var name = base.Compose(); var name = base.Compose();
var pv = ((byte)(Permission) << 1) | (Storage == StorageMode.Recordable ? 1 : 0);
if (WriteExpansion != null && ReadExpansion != null) if (WriteExpansion != null && ReadExpansion != null)
{ {
var rexp = DC.ToBytes(ReadExpansion); var rexp = DC.ToBytes(ReadExpansion);
var wexp = DC.ToBytes(WriteExpansion); var wexp = DC.ToBytes(WriteExpansion);
return BinaryList.ToBytes((byte)(0x38 | (byte)Permission), wexp.Length, wexp, rexp.Length, rexp, (byte)name.Length, name); return BinaryList.ToBytes((byte)(0x38 | pv), wexp.Length, wexp, rexp.Length, rexp, (byte)name.Length, name);
} }
else if (WriteExpansion != null) else if (WriteExpansion != null)
{ {
var wexp = DC.ToBytes(WriteExpansion); var wexp = DC.ToBytes(WriteExpansion);
return BinaryList.ToBytes((byte)(0x30 | (byte)Permission), wexp.Length, wexp, (byte)name.Length, name); return BinaryList.ToBytes((byte)(0x30 | pv), wexp.Length, wexp, (byte)name.Length, name);
} }
else if (ReadExpansion != null) else if (ReadExpansion != null)
{ {
var rexp = DC.ToBytes(ReadExpansion); var rexp = DC.ToBytes(ReadExpansion);
return BinaryList.ToBytes((byte)(0x28 | (byte)Permission), rexp.Length, rexp, (byte)name.Length, name); return BinaryList.ToBytes((byte)(0x28 | pv), rexp.Length, rexp, (byte)name.Length, name);
} }
else else
return BinaryList.ToBytes((byte)(0x20 | (byte)Permission), (byte)name.Length, name); return BinaryList.ToBytes((byte)(0x20 | pv), (byte)name.Length, name);
} }
public PropertyTemplate() { Type = MemberType.Property; } public PropertyTemplate(ResourceTemplate template, byte index, string name, string read, string write, StorageMode storage)
:base(template, MemberType.Property, index, name)
{
//this.Recordable = recordable;
this.Storage = storage;
this.ReadExpansion = read;
this.WriteExpansion = write;
}
} }
} }

View File

@ -155,12 +155,8 @@ namespace Esiur.Resource.Template
var ps = (ResourceProperty[])pi.GetCustomAttributes(typeof(ResourceProperty), true); var ps = (ResourceProperty[])pi.GetCustomAttributes(typeof(ResourceProperty), true);
if (ps.Length > 0) if (ps.Length > 0)
{ {
var pt = new PropertyTemplate(); var pt = new PropertyTemplate(this, i++, pi.Name, ps[0].ReadExpansion, ps[0].WriteExpansion, ps[0].Storage);
pt.Name = pi.Name; properties.Add(pt);
pt.Index = i++;
pt.ReadExpansion = ps[0].ReadExpansion;
pt.WriteExpansion = ps[0].WriteExpansion;
properties.Add(pt);
} }
} }
@ -171,10 +167,7 @@ namespace Esiur.Resource.Template
var es = (ResourceEvent[])ei.GetCustomAttributes(typeof(ResourceEvent), true); var es = (ResourceEvent[])ei.GetCustomAttributes(typeof(ResourceEvent), true);
if (es.Length > 0) if (es.Length > 0)
{ {
var et = new EventTemplate(); var et = new EventTemplate(this, i++, ei.Name, es[0].Expansion);
et.Name = ei.Name;
et.Index = i++;
et.Expansion = es[0].Expansion;
events.Add(et); events.Add(et);
} }
} }
@ -185,11 +178,7 @@ namespace Esiur.Resource.Template
var fs = (ResourceFunction[])mi.GetCustomAttributes(typeof(ResourceFunction), true); var fs = (ResourceFunction[])mi.GetCustomAttributes(typeof(ResourceFunction), true);
if (fs.Length > 0) if (fs.Length > 0)
{ {
var ft = new FunctionTemplate(); var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void), fs[0].Expansion);
ft.Name = mi.Name;
ft.Index = i++;
ft.IsVoid = mi.ReturnType == typeof(void);
ft.Expansion = fs[0].Expansion;
functions.Add(ft); functions.Add(ft);
} }
} }
@ -258,69 +247,76 @@ namespace Esiur.Resource.Template
if (type == 0) // function if (type == 0) // function
{ {
var ft = new FunctionTemplate(); string expansion = null;
ft.Index = functionIndex++; var hasExpansion = ((data[offset] & 0x10) == 0x10);
var expansion = ((data[offset] & 0x10) == 0x10); var isVoid = ((data[offset++] & 0x08) == 0x08);
ft.IsVoid = ((data[offset++] & 0x08) == 0x08); var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
ft.Name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
offset += (uint)data[offset] + 1; offset += (uint)data[offset] + 1;
if (expansion) // expansion ? if (hasExpansion) // expansion ?
{ {
var cs = data.GetUInt32(offset); var cs = data.GetUInt32(offset);
offset += 4; offset += 4;
ft.Expansion = data.GetString(offset, cs); expansion = data.GetString(offset, cs);
offset += cs; offset += cs;
} }
var ft = new FunctionTemplate(od, functionIndex++, name, isVoid, expansion);
od.functions.Add(ft); od.functions.Add(ft);
} }
else if (type == 1) // property else if (type == 1) // property
{ {
var pt = new PropertyTemplate(); string readExpansion = null, writeExpansion = null;
pt.Index = propertyIndex++;
var readExpansion = ((data[offset] & 0x8) == 0x8); var hasReadExpansion = ((data[offset] & 0x8) == 0x8);
var writeExpansion = ((data[offset] & 0x10) == 0x10); var hasWriteExpansion = ((data[offset] & 0x10) == 0x10);
pt.Permission = (PropertyTemplate.PropertyPermission)((data[offset++] >> 1) & 0x3); var recordable = ((data[offset] & 1) == 1);
pt.Name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]); var permission = (PropertyTemplate.PropertyPermission)((data[offset++] >> 1) & 0x3);
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
offset += (uint)data[offset] + 1; offset += (uint)data[offset] + 1;
if (readExpansion) // expansion ? if (hasReadExpansion) // expansion ?
{ {
var cs = data.GetUInt32(offset); var cs = data.GetUInt32(offset);
offset += 4; offset += 4;
pt.ReadExpansion = data.GetString(offset, cs); readExpansion = data.GetString(offset, cs);
offset += cs; offset += cs;
} }
if (writeExpansion) // expansion ? if (hasWriteExpansion) // expansion ?
{ {
var cs = data.GetUInt32(offset); var cs = data.GetUInt32(offset);
offset += 4; offset += 4;
pt.WriteExpansion = data.GetString(offset, cs); writeExpansion = data.GetString(offset, cs);
offset += cs; offset += cs;
} }
var pt = new PropertyTemplate(od, propertyIndex++, name, readExpansion, writeExpansion, recordable ? StorageMode.Recordable : StorageMode.Volatile);
od.properties.Add(pt); od.properties.Add(pt);
} }
else if (type == 2) // Event else if (type == 2) // Event
{ {
var et = new EventTemplate();
et.Index = eventIndex++;
var expansion = ((data[offset++] & 0x10) == 0x10);
et.Name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]); string expansion = null;
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
offset += (uint)data[offset] + 1; offset += (uint)data[offset] + 1;
if (expansion) // expansion ? if (hasExpansion) // expansion ?
{ {
var cs = data.GetUInt32(offset); var cs = data.GetUInt32(offset);
offset += 4; offset += 4;
et.Expansion = data.GetString(offset, cs); expansion = data.GetString(offset, cs);
offset += cs; offset += cs;
} }
var et = new EventTemplate(od, eventIndex++, name, expansion);
od.events.Add(et); od.events.Add(et);
} }

View File

@ -1,6 +1,31 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine; using Esiur.Engine;
using Esiur.Resource.Template; using Esiur.Resource.Template;
using Esiur.Security.Permissions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -14,12 +39,20 @@ namespace Esiur.Resource
{ {
//static byte prefixCounter; //static byte prefixCounter;
static List<IStore> stores = new List<IStore>(); static AutoList<IResource, Instance> stores = new AutoList<IResource, Instance>(null);
static Dictionary<uint, IResource> resources = new Dictionary<uint, IResource>(); static Dictionary<uint, IResource> resources = new Dictionary<uint, IResource>();
static uint resourceCounter = 0; static uint resourceCounter = 0;
static KeyList<Guid, ResourceTemplate> templates = new KeyList<Guid, ResourceTemplate>(); static KeyList<Guid, ResourceTemplate> templates = new KeyList<Guid, ResourceTemplate>();
static bool storeIsOpen = false;
public delegate void StoreConnectedEvent(IStore store, string name);
public delegate void StoreDisconnectedEvent(IStore store);
public static event StoreConnectedEvent StoreConnected;
public static event StoreDisconnectedEvent StoreDisconnected;
/// <summary> /// <summary>
/// Get a store by its name. /// Get a store by its name.
@ -30,7 +63,7 @@ namespace Esiur.Resource
{ {
foreach (var s in stores) foreach (var s in stores)
if (s.Instance.Name == name) if (s.Instance.Name == name)
return s; return s as IStore;
return null; return null;
} }
@ -44,7 +77,7 @@ namespace Esiur.Resource
if (resources.ContainsKey(id)) if (resources.ContainsKey(id))
return new AsyncReply<IResource>(resources[id]); return new AsyncReply<IResource>(resources[id]);
else else
return null; return new AsyncReply<IResource>(null);
} }
/// <summary> /// <summary>
@ -59,22 +92,38 @@ namespace Esiur.Resource
foreach (var store in stores) foreach (var store in stores)
bag.Add(store.Trigger(ResourceTrigger.Initialize)); bag.Add(store.Trigger(ResourceTrigger.Initialize));
foreach (var store in stores)
bag.Add(store.Trigger(ResourceTrigger.SystemInitialized));
bag.Seal(); bag.Seal();
var rt = new AsyncReply<bool>(); var rt = new AsyncReply<bool>();
bag.Then((x) => bag.Then((x) =>
{ {
foreach(var b in x) foreach (var b in x)
if (!b) if (!b)
{ {
rt.Trigger(false); rt.Trigger(false);
return; return;
} }
rt.Trigger(true); var rBag = new AsyncBag<bool>();
foreach (var rk in resources)
rBag.Add(rk.Value.Trigger(ResourceTrigger.SystemInitialized));
rBag.Seal();
rBag.Then(y =>
{
foreach (var b in y)
if (!b)
{
rt.Trigger(false);
return;
}
rt.Trigger(true);
storeIsOpen = true;
});
}); });
return rt; return rt;
@ -122,6 +171,63 @@ namespace Esiur.Resource
return rt; return rt;
} }
private static IResource[] QureyIn(string[] path, int index, AutoList<IResource, Instance> resources)
{
var rt = new List<IResource>();
if (index == path.Length - 1)
{
if (path[index] == "")
foreach (IResource child in resources)
rt.Add(child);
else
foreach (IResource child in resources)
if (child.Instance.Name == path[index])
rt.Add(child);
}
else
foreach (IResource child in resources)
if (child.Instance.Name == path[index])
rt.AddRange(QureyIn(path, index+1, child.Instance.Children));
return rt.ToArray();
}
public static AsyncReply<IResource[]> Query(string path)
{
if (path == null || path == "")
{
var roots = stores.Where(s => s.Instance.Parents.Count == 0).ToArray();
return new AsyncReply<IResource[]>(roots);
}
else
{
var rt = new AsyncReply<IResource[]>();
Get(path).Then(x =>
{
var p = path.Split('/');
if (x == null)
{
rt.Trigger(QureyIn(p, 0, stores));
}
else
{
var ar = QureyIn(p, 0, stores).Where(r => r != x).ToList();
ar.Insert(0, x);
rt.Trigger(ar.ToArray());
}
});
return rt;
}
}
/// <summary> /// <summary>
/// Get a resource by its path. /// Get a resource by its path.
/// Resource path is sperated by '/' character, e.g. "system/http". /// Resource path is sperated by '/' character, e.g. "system/http".
@ -169,9 +275,12 @@ namespace Esiur.Resource
/// <param name="name">Resource name.</param> /// <param name="name">Resource name.</param>
/// <param name="store">IStore that manages the resource. Can be null if the resource is a store.</param> /// <param name="store">IStore that manages the resource. Can be null if the resource is a store.</param>
/// <param name="parent">Parent resource. if not presented the store becomes the parent for the resource.</param> /// <param name="parent">Parent resource. if not presented the store becomes the parent for the resource.</param>
public static void Put(IResource resource, string name, IStore store = null, IResource parent = null) public static void Put(IResource resource, string name, IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null)
{ {
resource.Instance = new Instance(resourceCounter++, name, resource, store); resource.Instance = new Instance(resourceCounter++, name, resource, store, customTemplate, age);
if (manager != null)
resource.Instance.Managers.Add(manager);
if (store == parent) if (store == parent)
parent = null; parent = null;
@ -184,19 +293,27 @@ namespace Esiur.Resource
else else
parent.Instance.Children.Add(resource); parent.Instance.Children.Add(resource);
if (resource is IStore) if (resource is IStore)
{
stores.Add(resource as IStore); stores.Add(resource as IStore);
StoreConnected?.Invoke(resource as IStore, name);
}
else else
store.Put(resource); store.Put(resource);
resources.Add(resource.Instance.Id, resource); resources.Add(resource.Instance.Id, resource);
if (!storeIsOpen)
resource.Trigger(ResourceTrigger.Initialize);
} }
public static T New<T>(string name, IStore store = null, IResource parent = null) public static T New<T>(string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null)
{ {
var res = Activator.CreateInstance(typeof(T)) as IResource; var res = Activator.CreateInstance(typeof(T)) as IResource;
Put(res, name, store, parent); Put(res, name, store, parent, null, 0, manager);
return (T)res; return (T)res;
} }
@ -206,7 +323,7 @@ namespace Esiur.Resource
/// <param name="template">Resource template.</param> /// <param name="template">Resource template.</param>
public static void PutTemplate(ResourceTemplate template) public static void PutTemplate(ResourceTemplate template)
{ {
if (templates.ContainsKey(template.ClassId)) if (!templates.ContainsKey(template.ClassId))
templates.Add(template.ClassId, template); templates.Add(template.ClassId, template);
} }
@ -254,5 +371,36 @@ namespace Esiur.Resource
return null; return null;
} }
public static bool Remove(IResource resource)
{
if (resource.Instance == null)
return false;
if (resources.ContainsKey(resource.Instance.Id))
resources.Remove(resource.Instance.Id);
else
return false;
if (resource is IStore)
{
stores.Remove(resource as IStore);
// remove all objects associated with the store
var toBeRemoved = resources.Values.Where(x => x.Instance.Store == resource);
foreach (var o in toBeRemoved)
Remove(o);
StoreDisconnected?.Invoke(resource as IStore);
}
if (resource.Instance.Store != null)
resource.Instance.Store.Remove(resource);
resource.Destroy();
return true;
}
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,8 +32,8 @@ namespace Esiur.Security.Authority
{ {
public class AlienAuthentication : Authentication public class AlienAuthentication : Authentication
{ {
public AlienAuthentication(Certificate certificate, AuthenticationState state) : public AlienAuthentication() :
base(certificate, state, AuthenticationType.Alien) base(AuthenticationType.Alien)
{ {
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,28 +32,31 @@ namespace Esiur.Security.Authority
{ {
public class Authentication public class Authentication
{ {
Certificate certificate; AuthenticationType type;
AuthenticationState state;
AuthenticationType type;
public Certificate Certificate public string Username { get; set; }
{ public Certificate Certificate { get; set; }
get { return certificate; } public string Domain { get; set; }
}
public string FullName => Username + "@" + Domain;
public Source Source { get; } = new Source();
public AuthenticationState State public AuthenticationState State
{ {
get { return state; } get;
set;
} }
public AuthenticationType Type public AuthenticationType Type
{ {
get { return type; } get => type;
} }
public Authentication(Certificate certificate, AuthenticationState state, AuthenticationType type) public Authentication(AuthenticationType type)
{ {
this.type = type;
} }
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine; using Esiur.Engine;
using Esiur.Misc; using Esiur.Misc;
using Esiur.Security.Cryptography; using Esiur.Security.Cryptography;

View File

@ -1,4 +1,28 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine; using Esiur.Engine;
using Esiur.Misc; using Esiur.Misc;
using Esiur.Security.Cryptography; using Esiur.Security.Cryptography;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,27 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,10 +31,42 @@ namespace Esiur.Security.Authority
{ {
public class ClientAuthentication : Authentication public class ClientAuthentication : Authentication
{ {
public ClientAuthentication(byte[] credentials, UserCertificate certificate, AuthenticationState state) /*
: base(certificate, state, AuthenticationType.Client) string username;
byte[] password;
string domain;
byte[] token;
UserCertificate certificate;
public string Username => username;
public byte[] Password => password;
//public string Domain => domain;
public byte[] Token => token;
public byte[] Nounce { get; set; }
*/
public ClientAuthentication()
:base(AuthenticationType.Client)
{ {
} }
/*
public ClientAuthentication(byte[] token)
: base(AuthenticationType.Client)
{
this.token = token;
}
public ClientAuthentication(string username, byte[] password)
: base(AuthenticationType.Client)
{
this.username = username;
this.password = password;
//this.domain = domain;
}
*/
} }
} }

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,8 +32,8 @@ namespace Esiur.Security.Authority
{ {
public class CoHostAuthentication : Authentication public class CoHostAuthentication : Authentication
{ {
public CoHostAuthentication(DomainCertificate certificate, AuthenticationState state) public CoHostAuthentication()
: base(certificate, state, AuthenticationType.CoHost) : base(AuthenticationType.CoHost)
{ {
} }

View File

@ -1,4 +1,28 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Misc; using Esiur.Misc;
using Esiur.Security.Cryptography; using Esiur.Security.Cryptography;
using Esiur.Security.Integrity; using Esiur.Security.Integrity;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,10 +32,12 @@ namespace Esiur.Security.Authority
{ {
public class HostAuthentication : Authentication public class HostAuthentication : Authentication
{ {
public HostAuthentication(DomainCertificate certificate, AuthenticationState state)
: base(certificate, state, AuthenticationType.Host) public HostAuthentication()
:base(AuthenticationType.Host)
{ {
} }
}
}
} }

View File

@ -1,4 +1,27 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine; using Esiur.Engine;
using Esiur.Net; using Esiur.Net;
using Esiur.Resource; using Esiur.Resource;
@ -12,12 +35,27 @@ namespace Esiur.Security.Authority
{ {
public class Session public class Session
{ {
Authentication Authentication { get; } public Authentication LocalAuthentication => localAuth;
Source Source { get; } public Authentication RemoteAuthentication => remoteAuth;
string Id { get; }
DateTime Creation { get; } // public Source Source { get; }
DateTime Modification { get; } public byte[] Id { get; set; }
//KeyList<string, object> Variables { get; } public DateTime Creation { get; }
public DateTime Modification { get; }
public KeyList<string, object> Variables {get;} = new KeyList<string, object>();
//KeyList<string, object> Variables { get; }
//IStore Store { get; } //IStore Store { get; }
//string id;
Authentication localAuth, remoteAuth;
//string domain;
public Session(Authentication localAuthentication, Authentication remoteAuthentication)
{
this.localAuth = localAuthentication;
this.remoteAuth = remoteAuthentication;
}
} }
} }

View File

@ -1,4 +1,28 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -10,21 +34,26 @@ namespace Esiur.Security.Authority
public class Source public class Source
{ {
string id; //string id;
KeyList<SourceAttributeType, Structure> attributes; KeyList<SourceAttributeType, object> attributes;
string Id { get { return id; } } public string Id { get; set; }
KeyList<SourceAttributeType, Structure> Attributes public KeyList<SourceAttributeType, object> Attributes
{ {
get { return attributes; } get => attributes;
} }
public Source(string id, KeyList<SourceAttributeType, Structure> attributes) public Source(string id, KeyList<SourceAttributeType, object> attributes)
{ {
this.id = id; Id = id;
this.attributes = attributes; this.attributes = attributes;
} }
public Source()
{
attributes = new KeyList<SourceAttributeType, object>();
}
} }
} }

View File

@ -1,4 +1,28 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -11,7 +35,10 @@ namespace Esiur.Security.Authority
{ {
Mobility, // Stationary/Mobile Mobility, // Stationary/Mobile
CPU, // Arc, Speed, Cores CPU, // Arc, Speed, Cores
IP, // IPv4, IPv6 Address IPv4, // IPv4, IPv6 Address
IPv6, // IPv4, IPv6 Address
Port, // TCP or UDP port
Proxy, // Proxy
Route, // Trace Root Route, // Trace Root
Location, // Lon, Lat, Alt, Accuracy Location, // Lon, Lat, Alt, Accuracy
OS, // OS name, version, distro, kernel OS, // OS name, version, distro, kernel

View File

@ -1,4 +1,28 @@
using Esiur.Data; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Security.Cryptography; using Esiur.Security.Cryptography;
using Esiur.Security.Integrity; using Esiur.Security.Integrity;
using System; using System;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,27 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -1,4 +1,28 @@
using Esiur.Resource; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Resource;
using Esiur.Security.Authority; using Esiur.Security.Authority;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -22,8 +46,10 @@ namespace Esiur.Security.Membership
//DomainCertificate[] GetDomainCertificates(string domain); //DomainCertificate[] GetDomainCertificates(string domain);
bool UserExists(string username); AsyncReply<bool> UserExists(string username, string domain);
AsyncReply<byte[]> GetPassword(string username, string domain); AsyncReply<byte[]> GetPassword(string username, string domain);
AsyncReply<bool> Login(Session session);
AsyncReply<bool> Logout(Session session);
//ClientAuthentication Authenticate(string username, byte[] credentials, int flag); //ClientAuthentication Authenticate(string username, byte[] credentials, int flag);
//HostAuthentication Authenticate(DomainCertificate domainCertificate); //HostAuthentication Authenticate(DomainCertificate domainCertificate);

View File

@ -1,4 +1,28 @@
using Esiur.Engine; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Engine;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,4 +1,28 @@
using System; /*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -11,7 +35,16 @@ namespace Esiur.Security.Permissions
Attach, Attach,
Delete, Delete,
Execute, Execute,
Get, GetProperty,
Set, SetProperty,
CreateResource,
UpdateAttributes,
InquireAttributes,
AddParent,
RemoveParent,
AddChild,
RemoveChild,
Rename,
ReceiveEvent
} }
} }

View File

@ -1,18 +0,0 @@
using Esiur.Engine;
using Esiur.Net;
using Esiur.Resource;
using Esiur.Resource.Template;
using Esiur.Security.Authority;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Esiur.Security.Permissions
{
public interface IPermissionManager
{
bool Applicable(IResource resource, Session session, ActionType action, MemberTemplate member);
}
}

View File

@ -0,0 +1,56 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using Esiur.Data;
using Esiur.Engine;
using Esiur.Net;
using Esiur.Resource;
using Esiur.Resource.Template;
using Esiur.Security.Authority;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Esiur.Security.Permissions
{
public interface IPermissionsManager
{
/// <summary>
/// Check for permission.
/// </summary>
/// <param name="resource">IResource.</param>
/// <param name="session">Caller sessions.</param>
/// <param name="action">Action type</param>
/// <param name="member">Function, property or event to check for permission.</param>
/// <param name="inquirer">Permission inquirer object.</param>
/// <returns>Allowed or denined.</returns>
Ruling Applicable(IResource resource, Session session, ActionType action, MemberTemplate member, object inquirer = null);
bool Initialize(Structure settings, IResource resource);
Structure Settings { get; }
}
}

View File

@ -0,0 +1,60 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using Esiur.Data;
using Esiur.Engine;
using Esiur.Resource;
using Esiur.Resource.Template;
using Esiur.Security.Authority;
namespace Esiur.Security.Permissions
{
public class ParentalPermissionsManager : IPermissionsManager
{
Structure settings;
public Structure Settings => settings;
public Ruling Applicable(IResource resource, Session session, ActionType action, MemberTemplate member, object inquirer = null)
{
foreach (IResource parent in resource.Instance.Parents)
{
var ruling = parent.Instance.Applicable(session, action, member, inquirer);
if (ruling != Ruling.DontCare)
return ruling;
}
return Ruling.DontCare;
}
public bool Initialize(Structure settings, IResource resource)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Security.Permissions
{
public enum Ruling
{
Denied,
Allowed,
DontCare
}
}

Some files were not shown because too many files have changed in this diff Show More