2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-05-06 03:32:57 +00:00
This commit is contained in:
Ahmed Zamil 2020-02-26 03:14:22 +03:00
parent 7a21f6a928
commit fde1b1d8ad
39 changed files with 1108 additions and 502 deletions

View File

@ -3,6 +3,11 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Esyur.Stores.EntityCore</AssemblyName>
<Authors>Ahmed Kh. Zamil</Authors>
<Company>Esyur Foundation</Company>
<Description>Esyur for Entity Framework Core</Description>
<Product>Esyur Entity Framework Extension</Product>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>

View File

@ -35,18 +35,28 @@ namespace Esyur.Stores.EntityCore
{
public static class EsyurExtensions
{
public static T CreateResource<T>(this DbContext dbContext) where T:IResource
public static T CreateResource<T>(this DbContext dbContext, object properties = null) where T:class,IResource
{
return dbContext.GetInfrastructure().CreateResource<T>();
return dbContext.GetInfrastructure().CreateResource<T>(properties);
}
public static T CreateResource<T>(this IServiceProvider serviceProvider) where T:IResource
public static T CreateResource<T>(this DbSet<T> dbSet, object properties = null) where T:class,IResource
{
var resource = dbSet.GetInfrastructure().CreateResource<T>(properties);
dbSet.Add(resource);
return resource;
}
public static T CreateResource<T>(this IServiceProvider serviceProvider, object properties = null) where T:class,IResource
{
var options = serviceProvider.GetService<IDbContextOptions>().FindExtension<EsyurExtensionOptions>();
var manager = options.Store.Instance.Managers.Count > 0 ? options.Store.Instance.Managers.First() : null;
return Warehouse.New<T>("", options.Store, null, manager);
var resource = Warehouse.New<T>("", options.Store, null, null, null, properties);
resource.Instance.Managers.AddRange(options.Store.Instance.Managers.ToArray());
return resource;
}
public static DbContextOptionsBuilder UseEsyur(this DbContextOptionsBuilder optionsBuilder,

View File

@ -11,7 +11,7 @@
<PackageProjectUrl>http://www.esyur.com</PackageProjectUrl>
<RepositoryUrl>https://github.com/esyur/esyur-dotnet/</RepositoryUrl>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>1.3.3</Version>
<Version>1.4.0</Version>
</PropertyGroup>
<ItemGroup>

View File

@ -51,15 +51,15 @@ namespace Esyur.Stores.MongoDB
Dictionary<string, WeakReference> resources = new Dictionary<string, WeakReference>();
[ResourceEvent]
[Public]
public event ResourceEventHanlder ResourceAdded;
[ResourceEvent]
[Public]
public event ResourceEventHanlder ResourceRemoved;
int count = 0;
[ResourceProperty]
[Public]
public virtual int Count
{
get
@ -109,7 +109,7 @@ namespace Esyur.Stores.MongoDB
return true;
}
[ResourceFunction]
[Public]
public bool Remove(IResource resource)
{
var objectId = resource.Instance.Variables["objectId"].ToString();
@ -510,11 +510,11 @@ namespace Esyur.Stores.MongoDB
throw new NotImplementedException();
}
[ResourceAttribute]
[Attribute]
public string Connection { get; set; }
[ResourceAttribute]
[Attribute]
public string Collection { get; set; }
[ResourceAttribute]
[Attribute]
public string Database { get; set; }
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
@ -725,7 +725,7 @@ namespace Esyur.Stores.MongoDB
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 properties = resource.Instance.Template.Properties.Where(x => x.Recordable).ToList();
var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();
@ -751,7 +751,7 @@ namespace Esyur.Stores.MongoDB
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 properties = resource.Instance.Template.Properties.Where(x => x.Recordable).ToList();
var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();

View File

@ -35,13 +35,15 @@ namespace Esyur.Stores.MongoDB
{
public class MongoDBStore<T> : MongoDBStore where T:IResource
{
[ResourceFunction]
public T Create(string name, Structure values)
[Public]
public T New(string name = null, object properties = null)
{
return Warehouse.New<T>(name, this, null, null, null, null, values);
var resource = Warehouse.New<T>(name, this, null, null, null, properties);
resource.Instance.Managers.AddRange(this.Instance.Managers.ToArray());
return resource;
}
[ResourceFunction]
[Public]
public async AsyncReply<IResource[]> Slice(int index, int limit)
{
var list = await this.Instance.Children<IResource>();

View File

@ -32,7 +32,7 @@ using System.Reflection;
namespace Esyur.Data
{
public class AutoList<T, ST> : IEnumerable<T>
public class AutoList<T, ST> : IEnumerable<T>, ICollection, ICollection<T>
{
private readonly object syncRoot = new object();
@ -239,6 +239,10 @@ namespace Esyur.Data
get { return list.Count; }
}
public bool IsSynchronized => (list as ICollection).IsSynchronized;
public bool IsReadOnly => throw new NotImplementedException();
/// <summary>
/// Check if an item exists in the list
@ -282,5 +286,20 @@ namespace Esyur.Data
{
return ((IEnumerable<T>)list).GetEnumerator();
}
public void CopyTo(Array array, int index)
{
(list as ICollection).CopyTo(array, index);
}
public void CopyTo(T[] array, int arrayIndex)
{
list.CopyTo(array, arrayIndex);
}
bool ICollection<T>.Remove(T item)
{
return list.Remove(item);
}
}
}

View File

@ -43,13 +43,9 @@ namespace Esyur.Data
{
public static object CastConvert(object value, Type destinationType)
{
if (value == null)
return null;
//if (destinationType.IsArray && destinationType.GetElementType().IsArray)
// Console.Beep();
var sourceType = value.GetType();
if (destinationType == sourceType)
@ -69,22 +65,6 @@ namespace Esyur.Data
for (var i = 0; i < rt.Length; i++)
{
rt.SetValue(CastConvert(v.GetValue(i), destinationType), i);
// try
// {
//#if NETSTANDARD
// if (destinationType.GetTypeInfo().IsInstanceOfType(v.GetValue(i)))
//#else
// if (destinationType.IsInstanceOfType(v.GetValue(i)))
//#endif
// rt.SetValue(v.GetValue(i), i);
// else
// rt.SetValue(Convert.ChangeType(v.GetValue(i), destinationType), i);
// }
// catch
// {
// rt.SetValue(null, i);
// }
}
return rt;
@ -94,8 +74,6 @@ namespace Esyur.Data
{
try
{
var underType = Nullable.GetUnderlyingType(destinationType);
if (underType != null)
{
@ -105,7 +83,6 @@ namespace Esyur.Data
destinationType = underType;
}
if (destinationType.IsInstanceOfType(value))
{
return value;
@ -134,8 +111,6 @@ namespace Esyur.Data
}
public static byte[] ToBytes(sbyte value)
{
return new byte[1] { (byte)value };
@ -602,8 +577,6 @@ namespace Esyur.Data
return rt;
}
public static bool TryParse<T>(object Input, out T Results)
{
try
@ -918,20 +891,6 @@ namespace Esyur.Data
return rt;
}
/*
public static PhysicalAddress GetPhysicalAddress(this byte[] data, uint offset)
{
return new PhysicalAddress(Clip(data, offset, 6));
}
public static PhysicalAddress[] GetPhysicalAddressArray(this byte[] data, uint offset, uint length)
{
var rt = new PhysicalAddress[length / 6];
for (var i = 0; i < length; i += 6)
rt[i] = GetPhysicalAddress(data, (uint)(offset + i));
return rt;
}
*/
public static IPAddress GetIPv4Address(this byte[] data, uint offset)
{
return new IPAddress((long)GetUInt32(data, offset));
@ -958,83 +917,7 @@ namespace Esyur.Data
return rt;
}
/*
public static T FromBytes<T>(byte[] data, uint offset, uint length = 0)
{
if (typeof(T) == typeof(bool))
{
return (T)(object)(data[offset] == 1);
}
else if (typeof(T) == typeof(byte))
{
return (T)(object)data[offset];
}
else if (typeof(T) == typeof(char))
{
return (T)(object)BitConverter.ToChar(ReverseArray(data, offset, 2), 0);
}
else if (typeof(T) == typeof(short))
{
return (T)(object)BitConverter.ToInt16(ReverseArray(data, offset, 2), 0);
}
else if (typeof(T) == typeof(ushort))
{
return (T)(object)BitConverter.ToUInt16(ReverseArray(data, offset, 2), 0);
}
else if (typeof(T) == typeof(int))
{
return (T)(object)BitConverter.ToInt32(ReverseArray(data, offset, 4), 0);
}
else if (typeof(T) == typeof(uint))
{
return (T)(object)BitConverter.ToUInt32(ReverseArray(data, offset, 4), 0);
}
else if (typeof(T) == typeof(long))
{
return (T)(object)BitConverter.ToInt64(ReverseArray(data, offset, 8), 0);
}
else if (typeof(T) == typeof(ulong))
{
return (T)(object)BitConverter.ToUInt64(ReverseArray(data, offset, 8), 0);
}
else if (typeof(T) == typeof(float))
{
return (T)(object)BitConverter.ToSingle(ReverseArray(data, offset, 4), 0);
}
else if (typeof(T) == typeof(double))
{
return (T)(object)BitConverter.ToDouble(ReverseArray(data, offset, 8), 0);
}
else if (typeof(T) == typeof(string))
{
return (T)(object)Encoding.UTF8.GetString(data, (int)offset, (int)length);
}
else if (typeof(T) == typeof(Guid))
{
return (T)(object)new Guid(DC.Clip(data, offset, 16));
}
else if (typeof(T) == typeof(IPAddress))
{
if (length == 0)
return (T)(object)(new IPAddress((long)GetUInt32(data, offset)));
else
return (T)(object)(new IPAddress(Clip(data, offset, length)));
}
else if (typeof(T) == typeof(PhysicalAddress))
{
return (T)(object)new PhysicalAddress(Clip(data, offset, 6));
}
else if (typeof(T) == typeof(DateTime))
{
long ticks = BitConverter.ToInt64(ReverseArray(data, offset, 8), 0);
return (T)(object)new DateTime(ticks, DateTimeKind.Utc);
}
else
{
return default(T);
}
}
*/
public static byte[] Clip(this byte[] data, uint offset, uint length)
{

274
Esyur/Data/ResourceList.cs Normal file
View File

@ -0,0 +1,274 @@
/*
Copyright (c) 2020 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.Linq;
using System.Text;
using System.Collections;
using Esyur.Core;
using System.Reflection;
namespace Esyur.Data
{
public class ResourceList<T, ST> : IEnumerable<T>, ICollection, ICollection<T>
{
private readonly object syncRoot = new object();
private List<T> list = new List<T>();
public delegate void Modified(ST sender, int index, T oldValue, T newValue);
public delegate void Added(ST sender, T value);
public delegate void Removed(ST sender, int index, T value);
public delegate void Cleared(ST sender);
public event Modified OnModified;
public event Removed OnRemoved;
public event Cleared OnCleared;
public event Added OnAdd;
ST state;
public void Sort()
{
list.Sort();
}
public void Sort(IComparer<T> comparer)
{
list.Sort(comparer);
}
public void Sort(Comparison<T> comparison)
{
list.Sort(comparison);
}
public IEnumerable<T> Where(Func<T, bool> predicate)
{
return list.Where(predicate);
}
/// <summary>
/// Convert AutoList to array
/// </summary>
/// <returns>Array</returns>
public T[] ToArray()
{
// list.OrderBy()
return list.ToArray();
}
/// <summary>
/// Create a new instance of AutoList
/// </summary>
/// <param name="state">State object to be included when an event is raised.</param>
public ResourceList(ST state)
{
this.state = state;
}
/// <summary>
/// Create a new instance of AutoList
/// </summary>
/// <param name="values">Populate the list with items</param>
/// <returns></returns>
public ResourceList(ST state, T[] values)
{
this.state = state;
AddRange(values);
}
/// <summary>
/// Synchronization lock of the list
/// </summary>
public object SyncRoot
{
get
{
return syncRoot;
}
}
/// <summary>
/// First item in the list
/// </summary>
public T First()
{
return list.First();
}
/// <summary>
/// Get an item at a specified index
/// </summary>
public T this[int index]
{
get
{
return list[index];
}
set
{
var oldValue = list[index];
lock (syncRoot)
list[index] = value;
OnModified?.Invoke(state, index, oldValue, value);
}
}
/// <summary>
/// Add item to the list
/// </summary>
public void Add(T value)
{
lock (syncRoot)
list.Add(value);
OnAdd?.Invoke(state, value);
}
/// <summary>
/// Add an array of items to the list
/// </summary>
public void AddRange(T[] values)
{
foreach (var v in values)
Add(v);
}
private void ItemDestroyed(object sender)
{
Remove((T)sender);
}
/// <summary>
/// Clear the list
/// </summary>
public void Clear()
{
lock (syncRoot)
list.Clear();
OnCleared?.Invoke(state);
}
/// <summary>
/// Remove an item from the list
/// <param name="value">Item to remove</param>
/// </summary>
public void Remove(T value)
{
var index = 0;
lock (syncRoot)
{
index = list.IndexOf(value);
if (index == -1)
return;
list.RemoveAt(index);
}
OnRemoved?.Invoke(state, index, value);
}
/// <summary>
/// Number of items in the list
/// </summary>
public int Count
{
get { return list.Count; }
}
public bool IsSynchronized => (list as ICollection).IsSynchronized;
public bool IsReadOnly => throw new NotImplementedException();
/// <summary>
/// Check if an item exists in the list
/// </summary>
/// <param name="value">Item to check if exists</param>
public bool Contains(T value)
{
return list.Contains(value);
}
/// <summary>
/// Check if any item of the given array is in the list
/// </summary>
/// <param name="values">Array of items</param>
public bool ContainsAny(T[] values)
{
foreach (var v in values)
if (list.Contains(v))
return true;
return false;
}
/// <summary>
/// Check if any item of the given list is in the list
/// </summary>
/// <param name="values">List of items</param>
public bool ContainsAny(AutoList<T, ST> values)
{
foreach (var v in values)
if (list.Contains((T)v))
return true;
return false;
}
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)list).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<T>)list).GetEnumerator();
}
public void CopyTo(Array array, int index)
{
(list as ICollection).CopyTo(array, index);
}
public void CopyTo(T[] array, int arrayIndex)
{
list.CopyTo(array, arrayIndex);
}
bool ICollection<T>.Remove(T item)
{
return list.Remove(item);
}
}
}

View File

@ -7,7 +7,7 @@
<PackageLicenseUrl>https://github.com/Esyur/Esyur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>http://www.esyur.com</PackageProjectUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.4.9</Version>
<Version>1.5.0</Version>
<RepositoryUrl>https://github.com/esyur/esyur-dotnet</RepositoryUrl>
<Authors>Ahmed Kh. Zamil</Authors>
<AssemblyVersion>1.3.1.0</AssemblyVersion>
@ -29,7 +29,9 @@
<ItemGroup>
<Compile Remove="Core\AsyncReplyNon.cs" />
<Compile Remove="Core\IAsyncReply.cs" />
<Compile Remove="Net\UDP\UDPServer.cs" />
<Compile Remove="Resource\ResourceEvent.cs" />
<Compile Remove="Resource\ResourceFunction.cs" />
<Compile Remove="Resource\ResourceProperty.cs" />
</ItemGroup>
<ItemGroup>
@ -40,7 +42,9 @@
<ItemGroup>
<None Include="Core\AsyncReplyNon.cs" />
<None Include="Core\IAsyncReply.cs" />
<None Include="Net\UDP\UDPServer.cs" />
<None Include="Resource\ResourceEvent.cs" />
<None Include="Resource\ResourceFunction.cs" />
<None Include="Resource\ResourceProperty.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -141,6 +141,12 @@ namespace Esyur.Net.HTTP
}
}
public void Send(WebsocketPacket packet)
{
if (packet.Data != null)
base.Send(packet.Data);
}
public override void Send(string data)
{
Response.Message = Encoding.UTF8.GetBytes(data);

View File

@ -44,7 +44,7 @@ namespace Esyur.Net.HTTP
public class HTTPServer : NetworkServer<HTTPConnection>, IResource
{
Dictionary<string, HTTPSession> sessions= new Dictionary<string, HTTPSession>();
HTTPFilter[] filters = null;
HTTPFilter[] filters = new HTTPFilter[0];
public Instance Instance
{
@ -52,63 +52,55 @@ namespace Esyur.Net.HTTP
set;
}
[Storable]
public virtual string ip
{
get;
set;
}
[Storable]
public virtual ushort port
[Attribute]
public virtual string IP
{
get;
set;
}
[Storable]
public virtual uint timeout
[Attribute]
public virtual ushort Port
{
get;
set;
}
[Storable]
public virtual uint clock
[Attribute]
public virtual uint Timeout
{
get;
set;
}
[Storable]
public virtual uint maxPost
[Attribute]
public virtual uint Clock
{
get;
set;
}
[Storable]
public virtual bool ssl
[Attribute]
public virtual uint MaxPost
{
get;
set;
}
[Storable]
public virtual string certificate
[Attribute]
public virtual bool SSL
{
get;
set;
}
//public override void ClientConnected(TClient Sender)
//{
//}
/*
public DStringDictionary Configurations
[Attribute]
public virtual string Certificate
{
get { return config; }
get;
set;
}
*/
public enum ResponseCodes : int
{
@ -118,7 +110,7 @@ namespace Esyur.Net.HTTP
HTTP_MOVED = 301,
HTTP_NOTMODIFIED = 304,
HTTP_REDIRECT = 307
}
}
public HTTPSession CreateSession(string id, int timeout)
@ -132,27 +124,6 @@ namespace Esyur.Net.HTTP
return s;
}
/*
protected override void SessionModified(NetworkSession session, string key, object oldValue, object newValue)
{
foreach (var instance in Instance.Children)
{
var f = (HTTPFilter)instance;
f.SessionModified(session as HTTPSession, key, oldValue, newValue);
}
}
*/
//public override object InitializeLifetimeService()
//{
// return null;
//}
public static string MakeCookie(string Item, string Value, DateTime Expires, string Domain, string Path, bool HttpOnly)
{
@ -183,7 +154,7 @@ namespace Esyur.Net.HTTP
protected override void ClientDisconnected(HTTPConnection sender)
{
//Console.WriteLine("OUT: " + this.Connections.Count);
foreach (var filter in filters)
filter.ClientDisconnected(sender);
}
@ -222,11 +193,11 @@ namespace Esyur.Net.HTTP
}
else if (BL > 0)
{
if (BL > maxPost)
if (BL > MaxPost)
{
sender.Send(
"<html><body>POST method content is larger than "
+ maxPost
+ MaxPost
+ " bytes.</body></html>");
sender.Close();
@ -326,7 +297,7 @@ namespace Esyur.Net.HTTP
*/
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
public async AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
@ -341,19 +312,19 @@ namespace Esyur.Net.HTTP
ISocket listener;
IPAddress ipAdd;
if (ip == null)
if (IP == null)
ipAdd = IPAddress.Any;
else
ipAdd = IPAddress.Parse(ip);
ipAdd = IPAddress.Parse(IP);
// if (ssl)
// listener = new SSLSocket(new IPEndPoint(ipAdd, port), new X509Certificate2(certificate));
// else
listener = new TCPSocket(new IPEndPoint(ipAdd, port));
listener = new TCPSocket(new IPEndPoint(ipAdd, Port));
Start(listener,
timeout,
clock);
Timeout,
Clock);
}
else if (trigger == ResourceTrigger.Terminate)
{
@ -361,15 +332,15 @@ namespace Esyur.Net.HTTP
}
else if (trigger == ResourceTrigger.SystemReload)
{
Trigger(ResourceTrigger.Terminate);
Trigger(ResourceTrigger.Initialize);
await Trigger(ResourceTrigger.Terminate);
await Trigger(ResourceTrigger.Initialize);
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
Instance.Children<HTTPFilter>().Then(x => filters = x);
filters = await Instance.Children<HTTPFilter>();
}
return new AsyncReply<bool>(true);
return true;
}
@ -380,7 +351,7 @@ namespace Esyur.Net.HTTP
sender.SetParent(this);
//Console.WriteLine("IN: " + this.Connections.Count);
if (filters == null)
if (filters.Length == 0)
{
sender.Close();
return;

View File

@ -36,8 +36,8 @@ namespace Esyur.Net.HTTP
{
public class IIPoWS: HTTPFilter
{
[ResourceProperty]
public DistributedServer DistributedServer
[Attribute]
public DistributedServer Server
{
get;
set;
@ -48,7 +48,7 @@ namespace Esyur.Net.HTTP
if (sender.IsWebsocketRequest())
{
if (DistributedServer == null)
if (Server == null)
return false;
var tcpSocket = sender.Unassign();
@ -62,7 +62,7 @@ namespace Esyur.Net.HTTP
var iipConnection = new DistributedConnection();
DistributedServer.AddConnection(iipConnection);
Server.AddConnection(iipConnection);
iipConnection.Assign(wsSocket);
wsSocket.Begin();

View File

@ -801,13 +801,13 @@ namespace Esyur.Net.IIP
}
[ResourceAttribute]
[Attribute]
public string Username { get; set; }
[ResourceAttribute]
[Attribute]
public string Password { get; set; }
[ResourceAttribute]
[Attribute]
public string Domain { get; set; }
/// <summary>
/// Resource interface

View File

@ -39,48 +39,44 @@ namespace Esyur.Net.IIP
{
public class DistributedServer : NetworkServer<DistributedConnection>, IResource
{
//[Storable]
//[ResourceProperty]
public string ip
[Attribute]
public string IP
{
get;
set;
}
//[Storable]
//[ResourceProperty]
[Attribute]
public IMembership Membership
{
get;
set;
}
[Attribute]
public EntryPoint EntryPoint
{
get;
set;
}
//[Storable]
//[ResourceProperty]
public ushort port
[Attribute]
public ushort Port
{
get;
set;
}
//[Storable]
//[ResourceProperty]
public uint timeout
[Attribute]
public uint Timeout
{
get;
set;
}
//[Storable]
//[ResourceProperty]
public uint clock
[Attribute]
public uint Clock
{
get;
set;
@ -99,12 +95,12 @@ namespace Esyur.Net.IIP
{
TCPSocket listener;
if (ip != null)
listener = new TCPSocket(new IPEndPoint(IPAddress.Parse(ip), port));
if (IP != null)
listener = new TCPSocket(new IPEndPoint(IPAddress.Parse(IP), Port));
else
listener = new TCPSocket(new IPEndPoint(IPAddress.Any, port));
listener = new TCPSocket(new IPEndPoint(IPAddress.Any, Port));
Start(listener, timeout, clock);
Start(listener, Timeout, Clock);
}
else if (trigger == ResourceTrigger.Terminate)
{

View File

@ -35,6 +35,6 @@ namespace Esyur.Net.IIP
{
public abstract AsyncReply<IResource[]> Query(string path, DistributedConnection sender);
public abstract override bool Create();
protected abstract override bool Create();
}
}

View File

@ -31,18 +31,19 @@ using Esyur.Core;
using Esyur.Net.Sockets;
using Esyur.Resource;
using System.Threading.Tasks;
using System.Diagnostics;
namespace Esyur.Net
{
public abstract class NetworkServer<TConnection>: IDestructible where TConnection : NetworkConnection, new()
public abstract class NetworkServer<TConnection> : IDestructible where TConnection : NetworkConnection, new()
{
//private bool isRunning;
uint clock;
private ISocket listener;
private AutoList<TConnection, NetworkServer<TConnection>> connections;
//private Thread thread;
private Thread thread;
protected abstract void DataReceived(TConnection sender, NetworkBuffer data);
protected abstract void ClientConnected(TConnection sender);
@ -102,18 +103,18 @@ namespace Esyur.Net
}
*/
/*
protected virtual void SessionModified(NetworkSession session, string key, object oldValue, object newValue)
{
/*
protected virtual void SessionModified(NetworkSession session, string key, object oldValue, object newValue)
{
}
}
protected virtual void SessionEnded(NetworkSession session)
{
Sessions.Remove(session.Id);
session.Destroy();
}
*/
protected virtual void SessionEnded(NetworkSession session)
{
Sessions.Remove(session.Id);
session.Destroy();
}
*/
private void MinuteThread(object state)
{
@ -179,14 +180,21 @@ namespace Esyur.Net
listener = socket;
// Start accepting
var r = listener.Accept();
r.Then(NewConnection);
//var r = listener.Accept();
//r.Then(NewConnection);
//r.timeout?.Dispose();
//var rt = listener.Accept().Then()
//thread = new Thread(new System.Threading.ThreadStart(ListenForConnections));
thread = new Thread(new ThreadStart(() =>
{
while (true)
{
var s = listener.Accept();
NewConnection(s);
}
}));
//thread.Start();
thread.Start();
}
@ -221,7 +229,7 @@ namespace Esyur.Net
// wait until the listener stops
//while (isRunning)
//{
// Thread.Sleep(100);
// Thread.Sleep(100);
//}
//Console.WriteLine("Listener stopped");
@ -230,8 +238,8 @@ namespace Esyur.Net
//lock (connections.SyncRoot)
//{
foreach (TConnection con in cons)
con.Close();
foreach (TConnection con in cons)
con.Close();
//}
//Console.WriteLine("Sockets Closed");
@ -268,48 +276,35 @@ namespace Esyur.Net
private void NewConnection(ISocket sock)
{
try
{
/*
if (listener.State == SocketState.Closed || listener.State == SocketState.Terminated)
{
Console.WriteLine("Listen socket break ");
Console.WriteLine(listener.LocalEndPoint.Port);
break;
}
*/
if (sock == null)
{
//Console.Write("sock == null");
return;
}
//sock.ReceiveBufferSize = 102400;
//sock.SendBufferSize = 102400;
if (sock == null)
{
Console.Write("sock == null");
return;
}
TConnection c = new TConnection();
AddConnection(c);
TConnection c = new TConnection();
AddConnection(c);
c.Assign(sock);
c.Assign(sock);
try
{
ClientConnected(c);
}
catch
{
// something wrong with the child.
}
try
{
ClientConnected(c);
}
catch
{
// something wrong with the child.
}
// Accept more
listener.Accept().Then(NewConnection);
//l.timeout?.Dispose();
sock.Begin();
//listener.Accept().Then(NewConnection);
sock.Begin();
}
@ -332,7 +327,7 @@ namespace Esyur.Net
//isRunning;
}
}
public void OnDataReceived(NetworkConnection sender, NetworkBuffer data)
{
DataReceived((TConnection)sender, data);
@ -372,7 +367,7 @@ namespace Esyur.Net
GC.Collect();
}
public void Destroy()
{
Stop();

View File

@ -58,7 +58,9 @@ namespace Esyur.Net.Sockets
AsyncReply<bool> Connect(string hostname, ushort port);
bool Begin();
//ISocket Accept();
AsyncReply<ISocket> Accept();
AsyncReply<ISocket> AcceptAsync();
ISocket Accept();
IPEndPoint RemoteEndPoint { get; }
IPEndPoint LocalEndPoint { get; }

View File

@ -311,24 +311,26 @@ namespace Esyur.Net.Sockets
OnDestroy?.Invoke(this);
}
public AsyncReply<ISocket> Accept()
public async AsyncReply<ISocket> AcceptAsync()
{
var reply = new AsyncReply<ISocket>();
//var reply = new AsyncReply<ISocket>();
try
{
sock.AcceptAsync().ContinueWith((x) =>
{
try
{
reply.Trigger(new SSLSocket(x.Result, cert, true));
}
catch
{
reply.Trigger(null);
}
return new SSLSocket(await sock.AcceptAsync(), cert, true);
}, null);
//sock.AcceptAsync().ContinueWith((x) =>
//{
// try
// {
// reply.Trigger(new SSLSocket(x.Result, cert, true));
// }
// catch
// {
// reply.Trigger(null);
// }
//}, null);
}
catch
@ -337,7 +339,7 @@ namespace Esyur.Net.Sockets
return null;
}
return reply;
//return reply;
}
public void Hold()
@ -354,5 +356,18 @@ namespace Esyur.Net.Sockets
{
throw new NotImplementedException();
}
public ISocket Accept()
{
try
{
return new SSLSocket(sock.Accept(), cert, true);
}
catch
{
state = SocketState.Terminated;
return null;
}
}
}
}

View File

@ -178,7 +178,9 @@ namespace Esyur.Net.Sockets
//lock (receiveNetworkBuffer.SyncLock)
// Console.WriteLine(e. + " " + e.BytesTransferred);
receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)e.BytesTransferred);
var recCount = e.BytesTransferred > e.Count ? e.Count : e.BytesTransferred;
receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)recCount);
//Console.WriteLine("TC IN: " + (uint)e.BytesTransferred + " " + DC.ToHex(receiveBuffer, 0, (uint)e.BytesTransferred));
@ -365,7 +367,15 @@ namespace Esyur.Net.Sockets
else
{
asyncSending = true;
sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, PacketSent, null);
try
{
sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, PacketSent, null);
}
catch {
asyncSending = false;
state = SocketState.Terminated;
Close();
}
//sock.SendAsync(new ArraySegment<byte>(msg), SocketFlags.None).ContinueWith(DataSent);
}
}
@ -403,7 +413,7 @@ namespace Esyur.Net.Sockets
}
catch (Exception ex2)
{
Console.WriteLine("Level 2 {0}", ex2);
state = SocketState.Terminated;
}
Global.Log("TCPSocket", LogType.Error, ex.ToString());
@ -427,33 +437,35 @@ namespace Esyur.Net.Sockets
OnDestroy?.Invoke(this);
}
public AsyncReply<ISocket> Accept()
public ISocket Accept()
{
var reply = new AsyncReply<ISocket>();
try
{
sock.AcceptAsync().ContinueWith((x) =>
{
try
{
reply.Trigger(new TCPSocket(x.Result));
}
catch
{
reply.Trigger(null);
}
});
var s = sock.Accept();
return new TCPSocket(s);
}
catch
{
state = SocketState.Terminated;
return null;
}
return reply;
}
public async AsyncReply<ISocket> AcceptAsync()
{
try
{
var s = await sock.AcceptAsync();
return new TCPSocket(s);
}
catch
{
state = SocketState.Terminated;
return null;
}
}
public void Hold()
{
held = true;
@ -494,12 +506,23 @@ namespace Esyur.Net.Sockets
else
{
asyncSending = true;
sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, PacketSent, rt);// null);
try
{
sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, PacketSent, rt);// null);
}
catch
{
asyncSending = false;
state = SocketState.Terminated;
Close();
}
//sock.SendAsync(new ArraySegment<byte>(msg), SocketFlags.None).ContinueWith(DataSent);
}
return rt;
}
}
}
}

View File

@ -63,13 +63,13 @@ namespace Esyur.Net.Sockets
get { return (IPEndPoint)sock.LocalEndPoint; }
}
public IPEndPoint RemoteEndPoint
{
get { return sock.RemoteEndPoint; }
}
public IPEndPoint RemoteEndPoint
{
get { return sock.RemoteEndPoint; }
}
public SocketState State
{
@ -79,7 +79,7 @@ namespace Esyur.Net.Sockets
}
}
public WSSocket(ISocket socket)
{
pkt_send.FIN = true;
@ -103,7 +103,7 @@ namespace Esyur.Net.Sockets
if (processing)
return;
var msg = buffer.Read();
if (msg == null)
@ -161,7 +161,7 @@ namespace Esyur.Net.Sockets
if (offset == msg.Length)
{
// Console.WriteLine("WS IN: " + receiveNetworkBuffer.Available);
// Console.WriteLine("WS IN: " + receiveNetworkBuffer.Available);
OnReceive?.Invoke(receiveNetworkBuffer);
return;
}
@ -200,14 +200,14 @@ namespace Esyur.Net.Sockets
public void Send(WebsocketPacket packet)
{
lock(sendLock)
lock (sendLock)
if (packet.Compose())
sock.Send(packet.Data);
}
public void Send(byte[] message)
{
lock(sendLock)
lock (sendLock)
{
if (held)
{
@ -219,13 +219,16 @@ namespace Esyur.Net.Sockets
//Console.WriteLine("TX " + message.Length +"/"+totalSent);// + " " + DC.ToHex(message, 0, (uint)size));
pkt_send.Message = message;
if (pkt_send.Compose())
sock.Send(pkt_send.Data);
}
}
}
public void Send(byte[] message, int offset, int size)
{
lock (sendLock)
@ -258,7 +261,7 @@ namespace Esyur.Net.Sockets
throw new NotImplementedException();
}
public bool Begin()
{
return sock.Begin();
@ -275,20 +278,20 @@ namespace Esyur.Net.Sockets
OnDestroy?.Invoke(this);
}
public AsyncReply<ISocket> Accept()
public AsyncReply<ISocket> AcceptAsync()
{
throw new NotImplementedException();
}
public void Hold()
{
//Console.WriteLine("WS Hold ");
//Console.WriteLine("WS Hold ");
held = true;
}
public void Unhold()
{
lock(sendLock)
lock (sendLock)
{
held = false;
@ -305,7 +308,7 @@ namespace Esyur.Net.Sockets
if (pkt_send.Compose())
sock.Send(pkt_send.Data);
}
}
@ -314,5 +317,10 @@ namespace Esyur.Net.Sockets
{
throw new NotImplementedException();
}
public ISocket Accept()
{
throw new NotImplementedException();
}
}
}

View File

@ -39,26 +39,26 @@ namespace Esyur.Net.TCP
public class TCPServer : NetworkServer<TCPConnection>, IResource
{
[Storable]
string ip
[Attribute]
public string IP
{
get;
set;
}
[Attribute]
public ushort Port
{
get;
set;
}
[Storable]
ushort port
public uint Timeout
{
get;
set;
}
[Storable]
uint timeout
{
get;
set;
}
[Storable]
uint clock
[Attribute]
public uint Clock
{
get;
set;
@ -75,12 +75,12 @@ namespace Esyur.Net.TCP
TCPSocket listener;
if (ip != null)
listener =new TCPSocket(new IPEndPoint(IPAddress.Parse(ip), port));
if (IP != null)
listener = new TCPSocket(new IPEndPoint(IPAddress.Parse(IP), Port));
else
listener = new TCPSocket(new IPEndPoint(IPAddress.Any, port));
listener = new TCPSocket(new IPEndPoint(IPAddress.Any, Port));
Start(listener, timeout, clock);
Start(listener, Timeout, Clock);
}
@ -108,9 +108,9 @@ namespace Esyur.Net.TCP
var msg = data.Read();
foreach (var filter in filters)
{
if (filter.Execute(msg, data, sender))
return;
{
if (filter.Execute(msg, data, sender))
return;
}
}

View File

@ -30,8 +30,8 @@ using System.Text;
using System.Collections;
using Esyur.Data;
using Esyur.Misc;
using Esyur.Engine;
using Esyur.Resource;
using Esyur.Core;
namespace Esyur.Net.UDP
{
@ -43,8 +43,9 @@ namespace Esyur.Net.UDP
}*/
public class UDPServer : IResource
{
Thread Receiver;
UdpClient Udp;
Thread receiver;
UdpClient udp;
UDPFilter[] filters = new UDPFilter[0];
public event DestroyedEvent OnDestroy;
@ -54,48 +55,30 @@ namespace Esyur.Net.UDP
set;
}
[Storable]
string ip
[Attribute]
string IP
{
get;
set;
}
[Storable]
ushort port
[Attribute]
ushort Port
{
get;
set;
}
public bool Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
{
var address = ip == null ? IPAddress.Any : IPAddress.Parse(ip);
Udp = new UdpClient(new IPEndPoint(address, (int)port));
Receiver = new Thread(Receiving);
Receiver.Start();
}
else if (trigger == ResourceTrigger.Terminate)
{
if (Receiver != null)
Receiver.Abort();
}
return true;
}
private void Receiving()
private void Receiving()
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
byte[] b = Udp.Receive(ref ep);
byte[] b = udp.Receive(ref ep);
foreach(var child in Instance.Children)
foreach (var child in filters)
{
var f = child as UDPFilter;
@ -119,7 +102,7 @@ namespace Esyur.Net.UDP
{
try
{
Udp.Send(Data, Count, EP);
udp.Send(Data, Count, EP);
return true;
}
catch
@ -131,7 +114,7 @@ namespace Esyur.Net.UDP
{
try
{
Udp.Send(Data, Data.Length, EP);
udp.Send(Data, Data.Length, EP);
return true;
}
catch
@ -143,7 +126,7 @@ namespace Esyur.Net.UDP
{
try
{
Udp.Send(Data, Count, Host, Port);
udp.Send(Data, Count, Host, Port);
return true;
}
catch
@ -155,7 +138,7 @@ namespace Esyur.Net.UDP
{
try
{
Udp.Send(Data, Data.Length, Host, Port);
udp.Send(Data, Data.Length, Host, Port);
return true;
}
catch
@ -167,7 +150,7 @@ namespace Esyur.Net.UDP
{
try
{
Udp.Send(Encoding.Default.GetBytes(Data), Data.Length, EP);
udp.Send(Encoding.Default.GetBytes(Data), Data.Length, EP);
return true;
}
catch
@ -179,7 +162,7 @@ namespace Esyur.Net.UDP
{
try
{
Udp.Send(Encoding.Default.GetBytes(Data), Data.Length, Host, Port);
udp.Send(Encoding.Default.GetBytes(Data), Data.Length, Host, Port);
return true;
}
catch
@ -190,8 +173,32 @@ namespace Esyur.Net.UDP
public void Destroy()
{
Udp.Close();
udp.Close();
OnDestroy?.Invoke(this);
}
async AsyncReply<bool> IResource.Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
{
var address = IP == null ? IPAddress.Any : IPAddress.Parse(IP);
udp = new UdpClient(new IPEndPoint(address, Port));
receiver = new Thread(Receiving);
receiver.Start();
}
else if (trigger == ResourceTrigger.Terminate)
{
if (receiver != null)
receiver.Abort();
}
else if (trigger == ResourceTrigger.SystemInitialized)
{
filters = await Instance.Children<UDPFilter>();
}
return true;
}
}
}

View File

@ -51,9 +51,9 @@ namespace Esyur.Proxy
if (typeInfo.IsSealed || typeInfo.IsAbstract)
throw new Exception("Sealed/Abastract classes can't be proxied.");
var props = from p in typeInfo.GetProperties()
where p.CanWrite && p.GetSetMethod().IsVirtual &&
p.GetCustomAttributes(typeof(ResourceProperty), false).Count() > 0
var props = from p in typeInfo.GetProperties(BindingFlags.Instance | BindingFlags.Public)
where p.CanWrite && p.SetMethod.IsVirtual &&
p.GetCustomAttribute<PublicAttribute>(false) != null
select p;
#else

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Resource
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Event)]
public class AnnotationAttribute : Attribute
{
public string Annotation { get; set; }
public AnnotationAttribute(string annotation)
{
this.Annotation = annotation;
}
}
}

View File

@ -31,10 +31,10 @@ namespace Esyur.Resource
{
[AttributeUsage(AttributeTargets.Property)]
public class ResourceAttribute : System.Attribute
public class AttributeAttribute : System.Attribute
{
public ResourceAttribute()
public AttributeAttribute()
{
}

View File

@ -176,7 +176,8 @@ namespace Esyur.Resource
if (at != null)
if (at.Info.CanWrite)
at.Info.SetValue(res, kv.Value);
at.Info.SetValue(res, DC.CastConvert(kv.Value, at.Info.PropertyType));
}
}
@ -442,7 +443,7 @@ namespace Esyur.Resource
IResource res;
if (resource.TryGetTarget(out res))
{
var rt = pt.Serilize ? pt.Info.GetValue(res, null) : null;
var rt = pt.Info.GetValue(res, null);// pt.Serilize ? pt.Info.GetValue(res, null) : null;
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
}
@ -546,13 +547,14 @@ namespace Esyur.Resource
ages[pt.Index] = instanceAge;
modificationDates[pt.Index] = now;
if (pt.Storage == StorageMode.NonVolatile)
{
store.Modify(res, pt.Name, value, ages[pt.Index], now);
}
else if (pt.Storage == StorageMode.Recordable)
if (pt.Recordable)
{
store.Record(res, pt.Name, value, ages[pt.Index], now);
}
else //if (pt.Storage == StorageMode.Recordable)
{
store.Modify(res, pt.Name, value, ages[pt.Index], now);
}
ResourceModified?.Invoke(res, pt.Name, value);
@ -839,7 +841,7 @@ namespace Esyur.Resource
this.store = store;
this.resource = new WeakReference<IResource>(resource);
this.id = id;
this.name = name;
this.name = name ?? "";
this.instanceAge = age;
//this.attributes = new KeyList<string, object>(this);
@ -875,30 +877,32 @@ namespace Esyur.Resource
var events = t.GetEvents(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
#endif
foreach (var evt in events)
foreach (var evt in template.Events)
{
//if (evt.EventHandlerType != typeof(ResourceEventHanlder))
// continue;
if (evt.EventHandlerType == typeof(ResourceEventHanlder))
if (evt.Info.EventHandlerType == typeof(ResourceEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
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);
evt.Info.AddEventHandler(resource, proxyDelegate);
}
else if (evt.EventHandlerType == typeof(CustomResourceEventHanlder))
else if (evt.Info.EventHandlerType == typeof(CustomResourceEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
//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);
evt.Info.AddEventHandler(resource, proxyDelegate);
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Resource
{
public class PrivateAttribute:Attribute
{
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Resource
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Event | AttributeTargets.Class)]
public class PublicAttribute : Attribute
{
// public StorageMode Storage { get; set; }
//public bool Serialize { get; set; }
public PublicAttribute()//StorageMode storage = StorageMode.NonVolatile, bool serialize = true)
{
// Storage = storage;
//Serialize = serialize;
}
}
}

View File

@ -47,7 +47,7 @@ namespace Esyur.Resource
return new AsyncReply<bool>(true);
}
public virtual bool Create()
protected virtual bool Create()
{
return true;
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Resource
{
[AttributeUsage(AttributeTargets.Property)]
public class StorageAttribute:Attribute
{
public StorageMode Mode { get; set; }
public StorageAttribute(StorageMode mode)
{
Mode = mode;
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Text;
using Esyur.Core;
using Esyur.Data;
using Esyur.Resource.Template;
namespace Esyur.Resource
{
public abstract class Store<T> : IStore where T:IResource
{
public Instance Instance { get; set; }
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> AddChild(IResource parent, IResource child);
public abstract AsyncReply<bool> AddParent(IResource child, IResource parent);
public abstract AsyncBag<T1> Children<T1>(IResource resource, string name) where T1 : IResource;
public virtual void Destroy()
{
OnDestroy?.Invoke(this);
}
public abstract AsyncReply<IResource> Get(string path);
public abstract AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, DateTime fromDate, DateTime toDate);
public abstract string Link(IResource resource);
public abstract bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime);
public abstract AsyncBag<T1> Parents<T1>(IResource resource, string name) where T1 : IResource;
public abstract AsyncReply<bool> Put(IResource resource);
public abstract bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime);
public abstract bool Remove(IResource resource);
public abstract AsyncReply<bool> RemoveChild(IResource parent, IResource child);
public abstract AsyncReply<bool> RemoveParent(IResource child, IResource parent);
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public T New(string name = null, object attributes = null, object properties = null)
{
var resource = Warehouse.New<T>(name, this, null, null, attributes, properties);
resource.Instance.Managers.AddRange(this.Instance.Managers.ToArray());
return resource;
}
}
}

View File

@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
@ -15,6 +16,8 @@ namespace Esyur.Resource.Template
set;
}
public EventInfo Info { get; set; }
public override byte[] Compose()
{
var name = base.Compose();
@ -39,7 +42,7 @@ namespace Esyur.Resource.Template
}
public EventTemplate(ResourceTemplate template, byte index, string name, string expansion)
public EventTemplate(ResourceTemplate template, byte index, string name, string expansion = null)
:base(template, MemberType.Property, index, name)
{
this.Expansion = expansion;

View File

@ -45,7 +45,7 @@ namespace Esyur.Resource.Template
}
public FunctionTemplate(ResourceTemplate template, byte index, string name,bool isVoid, string expansion)
public FunctionTemplate(ResourceTemplate template, byte index, string name,bool isVoid, string expansion = null)
:base(template, MemberType.Property, index, name)
{
this.IsVoid = isVoid;

View File

@ -24,10 +24,12 @@ namespace Esyur.Resource.Template
set;
}
/*
public bool Serilize
{
get;set;
}
*/
//bool ReadOnly;
//IIPTypes::DataType ReturnType;
public PropertyPermission Permission {
@ -35,18 +37,19 @@ namespace Esyur.Resource.Template
set;
}
/*
public bool Recordable
{
get;
set;
}*/
}
public StorageMode Storage
/*
public PropertyType Mode
{
get;
set;
}
}*/
public string ReadExpansion
{
@ -71,7 +74,7 @@ namespace Esyur.Resource.Template
public override byte[] Compose()
{
var name = base.Compose();
var pv = ((byte)(Permission) << 1) | (Storage == StorageMode.Recordable ? 1 : 0);
var pv = ((byte)(Permission) << 1) | (Recordable ? 1 : 0);
if (WriteExpansion != null && ReadExpansion != null)
{
@ -117,11 +120,11 @@ namespace Esyur.Resource.Template
.ToArray();
}
public PropertyTemplate(ResourceTemplate template, byte index, string name, string read, string write, StorageMode storage)
public PropertyTemplate(ResourceTemplate template, byte index, string name, string read = null, string write = null, bool recordable = false)
:base(template, MemberType.Property, index, name)
{
//this.Recordable = recordable;
this.Storage = storage;
this.Recordable = recordable;
//this.Storage = storage;
this.ReadExpansion = read;
this.WriteExpansion = write;
}

View File

@ -8,6 +8,7 @@ using Esyur.Data;
using Esyur.Core;
using System.Security.Cryptography;
using Esyur.Proxy;
using Esyur.Net.IIP;
namespace Esyur.Resource.Template
{
@ -159,52 +160,87 @@ namespace Esyur.Resource.Template
MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
#endif
//byte currentIndex = 0;
bool classIsPublic = type.GetCustomAttribute<PublicAttribute>() != null;
byte i = 0;
foreach (var pi in propsInfo)
if (classIsPublic)
{
var rp = pi.GetCustomAttribute<ResourceProperty>(true);
if (rp != null)
{
var pt = new PropertyTemplate(this, i++, pi.Name, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
pt.Info = pi;
pt.Serilize = rp.Serialize;
properties.Add(pt);
}
var ra = pi.GetCustomAttribute<ResourceAttribute>(true);
if (ra != null)
{
var at = new AttributeTemplate(this, i++, pi.Name);
at.Info = pi;
attributes.Add(at);
}
}
i = 0;
foreach (var ei in eventsInfo)
else
{
var es = ei.GetCustomAttributes<ResourceEvent>(true).ToArray();
if (es.Length > 0)
foreach (var pi in propsInfo)
{
var et = new EventTemplate(this, i++, ei.Name, es[0].Expansion);
events.Add(et);
var publicAttr = pi.GetCustomAttribute<PublicAttribute>(true);
if (publicAttr != null)
{
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
var pt = new PropertyTemplate(this, i++, pi.Name);//, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
if (storageAttr != null)
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
if (annotationAttr != null)
pt.ReadExpansion = annotationAttr.Annotation;
else
pt.ReadExpansion = pi.PropertyType.Name;
pt.Info = pi;
//pt.Serilize = publicAttr.Serialize;
properties.Add(pt);
}
else
{
var attributeAttr = pi.GetCustomAttribute<AttributeAttribute>(true);
if (attributeAttr != null)
{
var at = new AttributeTemplate(this, 0, pi.Name);
at.Info = pi;
attributes.Add(at);
}
}
}
}
i = 0;
foreach (MethodInfo mi in methodsInfo)
{
var fs = mi.GetCustomAttributes<ResourceFunction>(true).ToArray();
if (fs.Length > 0)
i = 0;
foreach (var ei in eventsInfo)
{
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void), fs[0].Expansion);
functions.Add(ft);
var publicAttr = ei.GetCustomAttribute<PublicAttribute>(true);
if (publicAttr != null)
{
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
var et = new EventTemplate(this, i++, ei.Name);
et.Info = ei;
if (annotationAttr != null)
et.Expansion = annotationAttr.Annotation;
events.Add(et);
}
}
i = 0;
foreach (MethodInfo mi in methodsInfo)
{
var publicAttr = mi.GetCustomAttribute<PublicAttribute>(true);
if (publicAttr != null)
{
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void));
if (annotationAttr != null)
ft.Expansion = annotationAttr.Annotation;
else
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x=>x.ParameterType != typeof(DistributedConnection)).Select(x=> "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
functions.Add(ft);
}
}
}
@ -323,7 +359,7 @@ namespace Esyur.Resource.Template
offset += cs;
}
var pt = new PropertyTemplate(od, propertyIndex++, name, readExpansion, writeExpansion, recordable ? StorageMode.Recordable : StorageMode.Volatile);
var pt = new PropertyTemplate(od, propertyIndex++, name, readExpansion, writeExpansion, recordable);
od.properties.Add(pt);
}

View File

@ -35,6 +35,7 @@ using System.Threading.Tasks;
using Esyur.Net.IIP;
using System.Text.RegularExpressions;
using Esyur.Misc;
using System.Collections.Concurrent;
namespace Esyur.Resource
{
@ -43,8 +44,11 @@ namespace Esyur.Resource
{
//static byte prefixCounter;
static AutoList<IStore, Instance> stores = new AutoList<IStore, Instance>(null);
static Dictionary<uint, WeakReference<IResource>> resources = new Dictionary<uint, WeakReference<IResource>>();
//static AutoList<IStore, Instance> stores = new AutoList<IStore, Instance>(null);
static ConcurrentDictionary<uint, WeakReference<IResource>> resources = new ConcurrentDictionary<uint, WeakReference<IResource>>();
static ConcurrentDictionary<IStore, List<WeakReference<IResource>>> stores = new ConcurrentDictionary<IStore, List<WeakReference<IResource>>>();
static uint resourceCounter = 0;
static KeyList<Guid, ResourceTemplate> templates = new KeyList<Guid, ResourceTemplate>();
@ -61,7 +65,7 @@ namespace Esyur.Resource
private static Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)");
private static object resourcesLock = new object();
//private static object resourcesLock = new object();
static KeyList<string, Func<IStore>> getSupportedProtocols()
{
@ -78,8 +82,8 @@ namespace Esyur.Resource
public static IStore GetStore(string name)
{
foreach (var s in stores)
if (s.Instance.Name == name)
return s as IStore;
if (s.Key.Instance.Name == name)
return s.Key;
return null;
}
@ -113,22 +117,28 @@ namespace Esyur.Resource
{
warehouseIsOpen = true;
var resSnap = resources.Select(x => {
IResource r;
var resSnap = resources.Select(x =>
{
IResource r;
if (x.Value.TryGetTarget(out r))
return r;
else
return null;
}).Where(r=>r!=null).ToArray();
}).Where(r => r != null).ToArray();
foreach (var r in resSnap)
{
//IResource r;
//if (rk.Value.TryGetTarget(out r))
//{
var rt = await r.Trigger(ResourceTrigger.Initialize);
if (!rt)
return false;
var rt = await r.Trigger(ResourceTrigger.Initialize);
//if (!rt)
// return false;
if (!rt)
{
Console.WriteLine($"Resource failed at Initialize {r.Instance.Name} [{r.Instance.Template.ClassName}]");
}
//}
}
@ -137,9 +147,12 @@ namespace Esyur.Resource
//IResource r;
//if (rk.Value.TryGetTarget(out r))
//{
var rt = await r.Trigger(ResourceTrigger.SystemInitialized);
if (!rt)
return false;
var rt = await r.Trigger(ResourceTrigger.SystemInitialized);
if (!rt)
{
Console.WriteLine($"Resource failed at SystemInitialized {r.Instance.Name} [{r.Instance.Template.ClassName}]");
}
//return false;
//}
}
@ -217,7 +230,7 @@ namespace Esyur.Resource
}
foreach (var store in stores)
bag.Add(store.Trigger(ResourceTrigger.Terminate));
bag.Add(store.Key.Trigger(ResourceTrigger.Terminate));
foreach (var resource in resources.Values)
@ -232,7 +245,7 @@ namespace Esyur.Resource
foreach (var store in stores)
bag.Add(store.Trigger(ResourceTrigger.SystemTerminated));
bag.Add(store.Key.Trigger(ResourceTrigger.SystemTerminated));
bag.Seal();
@ -318,7 +331,7 @@ namespace Esyur.Resource
var p = path.Trim().Split('/');
IResource resource;
foreach (var store in stores)
foreach (var store in stores.Keys)
if (p[0] == store.Instance.Name)
{
@ -433,19 +446,26 @@ namespace Esyur.Resource
if (resource.Instance != null)
throw new Exception("Resource has a store.");
var resourceReference = new WeakReference<IResource>(resource);
if (store == null)
{
// assign parent as a store
if (parent is IStore)
{
store = (IStore)parent;
stores[store].Add(resourceReference);
}
// assign parent's store as a store
else if (parent != null)
{
store = parent.Instance.Store;
stores[store].Add(resourceReference);
}
// assign self as a store (root store)
else if (resource is IStore)
{
store = (IStore)resource;
stores.Add(resource as IStore);
}
else
throw new Exception("Can't find a store for the resource.");
@ -475,10 +495,13 @@ namespace Esyur.Resource
if (resource is IStore)
{
stores.TryAdd(resource as IStore, new List<WeakReference<IResource>>());
StoreConnected?.Invoke(resource as IStore, name);
}
//else
store.Put(resource);
@ -493,15 +516,17 @@ namespace Esyur.Resource
var t = resource.GetType();
Global.Counters["T-" + t.Namespace + "." + t.Name]++;
lock (resourcesLock)
resources.Add(resource.Instance.Id, new WeakReference<IResource>(resource));
//var wr = new WeakReference<IResource>(resource);
//lock (resourcesLock)
resources.TryAdd(resource.Instance.Id, resourceReference);
if (warehouseIsOpen)
resource.Trigger(ResourceTrigger.Initialize);
}
public static IResource New(Type type, string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, Structure attributes = null, Structure arguments = null, Structure properties = null)
public static IResource New(Type type, string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null)
{
type = ResourceProxy.GetProxy(type);
@ -539,9 +564,12 @@ namespace Esyur.Resource
*/
var res = Activator.CreateInstance(type) as IResource;
if (properties != null)
{
foreach (var p in properties)
var ps = Structure.FromObject(properties);
foreach (var p in ps)
{
var pi = type.GetProperty(p.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
if (pi != null)
@ -556,10 +584,10 @@ namespace Esyur.Resource
}
public static T New<T>(string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, Structure attributes = null, Structure arguments = null, Structure properties = null)
public static T New<T>(string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null)
where T : IResource
{
return (T)New(typeof(T), name, store, parent, manager, attributes, arguments, properties);
return (T)New(typeof(T), name, store, parent, manager, attributes, properties);
}
/// <summary>
@ -619,31 +647,45 @@ namespace Esyur.Resource
public static bool Remove(IResource resource)
{
if (resource.Instance == null)
return false;
//lock (resourcesLock)
//{
WeakReference<IResource> resourceReference;
if (resources.ContainsKey(resource.Instance.Id))
lock(resourcesLock)
resources.Remove(resource.Instance.Id);
resources.TryRemove(resource.Instance.Id, out resourceReference);
else
return false;
//}
if (resource != resource.Instance.Store)
stores[resource.Instance.Store].Remove(resourceReference);
if (resource is IStore)
{
stores.Remove(resource as IStore);
var store = resource as IStore;
WeakReference<IResource>[] toBeRemoved;
List<WeakReference<IResource>> toBeRemoved;// = stores[store];
stores.TryRemove(store, out toBeRemoved);
//lock (resourcesLock)
//{
// // remove all objects associated with the store
// toBeRemoved = resources.Values.Where(x =>
// {
// IResource r;
// if (x.TryGetTarget(out r))
// return r.Instance.Store == resource;
// else
// return false;
// }).ToArray();
//}
lock (resourcesLock)
{
// remove all objects associated with the store
toBeRemoved = resources.Values.Where(x =>
{
IResource r;
return x.TryGetTarget(out r) && r.Instance.Store == resource;
}).ToArray();
}
foreach (var o in toBeRemoved)
{

View File

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Security.Integrity
{
public class CRC16IBM
{
static UInt16[] table = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};
public static ushort Compute(byte[] data)
{
return Compute(data, 0, (uint)data.Length);
}
public static ushort Compute(byte[] data, uint offset, uint length)
{
ushort crc = 0;// 0xffff;
ushort x;
for (var i = offset; i < length; i++)
{
x = (ushort)(crc ^ data[i]);
crc = (UInt16)((crc >> 8) ^ table[x & 0x00FF]);
}
return crc;
}
public static ushort Compute2(byte[] data, uint offset, uint length)
{
ushort crc = 0;
for (var i = offset; i < length; i++)
{
crc ^= data[i];
for (var j = 0; j < 8; j++)
{
var carry = crc & 0x1;
crc >>= 1;
if (carry == 1)
crc ^= 0xa001;
}
}
return crc;
}
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Security.Integrity
{
public class CRC16ITU
{
static UInt16[] table =
{
0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF,
0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7,
0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E,
0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876,
0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD,
0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5,
0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C,
0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974,
0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB,
0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3,
0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A,
0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72,
0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9,
0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1,
0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738,
0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70,
0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7,
0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF,
0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036,
0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E,
0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5,
0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD,
0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134,
0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C,
0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3,
0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB,
0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232,
0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A,
0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1,
0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9,
0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330,
0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78,
};
public static ushort Compute(byte[] data)
{
return Compute(data, 0, (uint)data.Length);
}
public static ushort Compute(byte[] data, uint offset, uint length)
{
ushort fcs = 0xffff; // initialization
while (length > 0)
{
fcs = (ushort)((fcs >> 8) ^ table[(fcs ^ data[offset++]) & 0xff]);
length--;
}
return (ushort)~fcs; // negated
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Security.Integrity
{
public class NMEA0183
{
public static byte Compute(string data)
{
return Compute(data, 0, (uint)data.Length);
}
public static byte Compute(string data, uint offset, uint length)
{
byte rt = 0;
var ends = offset + length;
for (int i = (int)offset; i < ends; i++)
rt ^= (byte)data[i];
return rt;
}
}
}