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

AsyncReply is awaitable

This commit is contained in:
2019-07-21 05:29:58 +03:00
parent 48e450ffc4
commit 2d9f61c0d9
26 changed files with 561 additions and 213 deletions

View File

@ -171,7 +171,7 @@ namespace Esiur.Data
var result = (StructureComparisonResult)data[offset++];
AsyncReply previous = null;
IAsyncReply<Structure> previous = null;
// string[] previousKeys = null;
// DataType[] previousTypes = null;
@ -362,7 +362,7 @@ namespace Esiur.Data
/// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end.</param>
/// <param name="dataType">DataType, in case the data is not prepended with DataType</param>
/// <returns>Structure</returns>
public static AsyncReply Parse(byte[] data, uint offset, DistributedConnection connection, DataType dataType = DataType.Unspecified)
public static IAsyncReply<object> Parse(byte[] data, uint offset, DistributedConnection connection, DataType dataType = DataType.Unspecified)
{
uint size;
return Parse(data, offset, out size, connection);
@ -377,10 +377,9 @@ namespace Esiur.Data
/// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end.</param>
/// <param name="dataType">DataType, in case the data is not prepended with DataType</param>
/// <returns>Value</returns>
public static AsyncReply Parse(byte[] data, uint offset, out uint size, DistributedConnection connection, DataType dataType = DataType.Unspecified)
public static IAsyncReply<object> Parse(byte[] data, uint offset, out uint size, DistributedConnection connection, DataType dataType = DataType.Unspecified)
{
var reply = new AsyncReply();
bool isArray;
DataType t;
@ -480,40 +479,40 @@ namespace Esiur.Data
return new AsyncReply<object>(null);
case DataType.Bool:
return new AsyncReply<bool>(data.GetBoolean(offset));
return new AsyncReply<object>(data.GetBoolean(offset));
case DataType.UInt8:
return new AsyncReply<byte>(data[offset]);
return new AsyncReply<object>(data[offset]);
case DataType.Int8:
return new AsyncReply<sbyte>((sbyte)data[offset]);
return new AsyncReply<object>((sbyte)data[offset]);
case DataType.Char:
return new AsyncReply<char>(data.GetChar(offset));
return new AsyncReply<object>(data.GetChar(offset));
case DataType.Int16:
return new AsyncReply<short>(data.GetInt16(offset));
return new AsyncReply<object>(data.GetInt16(offset));
case DataType.UInt16:
return new AsyncReply<ushort>(data.GetUInt16(offset));
return new AsyncReply<object>(data.GetUInt16(offset));
case DataType.Int32:
return new AsyncReply<int>(data.GetInt32(offset));
return new AsyncReply<object>(data.GetInt32(offset));
case DataType.UInt32:
return new AsyncReply<uint>(data.GetUInt32(offset));
return new AsyncReply<object>(data.GetUInt32(offset));
case DataType.Int64:
return new AsyncReply<long>(data.GetInt64(offset));
return new AsyncReply<object>(data.GetInt64(offset));
case DataType.UInt64:
return new AsyncReply<ulong>(data.GetUInt64(offset));
return new AsyncReply<object>(data.GetUInt64(offset));
case DataType.Float32:
return new AsyncReply<float>(data.GetFloat32(offset));
return new AsyncReply<object>(data.GetFloat32(offset));
case DataType.Float64:
return new AsyncReply<double>(data.GetFloat64(offset));
return new AsyncReply<object>(data.GetFloat64(offset));
case DataType.String:
return new AsyncReply<string>(data.GetString(offset, contentLength));
@ -525,7 +524,7 @@ namespace Esiur.Data
return ParseDistributedResource(data, offset, connection);
case DataType.DateTime:
return new AsyncReply<DateTime>(data.GetDateTime(offset));
return new AsyncReply<object>(data.GetDateTime(offset));
case DataType.Structure:
return ParseStructure(data, offset, contentLength, connection);
@ -694,7 +693,7 @@ namespace Esiur.Data
//
var result = (ResourceComparisonResult)data[offset++];
AsyncReply previous = null;
IAsyncReply<IResource> previous = null;
if (result == ResourceComparisonResult.Null)
previous = new AsyncReply<IResource>(null);
@ -716,7 +715,7 @@ namespace Esiur.Data
{
result = (ResourceComparisonResult)data[offset++];
AsyncReply current = null;
IAsyncReply<IResource> current = null;
if (result == ResourceComparisonResult.Null)
{

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace Esiur.Engine
{
public class AsyncAwaiter<T> : INotifyCompletion
{
Action callback = null;
T result;
private bool completed;
public AsyncAwaiter(AsyncReply<T> reply)
{
reply.Then(x =>
{
completed = true;
result = x;
callback?.Invoke();
});
}
public T GetResult()
{
return result;
}
public bool IsCompleted => completed;
//From INotifyCompletion
public void OnCompleted(Action continuation)
{
Console.WriteLine("Continue....");
}
}
}

View File

@ -30,21 +30,23 @@ using System.Threading.Tasks;
namespace Esiur.Engine
{
public class AsyncBag<T>:AsyncReply
public class AsyncBag<T>: AsyncReply<T[]>
{
//Dictionary<AsyncReply, T> results = new Dictionary<AsyncReply, T>();
List<AsyncReply> replies = new List<AsyncReply>();
List<IAsyncReply<T>> replies = new List<IAsyncReply<T>>();
List<T> results = new List<T>();
int count = 0;
bool sealedBag = false;
/*
public AsyncBag<T> Then(Action<T[]> callback)
{
base.Then(new Action<object>(o => callback((T[])o)));
return this;
}
*/
public void Seal()
{
@ -72,7 +74,7 @@ namespace Esiur.Engine
}
}
public void Add(AsyncReply reply)
public void Add(IAsyncReply<T> reply)
{
if (!sealedBag)
{
@ -82,6 +84,12 @@ namespace Esiur.Engine
//results.Add(reply, default(T));
}
public void AddBag(AsyncBag<T> bag)
{
foreach (var r in bag.replies)
Add(r);
}
public AsyncBag()
{

View File

@ -63,23 +63,21 @@ namespace Esiur.Engine
{
AsyncReply.ErrorType type;
ExceptionCode code;
public readonly ErrorType Type;
public readonly ExceptionCode Code;
public AsyncReply.ErrorType Type => type;
public ExceptionCode Code => code;
public AsyncException(AsyncReply.ErrorType type, ushort code, string message)
: base(type == AsyncReply.ErrorType.Management ? ((ExceptionCode)code).ToString() : message)
public AsyncException(ErrorType type, ushort code, string message)
: base(type == ErrorType.Management ? ((ExceptionCode)code).ToString() : message)
{
this.type = type;
this.code = (ExceptionCode)code;
this.Type = type;
this.Code = (ExceptionCode)code;
}
public override string ToString()
{
return code.ToString() + ": " + Message;
return Code.ToString() + ": " + Message;
}
}
}

View File

@ -30,18 +30,18 @@ using System.Threading.Tasks;
namespace Esiur.Engine
{
public class AsyncQueue<T> : AsyncReply
public class AsyncQueue<T> : AsyncReply<T>
{
List<AsyncReply<T>> list = new List<AsyncReply<T>>();
//Action<T> callback;
object queueLock = new object();
public AsyncQueue<T> Then(Action<T> callback)
{
base.Then(new Action<object>(o => callback((T)o)));
//public AsyncQueue<T> Then(Action<T> callback)
//{
// base.Then(new Action<object>(o => callback((T)o)));
return this;
}
//return this;
//}
public void Add(AsyncReply<T> reply)
{

View File

@ -32,17 +32,9 @@ namespace Esiur.Engine
{
public class AsyncReply
{
public enum ErrorType
{
Management,
Exception
}
public enum ProgressType
{
Execution,
Network,
}
protected List<Action<object>> callbacks = new List<Action<object>>();
protected object result;

View File

@ -29,13 +29,175 @@ using System.Text;
using System.Threading.Tasks;
using Esiur.Resource;
using System.Reflection;
using System.Threading;
using System.Runtime.CompilerServices;
namespace Esiur.Engine
{
public class AsyncReply<T>: AsyncReply
public class AsyncReply<T>: IAsyncReply<T>
{
protected List<Action<T>> callbacks = new List<Action<T>>();
protected T result;
protected List<Action<AsyncException>> errorCallbacks = new List<Action<AsyncException>>();
public AsyncReply<T> Then(Action<T> callback)
protected List<Action<ProgressType, int, int>> progressCallbacks = new List<Action<ProgressType, int, int>>();
protected List<Action<T>> chunkCallbacks = new List<Action<T>>();
//List<AsyncAwaiter> awaiters = new List<AsyncAwaiter>();
object callbacksLock = new object();
protected bool resultReady = false;
AsyncException exception;
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
public bool Ready
{
get { return resultReady; }
}
public object Result
{
get { return result; }
}
public IAsyncReply<T> Then(Action<T> callback)
{
callbacks.Add(callback);
if (resultReady)
callback(result);
return this;
}
public IAsyncReply<T> Error(Action<AsyncException> callback)
{
errorCallbacks.Add(callback);
if (exception != null)
{
callback(exception);
tcs.SetException(exception);
}
return this;
}
public IAsyncReply<T> Progress(Action<ProgressType, int, int> callback)
{
progressCallbacks.Add(callback);
return this;
}
public IAsyncReply<T> Chunk(Action<T> callback)
{
chunkCallbacks.Add(callback);
return this;
}
public void Trigger(object result)
{
lock (callbacksLock)
{
if (resultReady)
return;
this.result = (T)result;
resultReady = true;
foreach (var cb in callbacks)
cb((T)result);
tcs.TrySetResult(result);
}
}
public void TriggerError(AsyncException exception)
{
if (resultReady)
return;
this.exception = exception;
lock (callbacksLock)
{
foreach (var cb in errorCallbacks)
cb(exception);
}
tcs.TrySetException(exception);
}
public void TriggerProgress(ProgressType type, int value, int max)
{
if (resultReady)
return;
lock (callbacksLock)
{
foreach (var cb in progressCallbacks)
cb(type, value, max);
}
}
public void TriggerChunk(object value)
{
if (resultReady)
return;
lock (callbacksLock)
{
foreach (var cb in chunkCallbacks)
cb((T)value);
}
}
public AsyncAwaiter<T> GetAwaiter()
{
return new AsyncAwaiter<T>(this);
}
public Task Task
{
get
{
return tcs.Task;
}
}
public AsyncReply()
{
}
public AsyncReply(T result)
{
resultReady = true;
tcs.SetResult(result);
this.result = result;
}
/*
public AsyncReply<T> Then(Action<T> callback)
{
base.Then(new Action<object>(o => callback((T)o)));
return this;
@ -46,6 +208,15 @@ namespace Esiur.Engine
Trigger((object)result);
}
public Task<bool> MoveNext(CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public void Dispose()
{
}
public AsyncReply()
{
@ -67,13 +238,15 @@ namespace Esiur.Engine
}
}
public T Current => throw new NotImplementedException();
public AsyncReply(T result)
: base(result)
{
}
*/
}
}

12
Esiur/Engine/ErrorType.cs Normal file
View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Engine
{
public enum ErrorType
{
Management,
Exception
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace Esiur.Engine
{
public interface IAsyncReply<out T>//IAsyncEnumerator<T>
{
IAsyncReply<T> Then(Action<T> callback);
IAsyncReply<T> Error(Action<AsyncException> callback);
IAsyncReply<T> Progress(Action<ProgressType, int, int> callback);
IAsyncReply<T> Chunk(Action<T> callback);
void Trigger(object result);
void TriggerError(AsyncException exception);
void TriggerProgress(ProgressType type, int value, int max);
void TriggerChunk(object value);
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Engine
{
public enum ProgressType
{
Execution,
Network,
}
}

View File

@ -7,9 +7,11 @@
<PackageLicenseUrl>https://github.com/esiur/esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.1.0</Version>
<Version>1.2.3</Version>
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
<Authors>Ahmed Kh. Zamil</Authors>
<AssemblyVersion>1.2.3.0</AssemblyVersion>
<Company>Esiur Foundation</Company>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -22,6 +24,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="Engine\AsyncReply.cs" />
<Compile Remove="Net\UDP\UDPServer.cs" />
</ItemGroup>
@ -30,12 +33,14 @@
</ItemGroup>
<ItemGroup>
<None Include="Engine\AsyncReply.cs" />
<None Include="Net\UDP\UDPServer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Diagnostics.StackTrace" Version="4.3.0" />
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
<PackageReference Include="System.Interactive.Async" Version="3.2.0" />
<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
<PackageReference Include="System.Net.Security" Version="4.3.1" />

View File

@ -50,7 +50,7 @@ namespace Esiur.Net.DataLink
public void Destroy()
{
throw new NotImplementedException();
}
}
}

View File

@ -36,8 +36,36 @@ namespace Esiur.Net.HTTP
{
public class IIPoWS: HTTPFilter
{
[ResourceProperty]
public DistributedServer DistributedServer
{
get;
set;
}
public override bool Execute(HTTPConnection sender)
{
if (DistributedServer == null)
return false;
var tcpSocket = sender.Unassign();
if (tcpSocket == null)
return false;
var httpServer = sender.Parent;
var wsSocket = new WSSocket(tcpSocket);
httpServer.RemoveConnection(sender);
var iipConnection = new DistributedConnection();
DistributedServer.AddConnection(iipConnection);
iipConnection.Assign(wsSocket);
wsSocket.Begin();
return true;
/*
if (sender.Request.Filename.StartsWith("/iip/"))
{
// find the service
@ -73,6 +101,7 @@ namespace Esiur.Net.HTTP
}
return false;
*/
}
private void IipConnection_OnReady(DistributedConnection sender)

View File

@ -524,13 +524,13 @@ namespace Esiur.Net.IIP
switch (packet.Report)
{
case IIPPacketReport.ManagementError:
IIPReportError(packet.CallbackId, AsyncReply.ErrorType.Management, packet.ErrorCode, null);
IIPReportError(packet.CallbackId, ErrorType.Management, packet.ErrorCode, null);
break;
case IIPPacketReport.ExecutionError:
IIPReportError(packet.CallbackId, AsyncReply.ErrorType.Exception, packet.ErrorCode, packet.ErrorMessage);
IIPReportError(packet.CallbackId, ErrorType.Exception, packet.ErrorCode, packet.ErrorMessage);
break;
case IIPPacketReport.ProgressReport:
IIPReportProgress(packet.CallbackId, AsyncReply.ProgressType.Execution, packet.ProgressValue, packet.ProgressMax);
IIPReportProgress(packet.CallbackId, ProgressType.Execution, packet.ProgressValue, packet.ProgressMax);
break;
case IIPPacketReport.ChunkStream:
IIPReportChunk(packet.CallbackId, packet.Content);
@ -735,5 +735,11 @@ namespace Esiur.Net.IIP
// nothing to do
return true;
}
public AsyncReply<bool> Open(Structure settings)
{
return new AsyncReply<bool>(true);
}
}
}

View File

@ -50,7 +50,7 @@ namespace Esiur.Net.IIP
Dictionary<Guid, ResourceTemplate> templates = new Dictionary<Guid, ResourceTemplate>();
KeyList<uint, AsyncReply> requests = new KeyList<uint, AsyncReply>();
KeyList<uint, IAsyncReply<object>> requests = new KeyList<uint, IAsyncReply<object>>();
uint callbackCounter = 0;
@ -62,7 +62,7 @@ namespace Esiur.Net.IIP
/// <param name="action">Packet action.</param>
/// <param name="args">Arguments to send.</param>
/// <returns></returns>
internal AsyncReply<object[]> SendRequest(IIPPacket.IIPPacketAction action, params object[] args)
internal IAsyncReply<object[]> SendRequest(IIPPacket.IIPPacketAction action, params object[] args)
{
var reply = new AsyncReply<object[]>();
callbackCounter++;
@ -100,11 +100,11 @@ namespace Esiur.Net.IIP
Send(bl.ToArray());
}
internal AsyncReply SendInvokeByArrayArguments(uint instanceId, byte index, object[] parameters)
internal AsyncReply<object> SendInvokeByArrayArguments(uint instanceId, byte index, object[] parameters)
{
var pb = Codec.ComposeVarArray(parameters, this, true);
var reply = new AsyncReply();
var reply = new AsyncReply<object>();
callbackCounter++;
var bl = new BinaryList((byte)(0x40 | (byte)Packets.IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments),
callbackCounter, instanceId, index, pb);
@ -114,11 +114,11 @@ namespace Esiur.Net.IIP
return reply;
}
internal AsyncReply SendInvokeByNamedArguments(uint instanceId, byte index, Structure parameters)
internal AsyncReply<object> SendInvokeByNamedArguments(uint instanceId, byte index, Structure parameters)
{
var pb = Codec.ComposeStructure(parameters, this, true, true, true);
var reply = new AsyncReply();
var reply = new AsyncReply<object>();
callbackCounter++;
var bl = new BinaryList((byte)(0x40 | (byte)Packets.IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments),
callbackCounter, instanceId, index, pb);
@ -129,12 +129,12 @@ namespace Esiur.Net.IIP
}
void SendError(AsyncReply.ErrorType type, uint callbackId, ushort errorCode, string errorMessage = "")
void SendError(ErrorType type, uint callbackId, ushort errorCode, string errorMessage = "")
{
var msg = DC.ToBytes(errorMessage);
if (type == AsyncReply.ErrorType.Management)
if (type == ErrorType.Management)
SendParams((byte)(0xC0 | (byte)IIPPacket.IIPPacketReport.ManagementError), callbackId, errorCode);
else if (type == AsyncReply.ErrorType.Exception)
else if (type == ErrorType.Exception)
SendParams((byte)(0xC0 | (byte)IIPPacket.IIPPacketReport.ExecutionError), callbackId, errorCode, (ushort)msg.Length, msg);
}
@ -165,13 +165,13 @@ namespace Esiur.Net.IIP
});
}
void IIPReportError(uint callbackId, AsyncReply.ErrorType errorType, ushort errorCode, string errorMessage)
void IIPReportError(uint callbackId, ErrorType errorType, ushort errorCode, string errorMessage)
{
var req = requests.Take(callbackId);
req?.TriggerError(new AsyncException(errorType, errorCode, errorMessage));
}
void IIPReportProgress(uint callbackId, AsyncReply.ProgressType type, int value, int max)
void IIPReportProgress(uint callbackId, ProgressType type, int value, int max)
{
var req = requests[callbackId];
req?.TriggerProgress(type, value, max);
@ -379,7 +379,7 @@ namespace Esiur.Net.IIP
{
if (res.Instance.Applicable(session, ActionType.Attach, null) == Ruling.Denied)
{
SendError(AsyncReply.ErrorType.Management, callback, 6);
SendError(ErrorType.Management, callback, 6);
return;
}
@ -415,7 +415,7 @@ namespace Esiur.Net.IIP
{
// reply failed
//SendParams(0x80, r.Instance.Id, r.Instance.Age, r.Instance.Serialize(false, this));
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
}
});
}
@ -459,7 +459,7 @@ namespace Esiur.Net.IIP
else
{
// reply failed
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
}
});
}
@ -480,7 +480,7 @@ namespace Esiur.Net.IIP
else
{
// reply failed
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
}
});
}
@ -492,20 +492,20 @@ namespace Esiur.Net.IIP
{
if (store == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.StoreNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.StoreNotFound);
return;
}
if (!(store is IStore))
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceIsNotStore);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceIsNotStore);
return;
}
// check security
if (store.Instance.Applicable(session, ActionType.CreateResource, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.CreateDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.CreateDenied);
return;
}
@ -517,7 +517,7 @@ namespace Esiur.Net.IIP
if (parent != null)
if (parent.Instance.Applicable(session, ActionType.AddChild, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.AddChildDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.AddChildDenied);
return;
}
@ -537,7 +537,7 @@ namespace Esiur.Net.IIP
if (type == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ClassNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ClassNotFound);
return;
}
@ -614,13 +614,13 @@ namespace Esiur.Net.IIP
{
if (r == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
if (r.Instance.Store.Instance.Applicable(session, ActionType.Delete, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.DeleteDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.DeleteDenied);
return;
}
@ -628,7 +628,7 @@ namespace Esiur.Net.IIP
SendReply(IIPPacket.IIPPacketAction.DeleteResource, callback);
//SendParams((byte)0x84, callback);
else
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.DeleteFailed);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.DeleteFailed);
});
}
@ -638,14 +638,14 @@ namespace Esiur.Net.IIP
{
if (r == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
// if (!r.Instance.Store.Instance.Applicable(r, session, ActionType.InquireAttributes, null))
if (r.Instance.Applicable(session, ActionType.InquireAttributes, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ViewAttributeDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ViewAttributeDenied);
return;
}
@ -660,7 +660,7 @@ namespace Esiur.Net.IIP
SendReply(all ? IIPPacket.IIPPacketAction.GetAllAttributes : IIPPacket.IIPPacketAction.GetAttributes, callback,
Codec.ComposeStructure(st, this, true, true, true));
else
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.GetAttributesFailed);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.GetAttributesFailed);
});
}
@ -671,7 +671,7 @@ namespace Esiur.Net.IIP
{
if (parent == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
@ -679,19 +679,19 @@ namespace Esiur.Net.IIP
{
if (child == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
if (parent.Instance.Applicable(this.session, ActionType.AddChild, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.AddChildDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.AddChildDenied);
return;
}
if (child.Instance.Applicable(this.session, ActionType.AddParent, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.AddParentDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.AddParentDenied);
return;
}
@ -710,7 +710,7 @@ namespace Esiur.Net.IIP
{
if (parent == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
@ -718,19 +718,19 @@ namespace Esiur.Net.IIP
{
if (child == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
if (parent.Instance.Applicable(this.session, ActionType.RemoveChild, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.AddChildDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.AddChildDenied);
return;
}
if (child.Instance.Applicable(this.session, ActionType.RemoveParent, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.AddParentDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.AddParentDenied);
return;
}
@ -749,13 +749,13 @@ namespace Esiur.Net.IIP
{
if (resource == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
if (resource.Instance.Applicable(this.session, ActionType.Rename, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.RenameDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.RenameDenied);
return;
}
@ -771,7 +771,7 @@ namespace Esiur.Net.IIP
{
if (resource == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
@ -789,7 +789,7 @@ namespace Esiur.Net.IIP
{
if (resource == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
@ -807,13 +807,13 @@ namespace Esiur.Net.IIP
{
if (r == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
if (r.Instance.Store.Instance.Applicable(session, ActionType.UpdateAttributes, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.UpdateAttributeDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.UpdateAttributeDenied);
return;
}
@ -825,7 +825,7 @@ namespace Esiur.Net.IIP
if (r.Instance.RemoveAttributes(attrs))
SendReply(all ? IIPPacket.IIPPacketAction.ClearAllAttributes : IIPPacket.IIPPacketAction.ClearAttributes, callback);
else
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.UpdateAttributeFailed);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.UpdateAttributeFailed);
});
}
@ -836,13 +836,13 @@ namespace Esiur.Net.IIP
{
if (r == null)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
return;
}
if (r.Instance.Store.Instance.Applicable(session, ActionType.UpdateAttributes, null) != Ruling.Allowed)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.UpdateAttributeDenied);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.UpdateAttributeDenied);
return;
}
@ -852,7 +852,7 @@ namespace Esiur.Net.IIP
SendReply(clearAttributes ? IIPPacket.IIPPacketAction.ClearAllAttributes : IIPPacket.IIPPacketAction.ClearAttributes,
callback);
else
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.UpdateAttributeFailed);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.UpdateAttributeFailed);
});
});
@ -868,7 +868,7 @@ namespace Esiur.Net.IIP
else
{
// reply failed
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
}
});
}
@ -882,7 +882,7 @@ namespace Esiur.Net.IIP
else
{
// reply failed
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
}
});
}
@ -899,7 +899,7 @@ namespace Esiur.Net.IIP
else
{
// reply failed
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
}
});
}
@ -916,7 +916,7 @@ namespace Esiur.Net.IIP
var list = r.Where(x => x.Instance.Applicable(session, ActionType.Attach, null) != Ruling.Denied).ToArray();
if (list.Length == 0)
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
else
SendReply(IIPPacket.IIPPacketAction.QueryLink, callback, Codec.ComposeResourceArray(list, this, true));
//}
@ -973,7 +973,7 @@ namespace Esiur.Net.IIP
{
if (r.Instance.Applicable(session, ActionType.Execute, ft) == Ruling.Denied)
{
SendError(AsyncReply.ErrorType.Management, callback,
SendError(ErrorType.Management, callback,
(ushort)ExceptionCode.InvokeDenied);
return;
}
@ -1009,7 +1009,7 @@ namespace Esiur.Net.IIP
}
catch(Exception ex)
{
SendError(AsyncReply.ErrorType.Exception, callback, 0, ex.ToString());
SendError(ErrorType.Exception, callback, 0, ex.ToString());
return;
}
@ -1038,14 +1038,15 @@ namespace Esiur.Net.IIP
//await t;
//SendParams((byte)0x90, callback, Codec.Compose(res, this));
}
else if (rt is AsyncReply) //(rt.GetType().IsGenericType && (rt.GetType().GetGenericTypeDefinition() == typeof(AsyncReply<>)))
else if (rt.GetType().GetTypeInfo().IsGenericType
&& rt.GetType().GetGenericTypeDefinition() == typeof(IAsyncReply<>))
{
(rt as AsyncReply).Then(res =>
(rt as IAsyncReply<object>).Then(res =>
{
SendReply(IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments, callback, Codec.Compose(res, this));
}).Error(ex =>
{
SendError(AsyncReply.ErrorType.Exception, callback, (ushort)ex.Code, ex.Message);
SendError(ErrorType.Exception, callback, (ushort)ex.Code, ex.Message);
}).Progress((pt, pv, pm) =>
{
SendProgress(callback, pv, pm);
@ -1119,7 +1120,7 @@ namespace Esiur.Net.IIP
{
if (r.Instance.Applicable(session, ActionType.Execute, ft) == Ruling.Denied)
{
SendError(AsyncReply.ErrorType.Management, callback,
SendError(ErrorType.Management, callback,
(ushort)ExceptionCode.InvokeDenied);
return;
}
@ -1150,7 +1151,7 @@ namespace Esiur.Net.IIP
}
catch (Exception ex)
{
SendError(AsyncReply.ErrorType.Exception, callback, 0, ex.ToString());
SendError(ErrorType.Exception, callback, 0, ex.ToString());
return;
}
@ -1177,14 +1178,16 @@ namespace Esiur.Net.IIP
});
}
else if (rt is AsyncReply)
{
(rt as AsyncReply).Then(res =>
// else if (rt is AsyncReply)
else if (rt.GetType().GetTypeInfo().IsGenericType
&& rt.GetType().GetGenericTypeDefinition() == typeof(IAsyncReply<>))
{
(rt as IAsyncReply<object>).Then(res =>
{
SendReply(IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments, callback, Codec.Compose(res, this));
}).Error(ex =>
{
SendError(AsyncReply.ErrorType.Exception, callback, (ushort)ex.Code, ex.Message);
SendError(ErrorType.Exception, callback, (ushort)ex.Code, ex.Message);
}).Progress((pt, pv, pm) =>
{
SendProgress(callback, pv, pm);
@ -1376,13 +1379,13 @@ namespace Esiur.Net.IIP
if (r.Instance.Applicable(session, ActionType.SetProperty, pt, this) == Ruling.Denied)
{
SendError(AsyncReply.ErrorType.Exception, callback, (ushort)ExceptionCode.SetPropertyDenied);
SendError(ErrorType.Exception, callback, (ushort)ExceptionCode.SetPropertyDenied);
return;
}
if (!pi.CanWrite)
{
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ReadOnlyProperty);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ReadOnlyProperty);
return;
}
@ -1405,14 +1408,14 @@ namespace Esiur.Net.IIP
}
catch(Exception ex)
{
SendError(AsyncReply.ErrorType.Exception, callback, 0, ex.Message);
SendError(ErrorType.Exception, callback, 0, ex.Message);
}
}
else
{
// pt found, pi not found, this should never happen
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.PropertyNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.PropertyNotFound);
}
}
@ -1421,13 +1424,13 @@ namespace Esiur.Net.IIP
else
{
// property not found
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.PropertyNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.PropertyNotFound);
}
}
else
{
// resource not found
SendError(AsyncReply.ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
}
});
}
@ -1718,7 +1721,7 @@ namespace Esiur.Net.IIP
SendRequest(IIPPacket.IIPPacketAction.ResourceChildren, resource.Instance.Id).Then(ar =>
{
var d = (byte[])ar;
var d = (byte[])ar[0];
Codec.ParseResourceArray(d, 0, (uint)d.Length, this).Then(resources =>
{
rt.Trigger(resources);
@ -1734,7 +1737,7 @@ namespace Esiur.Net.IIP
SendRequest(IIPPacket.IIPPacketAction.ResourceParents, resource.Instance.Id).Then(ar =>
{
var d = (byte[])ar;
var d = (byte[])ar[0];
Codec.ParseResourceArray(d, 0, (uint)d.Length, this).Then(resources =>
{
rt.Trigger(resources);

View File

@ -234,7 +234,7 @@ namespace Esiur.Net.IIP
Instance.EmitResourceEvent(null, null, et.Name, args);
}
public AsyncReply _InvokeByNamedArguments(byte index, Structure namedArgs)
public AsyncReply<object> _InvokeByNamedArguments(byte index, Structure namedArgs)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
@ -246,7 +246,7 @@ namespace Esiur.Net.IIP
return connection.SendInvokeByNamedArguments(instanceId, index, namedArgs);
}
public AsyncReply _InvokeByArrayArguments(byte index, object[] args)
public AsyncReply<object> _InvokeByArrayArguments(byte index, object[] args)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
@ -263,7 +263,7 @@ namespace Esiur.Net.IIP
{
var ft = Instance.Template.GetFunctionTemplate(binder.Name);
var reply = new AsyncReply();
var reply = new AsyncReply<object>();
if (isAttached && ft!=null)
{
@ -358,12 +358,12 @@ namespace Esiur.Net.IIP
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Value</param>
/// <returns>Indicator when the property is set.</returns>
internal AsyncReply _Set(byte index, object value)
internal AsyncReply<object> _Set(byte index, object value)
{
if (index >= properties.Length)
return null;
var reply = new AsyncReply();
var reply = new AsyncReply<object>();
var parameters = Codec.Compose(value, connection);
connection.SendRequest(Packets.IIPPacket.IIPPacketAction.SetProperty, instanceId, index, parameters).Then((res) =>

View File

@ -35,6 +35,7 @@ namespace Esiur.Resource
{
public interface IStore:IResource
{
AsyncReply<bool> Open(Structure settings);
AsyncReply<IResource> Get(string path);
AsyncReply<IResource> Retrieve(uint iid);
bool Put(IResource resource);

View File

@ -30,7 +30,7 @@ namespace Esiur.Resource.Template
if (Expansion != null)
{
var exp = DC.ToBytes(Expansion);
return BinaryList.ToBytes((byte)(0x10 | (IsVoid ? 0x8 : 0x0)), exp.Length, exp, (byte)name.Length, name);
return BinaryList.ToBytes((byte)(0x10 | (IsVoid ? 0x8 : 0x0)), (byte)name.Length, name, exp.Length, exp);
}
else
return BinaryList.ToBytes((byte)(IsVoid ? 0x8 : 0x0), (byte)name.Length, name);

View File

@ -66,17 +66,17 @@ namespace Esiur.Resource.Template
{
var rexp = DC.ToBytes(ReadExpansion);
var wexp = DC.ToBytes(WriteExpansion);
return BinaryList.ToBytes((byte)(0x38 | pv), wexp.Length, wexp, rexp.Length, rexp, (byte)name.Length, name);
return BinaryList.ToBytes((byte)(0x38 | pv), (byte)name.Length, name, wexp.Length, wexp, rexp.Length, rexp);
}
else if (WriteExpansion != null)
{
var wexp = DC.ToBytes(WriteExpansion);
return BinaryList.ToBytes((byte)(0x30 | pv), wexp.Length, wexp, (byte)name.Length, name);
return BinaryList.ToBytes((byte)(0x30 | pv), (byte)name.Length, name, wexp.Length, wexp);
}
else if (ReadExpansion != null)
{
var rexp = DC.ToBytes(ReadExpansion);
return BinaryList.ToBytes((byte)(0x28 | pv), rexp.Length, rexp, (byte)name.Length, name);
return BinaryList.ToBytes((byte)(0x28 | pv), (byte)name.Length, name, rexp.Length, rexp);
}
else
return BinaryList.ToBytes((byte)(0x20 | pv), (byte)name.Length, name);

View File

@ -228,7 +228,7 @@ namespace Esiur.Resource.Template
od.classId = data.GetGuid(offset);
offset += 16;
od.className = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
od.className = data.GetString(offset + 1, data[offset]);
offset += (uint)data[offset] + 1;
od.version = data.GetInt32(offset);
@ -250,7 +250,7 @@ namespace Esiur.Resource.Template
string expansion = null;
var hasExpansion = ((data[offset] & 0x10) == 0x10);
var isVoid = ((data[offset++] & 0x08) == 0x08);
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
var name = data.GetString(offset + 1, data[offset]);
offset += (uint)data[offset] + 1;
if (hasExpansion) // expansion ?

View File

@ -53,6 +53,7 @@ namespace Esiur.Resource
public static event StoreConnectedEvent StoreConnected;
public static event StoreDisconnectedEvent StoreDisconnected;
static KeyList<string, IStore> protocols = new KeyList<string, IStore>();
/// <summary>
/// Get a store by its name.
@ -234,7 +235,7 @@ namespace Esiur.Resource
/// </summary>
/// <param name="path"></param>
/// <returns>Resource instance.</returns>
public static AsyncReply<IResource> Get(string path)
public static AsyncReply<IResource> Get(string path, Structure settings = null, IResource parent = null, IPermissionsManager manager = null)
{
var p = path.Split('/');
@ -265,6 +266,41 @@ namespace Esiur.Resource
return new AsyncReply<IResource>(res);
}
// Should we create a new store ?
if (path.Contains("://"))
{
var url = path.Split(new string[] { "://" }, 2, StringSplitOptions.None);
var hostname = url[1].Split(new char[] { '/' }, 2)[0];
var pathname = string.Join("/", url[1].Split(new char[] { '/' }).Skip(1));
var rt = new AsyncReply<IResource>();
if (protocols.ContainsKey(url[0]))
{
var handler = protocols[url[0]];
var store = Activator.CreateInstance(handler.GetType()) as IStore;
Put(store, url[0] + "://" + hostname, null, parent, null, 0, manager);
store.Open(settings).Then(x => {
if (pathname.Length > 0 && pathname != "")
store.Get(pathname).Then(r => {
rt.Trigger(r);
}).Error(e => rt.TriggerError(e));
else
rt.Trigger(store);
}).Error(e => {
rt.TriggerError(e);
Warehouse.Remove(store);
});
}
return rt;
}
return new AsyncReply<IResource>(null);
}

View File

@ -75,5 +75,10 @@ namespace Esiur.Stores
{
return true;
}
public AsyncReply<bool> Open(Structure settings)
{
return new AsyncReply<bool>(true);
}
}
}