mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-09-13 12:43:17 +00:00
AsyncReply
This commit is contained in:
@@ -38,18 +38,19 @@ namespace Esiur.Core;
|
||||
[AsyncMethodBuilder(typeof(AsyncReplyBuilder))]
|
||||
public class AsyncReply
|
||||
{
|
||||
//public bool Debug = false;
|
||||
|
||||
protected List<Action<object>> callbacks = new List<Action<object>>();
|
||||
protected object result;
|
||||
|
||||
protected List<Action<AsyncException>> errorCallbacks = new List<Action<AsyncException>>();
|
||||
protected List<Action<AsyncException>> errorCallbacks = null;
|
||||
|
||||
protected List<Action<ProgressType, int, int>> progressCallbacks = new List<Action<ProgressType, int, int>>();
|
||||
protected List<Action<ProgressType, uint, uint>> progressCallbacks = null;
|
||||
|
||||
protected List<Action<object>> chunkCallbacks = new List<Action<object>>();
|
||||
protected List<Action<object>> chunkCallbacks = null;
|
||||
|
||||
protected List<Action<object>> propagationCallbacks = null;
|
||||
protected List<Action<byte, string>> warningCallbacks = null;
|
||||
|
||||
//List<AsyncAwaiter> awaiters = new List<AsyncAwaiter>();
|
||||
|
||||
object asyncLock = new object();
|
||||
|
||||
@@ -77,15 +78,8 @@ public class AsyncReply
|
||||
if (resultReady)
|
||||
return result;
|
||||
|
||||
//if (Debug)
|
||||
// Console.WriteLine($"AsyncReply: {Id} Wait");
|
||||
|
||||
//mutex = new AutoResetEvent(false);
|
||||
mutex.WaitOne();
|
||||
|
||||
//if (Debug)
|
||||
// Console.WriteLine($"AsyncReply: {Id} Wait ended");
|
||||
|
||||
if (exception != null)
|
||||
throw exception;
|
||||
|
||||
@@ -183,34 +177,52 @@ public class AsyncReply
|
||||
|
||||
public AsyncReply Error(Action<AsyncException> callback)
|
||||
{
|
||||
// lock (callbacksLock)
|
||||
// {
|
||||
|
||||
if (errorCallbacks == null)
|
||||
errorCallbacks = new List<Action<AsyncException>>();
|
||||
|
||||
errorCallbacks.Add(callback);
|
||||
|
||||
if (exception != null)
|
||||
callback(exception);
|
||||
|
||||
return this;
|
||||
//}
|
||||
}
|
||||
|
||||
public AsyncReply Progress(Action<ProgressType, int, int> callback)
|
||||
public AsyncReply Progress(Action<ProgressType, uint, uint> callback)
|
||||
{
|
||||
//lock (callbacksLock)
|
||||
//{
|
||||
if (progressCallbacks == null)
|
||||
progressCallbacks = new List<Action<ProgressType, uint, uint>>();
|
||||
|
||||
progressCallbacks.Add(callback);
|
||||
return this;
|
||||
//}
|
||||
}
|
||||
|
||||
public AsyncReply Warning(Action<byte, string> callback)
|
||||
{
|
||||
if (warningCallbacks == null)
|
||||
warningCallbacks = new List<Action<byte, string>>();
|
||||
|
||||
warningCallbacks.Add(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncReply Chunk(Action<object> callback)
|
||||
{
|
||||
// lock (callbacksLock)
|
||||
// {
|
||||
if (chunkCallbacks == null)
|
||||
chunkCallbacks = new List<Action<object>>();
|
||||
|
||||
chunkCallbacks.Add(callback);
|
||||
return this;
|
||||
// }
|
||||
}
|
||||
|
||||
public AsyncReply Propagation(Action<object> callback)
|
||||
{
|
||||
if (propagationCallbacks == null)
|
||||
propagationCallbacks = new List<Action<object>>();
|
||||
|
||||
propagationCallbacks.Add(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncReply Trigger(object result)
|
||||
@@ -259,45 +271,68 @@ public class AsyncReply
|
||||
else
|
||||
this.exception = new AsyncException(exception);
|
||||
|
||||
|
||||
// lock (callbacksLock)
|
||||
// {
|
||||
if (errorCallbacks != null)
|
||||
{
|
||||
foreach (var cb in errorCallbacks)
|
||||
cb(this.exception);
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
// no error handlers found
|
||||
throw exception;
|
||||
}
|
||||
|
||||
mutex?.Set();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncReply TriggerProgress(ProgressType type, int value, int max)
|
||||
public AsyncReply TriggerProgress(ProgressType type, uint value, uint max)
|
||||
{
|
||||
//timeout?.Dispose();
|
||||
|
||||
//lock (callbacksLock)
|
||||
//{
|
||||
if (progressCallbacks != null)
|
||||
foreach (var cb in progressCallbacks)
|
||||
cb(type, value, max);
|
||||
|
||||
//}
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncReply TriggerWarning(byte level, string message)
|
||||
{
|
||||
//timeout?.Dispose();
|
||||
|
||||
if (warningCallbacks != null)
|
||||
foreach (var cb in warningCallbacks)
|
||||
cb(level, message);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public AsyncReply TriggerPropagation(object value)
|
||||
{
|
||||
//timeout?.Dispose();
|
||||
|
||||
if (propagationCallbacks != null)
|
||||
foreach (var cb in propagationCallbacks)
|
||||
cb(value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public AsyncReply TriggerChunk(object value)
|
||||
{
|
||||
|
||||
//timeout?.Dispose();
|
||||
|
||||
|
||||
//lock (callbacksLock)
|
||||
//{
|
||||
if (chunkCallbacks != null)
|
||||
foreach (var cb in chunkCallbacks)
|
||||
cb(value);
|
||||
|
||||
//}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ public class AsyncReply<T> : AsyncReply
|
||||
return this;
|
||||
}
|
||||
|
||||
public new AsyncReply<T> Progress(Action<ProgressType, int, int> callback)
|
||||
public new AsyncReply<T> Progress(Action<ProgressType, uint, uint> callback)
|
||||
{
|
||||
base.Progress(callback);
|
||||
return this;
|
||||
|
@@ -7,5 +7,6 @@ namespace Esiur.Core;
|
||||
public enum ErrorType
|
||||
{
|
||||
Management,
|
||||
Exception
|
||||
Exception,
|
||||
Warning
|
||||
}
|
||||
|
@@ -40,10 +40,11 @@ public enum ExceptionCode : ushort
|
||||
AddToStoreFailed,
|
||||
NotAttached,
|
||||
AlreadyListened,
|
||||
AlreadyUnlistened,
|
||||
AlreadyUnsubscribed,
|
||||
NotSubscribable,
|
||||
ParseError,
|
||||
Timeout,
|
||||
NotSupported,
|
||||
NotImplemented
|
||||
NotImplemented,
|
||||
NotAllowed
|
||||
}
|
||||
|
@@ -47,47 +47,110 @@ public static class Codec
|
||||
static AsyncParser[][] FixedAsyncParsers = new AsyncParser[][]
|
||||
{
|
||||
new AsyncParser[]{
|
||||
DataDeserializer.NullParserAsync,
|
||||
DataDeserializer.BooleanFalseParserAsync,
|
||||
DataDeserializer.BooleanTrueParserAsync,
|
||||
DataDeserializer.NotModifiedParserAsync,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
DataDeserializer.UInt8ParserAsync,
|
||||
DataDeserializer.Int8ParserAsync,
|
||||
DataDeserializer.Char8ParserAsync,
|
||||
DataDeserializer.LocalResourceParser8Async,
|
||||
DataDeserializer.ResourceParser8Async,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
DataDeserializer.Int16ParserAsync,
|
||||
DataDeserializer.UInt16ParserAsync,
|
||||
DataDeserializer.Char16ParserAsync,
|
||||
DataDeserializer.LocalResourceParser16Async,
|
||||
DataDeserializer.ResourceParser16Async,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
DataDeserializer.Int32ParserAsync,
|
||||
DataDeserializer.UInt32ParserAsync,
|
||||
DataDeserializer.Float32ParserAsync,
|
||||
DataDeserializer.LocalResourceParser32Async,
|
||||
DataDeserializer.ResourceParser32Async,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
DataDeserializer.Int64ParserAsync,
|
||||
DataDeserializer.UInt64ParserAsync,
|
||||
DataDeserializer.Float64ParserAsync,
|
||||
DataDeserializer.DateTimeParserAsync,
|
||||
},
|
||||
new AsyncParser[]
|
||||
{
|
||||
DataDeserializer.Int128ParserAsync, // int 128
|
||||
DataDeserializer.UInt128ParserAsync, // uint 128
|
||||
DataDeserializer.Float128ParserAsync,
|
||||
}
|
||||
};
|
||||
|
||||
static AsyncParser[] DynamicAsyncParsers = new AsyncParser[]
|
||||
{
|
||||
DataDeserializer.RawDataParserAsync,
|
||||
DataDeserializer.StringParserAsync,
|
||||
DataDeserializer.ListParserAsync,
|
||||
DataDeserializer.ResourceListParserAsync,
|
||||
DataDeserializer.RecordListParserAsync,
|
||||
};
|
||||
|
||||
static AsyncParser[] TypedAsyncParsers = new AsyncParser[]
|
||||
{
|
||||
DataDeserializer.RecordParserAsync,
|
||||
DataDeserializer.TypedListParserAsync,
|
||||
DataDeserializer.TypedMapParserAsync,
|
||||
DataDeserializer.TupleParserAsync,
|
||||
DataDeserializer.EnumParserAsync,
|
||||
DataDeserializer.ConstantParserAsync,
|
||||
};
|
||||
|
||||
|
||||
static SyncParser[][] FixedParsers = new SyncParser[][]
|
||||
{
|
||||
new SyncParser[]{
|
||||
DataDeserializer.NullParser,
|
||||
DataDeserializer.BooleanFalseParser,
|
||||
DataDeserializer.BooleanTrueParser,
|
||||
DataDeserializer.NotModifiedParser,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
DataDeserializer.ByteParser,
|
||||
DataDeserializer.SByteParser,
|
||||
new SyncParser[]{
|
||||
DataDeserializer.UInt8Parser,
|
||||
DataDeserializer.Int8Parser,
|
||||
DataDeserializer.Char8Parser,
|
||||
DataDeserializer.LocalResourceParser8,
|
||||
DataDeserializer.ResourceParser8,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
new SyncParser[]{
|
||||
DataDeserializer.Int16Parser,
|
||||
DataDeserializer.UInt16Parser,
|
||||
DataDeserializer.Char16Parser,
|
||||
DataDeserializer.LocalResourceParser16,
|
||||
DataDeserializer.ResourceParser16,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
new SyncParser[]{
|
||||
DataDeserializer.Int32Parser,
|
||||
DataDeserializer.UInt32Parser,
|
||||
DataDeserializer.Float32Parser,
|
||||
DataDeserializer.LocalResourceParser32,
|
||||
DataDeserializer.ResourceParser32,
|
||||
},
|
||||
new AsyncParser[]{
|
||||
new SyncParser[]{
|
||||
DataDeserializer.Int64Parser,
|
||||
DataDeserializer.UInt64Parser,
|
||||
DataDeserializer.Float64Parser,
|
||||
DataDeserializer.DateTimeParser,
|
||||
},
|
||||
new AsyncParser[]
|
||||
new SyncParser[]
|
||||
{
|
||||
DataDeserializer.Int128Parser, // int 128
|
||||
DataDeserializer.UInt128Parser, // uint 128
|
||||
DataDeserializer.Float128Parser,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
static AsyncParser[] DynamicAsyncParsers = new AsyncParser[]
|
||||
static SyncParser[] DynamicParsers = new SyncParser[]
|
||||
{
|
||||
DataDeserializer.RawDataParser,
|
||||
DataDeserializer.StringParser,
|
||||
@@ -96,7 +159,7 @@ public static class Codec
|
||||
DataDeserializer.RecordListParser,
|
||||
};
|
||||
|
||||
static AsyncParser[] TypedAsyncParsers = new AsyncParser[]
|
||||
static SyncParser[] TypedParsers = new SyncParser[]
|
||||
{
|
||||
DataDeserializer.RecordParser,
|
||||
DataDeserializer.TypedListParser,
|
||||
@@ -106,7 +169,6 @@ public static class Codec
|
||||
DataDeserializer.ConstantParser,
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value
|
||||
/// </summary>
|
||||
|
@@ -373,7 +373,7 @@ public static class DataDeserializer
|
||||
|
||||
var initRecord = (TypeTemplate template) =>
|
||||
{
|
||||
ListParser(data, offset, length, connection, requestSequence).Then(r =>
|
||||
ListParserAsync(data, offset, length, connection, requestSequence).Then(r =>
|
||||
{
|
||||
var ar = (object[])r;
|
||||
|
||||
@@ -684,6 +684,31 @@ public static class DataDeserializer
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public static (uint, ulong, object[]) LimitedCountListParser(byte[] data, uint offset, ulong length, uint countLimit = uint.MaxValue)
|
||||
{
|
||||
var rt = new List<object>();
|
||||
|
||||
while (length > 0 && rt.Count < countLimit)
|
||||
{
|
||||
var (cs, reply) = Codec.ParseSync(data, offset);
|
||||
|
||||
rt.Add(reply);
|
||||
|
||||
if (cs > 0)
|
||||
{
|
||||
offset += (uint)cs;
|
||||
length -= (uint)cs;
|
||||
}
|
||||
else
|
||||
throw new Exception("Error while parsing structured data");
|
||||
|
||||
}
|
||||
|
||||
return (offset, length, rt.ToArray());
|
||||
}
|
||||
|
||||
|
||||
public static AsyncReply TypedMapParserAsync(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
|
||||
{
|
||||
// get key type
|
||||
@@ -826,6 +851,21 @@ public static class DataDeserializer
|
||||
var type = typeof(ValueTuple<,,,>).MakeGenericType(types.ToArray());
|
||||
rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3]));
|
||||
}
|
||||
else if (ar.Length == 5)
|
||||
{
|
||||
var type = typeof(ValueTuple<,,,,>).MakeGenericType(types.ToArray());
|
||||
rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3], ar[4]));
|
||||
}
|
||||
else if (ar.Length == 6)
|
||||
{
|
||||
var type = typeof(ValueTuple<,,,,,>).MakeGenericType(types.ToArray());
|
||||
rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3], ar[4], ar[5]));
|
||||
}
|
||||
else if (ar.Length == 7)
|
||||
{
|
||||
var type = typeof(ValueTuple<,,,,,,>).MakeGenericType(types.ToArray());
|
||||
rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3], ar[4], ar[5], ar[6]));
|
||||
}
|
||||
});
|
||||
|
||||
return rt;
|
||||
@@ -896,9 +936,12 @@ public static class DataDeserializer
|
||||
var type = typeof(ValueTuple<,,,,,,>).MakeGenericType(types.ToArray());
|
||||
return Activator.CreateInstance(type, results[0], results[1], results[2], results[3], results[4], results[5], results[6]);
|
||||
}
|
||||
|
||||
throw new Exception("Unknown tuple length.");
|
||||
|
||||
}
|
||||
|
||||
public static AsyncReply TypedListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
|
||||
public static AsyncReply TypedListParserAsync(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
|
||||
{
|
||||
var rt = new AsyncBag<object>();
|
||||
|
||||
@@ -932,13 +975,47 @@ public static class DataDeserializer
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static object TypedListParser(byte[] data, uint offset, uint length)
|
||||
{
|
||||
|
||||
public static AsyncBag<PropertyValue> PropertyValueArrayParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
|
||||
// get the type
|
||||
var (hdrCs, rep) = RepresentationType.Parse(data, offset);
|
||||
|
||||
offset += hdrCs;
|
||||
length -= hdrCs;
|
||||
|
||||
var runtimeType = rep.GetRuntimeType();
|
||||
|
||||
var list = new List<object>();
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var (cs, reply) = Codec.ParseSync(data, offset);
|
||||
|
||||
list.Add(reply);
|
||||
|
||||
if (cs > 0)
|
||||
{
|
||||
offset += (uint)cs;
|
||||
length -= (uint)cs;
|
||||
}
|
||||
else
|
||||
throw new Exception("Error while parsing structured data");
|
||||
|
||||
}
|
||||
|
||||
var rt = Array.CreateInstance(runtimeType, list.Count);
|
||||
Array.Copy(list.ToArray(), rt, rt.Length);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static AsyncBag<PropertyValue> PropertyValueArrayParserAsync(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
|
||||
{
|
||||
var rt = new AsyncBag<PropertyValue>();
|
||||
|
||||
|
||||
ListParser(data, offset, length, connection, requestSequence).Then(x =>
|
||||
ListParserAsync(data, offset, length, connection, requestSequence).Then(x =>
|
||||
{
|
||||
var ar = (object[])x;
|
||||
var pvs = new List<PropertyValue>();
|
||||
@@ -954,7 +1031,8 @@ public static class DataDeserializer
|
||||
|
||||
}
|
||||
|
||||
public static (uint, AsyncReply<PropertyValue>) PropertyValueParser(byte[] data, uint offset, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
|
||||
|
||||
public static (uint, AsyncReply<PropertyValue>) PropertyValueParserAsync(byte[] data, uint offset, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
|
||||
{
|
||||
var reply = new AsyncReply<PropertyValue>();
|
||||
|
||||
@@ -967,15 +1045,22 @@ public static class DataDeserializer
|
||||
|
||||
var (valueSize, results) = Codec.ParseAsync(data, offset, connection, requestSequence);
|
||||
|
||||
results.Then(value =>
|
||||
if (results is AsyncReply)
|
||||
{
|
||||
(results as AsyncReply).Then(value =>
|
||||
{
|
||||
reply.Trigger(new PropertyValue(value, age, date));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.Trigger(new PropertyValue(results, age, date));
|
||||
}
|
||||
|
||||
return (16 + valueSize, reply);
|
||||
}
|
||||
|
||||
public static AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> HistoryParser(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection, uint[] requestSequence)
|
||||
public static AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> HistoryParserAsync(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection, uint[] requestSequence)
|
||||
{
|
||||
//var count = (int)toAge - (int)fromAge;
|
||||
|
||||
@@ -994,7 +1079,7 @@ public static class DataDeserializer
|
||||
var cs = data.GetUInt32(offset, Endian.Little);
|
||||
offset += 4;
|
||||
|
||||
var (len, pv) = PropertyValueParser(data, offset, connection, requestSequence);
|
||||
var (len, pv) = PropertyValueParserAsync(data, offset, connection, requestSequence);
|
||||
|
||||
bagOfBags.Add(pv);// ParsePropertyValueArray(data, offset, cs, connection));
|
||||
offset += len;
|
||||
|
@@ -102,7 +102,7 @@ public static class DataSerializer
|
||||
var rt = new byte[16];
|
||||
fixed (byte* ptr = rt)
|
||||
*((decimal*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.Float128, rt);
|
||||
return (TransmissionTypeIdentifier.Decimal128, rt);
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ public static class DataSerializer
|
||||
rt.AddRange(template.ClassId.Data);
|
||||
rt.Add(ct.Index);
|
||||
|
||||
return (TransmissionTypeIdentifier.Enum, rt.ToArray());
|
||||
return (TransmissionTypeIdentifier.TypedEnum, rt.ToArray());
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) UInt8Composer(object value, DistributedConnection connection)
|
||||
@@ -274,7 +274,7 @@ public static class DataSerializer
|
||||
|
||||
var map = (IMap)value;
|
||||
|
||||
foreach(var el in map.Serialize())
|
||||
foreach (var el in map.Serialize())
|
||||
rt.AddRange(Codec.Compose(el, connection));
|
||||
|
||||
return (TransmissionTypeIdentifier.TypedMap, rt.ToArray());
|
||||
@@ -315,7 +315,6 @@ public static class DataSerializer
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) ResourceComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
var resource = (IResource)value;
|
||||
var rt = new byte[4];
|
||||
|
||||
if (resource.Instance == null || resource.Instance.IsDestroyed)
|
||||
{
|
||||
@@ -324,11 +323,25 @@ public static class DataSerializer
|
||||
|
||||
if (Codec.IsLocalResource(resource, connection))
|
||||
{
|
||||
var rid = (resource as DistributedResource).DistributedResourceInstanceId;
|
||||
|
||||
if (rid <= 0xFF)
|
||||
return (TransmissionTypeIdentifier.LocalResource8, new byte[] { (byte)rid });
|
||||
else if (rid <= 0xFFFF)
|
||||
{
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = (resource as DistributedResource).DistributedResourceInstanceId;
|
||||
*((ushort*)ptr) = (ushort)rid;
|
||||
|
||||
return (TransmissionTypeIdentifier.ResourceLocal, rt);
|
||||
return (TransmissionTypeIdentifier.LocalResource16, rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = rid;
|
||||
return (TransmissionTypeIdentifier.LocalResource32, rt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -336,11 +349,25 @@ public static class DataSerializer
|
||||
//rt.Append((value as IResource).Instance.Template.ClassId, (value as IResource).Instance.Id);
|
||||
connection.cache.Add(value as IResource, DateTime.UtcNow);
|
||||
|
||||
var rid = resource.Instance.Id;
|
||||
|
||||
if (rid <= 0xFF)
|
||||
return (TransmissionTypeIdentifier.RemoteResource8, new byte[] { (byte)rid });
|
||||
else if (rid <= 0xFFFF)
|
||||
{
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = resource.Instance.Id;
|
||||
*((ushort*)ptr) = (ushort)rid;
|
||||
|
||||
return (TransmissionTypeIdentifier.Resource, rt);
|
||||
return (TransmissionTypeIdentifier.RemoteResource16, rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = rid;
|
||||
return (TransmissionTypeIdentifier.RemoteResource32, rt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +442,7 @@ public static class DataSerializer
|
||||
else
|
||||
{
|
||||
rt.AddRange(composed);
|
||||
return (TransmissionTypeIdentifier.Tuple, rt.ToArray());
|
||||
return (TransmissionTypeIdentifier.TypedTuple, rt.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ using Esiur.Resource;
|
||||
using Esiur.Resource.Template;
|
||||
using Esiur.Security.Authority;
|
||||
using Esiur.Security.Membership;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
@@ -49,6 +50,39 @@ namespace Esiur.Net.IIP;
|
||||
public partial class DistributedConnection : NetworkConnection, IStore
|
||||
{
|
||||
|
||||
|
||||
public delegate void ProtocolGeneralHandler(DistributedConnection connection, TransmissionType dataType, byte[] data);
|
||||
|
||||
public delegate void ProtocolRequestReplyHandler(DistributedConnection connection, uint callbackId, TransmissionType dataType, byte[] data);
|
||||
|
||||
//ProtocolGeneralHandler[] NotificationHandlers = new ProtocolGeneralHandler[]
|
||||
//{
|
||||
// IIPNotificationResourceDestroyed,
|
||||
// IIPNotificationResourceReassigned,
|
||||
// IIPNotificationResourceMoved,
|
||||
// IIPNotificationSystemFailure,
|
||||
// IIPNotificationPropertyModified
|
||||
//};
|
||||
|
||||
//ProtocolRequestReplyHandler[] RequestHandlers = new ProtocolRequestReplyHandler[]
|
||||
//{
|
||||
// IIPRequestAttachResource,
|
||||
// IIPRequest
|
||||
|
||||
//};
|
||||
|
||||
//ProtocolRequestReplyHandler[] ReplyHandlers = new ProtocolRequestReplyHandler[]
|
||||
//{
|
||||
|
||||
//};
|
||||
|
||||
//ProtocolGeneralHandler[] ExtensionHandler = new ProtocolGeneralHandler[]
|
||||
//{
|
||||
|
||||
//};
|
||||
|
||||
|
||||
|
||||
// Delegates
|
||||
public delegate void ReadyEvent(DistributedConnection sender);
|
||||
public delegate void ErrorEvent(DistributedConnection sender, byte errorCode, string errorMessage);
|
||||
@@ -164,6 +198,9 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Send data to the other end as parameters
|
||||
/// </summary>
|
||||
@@ -373,16 +410,11 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
|
||||
lastKeepAliveSent = now;
|
||||
|
||||
SendRequest(IIPPacketRequest.KeepAlive)
|
||||
.AddDateTime(now)
|
||||
.AddUInt32(interval)
|
||||
.Done()
|
||||
SendRequest(IIPPacketRequest.KeepAlive, now, interval)
|
||||
.Then(x =>
|
||||
{
|
||||
|
||||
Jitter = (uint)x[1];
|
||||
Jitter = (uint)x;
|
||||
keepAliveTimer.Start();
|
||||
//Console.WriteLine($"Keep Alive Received {Jitter}");
|
||||
}).Error(ex =>
|
||||
{
|
||||
keepAliveTimer.Stop();
|
||||
@@ -393,9 +425,6 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
Close();
|
||||
});
|
||||
|
||||
//Console.WriteLine("Keep Alive sent");
|
||||
|
||||
|
||||
}
|
||||
|
||||
public uint KeepAliveInterval { get; set; } = 30;
|
||||
@@ -417,7 +446,6 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
|
||||
if (rt <= 0)
|
||||
{
|
||||
|
||||
var size = ends - offset;
|
||||
data.HoldFor(msg, offset, size, size + (uint)(-rt));
|
||||
return ends;
|
||||
@@ -427,311 +455,153 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
|
||||
offset += (uint)rt;
|
||||
|
||||
if (packet.DataType != null)
|
||||
if (packet.DataType == null)
|
||||
return offset;
|
||||
|
||||
|
||||
if (packet.Method == IIPPacketMethod.Notification)
|
||||
{
|
||||
var dt = packet.DataType.Value;
|
||||
|
||||
var (_, parsed) = Codec.Parse(msg, dt.Offset, this, null, dt);
|
||||
|
||||
parsed.Then(value =>
|
||||
{
|
||||
if (packet.Method == IIPPacketMethod.Notification)
|
||||
{
|
||||
switch (packet.Notification)
|
||||
{
|
||||
// Invoke
|
||||
case IIPPacketNotification.PropertyModified:
|
||||
IIPNotificationPropertyModified(dt, msg);
|
||||
break;
|
||||
case IIPPacketNotification.EventOccurred:
|
||||
IIPNotificationEventOccurred(dt, msg);
|
||||
break;
|
||||
// Manage
|
||||
case IIPPacketNotification.ResourceDestroyed:
|
||||
IIPNotificationResourceDestroyed(value);
|
||||
IIPNotificationResourceDestroyed(dt, msg);
|
||||
break;
|
||||
case IIPPacketNotification.ResourceReassigned:
|
||||
IIPNotificationResourceReassigned(value);
|
||||
IIPNotificationResourceReassigned(dt, msg);
|
||||
break;
|
||||
case IIPPacketNotification.ResourceMoved:
|
||||
IIPNotificationResourceMoved(value);
|
||||
IIPNotificationResourceMoved(dt, msg);
|
||||
break;
|
||||
case IIPPacketNotification.SystemFailure:
|
||||
IIPNotificationSystemFailure(value);
|
||||
IIPNotificationSystemFailure(dt, msg);
|
||||
break;
|
||||
case IIPPacketNotification.PropertyModified:
|
||||
IIPNotificationPropertyModified()
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (packet.Method == IIPPacketMethod.Notification)
|
||||
else if (packet.Method == IIPPacketMethod.Request)
|
||||
{
|
||||
switch (packet.Notification)
|
||||
var dt = packet.DataType.Value;
|
||||
|
||||
switch (packet.Request)
|
||||
{
|
||||
case IIPPacketNotification.ResourceDestroyed:
|
||||
|
||||
case IIPPacketEvent.ResourceReassigned:
|
||||
IIPEventResourceReassigned(packet.ResourceId, packet.NewResourceId);
|
||||
break;
|
||||
case IIPPacketEvent.ResourceDestroyed:
|
||||
IIPEventResourceDestroyed(packet.ResourceId);
|
||||
break;
|
||||
case IIPPacketEvent.PropertyUpdated:
|
||||
IIPEventPropertyUpdated(packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
|
||||
break;
|
||||
case IIPPacketEvent.EventOccurred:
|
||||
IIPEventEventOccurred(packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
|
||||
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.ResourceLink);
|
||||
break;
|
||||
case IIPPacketEvent.AttributesUpdated:
|
||||
// @TODO: fix this
|
||||
//IIPEventAttributesUpdated(packet.ResourceId, packet.Content);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (packet.Command == IIPPacketCommand.Request)
|
||||
{
|
||||
switch (packet.Action)
|
||||
{
|
||||
// Manage
|
||||
case IIPPacketRequest.AttachResource:
|
||||
IIPRequestAttachResource(packet.CallbackId, packet.ResourceId);
|
||||
break;
|
||||
case IIPPacketRequest.ReattachResource:
|
||||
IIPRequestReattachResource(packet.CallbackId, packet.ResourceId, packet.ResourceAge);
|
||||
break;
|
||||
case IIPPacketRequest.DetachResource:
|
||||
IIPRequestDetachResource(packet.CallbackId, packet.ResourceId);
|
||||
break;
|
||||
case IIPPacketRequest.CreateResource:
|
||||
//@TODO : fix this
|
||||
//IIPRequestCreateResource(packet.CallbackId, packet.StoreId, packet.ResourceId, packet.Content);
|
||||
break;
|
||||
case IIPPacketRequest.DeleteResource:
|
||||
IIPRequestDeleteResource(packet.CallbackId, packet.ResourceId);
|
||||
break;
|
||||
case IIPPacketRequest.AddChild:
|
||||
IIPRequestAddChild(packet.CallbackId, packet.ResourceId, packet.ChildId);
|
||||
break;
|
||||
case IIPPacketRequest.RemoveChild:
|
||||
IIPRequestRemoveChild(packet.CallbackId, packet.ResourceId, packet.ChildId);
|
||||
break;
|
||||
case IIPPacketRequest.RenameResource:
|
||||
IIPRequestRenameResource(packet.CallbackId, packet.ResourceId, packet.ResourceName);
|
||||
break;
|
||||
|
||||
// Inquire
|
||||
case IIPPacketRequest.TemplateFromClassName:
|
||||
IIPRequestTemplateFromClassName(packet.CallbackId, packet.ClassName);
|
||||
break;
|
||||
case IIPPacketRequest.TemplateFromClassId:
|
||||
IIPRequestTemplateFromClassId(packet.CallbackId, packet.ClassId);
|
||||
break;
|
||||
case IIPPacketRequest.TemplateFromResourceId:
|
||||
IIPRequestTemplateFromResourceId(packet.CallbackId, packet.ResourceId);
|
||||
break;
|
||||
case IIPPacketRequest.QueryLink:
|
||||
IIPRequestQueryResources(packet.CallbackId, packet.ResourceLink);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.ResourceChildren:
|
||||
IIPRequestResourceChildren(packet.CallbackId, packet.ResourceId);
|
||||
break;
|
||||
case IIPPacketRequest.ResourceParents:
|
||||
IIPRequestResourceParents(packet.CallbackId, packet.ResourceId);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.ResourceHistory:
|
||||
IIPRequestInquireResourceHistory(packet.CallbackId, packet.ResourceId, packet.FromDate, packet.ToDate);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.LinkTemplates:
|
||||
IIPRequestLinkTemplates(packet.CallbackId, packet.ResourceLink);
|
||||
break;
|
||||
|
||||
// Invoke
|
||||
case IIPPacketRequest.InvokeFunction:
|
||||
IIPRequestInvokeFunction(packet.CallbackId, packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
|
||||
IIPRequestInvokeFunction(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
//case IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments:
|
||||
// IIPRequestInvokeFunctionNamedArguments(packet.CallbackId, packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
|
||||
// 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 IIPPacketRequest.Listen:
|
||||
IIPRequestListen(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.Unlisten:
|
||||
IIPRequestUnlisten(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.SetProperty:
|
||||
IIPRequestSetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
|
||||
IIPRequestSetProperty(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
// Attribute
|
||||
case IIPPacketRequest.GetAllAttributes:
|
||||
// @TODO : fix this
|
||||
//IIPRequestGetAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
|
||||
case IIPPacketRequest.Subscribe:
|
||||
IIPRequestSubscribe(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketRequest.UpdateAllAttributes:
|
||||
// @TODO : fix this
|
||||
//IIPRequestUpdateAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
|
||||
case IIPPacketRequest.Unsubscribe:
|
||||
IIPRequestUnsubscribe(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketRequest.ClearAllAttributes:
|
||||
// @TODO : fix this
|
||||
//IIPRequestClearAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
|
||||
// Inquire
|
||||
case IIPPacketRequest.TemplateFromClassName:
|
||||
IIPRequestTemplateFromClassName(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketRequest.GetAttributes:
|
||||
// @TODO : fix this
|
||||
//IIPRequestGetAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
|
||||
case IIPPacketRequest.TemplateFromClassId:
|
||||
IIPRequestTemplateFromClassId(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketRequest.UpdateAttributes:
|
||||
// @TODO : fix this
|
||||
//IIPRequestUpdateAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
|
||||
case IIPPacketRequest.TemplateFromResourceId:
|
||||
IIPRequestTemplateFromResourceId(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketRequest.ClearAttributes:
|
||||
// @TODO : fix this
|
||||
//IIPRequestClearAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
|
||||
case IIPPacketRequest.Query:
|
||||
IIPRequestQueryResources(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.KeepAlive:
|
||||
IIPRequestKeepAlive(packet.CallbackId, packet.CurrentTime, packet.Interval);
|
||||
case IIPPacketRequest.LinkTemplates:
|
||||
IIPRequestLinkTemplates(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.ProcedureCall:
|
||||
IIPRequestProcedureCall(packet.CallbackId, packet.Procedure, (TransmissionType)packet.DataType, msg);
|
||||
case IIPPacketRequest.Token:
|
||||
IIPRequestToken(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.StaticCall:
|
||||
IIPRequestStaticCall(packet.CallbackId, packet.ClassId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
|
||||
case IIPPacketRequest.GetResourceIdByLink:
|
||||
IIPRequestGetResourceIdByLink(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if (packet.Command == IIPPacketCommand.Reply)
|
||||
{
|
||||
switch (packet.Action)
|
||||
{
|
||||
// Manage
|
||||
case IIPPacketRequest.AttachResource:
|
||||
IIPReply(packet.CallbackId, packet.ClassId, packet.ResourceAge, packet.ResourceLink, packet.DataType, msg);
|
||||
IIPRequestAttachResource(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.ReattachResource:
|
||||
IIPReply(packet.CallbackId, packet.ResourceAge, packet.DataType, msg);
|
||||
|
||||
IIPRequestReattachResource(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketRequest.DetachResource:
|
||||
IIPReply(packet.CallbackId);
|
||||
IIPRequestDetachResource(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.CreateResource:
|
||||
IIPReply(packet.CallbackId, packet.ResourceId);
|
||||
IIPRequestCreateResource(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.DeleteResource:
|
||||
case IIPPacketRequest.AddChild:
|
||||
case IIPPacketRequest.RemoveChild:
|
||||
case IIPPacketRequest.RenameResource:
|
||||
IIPReply(packet.CallbackId);
|
||||
IIPRequestDeleteResource(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
// Inquire
|
||||
|
||||
case IIPPacketRequest.TemplateFromClassName:
|
||||
case IIPPacketRequest.TemplateFromClassId:
|
||||
case IIPPacketRequest.TemplateFromResourceId:
|
||||
|
||||
var content = msg.Clip(packet.DataType.Value.Offset, (uint)packet.DataType.Value.ContentLength);
|
||||
IIPReply(packet.CallbackId, TypeTemplate.Parse(content));
|
||||
case IIPPacketRequest.MoveResource:
|
||||
IIPRequestMoveResource(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.QueryLink:
|
||||
case IIPPacketRequest.ResourceChildren:
|
||||
case IIPPacketRequest.ResourceParents:
|
||||
case IIPPacketRequest.ResourceHistory:
|
||||
case IIPPacketRequest.LinkTemplates:
|
||||
IIPReply(packet.CallbackId, (TransmissionType)packet.DataType, msg);// packet.Content);
|
||||
break;
|
||||
|
||||
// Invoke
|
||||
case IIPPacketRequest.InvokeFunction:
|
||||
case IIPPacketRequest.StaticCall:
|
||||
case IIPPacketRequest.ProcedureCall:
|
||||
IIPReplyInvoke(packet.CallbackId, (TransmissionType)packet.DataType, msg);// packet.Content);
|
||||
break;
|
||||
|
||||
//case IIPPacket.IIPPacketAction.GetProperty:
|
||||
// IIPReply(packet.CallbackId, packet.Content);
|
||||
// break;
|
||||
|
||||
//case IIPPacket.IIPPacketAction.GetPropertyIfModified:
|
||||
// IIPReply(packet.CallbackId, packet.Content);
|
||||
// break;
|
||||
|
||||
case IIPPacketRequest.Listen:
|
||||
case IIPPacketRequest.Unlisten:
|
||||
case IIPPacketRequest.SetProperty:
|
||||
IIPReply(packet.CallbackId);
|
||||
break;
|
||||
|
||||
// Attribute
|
||||
case IIPPacketRequest.GetAllAttributes:
|
||||
case IIPPacketRequest.GetAttributes:
|
||||
IIPReply(packet.CallbackId, (TransmissionType)packet.DataType, msg);// packet.Content);
|
||||
break;
|
||||
|
||||
case IIPPacketRequest.UpdateAllAttributes:
|
||||
case IIPPacketRequest.UpdateAttributes:
|
||||
case IIPPacketRequest.ClearAllAttributes:
|
||||
case IIPPacketRequest.ClearAttributes:
|
||||
IIPReply(packet.CallbackId);
|
||||
break;
|
||||
|
||||
// Static
|
||||
case IIPPacketRequest.KeepAlive:
|
||||
IIPReply(packet.CallbackId, packet.CurrentTime, packet.Jitter);
|
||||
IIPRequestKeepAlive(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketRequest.ProcedureCall:
|
||||
IIPRequestProcedureCall(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketRequest.StaticCall:
|
||||
IIPRequestStaticCall(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else if (packet.Command == IIPPacketCommand.Report)
|
||||
else if (packet.Method == IIPPacketMethod.Reply)
|
||||
{
|
||||
switch (packet.Report)
|
||||
var dt = packet.DataType.Value;
|
||||
|
||||
switch (packet.Reply)
|
||||
{
|
||||
case IIPPacketReport.ManagementError:
|
||||
IIPReportError(packet.CallbackId, ErrorType.Management, packet.ErrorCode, null);
|
||||
case IIPPacketReply.Completed:
|
||||
IIPReplyCompleted(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketReport.ExecutionError:
|
||||
IIPReportError(packet.CallbackId, ErrorType.Exception, packet.ErrorCode, packet.ErrorMessage);
|
||||
case IIPPacketReply.Propagated:
|
||||
IIPReplyPropagated(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
case IIPPacketReport.ProgressReport:
|
||||
IIPReportProgress(packet.CallbackId, ProgressType.Execution, packet.ProgressValue, packet.ProgressMax);
|
||||
case IIPPacketReply.PermissionError:
|
||||
IIPReplyError(packet.CallbackId, dt, msg, ErrorType.Management);
|
||||
break;
|
||||
case IIPPacketReply.ExecutionError:
|
||||
IIPReplyError(packet.CallbackId, dt, msg, ErrorType.Exception);
|
||||
break;
|
||||
case IIPPacketReport.ChunkStream:
|
||||
IIPReportChunk(packet.CallbackId, (TransmissionType)packet.DataType, msg);
|
||||
|
||||
case IIPPacketReply.Progress:
|
||||
IIPReplyProgress(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case IIPPacketReply.Chunk:
|
||||
IIPReplyChunk(packet.CallbackId, dt, msg);
|
||||
break;
|
||||
|
||||
case IIPPacketReply.Warning:
|
||||
IIPReplyWarning(packet.Extension, dt, msg);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if (packet.Method == IIPPacketMethod.Extension)
|
||||
{
|
||||
IIPExtensionAction(packet.Extension, packet.DataType, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// check if the reqeust through websockets
|
||||
// check if the request through Websockets
|
||||
|
||||
if (initialPacket)
|
||||
{
|
||||
@@ -755,7 +625,6 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
|
||||
HTTPConnection.Upgrade(req, res);
|
||||
|
||||
|
||||
res.Compose(HTTPComposeOption.AllCalculateLength);
|
||||
Send(res.Data);
|
||||
// replace my socket with websockets
|
||||
@@ -784,11 +653,8 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var rt = authPacket.Parse(msg, offset, ends);
|
||||
|
||||
|
||||
if (rt <= 0)
|
||||
{
|
||||
data.HoldFor(msg, ends + (uint)(-rt));
|
||||
@@ -810,9 +676,6 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
}
|
||||
|
||||
return offset;
|
||||
|
||||
//if (offset < ends)
|
||||
// processPacket(msg, offset, ends, data, chunkId);
|
||||
}
|
||||
|
||||
private void ProcessClientAuth(byte[] data)
|
||||
@@ -831,9 +694,9 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
|
||||
var dataType = authPacket.DataType.Value;
|
||||
|
||||
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
|
||||
var (_, parsed) = Codec.ParseSync(data, dataType.Offset, dataType);
|
||||
|
||||
var rt = (Map<byte, object>)parsed.Wait();
|
||||
var rt = (Map<byte, object>)parsed;
|
||||
|
||||
session.RemoteHeaders = rt.Select(x => new KeyValuePair<IIPAuthPacketHeader, object>((IIPAuthPacketHeader)x.Key, x.Value));
|
||||
|
||||
@@ -957,8 +820,8 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
else if (authPacket.Event == IIPAuthPacketEvent.IAuthPlain)
|
||||
{
|
||||
var dataType = authPacket.DataType.Value;
|
||||
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
|
||||
var rt = (Map<byte, object>)parsed.Wait();
|
||||
var (_, parsed) = Codec.ParseSync(data, dataType.Offset, dataType);
|
||||
var rt = (Map<byte, object>)parsed;
|
||||
|
||||
var headers = rt.Select(x => new KeyValuePair<IIPAuthPacketIAuthHeader, object>((IIPAuthPacketIAuthHeader)x.Key, x.Value));
|
||||
var iAuthRequest = new AuthorizationRequest(headers);
|
||||
@@ -983,7 +846,8 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
.Done();
|
||||
})
|
||||
.Timeout(iAuthRequest.Timeout * 1000,
|
||||
() => {
|
||||
() =>
|
||||
{
|
||||
SendParams()
|
||||
.AddUInt8((byte)IIPAuthPacketEvent.ErrorTerminate)
|
||||
.AddUInt8((byte)ExceptionCode.Timeout)
|
||||
@@ -996,8 +860,8 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
else if (authPacket.Event == IIPAuthPacketEvent.IAuthHashed)
|
||||
{
|
||||
var dataType = authPacket.DataType.Value;
|
||||
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
|
||||
var rt = (Map<byte, object>)parsed.Wait();
|
||||
var (_, parsed) = Codec.ParseSync(data, dataType.Offset, dataType);
|
||||
var rt = (Map<byte, object>)parsed;
|
||||
|
||||
|
||||
var headers = rt.Select(x => new KeyValuePair<IIPAuthPacketIAuthHeader, object>((IIPAuthPacketIAuthHeader)x.Key, x.Value));
|
||||
@@ -1033,7 +897,8 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
.Done();
|
||||
})
|
||||
.Timeout(iAuthRequest.Timeout * 1000,
|
||||
() => {
|
||||
() =>
|
||||
{
|
||||
SendParams()
|
||||
.AddUInt8((byte)IIPAuthPacketEvent.ErrorTerminate)
|
||||
.AddUInt8((byte)ExceptionCode.Timeout)
|
||||
@@ -1058,10 +923,9 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
|
||||
var dataType = authPacket.DataType.Value;
|
||||
|
||||
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
|
||||
|
||||
var rt = (Map<byte, object>)parsed.Wait();
|
||||
var (_, parsed) = Codec.ParseSync(data, dataType.Offset, dataType);
|
||||
|
||||
var rt = (Map<byte, object>)parsed;
|
||||
|
||||
session.RemoteHeaders = rt.Select(x => new KeyValuePair<IIPAuthPacketHeader, object>((IIPAuthPacketHeader)x.Key, x.Value));
|
||||
|
||||
@@ -1317,9 +1181,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
var reference = authPacket.Reference;
|
||||
var dataType = authPacket.DataType.Value;
|
||||
|
||||
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
|
||||
|
||||
var value = parsed.Wait();
|
||||
var (_, value) = Codec.ParseSync(data, dataType.Offset, dataType);
|
||||
|
||||
Server.Membership.AuthorizePlain(session, reference, value)
|
||||
.Then(x => ProcessAuthorization(x));
|
||||
@@ -1687,23 +1549,12 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
|
||||
try
|
||||
{
|
||||
var ar = await SendRequest(IIPPacketRequest.QueryLink)
|
||||
.AddUInt16((ushort)link.Length)
|
||||
.AddUInt8Array(link)
|
||||
.Done();
|
||||
var id = (uint)await SendRequest(IIPPacketRequest.GetResourceIdByLink, link);
|
||||
|
||||
var dataType = (TransmissionType)ar[0];
|
||||
var data = ar[1] as byte[];
|
||||
|
||||
if (dataType.Identifier == TransmissionTypeIdentifier.ResourceList)
|
||||
{
|
||||
|
||||
// remove from suspended.
|
||||
suspendedResources.Remove(r.DistributedResourceInstanceId);
|
||||
|
||||
// parse them as int
|
||||
var id = data.GetUInt32(8, Endian.Little);
|
||||
|
||||
// id changed ?
|
||||
if (id != r.DistributedResourceInstanceId)
|
||||
r.DistributedResourceInstanceId = id;
|
||||
@@ -1713,7 +1564,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
|
||||
await Fetch(id, null);
|
||||
|
||||
Global.Log("DistributedConnection", LogType.Debug, "Restored " + id);
|
||||
}
|
||||
|
||||
}
|
||||
catch (AsyncException ex)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -68,7 +68,7 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
||||
|
||||
string link;
|
||||
//ulong age;
|
||||
//ulong[] ages;
|
||||
|
||||
protected object[] properties;
|
||||
internal List<DistributedResource> parents = new List<DistributedResource>();
|
||||
internal List<DistributedResource> children = new List<DistributedResource>();
|
||||
@@ -174,16 +174,31 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
||||
/// <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));
|
||||
props[i] = new PropertyValue(properties[i],
|
||||
Instance.GetAge(i),
|
||||
Instance.GetModificationDate(i));
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
internal Map<byte, PropertyValue> _SerializeAfter(ulong age = 0)
|
||||
{
|
||||
var rt = new Map<byte, PropertyValue>();
|
||||
|
||||
for (byte i = 0; i < properties.Length; i++)
|
||||
if (Instance.GetAge(i) > age)
|
||||
rt.Add(i, new PropertyValue(properties[i],
|
||||
Instance.GetAge(i),
|
||||
Instance.GetModificationDate(i)));
|
||||
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
||||
internal bool _Attach(PropertyValue[] properties)
|
||||
{
|
||||
if (attached)
|
||||
|
@@ -6,13 +6,14 @@ namespace Esiur.Net.Packets
|
||||
{
|
||||
public enum IIPPacketNotification : byte
|
||||
{
|
||||
// Event Manage
|
||||
ResourceDestroyed = 0,
|
||||
ResourceReassigned,
|
||||
ResourceMoved,
|
||||
SystemFailure,
|
||||
// Event Invoke
|
||||
PropertyModified = 0x8,
|
||||
EventOccurred,
|
||||
// Notification Invoke
|
||||
PropertyModified = 0x0,
|
||||
EventOccurred = 0x1,
|
||||
|
||||
// Notification Manage
|
||||
ResourceDestroyed = 0x8,
|
||||
ResourceReassigned = 0x9,
|
||||
ResourceMoved = 0xA,
|
||||
SystemFailure = 0xB,
|
||||
}
|
||||
}
|
||||
|
@@ -11,8 +11,8 @@ namespace Esiur.Net.Packets
|
||||
Propagated = 0x1,
|
||||
|
||||
// Error
|
||||
Permission = 0x81,
|
||||
Execution = 0x82,
|
||||
PermissionError = 0x81,
|
||||
ExecutionError = 0x82,
|
||||
|
||||
// Partial
|
||||
Progress = 0x10,
|
||||
|
@@ -6,29 +6,30 @@ namespace Esiur.Net.Packets
|
||||
{
|
||||
public enum IIPPacketRequest : byte
|
||||
{
|
||||
// Request Manage
|
||||
AttachResource = 0x0,
|
||||
ReattachResource = 0x1,
|
||||
DetachResource = 0x2,
|
||||
CreateResource = 0x3,
|
||||
DeleteResource = 0x4,
|
||||
MoveResource = 0x5,
|
||||
// Request Invoke
|
||||
InvokeFunction = 0x0,
|
||||
SetProperty = 0x1,
|
||||
Subscribe = 0x2,
|
||||
Unsubscribe = 0x3,
|
||||
|
||||
// Request Inquire
|
||||
TemplateFromClassName = 0x8,
|
||||
TemplateFromClassId = 0x9,
|
||||
TemplateFromResourceId = 0xA,
|
||||
QueryLink = 0xB,
|
||||
Query = 0xB,
|
||||
LinkTemplates = 0xC,
|
||||
Token = 0xD,
|
||||
GetResourceIdByLink = 0xE,
|
||||
|
||||
// Request Invoke
|
||||
InvokeFunction = 0x10,
|
||||
Subscribe = 0x11,
|
||||
Unsubscribe = 0x12,
|
||||
SetProperty = 0x13,
|
||||
// Request Manage
|
||||
AttachResource = 0x10,
|
||||
ReattachResource = 0x11,
|
||||
DetachResource = 0x12,
|
||||
CreateResource = 0x13,
|
||||
DeleteResource = 0x14,
|
||||
MoveResource = 0x15,
|
||||
|
||||
// Static calling
|
||||
// Request Static
|
||||
KeepAlive = 0x18,
|
||||
ProcedureCall = 0x19,
|
||||
StaticCall = 0x1A
|
||||
|
@@ -48,6 +48,7 @@ public class Instance
|
||||
List<ulong?> ages = new();
|
||||
List<DateTime?> modificationDates = new();
|
||||
private ulong instanceAge;
|
||||
private byte hops;
|
||||
private DateTime instanceModificationDate;
|
||||
|
||||
uint id;
|
||||
@@ -389,6 +390,16 @@ public class Instance
|
||||
internal set { instanceAge = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of nodes to reach the original resource.
|
||||
/// </summary>
|
||||
public ulong Hops
|
||||
{
|
||||
get { return hops; }
|
||||
internal set { hops = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Last modification date.
|
||||
/// </summary>
|
||||
@@ -443,7 +454,7 @@ public class Instance
|
||||
/// <returns></returns>
|
||||
public PropertyValue[] Serialize()
|
||||
{
|
||||
List<PropertyValue> props = new List<PropertyValue>();
|
||||
var props = new List<PropertyValue>();
|
||||
|
||||
foreach (var pt in template.Properties)
|
||||
{
|
||||
@@ -459,6 +470,33 @@ public class Instance
|
||||
return props.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export all properties with ResourceProperty attributed as bytes array after a specific age.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Map<byte, PropertyValue> SerializeAfter(ulong age = 0)
|
||||
{
|
||||
var props = new Map<byte, PropertyValue>();
|
||||
|
||||
foreach (var pt in template.Properties)
|
||||
{
|
||||
IResource res;
|
||||
if (resource.TryGetTarget(out res))
|
||||
{
|
||||
if (res.Instance.GetAge(pt.Index) > age)
|
||||
{
|
||||
var rt = pt.PropertyInfo.GetValue(res, null);
|
||||
props.Add(pt.Index,
|
||||
new PropertyValue(rt,
|
||||
ages[pt.Index],
|
||||
modificationDates[pt.Index]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
/*
|
||||
public bool Deserialize(byte[] data, uint offset, uint length)
|
||||
{
|
||||
|
@@ -652,48 +652,23 @@ public static class Warehouse
|
||||
|
||||
type = ResourceProxy.GetProxy(type);
|
||||
|
||||
|
||||
/*
|
||||
if (arguments != null)
|
||||
{
|
||||
var constructors = type.GetConstructors(System.Reflection.BindingFlags.Public);
|
||||
|
||||
foreach(var constructor in constructors)
|
||||
{
|
||||
var pi = constructor.GetParameters();
|
||||
if (pi.Length == constructor.le)
|
||||
}
|
||||
|
||||
// cast arguments
|
||||
ParameterInfo[] pi = fi.GetParameters();
|
||||
|
||||
object[] args = new object[pi.Length];
|
||||
|
||||
for (var i = 0; i < pi.Length; i++)
|
||||
{
|
||||
if (pi[i].ParameterType == typeof(DistributedConnection))
|
||||
{
|
||||
args[i] = this;
|
||||
}
|
||||
else if (namedArgs.ContainsKey(pi[i].Name))
|
||||
{
|
||||
args[i] = DC.CastConvert(namedArgs[pi[i].Name], pi[i].ParameterType);
|
||||
}
|
||||
}
|
||||
|
||||
constructors[0].
|
||||
}
|
||||
*/
|
||||
var res = Activator.CreateInstance(type) as IResource;
|
||||
|
||||
|
||||
if (properties != null)
|
||||
{
|
||||
if (properties is Map<byte, object> map)
|
||||
{
|
||||
var template = GetTemplateByType(type);
|
||||
foreach(var kvp in map)
|
||||
template.GetPropertyTemplateByIndex(kvp.Key).PropertyInfo.SetValue(res, kvp.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ps = Map<string, object>.FromObject(properties);
|
||||
|
||||
foreach (var p in ps)
|
||||
{
|
||||
|
||||
var pi = type.GetProperty(p.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
|
||||
if (pi != null)
|
||||
{
|
||||
@@ -726,12 +701,10 @@ public static class Warehouse
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (store != null || parent != null || res is IStore)
|
||||
{
|
||||
//if (!await Put(name, res, store, parent, null, 0, manager, attributes))
|
||||
// return null;
|
||||
|
||||
await Put(name, res, store, parent, null, 0, manager, attributes);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user