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:
@ -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)
|
||||
{
|
||||
|
40
Esiur/Engine/AsyncAwaiter.cs
Normal file
40
Esiur/Engine/AsyncAwaiter.cs
Normal 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....");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -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()
|
||||
{
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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
12
Esiur/Engine/ErrorType.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Engine
|
||||
{
|
||||
public enum ErrorType
|
||||
{
|
||||
Management,
|
||||
Exception
|
||||
}
|
||||
}
|
21
Esiur/Engine/IAsyncReply.cs
Normal file
21
Esiur/Engine/IAsyncReply.cs
Normal 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);
|
||||
|
||||
|
||||
}
|
||||
}
|
12
Esiur/Engine/ProgressType.cs
Normal file
12
Esiur/Engine/ProgressType.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Engine
|
||||
{
|
||||
public enum ProgressType
|
||||
{
|
||||
Execution,
|
||||
Network,
|
||||
}
|
||||
}
|
@ -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" />
|
||||
|
@ -50,7 +50,7 @@ namespace Esiur.Net.DataLink
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) =>
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 ?
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -75,5 +75,10 @@ namespace Esiur.Stores
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public AsyncReply<bool> Open(Structure settings)
|
||||
{
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user