2
0
mirror of https://github.com/esiur/esiur-dart.git synced 2025-05-06 12:02:57 +00:00
This commit is contained in:
Ahmed Zamil 2019-08-07 05:12:10 +03:00
parent de338a3350
commit 29c8252c10
74 changed files with 10372 additions and 0 deletions

15
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Dart",
"program": "bin/main.dart",
"request": "launch",
"type": "dart",
""
}
]
}

58
bin/Core/AsyncBag.dart Normal file
View File

@ -0,0 +1,58 @@
import 'AsyncReply.dart';
class AsyncBag<T> extends AsyncReply<List<T>>
{
List<AsyncReply<T>> _replies = new List<AsyncReply<T>>();
List<T> _results = new List<T>();
int _count = 0;
bool _sealedBag = false;
seal()
{
if (_sealedBag)
return;
_sealedBag = true;
if (_results.length == 0)
trigger(new List<T>());
for (var i = 0; i < _results.length; i++)
{
var k = _replies[i];
var index = i;
k.then((r)
{
_results[index] = r;
_count++;
if (_count == _results.length)
trigger(_results);
});
}
}
add(AsyncReply<T> reply)
{
if (!_sealedBag)
{
_results.add(null);
_replies.add(reply);
}
}
addBag(AsyncBag<T> bag)
{
bag._replies.forEach((r) {
add(r);
});
}
AsyncBag()
{
}
}

View File

@ -0,0 +1,33 @@
import 'ExceptionCode.dart';
import 'ErrorType.dart';
class AsyncException implements Exception
{
final ErrorType type;
final int code;
final String message;
AsyncException(this.type, this.code, this.message)
{
}
static toAsyncException(Exception ex)
{
return ex is AsyncException ? ex
: new AsyncException(ErrorType.Exception, 0, ex.toString());
}
String errMsg() {
if (type == ErrorType.Management)
return ExceptionCode.values.elementAt(code).toString() + ": " + (message ?? "");
else
return code.toString() + ": " + message;
}
@override
String toString() {
return errMsg();
}
}

51
bin/Core/AsyncQueue.dart Normal file
View File

@ -0,0 +1,51 @@
library esiur;
import 'AsyncReply.dart';
class AsyncQueue<T> extends AsyncReply<T>
{
List<AsyncReply<T>> _list = new List<AsyncReply<T>>();
// object queueLock = new object();
add(AsyncReply<T> reply)
{
//lock (queueLock)
_list.add(reply);
//super._resultReady = false;
super.setResultReady(false);
reply.then(processQueue);
}
remove(AsyncReply<T> reply)
{
//lock (queueLock)
_list.remove(reply);
processQueue(null);
}
void processQueue(T o)
{
//lock (queueLock)
for (var i = 0; i < _list.length; i++)
if (_list[i].ready)
{
super.trigger(_list[i].result);
_list.removeAt(i);
i--;
}
else
break;
//super._resultReady = (_list.length == 0);
super.setResultReady(_list.length == 0);
}
AsyncQueue()
{
}
}

220
bin/Core/AsyncReply.dart Normal file
View File

@ -0,0 +1,220 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import 'dart:async';
import 'dart:core';
import 'AsyncException.dart';
import 'ProgressType.dart';
class AsyncReply<T> implements Future<T>
{
List<Function(T)> _callbacks = new List<Function(T)>();
T _result;
List<Function(AsyncException)> _errorCallbacks = new List<Function(AsyncException)>();
List<Function(ProgressType, int, int)> _progressCallbacks = new List<Function(ProgressType, int, int)>();
List<Function(T)> _chunkCallbacks = new List<Function(T)>();
bool _resultReady = false;
AsyncException _exception;
bool get ready
{
return _resultReady;
}
T get result
{
return _result;
}
setResultReady(bool val)
{
_resultReady = val;
}
AsyncReply<R> then<R>(FutureOr<R> onValue(T value), {Function onError})
{
_callbacks.add(onValue);
if (onError != null)
{
if (onError is Function(dynamic, dynamic))
{
_errorCallbacks.add((ex)=>onError(ex, null));
}
else if (onError is Function(dynamic))
{
_errorCallbacks.add(onError);
}
else if (onError is Function())
{
_errorCallbacks.add((ex)=>onError());
}
}
if (_resultReady)
onValue(result);
return this as AsyncReply<R>;
}
AsyncReply<T> whenComplete(FutureOr action())
{
return this;
//_callbacks.add(action);
}
Stream<T> asStream()
{
return null;
}
AsyncReply<T> catchError(Function onError, {bool test(Object error)})
{
return this.error(onError);
}
AsyncReply<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()})
{
return this;
}
AsyncReply<T> _then_old(Function(T) callback)
{
_callbacks.add(callback);
if (_resultReady)
callback(result);
return this;
}
AsyncReply<T> error(Function(dynamic) callback)
{
_errorCallbacks.add(callback);
if (_exception != null)
callback(_exception);
return this;
}
AsyncReply<T> progress(Function(ProgressType, int, int) callback)
{
_progressCallbacks.add(callback);
return this;
}
AsyncReply<T> chunk(Function(T) callback)
{
_chunkCallbacks.add(callback);
return this;
}
void trigger(T result)
{
// lock (callbacksLock)
// {
if (_resultReady)
return;
_result = result;
_resultReady = true;
_callbacks.forEach((x) {
x(result);
});
// }
}
triggerError(Exception exception)
{
if (_resultReady)
return;
_exception = AsyncException.toAsyncException(exception);
///lock (callbacksLock)
//{
_errorCallbacks.forEach((x) {
x(_exception);
});
//}
}
triggerProgress(ProgressType type, int value, int max)
{
if (_resultReady)
return;
//lock (callbacksLock)
//{
_progressCallbacks.forEach((x) {
x(type, value, max);
});
//}
}
triggerChunk(T value)
{
if (_resultReady)
return;
//lock (callbacksLock)
//{
_chunkCallbacks.forEach((x) {
x(value);
});
//}
}
AsyncReply.ready(T result)
{
_resultReady = true;
_result = result;
}
AsyncReply()
{
}
}

5
bin/Core/ErrorType.dart Normal file
View File

@ -0,0 +1,5 @@
enum ErrorType
{
Management,
Exception
}

View File

@ -0,0 +1,31 @@
enum ExceptionCode
{
HostNotReachable,
AccessDenied,
ResourceNotFound,
AttachDenied,
InvalidMethod,
InvokeDenied,
CreateDenied,
AddParentDenied,
AddChildDenied,
ViewAttributeDenied,
UpdateAttributeDenied,
StoreNotFound,
ParentNotFound,
ChildNotFound,
ResourceIsNotStore,
DeleteDenied,
DeleteFailed,
UpdateAttributeFailed,
GetAttributesFailed,
ClearAttributesFailed,
TemplateNotFound,
RenameDenied,
ClassNotFound,
MethodNotFound,
PropertyNotFound,
SetPropertyDenied,
ReadOnlyProperty
}

View File

@ -0,0 +1,10 @@
library esiur;
import 'IEventHandler.dart';
typedef DestroyedEvent(sender);
abstract class IDestructible extends IEventHandler
{
void destroy();
}

View File

@ -0,0 +1,48 @@
class IEventHandler
{
Map<String, List<Function>> _events;
register(String event)
{
_events[event.toLowerCase()] = [];
}
IEventHandler()
{
_events = {};
}
emitArgs(String event, List arguments)
{
event = event.toLowerCase();
if (_events.containsKey(event))
for(var i = 0; i < _events[event].length; i++)
if (Function.apply(_events[event][i], arguments) != null)
return true;
return false;
}
on(String event, Function callback)
{
event = event.toLowerCase();
// add
if (!_events.containsKey(event))
register(event);
_events[event].add(callback);
return this;
}
off(event, callback)
{
event = event.toString();
if (_events.containsKey(event))
{
if (callback != null)
_events[event].remove(callback);
else
this._events[event] = [];
}
}
}

View File

@ -0,0 +1,5 @@
enum ProgressType
{
Execution,
Network,
}

200
bin/Data/AutoList.dart Normal file
View File

@ -0,0 +1,200 @@
import '../Core/IDestructible.dart';
import 'Codec.dart';
import 'dart:collection';
class AutoList<T, ST> extends IDestructible with IterableMixin
{
List<T> _list = new List<T>();
ST _state;
bool _removableList;
sort(Function comparer)
{
_list.sort(comparer);
}
Iterator<T> get iterator => _list.iterator;
/// <summary>
/// Convert AutoList to array
/// </summary>
/// <returns>Array</returns>
//List<T> toList()
//{
// list.OrderBy()
// return _list;
//}
/// Create a new instance of AutoList
/// <param name="state">State object to be included when an event is raised.</param>
AutoList([ST state, List<T> values])
{
this._state = state;
this._removableList = Codec.implementsInterface<T, IDestructible>();
if (values != null)
addRange(values);
register("modified");
register("added");
register("removed");
register("cleared");
}
/// <summary>
/// Synchronization lock of the list
/// </summary>
//public object SyncRoot
//{
// get
// {
// return syncRoot;
// }
//}
/// <summary>
/// First item in the list
/// </summary>
//T first()
//{
// return _list.first;
//}
operator [](index)
{
return _list[index];
}
operator []=(index, value)
{
var oldValue = _list[index];
if (_removableList)
{
if (oldValue != null)
(oldValue as IDestructible).off("destroy", _itemDestroyed);
if (value != null)
value.on("destroy", _itemDestroyed);
}
//lock (syncRoot)
_list[index] = value;
emitArgs("modified", [_state, index, oldValue, value]);
}
/// <summary>
/// Add item to the list
/// </summary>
add(T value)
{
if (_removableList)
if (value != null)
(value as IDestructible).on("destroy", _itemDestroyed);
// lock (syncRoot)
_list.add(value);
emitArgs("add",[_state, value]);
}
/// <summary>
/// Add an array of items to the list
/// </summary>
addRange(List<T> values)
{
values.forEach((x)=>add(x));
}
_itemDestroyed(T sender)
{
remove(sender);
}
/// <summary>
/// Clear the list
/// </summary>
clear()
{
if (_removableList)
_list.forEach((x)=>(x as IDestructible)?.off("destroy", _itemDestroyed));
// lock (syncRoot)
_list.clear();
emitArgs("cleared", [_state]);
}
/// <summary>
/// Remove an item from the list
/// <param name="value">Item to remove</param>
/// </summary>
remove(T value)
{
if (!_list.contains(value))
return;
if (_removableList)
if (value != null)
(value as IDestructible).off("destroy", _itemDestroyed);
//lock (syncRoot)
_list.remove(value);
emitArgs("removed", [_state, value]);
}
/// <summary>
/// Number of items in the list
/// </summary>
get count => _list.length;
get length => _list.length;
/// <summary>
/// Check if an item exists in the list
/// </summary>
/// <param name="value">Item to check if exists</param>
//contains(T value) => _list.contains(value);
/// <summary>
/// Check if any item of the given array is in the list
/// </summary>
/// <param name="values">Array of items</param>
containsAny(values)
{
if (values is List<T>)
{
for(var v in values)
{
if (_list.contains(v))
return true;
}
}
else if (values is AutoList<T, ST>)
{
for(var v in values._list)
{
if (_list.contains(v))
return true;
}
}
return false;
}
@override
void destroy() {
clear();
}
}

550
bin/Data/BinaryList.dart Normal file
View File

@ -0,0 +1,550 @@
/*
* Copyright (c) 2019 Ahmed Kh. Zamil
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Created by Ahmed Zamil on 26/07/2019.
*/
import '../Core/AsyncReply.dart';
import 'dart:typed_data';
import 'DC.dart';
import 'DataType.dart';
import 'Guid.dart';
class BinaryList
{
var _list = new List<int>();
int get length => _list.length;
BinaryList addDateTime(DateTime value)
{
_list.addAll(DC.dateTimeToBytes(value));
return this;
}
BinaryList insertDateTime(int position, DateTime value)
{
_list.insertAll(position, DC.dateTimeToBytes(value));
return this;
}
BinaryList addDateTimeArray(List<DateTime> value)
{
_list.addAll(DC.dateTimeArrayToBytes(value));
return this;
}
BinaryList insertDateTimeArray(int position, List<DateTime> value)
{
_list.insertAll(position, DC.dateTimeArrayToBytes(value));
return this;
}
BinaryList addGuid(Guid value)
{
_list.addAll(DC.guidToBytes(value));
return this;
}
BinaryList insertGuid(int position, Guid value)
{
_list.insertAll(position, DC.guidToBytes(value));
return this;
}
BinaryList addGuidArray(List<Guid> value)
{
_list.addAll(DC.guidArrayToBytes(value));
return this;
}
BinaryList insertGuidArray(int position, List<Guid> value)
{
_list.insertAll(position, DC.guidArrayToBytes(value));
return this;
}
BinaryList addUint8Array(Uint8List value)
{
_list.addAll(value);
return this;
}
BinaryList addDC(DC value)
{
_list.addAll(value.toArray());
return this;
}
BinaryList insertUint8Array(int position, Uint8List value)
{
_list.insertAll(position, value);
return this;
}
/*
BinaryList addHex(String value)
{
return this.addUint8Array(DC.fromHex(value, null));
}
BinaryList insertHex(int position, String value)
{
return this.insertUint8Array(position, DC.fromHex(value, null));
}
*/
BinaryList addString(String value)
{
_list.addAll(DC.stringToBytes(value));
return this;
}
BinaryList insertString(int position, String value)
{
_list.insertAll(position, DC.stringToBytes(value));
return this;
}
BinaryList addStringArray(List<String> value)
{
_list.addAll(DC.stringArrayToBytes(value));
return this;
}
BinaryList insertStringArray(int position, List<String> value)
{
_list.insertAll(position, DC.stringArrayToBytes(value));
return this;
}
BinaryList insertUint8(int position, int value)
{
_list.insert(position, value);
return this;
}
BinaryList addUint8(int value)
{
_list.add(value);
return this;
}
BinaryList addInt8(int value)
{
_list.add(value);
return this;
}
BinaryList insertInt8(int position, int value)
{
_list.insert(position, value);
return this;
}
BinaryList addInt8Array(Int8List value)
{
_list.addAll(DC.int8ArrayToBytes(value));
return this;
}
BinaryList insertInt8Array(int position, Int8List value)
{
_list.insertAll(position, DC.int8ArrayToBytes(value));
return this;
}
BinaryList addChar(int value)
{
_list.addAll(DC.charToBytes(value));
return this;
}
BinaryList InsertChar(int position, int value)
{
_list.insertAll(position, DC.charToBytes(value));
return this;
}
BinaryList addCharArray(Uint16List value)
{
_list.addAll(DC.charArrayToBytes(value));
return this;
}
BinaryList InsertCharArray(int position, Uint16List value)
{
_list.insertAll(position, DC.charArrayToBytes(value));
return this;
}
BinaryList addBoolean(bool value)
{
_list.addAll(DC.boolToBytes(value));
return this;
}
BinaryList insertBoolean(int position, bool value)
{
_list.insertAll(position, DC.boolToBytes(value));
return this;
}
BinaryList addBooleanArray(List<bool> value)
{
_list.addAll(DC.boolToBytes(value));
return this;
}
BinaryList insertBooleanArray(int position, List<bool> value)
{
_list.insertAll(position, DC.boolToBytes(value));
return this;
}
BinaryList addUint16(int value)
{
_list.addAll(DC.uint16ToBytes(value));
return this;
}
BinaryList insertUint16(int position, int value)
{
_list.insertAll(position, DC.uint16ToBytes(value));
return this;
}
BinaryList addUint16Array(Uint16List value)
{
_list.addAll(DC.uint16ArrayToBytes(value));
return this;
}
BinaryList insertUint16Array(int position, Uint16List value)
{
_list.insertAll(position, DC.uint16ArrayToBytes(value));
return this;
}
BinaryList addInt16(int value)
{
_list.addAll(DC.int16ToBytes(value));
return this;
}
BinaryList insertInt16(int position, int value)
{
_list.insertAll(position, DC.int16ToBytes(value));
return this;
}
BinaryList addInt16Array(Int16List value)
{
_list.addAll(DC.int16ArrayToBytes(value));
return this;
}
BinaryList insertInt16Array(int position, Int16List value)
{
_list.insertAll(position, DC.int16ArrayToBytes(value));
return this;
}
BinaryList addUint32(int value)
{
_list.addAll(DC.uint32ToBytes(value));
return this;
}
BinaryList insertUint32(int position, int value)
{
_list.insertAll(position, DC.uint32ToBytes(value));
return this;
}
BinaryList addUint32Array(Uint32List value)
{
_list.addAll(DC.uint32ArrayToBytes(value));
return this;
}
BinaryList InsertUint32Array(int position, Uint32List value)
{
_list.insertAll(position, DC.uint32ArrayToBytes(value));
return this;
}
BinaryList addInt32(int value)
{
_list.addAll(DC.int32ToBytes(value));
return this;
}
BinaryList insertInt32(int position, int value)
{
_list.insertAll(position, DC.int32ToBytes(value));
return this;
}
BinaryList addInt32Array(Int32List value)
{
_list.addAll(DC.int32ArrayToBytes(value));
return this;
}
BinaryList insertInt32Array(int position, Int32List value)
{
_list.insertAll(position, DC.int32ArrayToBytes(value));
return this;
}
BinaryList addUint64(int value)
{
_list.addAll(DC.uint64ToBytes(value));
return this;
}
BinaryList insertUint64(int position, int value)
{
_list.insertAll(position, DC.uint64ToBytes(value));
return this;
}
BinaryList addUint64Array(Uint64List value)
{
_list.addAll(DC.uint64ArrayToBytes(value));
return this;
}
BinaryList InsertUint64Array(int position, Uint64List value)
{
_list.insertAll(position, DC.uint64ArrayToBytes(value));
return this;
}
BinaryList addInt64(int value)
{
_list.addAll(DC.int64ToBytes(value));
return this;
}
BinaryList insertInt64(int position, int value)
{
_list.insertAll(position, DC.int64ToBytes(value));
return this;
}
BinaryList addInt64Array(Int64List value)
{
_list.addAll(DC.int64ArrayToBytes(value));
return this;
}
BinaryList insertInt64Array(int position, Int64List value)
{
_list.insertAll(position, DC.int64ArrayToBytes(value));
return this;
}
BinaryList addFloat32(double value)
{
_list.addAll(DC.float32ToBytes(value));
return this;
}
BinaryList insertFloat32(int position, double value)
{
_list.insertAll(position, DC.float32ToBytes(value));
return this;
}
BinaryList addFloat32Array(Float32List value)
{
_list.addAll(DC.float32ArrayToBytes(value));
return this;
}
BinaryList insertFloat32Array(int position, Float32List value)
{
_list.insertAll(position, DC.float32ArrayToBytes(value));
return this;
}
BinaryList addFloat64(double value)
{
_list.addAll(DC.float64ToBytes(value));
return this;
}
BinaryList insertFloat64(int position, double value)
{
_list.insertAll(position, DC.float64ToBytes(value));
return this;
}
BinaryList addFloat64Array(Float64List value)
{
_list.addAll(DC.float64ArrayToBytes(value));
return this;
}
BinaryList insertFloat64Array(int position, Float64List value)
{
_list.insertAll(position, DC.float64ArrayToBytes(value));
return this;
}
BinaryList add(type, value)
{
switch (type)
{
case DataType.Bool:
addBoolean(value);
return this;
case DataType.BoolArray:
addBooleanArray(value);
return this;
case DataType.UInt8:
addUint8(value);
return this;
case DataType.UInt8Array:
addUint8Array(value);
return this;
case DataType.Int8:
addInt8(value);
return this;
case DataType.Int8Array:
addInt8Array(value);
return this;
case DataType.Char:
addChar(value);
return this;
case DataType.CharArray:
addCharArray(value);
return this;
case DataType.UInt16:
addUint16(value);
return this;
case DataType.UInt16Array:
addUint16Array(value);
return this;
case DataType.Int16:
addInt16(value);
return this;
case DataType.Int16Array:
addInt16Array(value);
return this;
case DataType.UInt32:
addUint32(value);
return this;
case DataType.UInt32Array:
addUint32Array(value);
return this;
case DataType.Int32:
addInt32(value);
return this;
case DataType.Int32Array:
addInt32Array(value);
return this;
case DataType.UInt64:
addUint64(value);
return this;
case DataType.UInt64Array:
addUint64Array(value);
return this;
case DataType.Int64:
addInt64(value);
return this;
case DataType.Int64Array:
addInt64Array(value);
return this;
case DataType.Float32:
addFloat32(value);
return this;
case DataType.Float32Array:
addFloat32Array(value);
return this;
case DataType.Float64:
addFloat64(value);
return this;
case DataType.Float64Array:
addFloat64Array(value);
return this;
case DataType.String:
addString(value);
return this;
case DataType.StringArray:
addStringArray(value);
return this;
case DataType.DateTime:
addDateTime(value);
return this;
case DataType.DateTimeArray:
addDateTimeArray(value);
return this;
default:
throw new Exception("Not Implemented " + type.ToString());
//return this;
}
}
/// <summary>
/// Convert the _list to an array of bytes
/// </summary>
/// <returns>Bytes array</returns>
Uint8List toArray()
{
return Uint8List.fromList(_list);
}
DC toDC()
{
return new DC.fromUint8Array(toArray());
}
AsyncReply<dynamic> done()
{
return null;
//
}
}

1074
bin/Data/Codec.dart Normal file

File diff suppressed because it is too large Load Diff

643
bin/Data/DC.dart Normal file
View File

@ -0,0 +1,643 @@
/*
* Copyright (c) 2019 Ahmed Kh. Zamil
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import 'dart:typed_data';
import 'dart:convert';
import 'BinaryList.dart';
import 'dart:collection';
import 'Guid.dart';
/**
* Created by Ahmed Zamil on 6/10/2019.
*/
const UNIX_EPOCH = 621355968000000000;
const TWO_PWR_32 = (1 << 16) * (1 << 16);
class DC with IterableMixin<int>
{
Uint8List _data;
ByteData _dv;
DC(int length)
{
_data = new Uint8List(length);
_dv = ByteData.view(_data.buffer);
}
DC.fromUint8Array(Uint8List array)
{
_data = array;
_dv = ByteData.view(_data.buffer);
}
DC.fromList(List<int> list)
{
_data = Uint8List.fromList(list);
_dv = ByteData.view(_data.buffer);
}
operator [](index) => _data[index];
operator []=(index,value) => _data[index] = value;
int get length => _data.length;
Iterator<int> get iterator => _data.iterator;
static DC hexToBytes(String value)
{
// convert hex to Uint8Array
var rt = new DC(value.length~/2);
for(var i = 0; i < rt.length; i++)
rt[i] = int.parse(value.substring(i*2, 2), radix: 16);
return rt;
}
static DC boolToBytes(value)
{
var rt = new DC(1);
rt.setBoolean(0, value);
return rt;
}
static DC guidToBytes(Guid value)
{
var rt = new DC(16);
rt.setGuid(0, value);
return rt;
}
static DC guidArrayToBytes(List<Guid> value)
{
var rt = new DC(value.length * 16);
for(var i = 0; i < value.length; i++)
rt.setGuid(i * 16, value[i]);
return rt;
}
static DC boolArrayToBytes(List<bool> value)
{
var rt = new DC(value.length);
for(var i = 0; i < value.length; i++)
rt[i] = value[i] ? 1 : 0;
return rt;
}
static DC int8ToBytes(value)
{
var rt = new DC(1);
rt.setInt8(0, value);
return rt;
}
static DC int8ArrayToBytes(Int8List value)
{
var rt = new DC(value.length);
for(var i = 0; i < value.length; i++)
rt.setInt8(i, value[i]);
return rt;
}
static DC uint8ToBytes(value)
{
var rt = new DC(1);
rt.setUint8(0, value);
return rt;
}
static DC uint8ArrayToBytes(Uint8List value)
{
var rt = new DC(value.length);
for(var i = 0; i < value.length; i++)
rt.setUint8(i, value[i]);
return rt;
}
static DC charToBytes(int value)
{
var rt = new DC(2);
rt.setChar(0, value);
return rt;
}
static DC charArrayToBytes(Uint16List value)
{
var rt = new DC(value.length * 2);
for(var i = 0; i < value.length; i++)
rt.setChar(i*2, value[i]);
return rt;
}
static DC int16ToBytes(int value)
{
var rt = new DC(2);
rt.setInt16(0, value);
return rt;
}
static DC int16ArrayToBytes(List<int> value)
{
var rt = new DC(value.length * 2);
for(var i = 0; i < value.length; i++)
rt.setInt16(i*2, value[i]);
return rt;
}
static DC uint16ToBytes(int value)
{
var rt = new DC(2);
rt.setUint16(0, value);
return rt;
}
static DC uint16ArrayToBytes(Uint16List value)
{
var rt = new DC(value.length * 2);
for(var i = 0; i < value.length; i++)
rt.setUint16(i*2, value[i]);
return rt;
}
static DC int32ToBytes(int value)
{
var rt = new DC(4);
rt.setInt32(0, value);
return rt;
}
static DC int32ArrayToBytes(Int32List value)
{
var rt = new DC(value.length * 4);
for(var i = 0; i < value.length; i++)
rt.setInt32(i*4, value[i]);
return rt;
}
static DC uint32ToBytes(int value)
{
var rt = new DC(4);
rt.setUint32(0, value);
return rt;
}
static DC uint32ArrayToBytes(Uint32List value)
{
var rt = new DC(value.length * 4);
for(var i = 0; i < value.length; i++)
rt.setUint32(i*4, value[i]);
return rt;
}
static DC float32ToBytes(double value)
{
var rt = new DC(4);
rt.setFloat32(0, value);
return rt;
}
static DC float32ArrayToBytes(Float32List value)
{
var rt = new DC(value.length * 4);
for(var i = 0; i < value.length; i++)
rt.setFloat32(i*4, value[i]);
return rt;
}
static DC int64ToBytes(int value)
{
var rt = new DC(8);
rt.setInt64(0, value);
return rt;
}
static DC int64ArrayToBytes(Int64List value)
{
var rt = new DC(value.length * 8);
for(var i = 0; i < value.length; i++)
rt.setInt64(i*8, value[i]);
return rt;
}
static DC uint64ToBytes(int value)
{
var rt = new DC(8);
rt.setUint64(0, value);
return rt;
}
static DC uint64ArrayToBytes(Uint64List value)
{
var rt = new DC(value.length * 8);
for(var i = 0; i < value.length; i++)
rt.setUint64(i*8, value[i]);
return rt;
}
static DC float64ToBytes(double value)
{
var rt = new DC(8);
rt.setFloat64(0, value);
return rt;
}
static DC float64ArrayToBytes(Float64List value)
{
var rt = new DC(value.length * 8);
for(var i = 0; i < value.length; i++)
rt.setFloat64(i*8, value[i]);
return rt;
}
static DC dateTimeToBytes(DateTime value)
{
var rt = new DC(8);
rt.setDateTime(0, value);
return rt;
}
static DC dateTimeArrayToBytes(List<DateTime> value)
{
var rt = new DC(value.length * 8);
for(var i = 0; i < value.length; i++)
rt.setDateTime(i*8, value[i]);
return rt;
}
static DC stringToBytes(String value)
{
var bytes = utf8.encode(value);
var rt = new DC.fromList(bytes);
return rt;
}
static DC stringArrayToBytes(List<String> value)
{
var list = new BinaryList();
for(var i = 0; i < value.length; i++)
{
var s = DC.stringToBytes(value[i]);
list.addUint32(s.length).addUint8Array(s.toArray());
}
return list.toDC();
}
DC append(DC src, int offset, int length)
{
//if (!(src is DC))
// src = new DC(src);
var appendix = src.clip(offset, length);
var rt = new DC(this.length + appendix.length);
rt.set(this, 0);
rt.set(appendix, this.length);
this._data = rt._data;
this._dv = rt._dv;
return this;
}
set(DC dc, int offset)
{
_data.setRange(offset, offset + dc.length, dc._data);
}
static combine(a, aOffset, aLength, b, bOffset, bLength)
{
if (!(a is DC))
a = new DC(a);
if (!(b is DC))
b = new DC(b);
a = a.clip(aOffset, aLength);
b = b.clip(bOffset, bLength);
var rt = new DC(a.length + b.length);
rt.set(a, 0);
rt.set(b, a.length);
return rt;
}
DC clip(offset, length)
{
return DC.fromUint8Array(Uint8List.fromList(_data.getRange(offset, offset + length).toList()));
}
getInt8(int offset)
{
return _dv.getInt8(offset);
}
getUint8(int offset)
{
return _data[offset];// this.dv.getUint8(offset);
}
getInt16(int offset)
{
return _dv.getInt16(offset);
}
getUint16(int offset)
{
return _dv.getUint16(offset);
}
getInt32(int offset)
{
return _dv.getInt32(offset);
}
getUint32(int offset)
{
return _dv.getUint32(offset);
}
getFloat32(int offset)
{
return _dv.getFloat32(offset);
}
getFloat64(int offset)
{
return _dv.getFloat64(offset);
}
setInt8(int offset, int value)
{
return _dv.setInt8(offset, value);
}
setUint8(int offset, int value)
{
return _dv.setUint8(offset, value);
}
setInt16(int offset, int value)
{
return _dv.setInt16(offset, value);
}
setUint16(int offset, int value)
{
return _dv.setUint16(offset, value);
}
setInt32(int offset, int value)
{
return _dv.setInt32(offset, value);
}
setUint32(int offset, int value)
{
return _dv.setUint32(offset, value);
}
setFloat32(int offset, double value)
{
return _dv.setFloat32(offset, value);
}
setFloat64(int offset, double value)
{
return _dv.setFloat64(offset, value);
}
Int8List getInt8Array(int offset, int length)
{
return _data.buffer.asInt8List(offset, length);
}
Uint8List getUint8Array(int offset, int length)
{
return _data.buffer.asUint8List(offset, length);
}
Int16List getInt16Array(int offset, int length)
{
return _data.buffer.asInt16List(offset, length);
}
Uint16List getUint16Array(int offset, int length)
{
return _data.buffer.asUint16List(offset, length);
}
Int32List getInt32Array(int offset, int length)
{
return _data.buffer.asInt32List(offset, length);
}
Uint32List getUint32Array(int offset, int length)
{
return _data.buffer.asUint32List(offset, length);
}
Float32List getFloat32Array(int offset, int length)
{
return _data.buffer.asFloat32List(offset, length);
}
Float64List getFloat64Array(int offset, int length)
{
return _data.buffer.asFloat64List(offset, length);
}
Int64List getInt64Array(int offset, int length)
{
return _data.buffer.asInt64List(offset, length);
}
Uint64List getUint64Array(int offset, int length)
{
return _data.buffer.asUint64List(offset, length);
}
bool getBoolean(int offset)
{
return this.getUint8(offset) > 0;
}
setBoolean(int offset, bool value)
{
this.setUint8(offset, value ? 1: 0);
}
List<bool> getBooleanArray(int offset, int length)
{
var rt = new List<bool>();
for(var i = 0; i < length; i++)
rt.add(this.getBoolean(offset+i));
return rt;
}
String getChar(int offset)
{
return String.fromCharCode(this.getUint16(offset));
}
setChar(int offset, int value)
{
this.setUint16(offset, value); //value.codeUnitAt(0));
}
List<String> getCharArray(int offset, int length)
{
var rt = new List<String>();
for(var i = 0; i < length; i+=2)
rt.add(this.getChar(offset+i));
return rt;
}
String getHex(offset, length)
{
var rt = "";
for(var i = offset; i < offset + length; i++) {
var h = this[i].toString(16);
rt += h.length == 1 ? "0" + h : h;
}
return rt;
}
/*
List<T> toList<T>(offset, length)
{
var rt = new List<T>();
for(var i = 0; i < length; i++)
rt[i] = _data[offset+i] as T;
return rt;
}*/
Uint8List toArray() => _data;
String getString(offset, length)
{
var bytes = clip(offset, length)._data;// toList(offset, length);
var str = utf8.decode(bytes);
return str;
}
List<String> getStringArray(offset, length)
{
var rt = List<String>();
var i = 0;
while (i < length)
{
var cl = this.getUint32(offset + i);
i += 4;
rt.add(this.getString(offset + i, cl));
i += cl;
}
return rt;
}
getInt64(offset)
{
return _dv.getUint64(offset);
}
getUint64(offset)
{
return _dv.getInt64(offset);
}
void setInt64(offset, value)
{
_dv.setInt64(offset, value);
}
void setUint64(offset, value)
{
_dv.setUint64(offset, value);
}
setDateTime(offset, value)
{
// Unix Epoch
var ticks = 621355968000000000 + (value.getTime() * 10000);
this.setUint64(offset, ticks);
}
DateTime getDateTime(int offset)
{
var ticks = this.getUint64(offset);
// there are 10,000 ticks in a millisecond
return DateTime.fromMillisecondsSinceEpoch((ticks-UNIX_EPOCH)~/10000);
}
List<DateTime> getDateTimeArray(int offset, int length)
{
var rt = new List<DateTime>();
for(var i = 0; i < length; i+=8)
rt.add(this.getDateTime(offset+i));
return rt;
}
Guid getGuid(int offset)
{
return new Guid(this.clip(offset, 16));
}
setGuid(int offset, Guid guid)
{
set(guid.value, offset);
}
List<Guid> getGuidArray(int offset, int length)
{
var rt = [];
for(var i = 0; i < length; i+=16)
rt.add(this.getGuid(offset+i));
return rt;
}
bool sequenceEqual(ar)
{
if (ar.length != this.length)
return false;
else
{
for(var i = 0; i < this.length; i++)
if (ar[i] != this[i])
return false;
}
return true;
}
}

115
bin/Data/DataType.dart Normal file
View File

@ -0,0 +1,115 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
class DataType
{
static const int Void = 0x0,
//Variant,
Bool = 1,
Int8 = 2,
UInt8 = 3,
Char = 4,
Int16 = 5,
UInt16 = 6,
Int32 = 7,
UInt32 = 8,
Int64 = 9,
UInt64 = 0xA,
Float32 = 0xB,
Float64 = 0xC,
Decimal = 0xD,
DateTime = 0xE,
Resource = 0xF,
DistributedResource = 0x10,
ResourceLink = 0x11,
String = 0x12,
Structure = 0x13,
//Stream,
//Array = 0x80,
VarArray = 0x80,
BoolArray = 0x81,
UInt8Array = 0x82,
Int8Array = 0x83,
CharArray = 0x84,
Int16Array = 0x85,
UInt16Array = 0x86,
Int32Array = 0x87,
UInt32Array = 0x88,
Int64Array = 0x89,
UInt64Array = 0x8A,
Float32Array = 0x8B,
Float64Array = 0x8C,
DecimalArray = 0x8D,
DateTimeArray = 0x8E,
ResourceArray = 0x8F,
DistributedResourceArray = 0x90,
ResourceLinkArray = 0x91,
StringArray = 0x92,
StructureArray = 0x93,
NotModified = 0x7F,
Unspecified = 0xFF;
static bool isArray(int type)
{
return ((type & 0x80) == 0x80) && (type != NotModified);
}
static int getElementType(int type)
{
return type & 0x7F;
}
static int size(int type)
{
switch (type)
{
case DataType.Void:
case DataType.NotModified:
return 0;
case DataType.Bool:
case DataType.UInt8:
case DataType.Int8:
return 1;
case DataType.Char:
case DataType.UInt16:
case DataType.Int16:
return 2;
case DataType.Int32:
case DataType.UInt32:
case DataType.Float32:
case DataType.Resource:
return 4;
case DataType.Int64:
case DataType.UInt64:
case DataType.Float64:
case DataType.DateTime:
return 8;
case DataType.DistributedResource:
return 4;
default:
return -1;
}
}
}

18
bin/Data/Guid.dart Normal file
View File

@ -0,0 +1,18 @@
import 'DC.dart';
class Guid
{
DC _data;
Guid(DC data)
{
_data = data;
}
DC get value => _data;
@override
String toString() {
return _data.getString(0, _data.length);
}
}

156
bin/Data/KeyList.dart Normal file
View File

@ -0,0 +1,156 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../Core/IEventHandler.dart';
import '../Core/IDestructible.dart';
import 'dart:collection';
import 'Codec.dart';
class KeyList<KT, T> extends IEventHandler with MapMixin<KT, T>
{
dynamic owner;
Map<KT, T> _map = new Map<KT, T>();
Iterator<KT> get iterator => _map.keys.iterator;
Iterable<KT> get keys => _map.keys;
Iterable<T> get values => _map.values;
operator[](index) => _map[index];
operator []= (index, value) => add(index, value);
at(int index) => _map.values.elementAt(index);
bool _removableList;
T take(KT key)
{
if (_map.containsKey(key))
{
var v = _map[key];
remove(key);
return v;
}
else
return null;
}
List<T> toArray() => _map.values.toList();
void add(KT key, T value)
{
if (_removableList)
if (value != null)
(value as IDestructible).on("destroy", _itemDestroyed);
if (_map.containsKey(key))
{
var oldValue = _map[key];
if (_removableList)
if (oldValue != null)
(oldValue as IDestructible).off("destroy", _itemDestroyed);
_map[key] = value;
emitArgs("modified", [key, oldValue, value, this]);
}
else
{
_map[key] = value;
emitArgs("add", [value, this]);
}
}
_itemDestroyed(T sender)
{
removeValue(sender);
}
removeValue(T value)
{
var toRemove = new List<KT>();
for (var k in _map.keys)
if (_map[k] == value)
toRemove.add(k);
for (var k in toRemove)
remove(k);
}
clear()
{
if (_removableList)
for (var v in _map.values)
(v as IDestructible)?.off("destroy", _itemDestroyed);
_map.clear();
emitArgs("cleared", [this]);
}
T remove(key)
{
if (!_map.containsKey(key))
return null;
var value = _map[key];
if (_removableList)
(value as IDestructible)?.off("destroy", _itemDestroyed);
_map.remove(key);
emitArgs("removed", [key, value, this]);
return value;
}
int get count => _map.length;
bool contains(KT key) => _map.containsKey(key);
KeyList([owner = null])
{
_removableList = Codec.implementsInterface<T, IDestructible>();
this.owner = owner;
}
}

View File

@ -0,0 +1,4 @@
class NotModified
{
}

View File

@ -0,0 +1,23 @@
class PropertyValue
{
/// <summary>
/// Get or set the value.
/// </summary>
dynamic value;
/// <summary>
/// Get or set date of modification or occurrence.
/// </summary>
DateTime date;
/// <summary>
/// Get or set property age.
/// </summary>
int age;
/// <summary>
/// Create an instance of PropertyValue.
/// </summary>
/// <param name="value">Value.</param>
/// <param name="age">Age.</param>
/// <param name="date">Date.</param>
PropertyValue(this.value, this.age, this.date);
}

View File

@ -0,0 +1,7 @@
class ResourceComparisonResult
{
static const Null = 0;
static const Distributed = 1;
static const Local = 2;
static const Same = 3;
}

4
bin/Data/SizeObject.dart Normal file
View File

@ -0,0 +1,4 @@
class SizeObject
{
int size;
}

59
bin/Data/Structure.dart Normal file
View File

@ -0,0 +1,59 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import 'dart:collection';
class Structure with MapMixin<String, Object>//, IterableMixin<String>
{
Map<String, Object> _map = new Map<String, Object>();
Iterator<String> get iterator => _map.keys.iterator;
Iterable<String> get keys => _map.keys;
operator[](index) => _map[index];
operator []= (index, value) => _map[index] = value;
remove(key) => _map.remove(key);
clear() => _map.clear();
at(int index) => _map.values.elementAt(index);
List<String> getKeys() => _map.keys.toList();
Structure.fromMap(Map map)
{
for(var i in map.keys)
_map[i.toString()] = map[i];
}
Structure()
{
// do nothing
}
}

View File

@ -0,0 +1,8 @@
class StructureComparisonResult
{
static const int Null = 0;
static const int Structure = 1;
static const int StructureSameKeys = 2;
static const int StructureSameTypes = 3;
static const int Same = 4;
}

View File

@ -0,0 +1,8 @@
class StructureMetadata
{
List<String> keys;
List<int> types;
//const StructureMetadata(this.keys, this.types);
}

View File

@ -0,0 +1,4 @@
class ValueObject
{
dynamic value;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
import 'DistributedConnection.dart';
class DistributedPropertyContext
{
dynamic value;
DistributedConnection connection;
dynamic Function(DistributedConnection) method;
DistributedPropertyContext(this.method)
{
}
DistributedPropertyContext.setter(this.value, this.connection)
{
}
}

View File

@ -0,0 +1,300 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../../Resource/IResource.dart';
import '../../Core/AsyncReply.dart';
import '../../Data/PropertyValue.dart';
import '../../Data/Structure.dart';
import '../../Data/Codec.dart';
import './DistributedConnection.dart';
import '../Packets/IIPPacketAction.dart';
class DistributedResource extends IResource
{
int _instanceId;
DistributedConnection _connection;
bool _isAttached = false;
bool _isReady = false;
String _link;
List _properties;
bool _destroyed = false;
/// <summary>
/// Connection responsible for the distributed resource.
/// </summary>
DistributedConnection get connection => _connection;
/// <summary>
/// Resource link
/// </summary>
String get link => _link;
/// <summary>
/// Instance Id given by the other end.
/// </summary>
int get id => _instanceId;
/// <summary>
/// IDestructible interface.
/// </summary>
void destroy()
{
_destroyed = true;
emitArgs("destroy", [this]);
}
/// <summary>
/// Resource is ready when all its properties are attached.
/// </summary>
bool get isReady => _isReady;
/// <summary>
/// Resource is attached when all its properties are received.
/// </summary>
bool get IsAttached => _isAttached;
// public DistributedResourceStack Stack
//{
// get { return stack; }
//}
/// <summary>
/// Create a new distributed resource.
/// </summary>
/// <param name="connection">Connection responsible for the distributed resource.</param>
/// <param name="template">Resource template.</param>
/// <param name="instanceId">Instance Id given by the other end.</param>
/// <param name="age">Resource age.</param>
DistributedResource(DistributedConnection connection, int instanceId, int age, String link)
{
this._link = link;
this._connection = connection;
this._instanceId = instanceId;
}
void _ready()
{
_isReady = true;
}
/// <summary>
/// Export all properties with ResourceProperty attributed as bytes array.
/// </summary>
/// <returns></returns>
List<PropertyValue> serialize()
{
var props = new List<PropertyValue>(_properties.length);
for (var i = 0; i < _properties.length; i++)
props[i] = new PropertyValue(_properties[i], instance.getAge(i), instance.getModificationDate(i));
return props;
}
bool attached(List<PropertyValue> properties)
{
if (_isAttached)
return false;
else
{
_properties = new List(properties.length);// object[properties.Length];
//_events = new DistributedResourceEvent[Instance.Template.Events.Length];
for (var i = 0; i < properties.length; i++)
{
instance.setAge(i, properties[i].age);
instance.setModificationDate(i, properties[i].date);
_properties[i] = properties[i].value;
}
// trigger holded events/property updates.
//foreach (var r in afterAttachmentTriggers)
// r.Key.Trigger(r.Value);
//afterAttachmentTriggers.Clear();
_isAttached = true;
}
return true;
}
void emitEventByIndex(int index, List<dynamic> args)
{
var et = instance.template.getEventTemplateByIndex(index);
//events[index]?.Invoke(this, args);
emitArgs(et.name, args);
instance.emitResourceEvent(null, null, et.name, args);
}
AsyncReply<dynamic> invokeByNamedArguments(int index, Structure namedArgs)
{
if (_destroyed)
throw new Exception("Trying to access destroyed object");
if (index >= instance.template.functions.length)
throw new Exception("Function index is incorrect");
return connection.sendInvokeByNamedArguments(_instanceId, index, namedArgs);
}
AsyncReply<dynamic> invokeByArrayArguments(int index, List<dynamic> args)
{
if (_destroyed)
throw new Exception("Trying to access destroyed object");
if (index >= instance.template.functions.length)
throw new Exception("Function index is incorrect");
return connection.sendInvokeByArrayArguments(_instanceId, index, args);
}
String _getMemberName(Symbol symbol)
{
var memberName = symbol.toString();
if (memberName.endsWith("=\")"))
return memberName.substring(8, memberName.length - 3);
else
return memberName.substring(8, memberName.length - 2);
}
@override //overring noSuchMethod
noSuchMethod(Invocation invocation)
{
var memberName = _getMemberName(invocation.memberName);
if (invocation.isMethod)
{
var ft = instance.template.getFunctionTemplateByName(memberName);
if (_isAttached && ft!=null)
{
if (invocation.namedArguments.length > 0)
{
var namedArgs = new Structure();
for(var p in invocation.namedArguments.keys)
namedArgs[_getMemberName(p)] = invocation.namedArguments[p];
return invokeByNamedArguments(ft.index, namedArgs);
}
else
{
return invokeByArrayArguments(ft.index, invocation.positionalArguments);
}
}
}
else if (invocation.isSetter)
{
var pt = instance.template.getPropertyTemplateByName(memberName);
if (pt != null)
{
set(pt.index, invocation.positionalArguments[0]);
return true;
}
}
else if (invocation.isGetter)
{
var pt = instance.template.getPropertyTemplateByName(memberName);
if (pt != null)
{
return get(pt.index);
}
}
return null;
}
/// <summary>
/// Get a property value.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <returns>Value</returns>
get(int index)
{
if (index >= _properties.length)
return null;
return _properties[index];
}
void updatePropertyByIndex(int index, dynamic value)
{
var pt = instance.template.getPropertyTemplateByIndex(index);
_properties[index] = value;
instance.emitModification(pt, value);
}
/// <summary>
/// Set property value.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Value</param>
/// <returns>Indicator when the property is set.</returns>
AsyncReply<dynamic> set(int index, dynamic value)
{
if (index >= _properties.length)
return null;
var reply = new AsyncReply<dynamic>();
var parameters = Codec.compose(value, connection);
connection.sendRequest(IIPPacketAction.SetProperty)
.addUint32(_instanceId)
.addUint8(index)
.addDC(parameters)
.done()
.then((res)
{
// not really needed, server will always send property modified,
// this only happens if the programmer forgot to emit in property setter
_properties[index] = value;
reply.trigger(null);
});
return reply;
}
}

View File

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

View File

@ -0,0 +1,5 @@
enum DistributedResourceQueueItemType
{
Propery,
Event
}

134
bin/Net/NetworkBuffer.dart Normal file
View File

@ -0,0 +1,134 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../Data/DC.dart';
import 'dart:core';
class NetworkBuffer
{
DC _data;
int _neededDataLength = 0;
NetworkBuffer()
{
_data = new DC(0);
}
bool get protected => _neededDataLength > _data.length;
int get available => _data.length;
void holdForNextWrite(DC src, int offset, int size)
{
holdFor(src, offset, size, size + 1);
}
void holdFor(DC src, int offset, int size, int needed)
{
//lock (syncLock)
//{
if (size >= needed)
throw new Exception("Size >= Needed !");
//trim = true;
_data = DC.combine(src, offset, size, _data, 0, _data.length);
_neededDataLength = needed;
//}
}
void holdForNeeded(DC src, int needed)
{
holdFor(src, 0, src.length, needed);
}
bool protect(DC data, int offset, int needed)
{
int dataLength = _data.length - offset;
// protection
if (dataLength < needed)
{
holdFor(data, offset, dataLength, needed);
return true;
}
else
return false;
}
void write(DC src, int offset, int length)
{
//lock(syncLock)
_data.append(src, offset, length);
}
bool get canRead
{
if (_data.length == 0)
return false;
if (_data.length < _neededDataLength)
return false;
return true;
}
DC read()
{
//lock (syncLock)
//{
if (_data.length == 0)
return null;
DC rt = null;
if (_neededDataLength == 0)
{
rt = _data;
_data = new DC(0);
}
else
{
if (_data.length >= _neededDataLength)
{
rt = _data;
_data = new DC(0);
_neededDataLength = 0;
return rt;
}
else
{
return null;
}
}
//}
return rt;
}
}

View File

@ -0,0 +1,198 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../Core/IDestructible.dart';
import 'Sockets/ISocket.dart';
import 'Sockets/SocketState.dart';
import 'NetworkBuffer.dart';
import '../Data/DC.dart';
import 'Sockets/IPEndPoint.dart';
class NetworkConnection extends IDestructible
{
ISocket _sock;
DateTime _lastAction;
//public delegate void DataReceivedEvent(NetworkConnection sender, NetworkBuffer data);
//public delegate void ConnectionClosedEvent(NetworkConnection sender);
//public delegate void ConnectionEstablishedEvent(NetworkConnection sender);
//public event ConnectionEstablishedEvent OnConnect;
//public event DataReceivedEvent OnDataReceived;
//public event ConnectionClosedEvent OnClose;
//public event DestroyedEvent OnDestroy;
//object receivingLock = new object();
bool _processing = false;
void destroy()
{
// if (connected)
close();
emitArgs("close", [this]);
//OnDestroy?.Invoke(this);
}
NetworkConnection()
{
}
ISocket get socket => _sock;
void assign(ISocket socket)
{
_lastAction = DateTime.now();
_sock = socket;
socket.on("receive", socket_OnReceive);
socket.on("close", socket_OnClose);
socket.on("connect", socket_OnConnect);
}
void socket_OnConnect()
{
emitArgs("connect", [this]);
}
void socket_OnClose()
{
emitArgs("close", [this]);
}
void socket_OnReceive(NetworkBuffer buffer)
{
try
{
// Unassigned ?
if (_sock == null)
return;
// Closed ?
if (_sock.state == SocketState.Closed || _sock.state == SocketState.Terminated) // || !connected)
return;
_lastAction = DateTime.now();
if (!_processing)
{
_processing = true;
try
{
while (buffer.available > 0 && !buffer.protected)
dataReceived(buffer);
}
catch(ex)
{
}
_processing = false;
}
}
catch (ex)
{
//Global.Log("NetworkConnection", LogType.Warning, ex.ToString());
}
}
ISocket unassign()
{
if (_sock != null)
{
// connected = false;
_sock.off("close", socket_OnClose);
_sock.off("connect", socket_OnConnect);
_sock.off("receive", socket_OnReceive);
var rt = _sock;
_sock = null;
return rt;
}
else
return null;
}
void dataReceived(NetworkBuffer data)
{
emitArgs("dataReceived", [data]);
}
void close()
{
try
{
if (_sock != null)
_sock.close();
}
catch(ex)
{
//Global.Log("NetworkConenction:Close", LogType.Error, ex.ToString());
}
}
DateTime get lastAction => _lastAction;
IPEndPoint get remoteEndPoint => _sock?.remoteEndPoint;
IPEndPoint get localEndPoint => _sock?.localEndPoint;
bool get connected => _sock.state == SocketState.Established;
void send(DC msg)
{
try
{
if (_sock != null)
{
_lastAction = DateTime.now();
_sock.send(msg);
}
}
catch (ex)
{
//Console.WriteLine(ex.ToString());
}
}
void sendString(String data)
{
send(DC.stringToBytes(data));
}
}

View File

@ -0,0 +1,278 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../../Data/DC.dart';
import 'IIPAuthPacketAction.dart';
import 'IIPAuthPacketCommand.dart';
import 'IIPAuthPacketMethod.dart';
class IIPAuthPacket
{
int command;
int action;
int errorCode;
String errorMessage;
int localMethod;
DC sourceInfo;
DC hash;
DC sessionId;
int remoteMethod;
String domain;
int certificateId;
String localUsername;
String remoteUsername;
DC localPassword;
DC remotePassword;
DC localToken;
DC remoteToken;
DC asymetricEncryptionKey;
DC localNonce;
DC remoteNonce;
int _dataLengthNeeded;
bool _notEnough(int offset, int ends, int needed)
{
if (offset + needed > ends)
{
_dataLengthNeeded = needed - (ends - offset);
return true;
}
else
return false;
}
toString()
{
return command.toString() + " " + action.toString();
}
int parse(DC data, int offset, int ends)
{
var oOffset = offset;
if (_notEnough(offset, ends, 1))
return -_dataLengthNeeded;
command = (data[offset] >> 6);
if (command == IIPAuthPacketCommand.Action)
{
action = (data[offset++] & 0x3f);
if (action == IIPAuthPacketAction.AuthenticateHash)
{
if (_notEnough(offset, ends, 32))
return -_dataLengthNeeded;
hash = data.clip(offset, 32);
//var hash = new byte[32];
//Buffer.BlockCopy(data, (int)offset, hash, 0, 32);
//Hash = hash;
offset += 32;
}
else if (action == IIPAuthPacketAction.NewConnection)
{
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
var length = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, length))
return -_dataLengthNeeded;
sourceInfo = data.clip(offset, length);
//var sourceInfo = new byte[length];
//Buffer.BlockCopy(data, (int)offset, sourceInfo, 0, length);
//SourceInfo = sourceInfo;
offset += 32;
}
else if (action == IIPAuthPacketAction.ResumeConnection
|| action == IIPAuthPacketAction.ConnectionEstablished)
{
//var sessionId = new byte[32];
if (_notEnough(offset, ends, 32))
return -_dataLengthNeeded;
sessionId = data.clip(offset, 32);
//Buffer.BlockCopy(data, (int)offset, sessionId, 0, 32);
//SessionId = sessionId;
offset += 32;
}
}
else if (command == IIPAuthPacketCommand.Declare)
{
remoteMethod = ((data[offset] >> 4) & 0x3);
localMethod = ((data[offset] >> 2) & 0x3);
var encrypt = ((data[offset++] & 0x2) == 0x2);
if (_notEnough(offset, ends, 1))
return -_dataLengthNeeded;
var domainLength = data[offset++];
if (_notEnough(offset, ends, domainLength))
return -_dataLengthNeeded;
var domain = data.getString(offset, domainLength);
this.domain = domain;
offset += domainLength;
if (remoteMethod == IIPAuthPacketMethod.Credentials)
{
if (localMethod == IIPAuthPacketMethod.None)
{
if (_notEnough(offset, ends, 33))
return -_dataLengthNeeded;
remoteNonce = data.clip(offset, 32);
offset += 32;
var length = data[offset++];
if (_notEnough(offset, ends, length))
return -_dataLengthNeeded;
remoteUsername = data.getString(offset, length);
offset += length;
}
}
if (encrypt)
{
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
var keyLength = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, keyLength))
return -_dataLengthNeeded;
asymetricEncryptionKey = data.clip(offset, keyLength);
offset += keyLength;
}
}
else if (command == IIPAuthPacketCommand.Acknowledge)
{
remoteMethod = ((data[offset] >> 4) & 0x3);
localMethod = ((data[offset] >> 2) & 0x3);
var encrypt = ((data[offset++] & 0x2) == 0x2);
if (_notEnough(offset, ends, 1))
return -_dataLengthNeeded;
if (remoteMethod == IIPAuthPacketMethod.Credentials)
{
if (localMethod == IIPAuthPacketMethod.None)
{
if (_notEnough(offset, ends, 32))
return -_dataLengthNeeded;
remoteNonce = data.clip(offset, 32);
offset += 32;
}
}
if (encrypt)
{
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
var keyLength = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, keyLength))
return -_dataLengthNeeded;
asymetricEncryptionKey = data.clip(offset, keyLength);
offset += keyLength;
}
}
else if (command == IIPAuthPacketCommand.Error)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
offset++;
errorCode = data[offset++];
var cl = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
errorMessage = data.getString(offset, cl);
offset += cl;
}
return offset - oOffset;
}
}

View File

@ -0,0 +1,16 @@
class IIPAuthPacketAction
{
// Authenticate
static const int AuthenticateHash = 0;
//Challenge,
//CertificateRequest,
//CertificateReply,
//EstablishRequest,
//EstablishReply
static const int NewConnection = 0x20;
static const int ResumeConnection = 0x21;
static const int ConnectionEstablished = 0x28;
}

View File

@ -0,0 +1,7 @@
class IIPAuthPacketCommand
{
static const int Action = 0;
static const int Declare = 1;
static const int Acknowledge = 2;
static const int Error = 3;
}

View File

@ -0,0 +1,8 @@
class IIPAuthPacketMethod
{
static const int None = 0;
static const int Certificate = 1;
static const int Credentials = 2;
static const int Token = 3;
}

View File

@ -0,0 +1,727 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../../Data/DC.dart';
import '../../Data/Guid.dart';
import 'IIPPacketAction.dart';
import 'IIPPacketCommand.dart';
import 'IIPPacketEvent.dart';
import 'IIPPacketReport.dart';
import '../../Data/Codec.dart';
import '../../Data/DataType.dart';
class IIPPacket
{
int report;
int command;
int action;
int event;
int previousCommand;
int previousAction;
int previousEvent;
int resourceId;
int newResourceId;
int childId;
int storeId;
int resourceAge;
DC content;
int errorCode;
String errorMessage;
String className ;
String resourceLink ;
Guid classId ;
int methodIndex ;
String methodName;
int callbackId ;
int progressValue;
int progressMax ;
DateTime fromDate ;
DateTime toDate;
int fromAge;
int toAge;
int _dataLengthNeeded;
int _originalOffset;
bool _notEnough(int offset, int ends, int needed)
{
if (offset + needed > ends)
{
//dataLengthNeeded = needed - (ends - offset);
_dataLengthNeeded = needed - (ends - _originalOffset);
return true;
}
else
return false;
}
int parse(DC data, int offset, int ends)
{
_originalOffset = offset;
if (_notEnough(offset, ends, 1))
return -_dataLengthNeeded;
previousCommand = command;
command = (data[offset] >> 6);
if (command == IIPPacketCommand.Event)
{
event = (data[offset++] & 0x3f);
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
}
else if (command == IIPPacketCommand.Report)
{
report = (data[offset++] & 0x3f);
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
callbackId = data.getUint32(offset);
offset += 4;
}
else
{
previousAction = action;
action = (data[offset++] & 0x3f);
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
callbackId = data.getUint32(offset);
offset += 4;
}
if (command == IIPPacketCommand.Event)
{
if (event == IIPPacketEvent.ResourceReassigned)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
newResourceId = data.getUint32( offset);
offset += 4;
}
else if (event == IIPPacketEvent.ResourceDestroyed)
{
// nothing to parse
}
else if (event == IIPPacketEvent.ChildAdded
|| event == IIPPacketEvent.ChildRemoved)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
childId = data.getUint32(offset);
offset += 4;
}
else if(event == IIPPacketEvent.Renamed)
{
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
var cl = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset, cl);
offset += cl;
}
else if (event == IIPPacketEvent.PropertyUpdated)
{
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
methodIndex = data[offset++];
var dt = data[offset++];
var size = DataType.size(dt);
if (size < 0)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
var cl = data.getUint32( offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip( offset - 5, cl + 5);
offset += cl;
}
else
{
if (_notEnough(offset, ends, size))
return -_dataLengthNeeded;
content = data.clip(offset - 1, size + 1);
offset += size;
}
}
else if (event == IIPPacketEvent.EventOccurred)
{
if (_notEnough(offset, ends, 5))
return -_dataLengthNeeded;
methodIndex = data[offset++];
var cl = data.getUint32( offset);
offset += 4;
content = data.clip(offset, cl);
offset += cl;
}
// Attribute
else if (event == IIPPacketEvent.AttributesUpdated)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
var cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset, cl);
offset += cl;
}
}
else if (command == IIPPacketCommand.Request)
{
if (action == IIPPacketAction.AttachResource)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
}
else if (action == IIPPacketAction.ReattachResource)
{
if (_notEnough(offset, ends, 12))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
resourceAge = data.getUint64(offset);
offset += 8;
}
else if (action == IIPPacketAction.DetachResource)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
}
else if (action == IIPPacketAction.CreateResource)
{
if (_notEnough(offset, ends, 12))
return -_dataLengthNeeded;
storeId = data.getUint32(offset);
offset += 4;
resourceId = data.getUint32(offset);
offset += 4;
var cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset, cl);
}
else if (action == IIPPacketAction.DeleteResource)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
}
else if (action == IIPPacketAction.AddChild
|| action == IIPPacketAction.RemoveChild)
{
if (_notEnough(offset, ends, 8))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
childId = data.getUint32(offset);
offset += 4;
}
else if (action == IIPPacketAction.RenameResource)
{
if (_notEnough(offset, ends, 6))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
var cl = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset, cl);
offset += cl;
}
else if (action == IIPPacketAction.TemplateFromClassName)
{
if (_notEnough(offset, ends, 1))
return -_dataLengthNeeded;
var cl = data[offset++];
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
className = data.getString(offset, cl);
offset += cl;
}
else if (action == IIPPacketAction.TemplateFromClassId)
{
if (_notEnough(offset, ends, 16))
return -_dataLengthNeeded;
classId = data.getGuid(offset);
offset += 16;
}
else if (action == IIPPacketAction.TemplateFromResourceId)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
}
else if (action == IIPPacketAction.QueryLink)
{
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
var cl = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
resourceLink = data.getString(offset, cl);
offset += cl;
}
else if (action == IIPPacketAction.ResourceChildren
|| action == IIPPacketAction.ResourceParents)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
}
else if (action == IIPPacketAction.ResourceHistory)
{
if (_notEnough(offset, ends, 20))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
fromDate = data.getDateTime(offset);
offset += 8;
toDate = data.getDateTime(offset);
offset += 8;
}
else if (action == IIPPacketAction.InvokeFunctionArrayArguments
|| action == IIPPacketAction.InvokeFunctionNamedArguments)
{
if (_notEnough(offset, ends, 9))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
methodIndex = data[offset++];
var cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset, cl);
offset += cl;
}
else if (action == IIPPacketAction.GetProperty)
{
if (_notEnough(offset, ends, 5))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
methodIndex = data[offset++];
}
else if (action == IIPPacketAction.GetPropertyIfModified)
{
if (_notEnough(offset, ends, 9))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
methodIndex = data[offset++];
resourceAge = data.getUint64(offset);
offset += 8;
}
else if (action == IIPPacketAction.SetProperty)
{
if (_notEnough(offset, ends, 6))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
methodIndex = data[offset++];
var dt = data[offset++];
var size = DataType.size(dt);
if (size < 0)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
var cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset-5, cl + 5);
offset += cl;
}
else
{
if (_notEnough(offset, ends, size))
return -_dataLengthNeeded;
content = data.clip(offset-1, size + 1);
offset += size;
}
}
// Attributes
else if (action == IIPPacketAction.UpdateAllAttributes
|| action == IIPPacketAction.GetAttributes
|| action == IIPPacketAction.UpdateAttributes
|| action == IIPPacketAction.ClearAttributes)
{
if (_notEnough(offset, ends, 8))
return -_dataLengthNeeded;
resourceId = data.getUint32(offset);
offset += 4;
var cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset, cl);
offset += cl;
}
}
else if (command == IIPPacketCommand.Reply)
{
if (action == IIPPacketAction.AttachResource
|| action == IIPPacketAction.ReattachResource)
{
if (_notEnough(offset, ends, 26))
return -_dataLengthNeeded;
classId = data.getGuid(offset);
offset += 16;
resourceAge = data.getUint64(offset);
offset += 8;
var cl = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
resourceLink = data.getString(offset, cl);
offset += cl;
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset, cl);
offset += cl;
}
else if (action == IIPPacketAction.DetachResource)
{
// nothing to do
}
else if (action == IIPPacketAction.CreateResource)
{
if (_notEnough(offset, ends, 20))
return -_dataLengthNeeded;
//ClassId = data.GetGuid(offset);
//offset += 16;
resourceId = data.getUint32(offset);
offset += 4;
}
else if (action == IIPPacketAction.DetachResource)
{
// nothing to do
}
// Inquire
else if (action == IIPPacketAction.TemplateFromClassName
|| action == IIPPacketAction.TemplateFromClassId
|| action == IIPPacketAction.TemplateFromResourceId
|| action == IIPPacketAction.QueryLink
|| action == IIPPacketAction.ResourceChildren
|| action == IIPPacketAction.ResourceParents
|| action == IIPPacketAction.ResourceHistory
// Attribute
|| action == IIPPacketAction.GetAllAttributes
|| action == IIPPacketAction.GetAttributes)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
var cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset, cl);
offset += cl;
}
else if (action == IIPPacketAction.InvokeFunctionArrayArguments
|| action == IIPPacketAction.InvokeFunctionNamedArguments
|| action == IIPPacketAction.GetProperty
|| action == IIPPacketAction.GetPropertyIfModified)
{
if (_notEnough(offset, ends, 1))
return -_dataLengthNeeded;
var dt = data[offset++];
var size = DataType.size(dt);
if (size < 0)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
var cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset - 5, cl + 5);
offset += cl;
}
else
{
if (_notEnough(offset, ends, size))
return -_dataLengthNeeded;
content = data.clip(offset - 1, size + 1);
offset += size;
}
}
else if (action == IIPPacketAction.SetProperty)
{
// nothing to do
}
}
else if (command == IIPPacketCommand.Report)
{
if (report == IIPPacketReport.ManagementError)
{
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
errorCode = data.getUint16(offset);
offset += 2;
}
else if (report == IIPPacketReport.ExecutionError)
{
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
errorCode = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, 2))
return -_dataLengthNeeded;
var cl = data.getUint16(offset);
offset += 2;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
errorMessage = data.getString(offset, cl);
offset += cl;
}
else if (report == IIPPacketReport.ProgressReport)
{
if (_notEnough(offset, ends, 8))
return -_dataLengthNeeded;
progressValue = data.getInt32(offset);
offset += 4;
progressMax = data.getInt32(offset);
offset += 4;
}
else if (report == IIPPacketReport.ChunkStream)
{
if (_notEnough(offset, ends, 1))
return -_dataLengthNeeded;
var dt = data[offset++];
var size = DataType.size(dt);
if (size < 0)
{
if (_notEnough(offset, ends, 4))
return -_dataLengthNeeded;
var cl = data.getUint32(offset);
offset += 4;
if (_notEnough(offset, ends, cl))
return -_dataLengthNeeded;
content = data.clip(offset - 5, cl + 5);
offset += cl;
}
else
{
if (_notEnough(offset, ends, size))
return -_dataLengthNeeded;
content = data.clip(offset - 1, size + 1);
offset += size;
}
}
}
return offset - _originalOffset;
}
toString()
{
var rt = command.toString();
if (command == IIPPacketCommand.Event)
{
rt += " " + event.toString();
}
else if (command == IIPPacketCommand.Request)
{
rt += " " + action.toString();
if (action == IIPPacketAction.AttachResource)
{
rt += " CID: " + callbackId.toString() + " RID: " + resourceId.toString();
}
}
else if (command == IIPPacketCommand.Reply)
rt += " " + action.toString();
else if (command == IIPPacketCommand.Report)
rt += " " + report.toString();
return rt;
}
}

View File

@ -0,0 +1,36 @@
class IIPPacketAction
{
// Request Manage
static const int AttachResource = 0x0;
static const int ReattachResource = 0x1;
static const int DetachResource = 0x2;
static const int CreateResource = 0x3;
static const int DeleteResource = 0x4;
static const int AddChild = 0x5;
static const int RemoveChild = 0x6;
static const int RenameResource = 0x7;
// Request Inquire
static const int TemplateFromClassName = 0x8;
static const int TemplateFromClassId = 0x9;
static const int TemplateFromResourceId = 0xA;
static const int QueryLink = 0xB;
static const int ResourceHistory = 0xC;
static const int ResourceChildren = 0xD;
static const int ResourceParents = 0xE;
// Request Invoke
static const int InvokeFunctionArrayArguments = 0x10;
static const int GetProperty = 0x11;
static const int GetPropertyIfModified = 0x12;
static const int SetProperty = 0x13;
static const int InvokeFunctionNamedArguments = 0x14;
// Request Attribute
static const int GetAllAttributes = 0x18;
static const int UpdateAllAttributes = 0x19;
static const int ClearAllAttributes = 0x1A;
static const int GetAttributes = 0x1B;
static const int UpdateAttributes = 0x1C;
static const int ClearAttributes = 0x1D;
}

View File

@ -0,0 +1,7 @@
class IIPPacketCommand
{
static const int Event = 0;
static const int Request = 1;
static const int Reply = 2;
static const int Report = 3;
}

View File

@ -0,0 +1,15 @@
class IIPPacketEvent
{
// Event Manage
static const int ResourceReassigned = 0;
static const int ResourceDestroyed = 1;
static const int ChildAdded = 2;
static const int ChildRemoved = 3;
static const int Renamed = 4;
// Event Invoke
static const int PropertyUpdated = 0x10;
static const int EventOccurred = 0x11;
// Attribute
static const int AttributesUpdated = 0x18;
}

View File

@ -0,0 +1,7 @@
class IIPPacketReport
{
static const int ManagementError = 0;
static const int ExecutionError = 1;
static const int ProgressReport = 0x8;
static const int ChunkStream = 0x9;
}

22
bin/Net/SendList.dart Normal file
View File

@ -0,0 +1,22 @@
import '../Data/BinaryList.dart';
import '../Core/AsyncReply.dart';
import 'NetworkConnection.dart';
class SendList extends BinaryList
{
NetworkConnection connection;
AsyncReply<List<dynamic>> reply;
SendList(NetworkConnection connection, AsyncReply<List<dynamic>> reply)
{
this.reply = reply;
this.connection = connection;
}
@override
AsyncReply<List<dynamic>> done()
{
connection.send(super.toDC());
return reply;
}
}

View File

@ -0,0 +1,25 @@
class IPEndPoint
{
List<int> ip;
int port;
String getIP()
{
return ip.join(".");
//return "${(ip >> 24) & 0xFF}.${(ip >> 16) & 0xFF}.${(ip >> 8) & 0xFF}.${ip & 0xFF}";
}
String get address => getIP();
@override
String toString() {
return "${getIP()}:${port}";
}
IPEndPoint(this.ip, this.port)
{
}
}

View File

@ -0,0 +1,47 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../../Core/IDestructible.dart';
import '../../Data/DC.dart';
import 'IPEndPoint.dart';
import '../../Core/AsyncReply.dart';
import 'SocketState.dart';
abstract class ISocket extends IDestructible
{
SocketState get state ; //{ get; }
//event ISocketReceiveEvent OnReceive;
//event ISocketConnectEvent OnConnect;
//event ISocketCloseEvent OnClose;
//void send(DC message);
void send(DC message, [int offset, int size]);
void close();
AsyncReply<bool> connect(String hostname, int port);
bool begin();
AsyncReply<ISocket> accept();
IPEndPoint remoteEndPoint;
IPEndPoint localEndPoint;
}

View File

@ -0,0 +1,9 @@
enum SocketState
{
Initial,
Listening,
Connecting,
Established,
Closed,
Terminated
}

View File

@ -0,0 +1,212 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import 'dart:io';
import 'ISocket.dart';
import '../../Data/DC.dart';
import '../NetworkBuffer.dart';
import 'SocketState.dart';
import 'IPEndPoint.dart';
import '../../Core/AsyncReply.dart';
class TCPSocket extends ISocket
{
Socket sock;
NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
//bool asyncSending;
bool began = false;
SocketState _state = SocketState.Initial;
//public event ISocketReceiveEvent OnReceive;
//public event ISocketConnectEvent OnConnect;
//public event ISocketCloseEvent OnClose;
//public event DestroyedEvent OnDestroy;
//SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs();
/*
void connected(Task t)
{
state = SocketState.Established;
OnConnect?.Invoke();
Begin();
}
*/
IPEndPoint _localEP, _remoteEP;
bool begin()
{
if (began)
return false;
began = true;
_localEP = IPEndPoint(sock.address.rawAddress, sock.port);
_remoteEP = IPEndPoint(sock.remoteAddress.rawAddress, sock.remotePort);
return true;
}
void dataHandler(List<int> data){
//print(new String.fromCharCodes(data).trim());
try
{
if (_state == SocketState.Closed || _state == SocketState.Terminated)
return;
var dc = new DC.fromList(data);
receiveNetworkBuffer.write(dc, 0, dc.length);
emitArgs("receive", [receiveNetworkBuffer]);
}
catch (ex)
{
if (_state != SocketState.Closed)// && !sock.connected)
{
_state = SocketState.Terminated;
close();
}
}
}
void errorHandler(error, StackTrace trace){
print(error);
}
void doneHandler(){
sock.destroy();
}
AsyncReply<bool> connect(String hostname, int port)
{
var rt = new AsyncReply<bool>();
try
{
_state = SocketState.Connecting;
Socket.connect(hostname, port).then((s){
sock = s;
s.listen(dataHandler,
onError: errorHandler,
onDone: doneHandler,
cancelOnError: false);
_state = SocketState.Established;
emitArgs("connect", []);
begin();
rt.trigger(true);
}).catchError((ex){
close();
rt.triggerError(ex);
});
}
catch(ex)
{
rt.triggerError(ex);
}
return rt;
}
IPEndPoint get localEndPoint => _localEP;
IPEndPoint get remoteEndPoint => _remoteEP;
SocketState get state => _state;
TCPSocket.fromSocket(Socket socket)
{
sock = socket;
//if (socket.)
// _state = SocketState.Established;
}
TCPSocket()
{
// default constructor
}
void close()
{
if (state != SocketState.Closed && state != SocketState.Terminated)
_state = SocketState.Closed;
sock?.close();
emitArgs("close", []);
}
void send(DC message, [int offset, int size])
{
if (state == SocketState.Established)
sock.add(message.toList());
}
void destroy()
{
close();
emitArgs("destroy", [this]);
}
AsyncReply<ISocket> accept()
{
var reply = new AsyncReply<ISocket>();
return reply;
/*
ServerSocket.bind(InternetAddress.ANY_IP_V4, 4567).then(
(ServerSocket server) {
server.listen(handleClient);
}
);
void handleClient(Socket client){
print('Connection from '
'${client.remoteAddress.address}:${client.remotePort}');
client.write("Hello from simple server!\n");
client.close();
}
*/
}
}

View File

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

43
bin/Resource/IStore.dart Normal file
View File

@ -0,0 +1,43 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import './IResource.dart';
import '../Core/AsyncReply.dart';
import '../Data/KeyList.dart';
import './Template/PropertyTemplate.dart';
import '../Data/PropertyValue.dart';
abstract class IStore extends IResource
{
AsyncReply<IResource> get(String path);
AsyncReply<IResource> retrieve(int iid);
bool put(IResource resource);
String link(IResource resource);
bool record(IResource resource, String propertyName, dynamic value, int age, DateTime dateTime);
bool modify(IResource resource, String propertyName, dynamic value, int age, DateTime dateTime);
bool remove(IResource resource);
AsyncReply<KeyList<PropertyTemplate, List<PropertyValue>>> getRecord(IResource resource, DateTime fromDate, DateTime toDate);
}

680
bin/Resource/Instance.dart Normal file
View File

@ -0,0 +1,680 @@
import 'dart:core';
import '../Data/DC.dart';
import '../Data/Structure.dart';
import '../Data/AutoList.dart';
import './IStore.dart';
import './IResource.dart';
import '../Data/KeyList.dart';
import './StorageMode.dart';
import '../Data/ValueObject.dart';
import '../Core/IEventHandler.dart';
import '../Security/Permissions/Ruling.dart';
import '../Security/Permissions/IPermissionsManager.dart';
import '../Security/Permissions/ActionType.dart';
import './Template/ResourceTemplate.dart';
import './Template/PropertyTemplate.dart';
import './Template/FunctionTemplate.dart';
import './Template/EventTemplate.dart';
import '../Security/Authority/Session.dart';
import './Template/MemberTemplate.dart';
import '../Data/PropertyValue.dart';
import 'Warehouse.dart';
class Instance extends IEventHandler
{
String _name;
AutoList<IResource, Instance> _children;
IResource _resource;
IStore _store;
AutoList<IResource, Instance> _parents;
//bool inherit;
ResourceTemplate _template;
AutoList<IPermissionsManager, Instance> _managers;
KeyList<String, dynamic> _attributes;
List<int> _ages = new List<int>();
List<DateTime> _modificationDates = new List<DateTime>();
int _instanceAge;
DateTime _instanceModificationDate;
int _id;
/// <summary>
/// Instance attributes are custom properties associated with the instance, a place to store information by IStore.
/// </summary>
KeyList<String, dynamic> get attributes => _attributes;
@override
String toString() => _name + " (" + link + ")";
bool removeAttributes([List<String> attributes = null])
{
if (attributes == null)
this._attributes.clear();
else
{
for (var attr in attributes)
this.attributes.remove(attr);
}
return true;
}
Structure getAttributes([List<String> attributes = null])
{
var st = new Structure();
if (attributes == null)
{
var clone = this.attributes.keys.toList();
clone.add("managers");
attributes = clone.toList();
}
for(var attr in attributes)
{
if (attr == "name")
st["name"] = _name;
else if (attr == "managers")
{
var mngrs = new List<Structure>();
for (var i = 0; i < _managers.length; i++)
{
var mst = new Structure();
mst["type"] = _managers[i].runtimeType;
mst["settings"] = _managers[i].settings;
mngrs.add(mst);
}
st["managers"] = mngrs;
}
else if (attr == "parents")
{
st["parents"] = _parents.toList();
}
else if (attr == "children")
{
st["children"] = _children.toList();
}
else if (attr == "childrenCount")
{
st["childrenCount"] = _children.count;
}
else if (attr == "type")
{
st["type"] = resource.runtimeType;
}
else
st[attr] = _attributes[attr];
}
return st;
}
bool setAttributes(Structure attributes, [bool clearAttributes = false])
{
try
{
if (clearAttributes)
_attributes.clear();
for (var attrKey in attributes.keys)
if (attrKey == "name")
_name = attributes[attrKey];
else if (attrKey == "managers")
{
_managers.clear();
var mngrs = attributes[attrKey] as List;
// this is not implemented now, Flutter doesn't support mirrors, needs a workaround @ Warehouse.registerManager
/*
for (var mngr in mngrs)
{
var m = mngr as Structure;
var type = Type.GetType(m["type"] as string);
if (Codec.implementsInterface<type, typeof(IPermissionsManager)))
{
var settings = m["settings"] as Structure;
var manager = Activator.CreateInstance(type) as IPermissionsManager;
manager.Initialize(settings, this.resource);
this.managers.Add(manager);
}
else
return false;
}
*/
}
else
{
_attributes[attrKey] = attributes[attrKey];
}
}
catch(ex)
{
return false;
}
return true;
}
/*
public Structure GetAttributes()
{
var st = new Structure();
foreach (var a in attributes.Keys)
st[a] = attributes[a];
st["name"] = name;
var mngrs = new List<Structure>();
foreach (var manager in managers)
{
var mngr = new Structure();
mngr["settings"] = manager.Settings;
mngr["type"] = manager.GetType().FullName;
mngrs.Add(mngr);
}
st["managers"] = mngrs;
return st;
}*/
/// <summary>
/// Get the age of a given property index.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <returns>Age.</returns>
int getAge(int index)
{
if (index < _ages.length)
return _ages[index];
else
return 0;
}
/// <summary>
/// Set the age of a property.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Age.</param>
void setAge(int index, int value)
{
if (index < _ages.length)
{
_ages[index] = value;
if (value > _instanceAge)
_instanceAge = value;
}
}
/// <summary>
/// Set the modification date of a property.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Modification date.</param>
void setModificationDate(int index, DateTime value)
{
if (index < _modificationDates.length)
{
_modificationDates[index] = value;
if (_instanceModificationDate == null || value.millisecondsSinceEpoch > _instanceModificationDate.millisecondsSinceEpoch)
_instanceModificationDate = value;
}
}
/// <summary>
/// Get modification date of a specific property.
/// </summary>
/// <param name="index">Zero-based property index</param>
/// <returns>Modification date.</returns>
DateTime getModificationDate(int index)
{
if (index < _modificationDates.length)
return _modificationDates[index];
else
return new DateTime(0);
}
/// <summary>
/// Load property value (used by stores)
/// </summary>
/// <param name="name">Property name</param>
/// <param name="age">Property age</param>
/// <param name="value">Property value</param>
/// <returns></returns>
bool loadProperty(String name, int age, DateTime modificationDate, dynamic value)
{
/*
var pt = _template.getPropertyTemplate(name);
if (pt == null)
return false;
if (pt.info.propertyType == typeof(DistributedPropertyContext))
return false;
try
{
if (pt.into.canWrite)
pt.info.setValue(resource, DC.CastConvert(value, pt.Info.PropertyType));
}
catch(ex)
{
//
}
setAge(pt.index, age);
setModificationDate(pt.index, modificationDate);
*/
return true;
}
/// <summary>
/// Age of the instance, incremented by 1 in every modification.
/// </summary>
int get age => _instanceAge;
// this must be internal
set age (value) => _instanceAge = value;
/// <summary>
/// Last modification date.
/// </summary>
DateTime get modificationDate => _instanceModificationDate;
/// <summary>
/// Instance Id.
/// </summary>
int get id => _id;
/// <summary>
/// Import properties from bytes array.
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
bool deserialize(List<PropertyValue> properties)
{
for (var i = 0; i < properties.length; i++)
{
var pt = _template.getPropertyTemplateByIndex(i);
if (pt != null)
{
var pv = properties[i];
loadProperty(pt.name, pv.age, pv.date, pv.value);
}
}
return true;
}
/// <summary>
/// Export all properties with ResourceProperty attributed as bytes array.
/// </summary>
/// <returns></returns>
List<PropertyValue> serialize()
{
List<PropertyValue> props = new List<PropertyValue>();
for (var pt in _template.properties)
{
// var rt = pt.info.getValue(resource, null);
// props.add(new PropertyValue(rt, _ages[pt.index], _modificationDates[pt.index]));
}
return props;
}
/*
public bool Deserialize(byte[] data, uint offset, uint length)
{
var props = Codec.ParseValues(data, offset, length);
Deserialize(props);
return true;
}
*/
/*
public byte[] Serialize(bool includeLength = false, DistributedConnection sender = null)
{
//var bl = new BinaryList();
List<object> props = new List<object>();
foreach (var pt in template.Properties)
{
var pi = resource.GetType().GetProperty(pt.Name);
var rt = pi.GetValue(resource, null);
// this is a cool hack to let the property know the sender
if (rt is Func<DistributedConnection, object>)
rt = (rt as Func<DistributedConnection, object>)(sender);
props.Add(rt);
}
if (includeLength)
{
return Codec.Compose(props.ToArray(), false);
}
else
{
var rt = Codec.Compose(props.ToArray(), false);
return DC.Clip(rt, 4, (uint)(rt.Length - 4));
}
}
public byte[] StorageSerialize()
{
var props = new List<object>();
foreach(var pt in template.Properties)
{
if (!pt.Storable)
continue;
var pi = resource.GetType().GetProperty(pt.Name);
if (!pi.CanWrite)
continue;
var rt = pi.GetValue(resource, null);
props.Add(rt);
}
return Codec.Compose(props.ToArray(), false);
}
*/
/// <summary>
/// If True, the instance can be stored to disk.
/// </summary>
/// <returns></returns>
bool isStorable()
{
return false;
}
void emitModification(PropertyTemplate pt, dynamic value)
{
_instanceAge++;
var now = DateTime.now().toUtc();
_ages[pt.index] = _instanceAge;
_modificationDates[pt.index] = now;
if (pt.storage == StorageMode.NonVolatile)
{
_store.modify(_resource, pt.name, value, _ages[pt.index], now);
}
else if (pt.storage == StorageMode.Recordable)
{
_store.record(_resource, pt.name, value, _ages[pt.index], now);
}
emitArgs("resourceModified", [_resource, pt.name, value]);
}
/// <summary>
/// Notify listeners that a property was modified.
/// </summary>
/// <param name="propertyName"></param>
/// <param name="newValue"></param>
/// <param name="oldValue"></param>
modified(String propertyName)
{
var valueObject = new ValueObject();
if (getPropertyValue(propertyName, valueObject))
{
var pt = _template.getPropertyTemplateByName(propertyName);
emitModification(pt, valueObject.value);
}
}
emitResourceEvent(issuer, List<Session> receivers, String name, List<dynamic> args)
{
emitArgs("resourceEventOccurred", [_resource, issuer, receivers, name, args]);
}
/// <summary>
/// Get the value of a given property by name.
/// </summary>
/// <param name="name">Property name</param>
/// <param name="value">Output value</param>
/// <returns>True, if the resource has the property.</returns>
bool getPropertyValue(String name, ValueObject valueObject)
{
var pt = _template.getPropertyTemplateByName(name);
/*
if (pt != null && pt.info != null)
{
valueObject.value = pt.info.getValue(_resource, null);
return true;
}*/
valueObject.value = null;
return false;
}
/*
public bool Inherit
{
get { return inherit; }
}*/
/// <summary>
/// List of parents.
/// </summary>
AutoList<IResource, Instance> get parents => _parents;
/// <summary>
/// Store responsible for creating and keeping the resource.
/// </summary>
IStore get store => _store;
/// <summary>
/// List of children.
/// </summary>
AutoList<IResource, Instance> get children => _children;
/// <summary>
/// The unique and permanent link to the resource.
/// </summary>
String get link
{
if (_store != null)
return _store.link(_resource);
else
{
var l = new List<String>();
var p = _resource;
while (true)
{
l.insert(0, p.instance.name);
if (p.instance.parents.count == 0)
break;
p = p.instance.parents.first();
}
return l.join("/");
}
}
/// <summary>
/// Instance name.
/// </summary>
String get name => _name;
set name(value) => name = value;
/// <summary>
/// Resource managed by this instance.
/// </summary>
IResource get resource => _resource;
/// <summary>
/// Resource template describes the properties, functions and events of the resource.
/// </summary>
ResourceTemplate get template => _template;
/// <summary>
/// Check for permission.
/// </summary>
/// <param name="session">Caller sessions.</param>
/// <param name="action">Action type</param>
/// <param name="member">Function, property or event to check for permission.</param>
/// <param name="inquirer">Permission inquirer.</param>
/// <returns>Ruling.</returns>
Ruling applicable(Session session, ActionType action, MemberTemplate member, [dynamic inquirer = null])
{
for(var i = 0; i < _managers.length; i++)
{
var r = _managers[i].applicable(this.resource, session, action, member, inquirer);
if (r != Ruling.DontCare)
return r;
}
return Ruling.DontCare;
}
/// <summary>
/// Execution managers.
/// </summary>
AutoList<IPermissionsManager, Instance> get managers => _managers;
/// <summary>
/// Create new instance.
/// </summary>
/// <param name="id">Instance Id.</param>
/// <param name="name">Name of the instance.</param>
/// <param name="resource">Resource to manage.</param>
/// <param name="store">Store responsible for the resource.</param>
Instance(int id, String name, IResource resource, IStore store, [ResourceTemplate customTemplate = null, int age = 0])
{
_store = store;
_resource = resource;
_id = id;
_name = name;
_instanceAge = age;
_attributes = new KeyList<String, dynamic>(this);
_children = new AutoList<IResource, Instance>(this);
_parents = new AutoList<IResource, Instance>(this);
_managers = new AutoList<IPermissionsManager, Instance>(this);
_children.on("add", children_OnAdd);
_children.on("remove", children_OnRemoved);
_parents.on("add", parents_OnAdd);
_parents.on("remove", parents_OnRemoved);
resource.on("destroy", resource_OnDestroy);
if (customTemplate != null)
_template = customTemplate;
else
_template = Warehouse.getTemplateByType(resource.runtimeType);
// set ages
for (int i = 0; i < _template.properties.length; i++)
{
_ages.add(0);
_modificationDates.add(new DateTime(0));//DateTime.MinValue);
}
/*
// connect events
Type t = resource.runtimeType;
var events = t.GetTypeInfo().GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach (var evt in events)
{
//if (evt.EventHandlerType != typeof(ResourceEventHanlder))
// continue;
if (evt.EventHandlerType == typeof(ResourceEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
ResourceEventHanlder proxyDelegate = (args) => EmitResourceEvent(null, null, evt.Name, args);
evt.AddEventHandler(resource, proxyDelegate);
}
else if (evt.EventHandlerType == typeof(CustomResourceEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
CustomResourceEventHanlder proxyDelegate = (issuer, receivers, args) => EmitResourceEvent(issuer, receivers, evt.Name, args);
evt.AddEventHandler(resource, proxyDelegate);
}
}
*/
}
void children_OnRemoved(Instance parent, IResource value)
{
value.instance.parents.remove(_resource);
}
void children_OnAdd(Instance parent, IResource value)
{
if (!value.instance.parents.contains(_resource))
value.instance.parents.add(_resource);
}
void parents_OnRemoved(Instance parent, IResource value)
{
value.instance.children.remove(_resource);
}
void parents_OnAdd(Instance parent, IResource value)
{
if (!value.instance.children.contains(_resource))
value.instance.children.add(_resource);
}
void resource_OnDestroy(sender)
{
emitArgs("resourceDestroyed", [sender]);
}
}

View File

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

View File

@ -0,0 +1,6 @@
class StorageMode
{
static const NonVolatile = 0;
static const Volatile = 1;
static const Recordable = 2;
}

View File

@ -0,0 +1,45 @@
import 'MemberTemplate.dart';
import '../../Data/DC.dart';
import '../../Data/BinaryList.dart';
import 'ResourceTemplate.dart';
import 'MemberType.dart';
class EventTemplate extends MemberTemplate
{
String expansion;
DC compose()
{
var name = super.compose();
if (expansion != null)
{
var exp = DC.stringToBytes(expansion);
return new BinaryList()
.addUint8(0x50)
.addInt32(exp.length)
.addDC(exp)
.addUint8(name.length)
.addDC(name)
.toDC();
}
else
{
return new BinaryList()
.addUint8(0x40)
.addUint8(name.length)
.addDC(name)
.toDC();
}
}
EventTemplate(ResourceTemplate template, int index, String name, String expansion)
: super(template, MemberType.Property, index, name)
{
this.expansion = expansion;
}
}

View File

@ -0,0 +1,42 @@
import 'MemberTemplate.dart';
import '../../Data/DC.dart';
import '../../Data/BinaryList.dart';
import 'ResourceTemplate.dart';
import 'MemberType.dart';
class FunctionTemplate extends MemberTemplate
{
String expansion;
bool isVoid;
DC compose()
{
var name = super.compose();
if (expansion != null)
{
var exp = DC.stringToBytes(expansion);
return new BinaryList().addUint8((0x10 | (isVoid ? 0x8 : 0x0)))
.addUint8(name.length)
.addDC(name)
.addInt32(exp.length)
.addDC(exp)
.toDC();
}
else
return new BinaryList().addUint8((isVoid ? 0x8 : 0x0))
.addUint8(name.length)
.addDC(name)
.toDC();
}
FunctionTemplate(ResourceTemplate template, int index, String name, bool isVoid, String expansion)
:super(template, MemberType.Property, index, name)
{
this.isVoid = isVoid;
this.expansion = expansion;
}
}

View File

@ -0,0 +1,34 @@
import 'MemberType.dart';
import '../../Data/DC.dart';
import './ResourceTemplate.dart';
class MemberTemplate
{
int get index => _index;
String get name => _name;
MemberType get type => _type;
ResourceTemplate _template;
String _name;
MemberType _type;
int _index;
ResourceTemplate get template => _template;
MemberTemplate(ResourceTemplate template, MemberType type, int index, String name)
{
this._template = template;
this._type = type;
this._index = index;
this._name = name;
}
String get fullname => _template.className + "." + _name;
DC compose()
{
// return DC.ToBytes(Name);
}
}

View File

@ -0,0 +1,6 @@
enum MemberType
{
Function,// = 0,
Property,// = 1,
Event// = 2,
}

View File

@ -0,0 +1,6 @@
class PropertyPermission
{
static const int Read = 1;
static const int Write = 2;
static const int ReadWrite = 3;
}

View File

@ -0,0 +1,80 @@
import 'MemberTemplate.dart';
import '../../Data/DC.dart';
import '../../Data/BinaryList.dart';
import 'ResourceTemplate.dart';
import 'MemberType.dart';
import 'PropertyPermission.dart';
import '../StorageMode.dart';
class PropertyTemplate extends MemberTemplate
{
int permission;
int storage;
String readExpansion;
String writeExpansion;
DC compose()
{
var name = super.compose();
var pv = ((permission) << 1) | (storage == StorageMode.Recordable ? 1 : 0);
if (writeExpansion != null && readExpansion != null)
{
var rexp = DC.stringToBytes(readExpansion);
var wexp = DC.stringToBytes(writeExpansion);
return new BinaryList()
.addUint8(0x38 | pv)
.addUint8(name.length)
.addDC(name)
.addInt32(wexp.length)
.addDC(wexp)
.addInt32(rexp.length)
.addDC(rexp)
.toDC();
}
else if (writeExpansion != null)
{
var wexp = DC.stringToBytes(writeExpansion);
return new BinaryList()
.addUint8(0x30 | pv)
.addUint8(name.length)
.addDC(name)
.addInt32(wexp.length)
.addDC(wexp)
.toDC();
}
else if (readExpansion != null)
{
var rexp = DC.stringToBytes(readExpansion);
return new BinaryList()
.addUint8(0x28 | pv)
.addUint8(name.length)
.addDC(name)
.addInt32(rexp.length)
.addDC(rexp)
.toDC();
}
else
return new BinaryList()
.addUint8(0x20 | pv)
.addUint8(name.length)
.addDC(name)
.toDC();
}
PropertyTemplate(ResourceTemplate template, int index, String name, String read, String write, int storage)
:super(template, MemberType.Property, index, name)
{
//this.Recordable = recordable;
this.storage = storage;
this.readExpansion = read;
this.writeExpansion = write;
}
}

View File

@ -0,0 +1,330 @@
import './MemberTemplate.dart';
import '../../Data/Guid.dart';
import '../../Data/DC.dart';
import './EventTemplate.dart';
import './PropertyTemplate.dart';
import './FunctionTemplate.dart';
import '../StorageMode.dart';
class ResourceTemplate
{
Guid _classId;
String _className;
List<MemberTemplate> _members = new List<MemberTemplate>();
List<FunctionTemplate> _functions = new List<FunctionTemplate>();
List<EventTemplate> _events = new List<EventTemplate>();
List<PropertyTemplate> _properties = new List<PropertyTemplate>();
int _version;
//bool isReady;
DC _content;
DC get content => _content;
/*
MemberTemplate getMemberTemplate(MemberInfo member)
{
if (member is MethodInfo)
return getFunctionTemplate(member.Name);
else if (member is EventInfo)
return getEventTemplate(member.Name);
else if (member is PropertyInfo)
return getPropertyTemplate(member.Name);
else
return null;
}
*/
EventTemplate getEventTemplateByName(String eventName)
{
for (var i in _events)
if (i.name == eventName)
return i;
return null;
}
EventTemplate getEventTemplateByIndex(int index)
{
for (var i in _events)
if (i.index == index)
return i;
return null;
}
FunctionTemplate getFunctionTemplateByName(String functionName)
{
for (var i in _functions)
if (i.name == functionName)
return i;
return null;
}
FunctionTemplate getFunctionTemplateByIndex(int index)
{
for (var i in _functions)
if (i.index == index)
return i;
return null;
}
PropertyTemplate getPropertyTemplateByIndex(int index)
{
for (var i in _properties)
if (i.index == index)
return i;
return null;
}
PropertyTemplate getPropertyTemplateByName(String propertyName)
{
for (var i in _properties)
if (i.name == propertyName)
return i;
return null;
}
Guid get classId => _classId;
String get className => _className;
List<MemberTemplate> get methods => _members;
List<FunctionTemplate> get functions => _functions;
List<EventTemplate> get events => _events;
List<PropertyTemplate> get properties => _properties;
ResourceTemplate()
{
}
ResourceTemplate.fromType(Type type)
{
}
/*
ResourceTemplate(Type type)
{
type = ResourceProxy.GetBaseType(type);
// set guid
var typeName = Encoding.UTF8.GetBytes(type.FullName);
var hash = SHA256.Create().ComputeHash(typeName).Clip(0, 16);
classId = new Guid(hash);
className = type.FullName;
#if NETSTANDARD1_5
PropertyInfo[] propsInfo = type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
EventInfo[] eventsInfo = type.GetTypeInfo().GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
MethodInfo[] methodsInfo = type.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
#else
PropertyInfo[] propsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
EventInfo[] eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
#endif
//byte currentIndex = 0;
byte i = 0;
foreach (var pi in propsInfo)
{
var ps = (ResourceProperty[])pi.GetCustomAttributes(typeof(ResourceProperty), true);
if (ps.Length > 0)
{
var pt = new PropertyTemplate(this, i++, pi.Name, ps[0].ReadExpansion, ps[0].WriteExpansion, ps[0].Storage);
pt.Info = pi;
properties.Add(pt);
}
}
i = 0;
foreach (var ei in eventsInfo)
{
var es = (ResourceEvent[])ei.GetCustomAttributes(typeof(ResourceEvent), true);
if (es.Length > 0)
{
var et = new EventTemplate(this, i++, ei.Name, es[0].Expansion);
events.Add(et);
}
}
i = 0;
foreach (MethodInfo mi in methodsInfo)
{
var fs = (ResourceFunction[])mi.GetCustomAttributes(typeof(ResourceFunction), true);
if (fs.Length > 0)
{
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void), fs[0].Expansion);
functions.Add(ft);
}
}
// append signals
for (i = 0; i < events.Count; i++)
members.Add(events[i]);
// append slots
for (i = 0; i < functions.Count; i++)
members.Add(functions[i]);
// append properties
for (i = 0; i < properties.Count; i++)
members.Add(properties[i]);
// bake it binarily
var b = new BinaryList();
b.AddGuid(classId)
.AddUInt8((byte)className.Length)
.AddString(className)
.AddInt32(version)
.AddUInt16((ushort)members.Count);
foreach (var ft in functions)
b.AddUInt8Array(ft.Compose());
foreach (var pt in properties)
b.AddUInt8Array(pt.Compose());
foreach (var et in events)
b.AddUInt8Array(et.Compose());
content = b.ToArray();
}
*/
ResourceTemplate.parse(DC data, [int offset = 0, int contentLength])
{
// cool Dart feature
contentLength ??= data.length;
int ends = offset + contentLength;
int oOffset = offset;
// start parsing...
//var od = new ResourceTemplate();
_content = data.clip(offset, contentLength);
_classId = data.getGuid(offset);
offset += 16;
_className = data.getString(offset + 1, data[offset]);
offset += data[offset] + 1;
_version = data.getInt32(offset);
offset += 4;
var methodsCount = data.getUint16(offset);
offset += 2;
var functionIndex = 0;
var propertyIndex = 0;
var eventIndex = 0;
for (int i = 0; i < methodsCount; i++)
{
var type = data[offset] >> 5;
if (type == 0) // function
{
String expansion = null;
var hasExpansion = ((data[offset] & 0x10) == 0x10);
var isVoid = ((data[offset++] & 0x08) == 0x08);
var name = data.getString(offset + 1, data[offset]);
offset += data[offset] + 1;
if (hasExpansion) // expansion ?
{
var cs = data.getUint32(offset);
offset += 4;
expansion = data.getString(offset, cs);
offset += cs;
}
var ft = new FunctionTemplate(this, functionIndex++, name, isVoid, expansion);
_functions.add(ft);
}
else if (type == 1) // property
{
String readExpansion = null, writeExpansion = null;
var hasReadExpansion = ((data[offset] & 0x8) == 0x8);
var hasWriteExpansion = ((data[offset] & 0x10) == 0x10);
var recordable = ((data[offset] & 1) == 1);
var permission = (data[offset++] >> 1) & 0x3;
var name = data.getString(offset + 1, data[offset]);
offset += data[offset] + 1;
if (hasReadExpansion) // expansion ?
{
var cs = data.getUint32(offset);
offset += 4;
readExpansion = data.getString(offset, cs);
offset += cs;
}
if (hasWriteExpansion) // expansion ?
{
var cs = data.getUint32(offset);
offset += 4;
writeExpansion = data.getString(offset, cs);
offset += cs;
}
var pt = new PropertyTemplate(this, propertyIndex++, name, readExpansion, writeExpansion, recordable ? StorageMode.Recordable : StorageMode.Volatile);
_properties.add(pt);
}
else if (type == 2) // Event
{
String expansion = null;
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
var name = data.getString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
offset += data[offset] + 1;
if (hasExpansion) // expansion ?
{
var cs = data.getUint32(offset);
offset += 4;
expansion = data.getString(offset, cs);
offset += cs;
}
var et = new EventTemplate(this, eventIndex++, name, expansion);
_events.add(et);
}
}
// append signals
for (int i = 0; i < _events.length; i++)
_members.add(_events[i]);
// append slots
for (int i = 0; i < _functions.length; i++)
_members.add(_functions[i]);
// append properties
for (int i = 0; i < _properties.length; i++)
_members.add(_properties[i]);
}
}

458
bin/Resource/Warehouse.dart Normal file
View File

@ -0,0 +1,458 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../Data/AutoList.dart';
import './Template/ResourceTemplate.dart';
import '../Data/Guid.dart';
import '../Data/KeyList.dart';
import '../Data/Structure.dart';
import '../Security/Permissions/IPermissionsManager.dart';
import 'IResource.dart';
import 'Instance.dart';
import 'IStore.dart';
import '../Core/AsyncReply.dart';
import '../Core/AsyncBag.dart';
import 'ResourceTrigger.dart';
import '../Net/IIP/DistributedConnection.dart';
// Centeral Resource Issuer
class Warehouse
{
static AutoList<IResource, Instance> _stores = new AutoList<IResource, Instance>(null);
static Map<int, IResource> _resources = new Map<int, IResource>();
static int resourceCounter = 0;
static KeyList<Guid, ResourceTemplate> _templates = new KeyList<Guid, ResourceTemplate>();
static bool storeIsOpen = false;
//public delegate void StoreConnectedEvent(IStore store, string name);
//public delegate void StoreDisconnectedEvent(IStore store);
//public static event StoreConnectedEvent StoreConnected;
///public static event StoreDisconnectedEvent StoreDisconnected;
static KeyList<String, IStore Function()> protocols = getProtocols();
/// <summary>
/// Get a store by its name.
/// </summary>
/// <param name="name">Store instance name</param>
/// <returns></returns>
static IStore getStore(String name)
{
for(var s in _stores)
if (s.instance.name == name)
return s;
return null;
}
/// <summary>
/// Get a resource by instance Id.
/// </summary>
/// <param name="id">Instance Id</param>
/// <returns></returns>
static AsyncReply<IResource> getById(int id)
{
if (_resources.containsKey(id))
return new AsyncReply<IResource>.ready(_resources[id]);
else
return new AsyncReply<IResource>.ready(null);
}
/// <summary>
/// Open the warehouse.
/// This function issues the initialize trigger to all stores and resources.
/// </summary>
/// <returns>True, if no problem occurred.</returns>
static AsyncReply<bool> open()
{
var bag = new AsyncBag<bool>();
for(var s in _stores)
bag.add(s.trigger(ResourceTrigger.Initialize));
bag.seal();
var rt = new AsyncReply<bool>();
bag.then((x)
{
for (var b in x)
if (!b)
{
rt.trigger(false);
return;
}
var rBag = new AsyncBag<bool>();
for (var rk in _resources.keys)
rBag.add(_resources[rk].trigger(ResourceTrigger.SystemInitialized));
rBag.seal();
rBag.then((y)
{
for (var b in y)
if (!b)
{
rt.trigger(false);
return;
}
rt.trigger(true);
storeIsOpen = true;
});
});
return rt;
}
/// <summary>
/// Close the warehouse.
/// This function issues terminate trigger to all resources and stores.
/// </summary>
/// <returns>True, if no problem occurred.</returns>
static AsyncReply<bool> close()
{
var bag = new AsyncBag<bool>();
for (var resource in _resources.values)
if (!(resource is IStore))
bag.add(resource.trigger(ResourceTrigger.Terminate));
for (var s in _stores)
bag.add(s.trigger(ResourceTrigger.Terminate));
for (var resource in _resources.values)
if (!(resource is IStore))
bag.add(resource.trigger(ResourceTrigger.SystemTerminated));
for (var store in _stores)
bag.add(store.trigger(ResourceTrigger.SystemTerminated));
bag.seal();
var rt = new AsyncReply<bool>();
bag.then((x)
{
for (var b in x)
if (!b)
{
rt.trigger(false);
return;
}
rt.trigger(true);
});
return rt;
}
static List<IResource> qureyIn(List<String> path, int index, AutoList<IResource, Instance> resources)
{
var rt = new List<IResource>();
if (index == path.length - 1)
{
if (path[index] == "")
for (var child in resources)
rt.add(child);
else
for (var child in resources)
if (child.instance.name == path[index])
rt.add(child);
}
else
for (var child in resources)
if (child.instance.name == path[index])
rt.addAll(qureyIn(path, index+1, child.instance.children));
return rt;
}
static AsyncReply<List<IResource>> query(String path)
{
if (path == null || path == "")
{
var roots = _stores.where((s) => s.instance.parents.length == 0).toList();
return new AsyncReply<List<IResource>>.ready(roots);
}
else
{
var rt = new AsyncReply<List<IResource>>();
get(path).then((x)
{
var p = path.split('/');
if (x == null)
{
rt.trigger(qureyIn(p, 0, _stores));
}
else
{
var ar = qureyIn(p, 0, _stores).where((r) => r != x).toList();
ar.insert(0, x);
rt.trigger(ar);
}
});
return rt;
}
}
/// <summary>
/// Get a resource by its path.
/// Resource path is sperated by '/' character, e.g. "system/http".
/// </summary>
/// <param name="path"></param>
/// <returns>Resource instance.</returns>
static AsyncReply<dynamic> get(String path, [attributes = null, IResource parent = null, IPermissionsManager manager = null])
{
var p = path.split('/');
IResource res;
for(IStore d in _stores)
if (p[0] == d.instance.name)
{
var i = 1;
res = d;
while(p.length > i)
{
var si = i;
for (IResource r in res.instance.children)
if (r.instance.name == p[i])
{
i++;
res = r;
break;
}
if (si == i)
// not found, ask the store
return d.get(path.substring(p[0].length + 1));
}
return new AsyncReply<IResource>.ready(res);
}
// Should we create a new store ?
if (path.contains("://"))
{
var url = path.split("://");
var hostname = url[1].split('/')[0];
var pathname = url[1].split('/').skip(1).join("/");
var rt = new AsyncReply<IResource>();
if (protocols.containsKey(url[0]))
{
var handler = protocols[url[0]];
var store = handler();
put(store, url[0] + "://" + hostname, null, parent, null, 0, manager, attributes);
store.trigger(ResourceTrigger.Open).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>.ready(null);
}
/// <summary>
/// Put a resource in the warehouse.
/// </summary>
/// <param name="resource">Resource instance.</param>
/// <param name="name">Resource name.</param>
/// <param name="store">IStore that manages the resource. Can be null if the resource is a store.</param>
/// <param name="parent">Parent resource. if not presented the store becomes the parent for the resource.</param>
static void put(IResource resource, String name, [IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, int age = 0, IPermissionsManager manager = null, attributes = null])
{
resource.instance = new Instance(resourceCounter++, name, resource, store, customTemplate, age);
if (attributes != null)
resource.instance.setAttributes(Structure.fromMap(attributes));
if (manager != null)
resource.instance.managers.add(manager);
if (store == parent)
parent = null;
if (parent == null)
{
if (!(resource is IStore))
store.instance.children.add(resource);
}
else
parent.instance.children.add(resource);
if (resource is IStore)
{
_stores.add(resource);
//StoreConnected?.Invoke(resource as IStore, name);
}
else
store.put(resource);
_resources[resource.instance.id] = resource;
//if (!storeIsOpen)
// resource.trigger(ResourceTrigger.Initialize);
}
static T New<T extends IResource>(String name, [IStore store = null, IResource parent = null, IPermissionsManager manager = null, Structure attributes = null])
{
/*
var type = ResourceProxy.GetProxy<T>();
var res = Activator.CreateInstance(type) as IResource;
put(res, name, store, parent, null, 0, manager, attributes);
return (T)res;
*/
}
/// <summary>
/// Put a resource template in the templates warehouse.
/// </summary>
/// <param name="template">Resource template.</param>
static void putTemplate(ResourceTemplate template)
{
if (!_templates.containsKey(template.classId))
_templates.add(template.classId, template);
}
/// <summary>
/// Get a template by type from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
/// </summary>
/// <param name="type">.Net type.</param>
/// <returns>Resource template.</returns>
static ResourceTemplate getTemplateByType(Type type)
{
// loaded ?
for (var t in _templates.values)
if (t.className == type.toString())
return t;
var template = new ResourceTemplate.fromType(type);
_templates.add(template.classId, template);
return template;
}
/// <summary>
/// Get a template by class Id from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
/// </summary>
/// <param name="classId">Class Id.</param>
/// <returns>Resource template.</returns>
static AsyncReply<ResourceTemplate> getTemplateByClassId(Guid classId)
{
if (_templates.containsKey(classId))
return new AsyncReply<ResourceTemplate>.ready(_templates[classId]);
return null;
}
/// <summary>
/// Get a template by class name from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
/// </summary>
/// <param name="className">Class name.</param>
/// <returns>Resource template.</returns>
static AsyncReply<ResourceTemplate> getTemplateByClassName(String className)
{
for (var t in _templates.values)
if (t.className == className)
return new AsyncReply<ResourceTemplate>.ready(t);
return null;
}
static bool remove(IResource resource)
{
if (resource.instance == null)
return false;
if (_resources.containsKey(resource.instance.id))
_resources.remove(resource.instance.id);
else
return false;
if (resource is IStore)
{
_stores.remove(resource);
// remove all objects associated with the store
var toBeRemoved = _resources.values.where((x) => x.instance.store == resource);
for (var o in toBeRemoved)
remove(o);
// StoreDisconnected?.Invoke(resource as IStore);
}
if (resource.instance.store != null)
resource.instance.store.remove(resource);
resource.destroy();
return true;
}
}
KeyList<String, IStore Function()> getProtocols()
{
var rt = new KeyList<String, IStore Function()>();
rt.add("iip", () => new DistributedConnection());
return rt;
}

View File

@ -0,0 +1,48 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import 'AuthenticationType.dart';
import 'Source.dart';
class Authentication
{
String username;
//Certificate certificate;
String domain;
String get fullName => username + "@" + domain;
int state;
Source source = new Source();
final AuthenticationType type;
Authentication(this.type)
{
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,54 @@
/*
Copyright (c) 2019 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import '../../Data/DC.dart';
import 'Authentication.dart';
import '../../Data/KeyList.dart';
class Session
{
Authentication get localAuthentication => _localAuth;
Authentication get remoteAuthentication => _remoteAuth;
// public Source Source { get; }
DC id;
//DateTime get creation => _creation;
//public DateTime Modification { get; }
final KeyList<String, dynamic> variables = new KeyList<String, dynamic>();
//KeyList<string, object> Variables { get; }
//IStore Store { get; }
//string id;
Authentication _localAuth, _remoteAuth;
Session(Authentication localAuthentication, Authentication remoteAuthentication)
{
this._localAuth = localAuthentication;
this._remoteAuth = remoteAuthentication;
}
}

View File

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

View File

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

View File

@ -0,0 +1,160 @@
import '../../Data/DC.dart';
import '../../Data/BinaryList.dart';
import 'dart:typed_data';
class SHA256
{
static int RROT(int n, int d)
{
return ZSHIFT(n, d) | (n << (32 - d));
}
// Zero-fill right shift
static int ZSHIFT(int n, int d)
{
return (n & 0xFFFFFFFF) >> d;
}
static DC compute(DC msg)
{
/*
Note 1: All variables are 32 bit unsigned integers and addition is calculated modulo 2^32
Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 i 63
Note 3: The compression function uses 8 working variables, a through h
Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
and when parsing message block data from bytes to words, for example,
the first word of the input message "abc" after padding is 0x61626380
*/
// Initialize hash values:
// (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
var hash = new Uint32List.fromList([0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f,
0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ]);
// Initialize array of round constants:
// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
var k = new Uint32List.fromList([
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ]);
// Pre-processing:
// begin with the original message of length L bits
int L = msg.length * 8;
// append a single '1' bit
// append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512
var K = 512 - ((L + 1 + 64) % 512);
if (K == 512)
K = 0;
var paddingLength = (K + 1) ~/ 8;
var paddingBytes = new DC(paddingLength);
paddingBytes[0] = 0x80;
var data = new BinaryList().addDC(msg).addDC(paddingBytes).addUint64(L).toDC();
// append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits
// Process the message in successive 512-bit chunks:
// break message into 512-bit chunks
// for each chunk
for (var chunk = 0; chunk < data.length; chunk += 64)
{
// create a 64-entry message schedule array w[0..63] of 32-bit words
// (The initial values in w[0..63] don't matter, so many implementations zero them here)
// copy chunk into first 16 words w[0..15] of the message schedule array
var w = new Uint64List(64);// uint[64];
for (var i = 0; i < 16; i++)
w[i] = data.getUint32(chunk + (i * 4));
//for(var i = 16; i < 64; i++)
// w[i] = 0;
// Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
// for i from 16 to 63
// s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
// s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10)
// w[i] := w[i-16] + s0 + w[i-7] + s1
for (var i = 16; i < 64; i++)
{
var s0 = SHA256.RROT(w[i - 15], 7) ^ SHA256.RROT(w[i - 15], 18) ^ ZSHIFT(w[i - 15], 3);
var s1 = SHA256.RROT(w[i - 2], 17) ^ SHA256.RROT(w[i - 2], 19) ^ ZSHIFT(w[i - 2], 10);
w[i] = w[i - 16] + s0 + w[i - 7] + s1;
}
// Initialize working variables to current hash value:
var a = hash[0];
var b = hash[1];
var c = hash[2];
var d = hash[3];
var e = hash[4];
var f = hash[5];
var g = hash[6];
var h = hash[7];
// Compression function main loop:
for (var i = 0; i < 64; i++)
{
var S1 = SHA256.RROT(e, 6) ^ SHA256.RROT(e, 11) ^ SHA256.RROT(e, 25);
var ch = (e & f) ^ ((~e) & g);
var temp1 = h + S1 + ch + k[i] + w[i];
var S0 = SHA256.RROT(a, 2) ^ SHA256.RROT(a, 13) ^ SHA256.RROT(a, 22);
var maj = (a & b) ^ (a & c) ^ (b & c);
int temp2 = S0 + maj;
h = g;
g = f;
f = e;
e = ZSHIFT(d + temp1, 0);
d = c;
c = b;
b = a;
a = ZSHIFT(temp1 + temp2, 0);
}
// Add the compressed chunk to the current hash value:
hash[0] = ZSHIFT(hash[0] + a, 0);
hash[1] = ZSHIFT(hash[1] + b , 0);
hash[2] = ZSHIFT(hash[2] + c , 0);
hash[3] = ZSHIFT(hash[3] + d , 0);
hash[4] = ZSHIFT(hash[4] + e , 0);
hash[5] = ZSHIFT(hash[5] + f , 0);
hash[6] = ZSHIFT(hash[6] + g , 0);
hash[7] = ZSHIFT(hash[7] + h, 0);
}
// Produce the final hash value (big-endian):
//digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
var results = new BinaryList();
for (var i = 0; i < 8; i++)
results.addUint32(hash[i]);
return results.toDC();
}
}

View File

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

View File

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

View File

@ -0,0 +1,6 @@
enum Ruling
{
Denied,
Allowed,
DontCare
}

2
bin/esiur.dart Normal file
View File

@ -0,0 +1,2 @@
export 'Resource/Warehouse.dart';

24
bin/main.dart Normal file
View File

@ -0,0 +1,24 @@
//import 'Net/IIP/DistributedConnection.dart';
//import 'Resource/Warehouse.dart';
import 'esiur.dart';
main() async
{
var x = await Warehouse.get("iip://localhost:5000/db/my", {"username": "demo", "password": "1234"});//.then((x){
// get property
print(x.Level);
// listen to event
x.on("LevelUp", (v,y,z)=>print("Level up ${v} ${y}${z}"));
// use await
print("Added successfully ${await x.Add(40)}");
// use named arguments
await x.Add(value: 20);
// test chunks
x.Stream(10).chunk((c)=>print(c));
x.Level += 900;
print("Done");
}