2
0
mirror of https://github.com/esiur/esiur-js.git synced 2025-06-27 07:13:12 +00:00
This commit is contained in:
2019-06-07 23:07:15 +03:00
parent 054a4a0bd8
commit 144db9ee8b
100 changed files with 25137 additions and 1552 deletions

View File

@ -23,6 +23,8 @@
* Created by Ahmed Zamil on 25/07/2017.
*/
"use strict";
class AsyncBag extends AsyncReply
{
constructor() {
@ -42,13 +44,27 @@ class AsyncBag extends AsyncReply
var self = this;
var singleTaskCompleted = function(taskIndex)
{
return function(results, reply){
self.results[taskIndex] = results;
self.count++;
if (self.count == self.results.length)
self.trigger(self.results);
};
};
for(var i = 0; i < this.results.length; i++)
this.replies[i].then(singleTaskCompleted(i));
/*
this.replies[i].then(function(r, reply){
self.results[self.replies.indexOf(reply)] = r;
self.count++;
if (self.count == self.results.length)
self.trigger(self.results);
});
*/
}
add(reply)

88
src/AsyncException.js Normal file
View File

@ -0,0 +1,88 @@
/*
* 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.
*/
/**
* Created by Ahmed Zamil on 18/11/2017.
*/
"use strict";
const ExceptionCode =
{
HostNotReachable: 0,
AccessDenied: 1,
ResourceNotFound: 2,
AttachDenied: 3,
InvalidMethod: 4,
InvokeDenied: 5,
CreateDenied: 6,
AddParentDenied: 7,
AddChildDenied: 8,
ViewAttributeDenied: 9,
UpdateAttributeDenied: 10,
StoreNotFound: 11,
ParentNotFound: 12,
ChildNotFound: 13,
ResourceIsNotStore: 14,
DeleteDenied: 15,
DeleteFailed: 16,
UpdateAttributeFailed: 17,
GetAttributesFailed: 18,
ClearAttributesFailed: 19,
TemplateNotFound: 20,
RenameDenied: 21,
ClassNotFound: 22,
MethodNotFound: 23,
PropertyNotFound: 24,
SetPropertyDenied: 25,
ReadOnlyProperty: 26
};
class AsyncException extends Error
{
constructor()
{
super();
this.raised = false;
}
raise(type, code, message)
{
this.type = (type == 0 ? "Management" : "Execusion");
this.code = code;
if (type == 0)
for(var i in ExceptionCode)
if (ExceptionCode[i] == code)
{
this.message = i;
break;
}
else
this.message = message;
this.raised = true;
}
toString()
{
return this.type + " " + this.code + " " + this.message;
}
}

View File

@ -22,6 +22,9 @@
/**
* Created by Ahmed Zamil on 25/07/2017.
*/
"use strict";
class AsyncQueue extends AsyncReply
{

View File

@ -23,13 +23,72 @@
/**
* Created by Ahmed Zamil on 25/07/2017.
*/
"use strict";
const ErrorType = {
Management: 0,
Exception: 1
};
const ProgressType = {
Execution: 0,
Network: 1
};
class AsyncReply
{
then(callback)
{
this.callbacks.push(callback);
if (this.ready)
{
callback(this.result, this);
if (!this.taskExpired)
{
this.taskExpired = true;
this.resolveTask(this.result);
}
}
return this;
}
catch(callback)
{
return error(callback);
}
error(callback)
{
this.errorCallbacks.push(callback);
if (this.exception.raised)
{
callback(this.exception);
if (!this.taskExpired)
{
this.taskExpired = true;
this.rejectTask(this.exception);
}
}
return this;
}
progress(callback)
{
this.progressCallbacks.push(callback);
return this;
}
chunk(callback)
{
this.chunkCallbacks.push(callback);
return this;
}
trigger(result)
@ -39,15 +98,79 @@ class AsyncReply
for(var i = 0; i < this.callbacks.length; i++)
this.callbacks[i](result, this);
if (!this.taskExpired)
{
this.taskExpired = true;
this.resolveTask(this.result);
}
}
triggerError(type, code, message)//exception)
{
if (this.ready)
return;
this.exception.raise(type, code, message);// = exception;
for(var i = 0; i < this.errorCallbacks.length; i++)
this.errorCallbacks[i](this.exception, this);
if (!this.taskExpired)
{
this.taskExpired = true;
this.rejectTask(this.exception);
}
}
triggerProgress(type, value, max)
{
if (this.ready)
return;
for(var i = 0; i < this.progressCallbacks.length; i++)
this.progressCallbacks[i](type, value, max, this);
}
triggerChunk(value)
{
if (this.ready)
return;
for(var i = 0; i < this.chunkCallbacks.length; i++)
this.chunkCallbacks[i](value, this);
}
constructor(result)
{
this.callbacks = [];
this.errorCallbacks = [];
this.progressCallbacks = [];
this.chunkCallbacks = [];
this.exception = new AsyncException();// null;
if (result) {
var self = this;
this.task = new Promise(function(resolve, reject){
self.resolveTask = resolve;
self.rejectTask = reject;
});
if (result !== undefined) {
this.result = result;
this.ready = true;
this.taskExpired = true;
this.resolveTask(result);
}
else
{
this.taskExpired = false;
this.ready = false;
this.result = null;
}
}
}

50
src/Authentication.js Normal file
View File

@ -0,0 +1,50 @@
/*
* 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.
*/
/**
* Created by Ahmed Zamil on 16/11/2017.
*/
"use strict";
const AuthenticationType = {
Host: 0,
CoHost: 1,
Client: 2,
Alien: 3
};
class Authentication
{
constructor(type)
{
this.type = type;
this.state = 0;
this.domain = null;
this.username = null;
}
get fullName()
{
return this.domain + "@" + this.username;
}
}

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 05/09/2017.
*/
"use strict";
class AutoList extends IEventHandler
{
constructor()
@ -32,10 +34,15 @@ class AutoList extends IEventHandler
this.list = [];
}
get length()
{
return this.list.length;
}
add(value)
{
if (value instanceof IDestructible)
value.on("destroy", this._item_destroyed);
value.on("destroy", this._item_destroyed, this);
this.list.push(value);
@ -48,7 +55,7 @@ class AutoList extends IEventHandler
return;
if (value instanceof IDestructible)
value.on("destroy", this._item_destroyed);
value.on("destroy", this._item_destroyed, this);
if (this.list[index] instanceof IDestructible)
this.list[index].off("destroy", this._item_destroyed);
@ -56,6 +63,16 @@ class AutoList extends IEventHandler
this.list[index] = value;
}
at(index)
{
return this.list[index];
}
item(index)
{
return this.list[index];
}
remove(value)
{
this.removeAt(this.list.indexOf(value));
@ -66,6 +83,11 @@ class AutoList extends IEventHandler
return this.list.indexOf(value) > -1;
}
toArray()
{
return this.list.slice(0);
}
removeAt(index)
{
if (index >= this.list.length || index < 0)

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 05/09/2017.
*/
"use strict";
class AutoMap extends IEventHandler
{
constructor()

View File

@ -24,7 +24,9 @@
* Created by Ahmed Zamil on 25/08/2017.
*/
var BL = function(){
"use strict";
function BL(){
return new BinaryList();
};
@ -140,6 +142,16 @@ class BinaryList
return rt;
}
toDC()
{
return new DC(this.toArray());
}
addDateTime(value, position)
{
return this.add({type: DataType.DateTime, value: value}, position);
}
addUint8Array(value, position)
{
return this.add({type: DataType.UInt8Array, value: value}, position);

View File

@ -24,16 +24,17 @@
* Created by Ahmed Zamil on 25/07/2017.
*/
var ResourceComparisonResult =
"use strict";
const ResourceComparisonResult =
{
Null: 0,
Distributed: 1,
DistributedSameClass: 2,
Local: 3,
Same: 4
Local: 2,
Same: 3
};
var StructureComparisonResult =
const StructureComparisonResult =
{
Null: 0,
Structure: 1,
@ -44,6 +45,7 @@ var StructureComparisonResult =
class Codec {
static parse(data, offset, sizeObject, connection, dataType = DataType.Unspecified) {
var size;
@ -215,16 +217,251 @@ class Codec {
return connection.fetch(iid);// Warehouse.Get(iid);
}
/// <summary>
/// Parse an array of bytes into array of resources
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="length">Number of bytes to parse.</param>
/// <param name="offset">Zero-indexed offset.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <returns>Array of resources.</returns>
static parseResourceArray(data, offset, length, connection)
{
var reply = new AsyncBag();
if (length == 0)
{
reply.seal();
return reply;
}
static parseStructure(data, offset, contentLength, connection, keylist = null, typelist = null, keys = null, types = null) {
var reply = new AsyncReply();
var bag = new AsyncBag();
var end = offset + length;
//
var result = data[offset++];
var previous = null;
if (result == ResourceComparisonResult.Null)
previous = new AsyncReply(null);
else if (result == ResourceComparisonResult.Local)
{
previous = Warehouse.get(data.getUint32(offset));
offset += 4;
}
else if (result == ResourceComparisonResult.Distributed)
{
previous = connection.fetch(data.getUint32(offset));
offset += 4;
}
reply.add(previous);
if (keylist == null)
keylist = [];
if (typelist == null)
typelist = [];
while (offset < end)
{
result = data[offset++];
var current = null;
if (result == ResourceComparisonResult.Null)
{
current = new AsyncReply(null);
}
else if (result == ResourceComparisonResult.Same)
{
current = previous;
}
else if (result == ResourceComparisonResult.Local)
{
current = Warehouse.get(data.getUint32(offset));
offset += 4;
}
else if (result == ResourceComparisonResult.Distributed)
{
current = connection.fetch(data.getUint32(offset));
offset += 4;
}
reply.add(current);
previous = current;
}
reply.seal();
return reply;
}
/// <summary>
/// Compose an array of property values.
/// </summary>
/// <param name="array">PropertyValue array.</param>
/// <param name="connection">DistributedConnection is required to check locality.</param>
/// <param name="prependLength">If True, prepend the length as UInt32 at the beginning of the output.</param>
/// <returns>Array of bytes in the network byte order.</returns>
static composePropertyValueArray(array, connection, prependLength = false)
{
var rt = BL();
for (var i = 0; i < array.Length; i++)
rt.addUint8Array(Codec.composePropertyValue(array[i], connection));
if (prependLength)
rt.addUint32(rt.length, 0);
return rt.toArray();
}
/// <summary>
/// Compose a property value.
/// </summary>
/// <param name="propertyValue">Property value</param>
/// <param name="connection">DistributedConnection is required to check locality.</param>
/// <returns>Array of bytes in the network byte order.</returns>
static composePropertyValue(propertyValue, connection)
{
// age, date, value
return BL().addUint64(propertyValue.age)
.addDateTime(propertyValue.date)
.addUint8Array(Codec.compose(propertyValue.value, connection))
.toArray();
}
/// <summary>
/// Parse property value.
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="offset">Zero-indexed offset.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <param name="cs">Output content size.</param>
/// <returns>PropertyValue.</returns>
static parsePropertyValue(data, offset, sizeObject, connection)
{
var reply = new AsyncReply();
var age = data.getUint64(offset);
offset += 8;
var date = data.getDateTime(offset);
offset += 8;
var cs = {};
Codec.parse(data, offset, cs, connection).then(function(value)
{
reply.trigger(new PropertyValue(value, age, date));
});
sizeObject.size = 16 + cs.size;
return reply;
}
/// <summary>
/// Parse resource history
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="offset">Zero-indexed offset.</param>
/// <param name="length">Number of bytes to parse.</param>
/// <param name="resource">Resource</param>
/// <param name="fromAge">Starting age.</param>
/// <param name="toAge">Ending age.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <returns></returns>
static parseHistory(data, offset, length, resource, connection)
{
var list = new KeyList();
var reply = new AsyncReply();
var bagOfBags = new AsyncBag();
var ends = offset + length;
while (offset < ends)
{
var index = data[offset++];
var pt = resource.instance.template.getPropertyTemplateByIndex(index);
list.add(pt, null);
var cs = data.getUint32(offset);
offset += 4;
bagOfBags.add(Codec.parsePropertyValueArray(data, offset, cs, connection));
offset += cs;
}
bagOfBags.seal();
bagOfBags.then(x =>
{
for(var i = 0; i < list.length; i++)
list.values[i] = x[i];
reply.trigger(list);
});
return reply;
}
/// <summary>
/// Compose resource history
/// </summary>
/// <param name="history">History</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <returns></returns>
static composeHistory(history, connection, prependLength = false)
{
var rt = new BinaryList();
for (var i = 0; i < history.length; i++)
rt.addUint8(history.keys[i].index).addUint8Array(Codec.composePropertyValueArray(history.values[i], connection, true));
if (prependLength)
rt.addUint32(rt.length, 0);
return rt.toArray();
}
/// <summary>
/// Parse an array of ProperyValue.
/// </summary>
/// <param name="data">Array of bytes.</param>
/// <param name="offset">Zero-indexed offset.</param>
/// <param name="length">Number of bytes to parse.</param>
/// <param name="connection">DistributedConnection is required to fetch resources.</param>
/// <returns></returns>
static parsePropertyValueArray(data, offset, length, connection)
{
var rt = new AsyncBag();
while (length > 0)
{
var cs = {};
rt.add(Codec.parsePropertyValue(data, offset, cs, connection));
if (cs.size > 0)
{
offset += cs.size;
length -= cs.size;
}
else
throw new Exception("Error while parsing ValueInfo structured data");
}
rt.seal();
return rt;
}
static parseStructure(data, offset, contentLength, connection, metadata = null, keys = null, types = null)
{
var reply = new AsyncReply();
var bag = new AsyncBag();
var keylist = [];
var typelist = [];
if (keys == null) {
while (contentLength > 0) {
@ -249,11 +486,12 @@ class Codec {
var rt = {};
bag.add(Codec.parse(data, offset, rt, connection));
contentLength -= rt.size + 1;
offset += rt.size + 1;
contentLength -= rt.size;
offset += rt.size;
}
}
else {
for (var i = 0; i < keys.length; i++) {
keylist.push(keys[i]);
typelist.push(types[i]);
@ -279,7 +517,12 @@ class Codec {
reply.trigger(s);
});
if (metadata != null)
{
metadata.keys = keylist;
metadata.types = typelist;
}
return reply;
}
@ -308,6 +551,11 @@ class Codec {
static compose(value, connection, prependType = true) {
if (value instanceof Function)
value = value(connection);
else if (value instanceof DistributedPropertyContext)
value = value.method(this);
var type = Codec.getDataType(value, connection);
var rt = new BinaryList();
@ -322,7 +570,7 @@ class Codec {
break;
case DataType.Resource:
rt.addUint32(value.instance.id);
rt.addUint32(value._p.instanceId);
break;
case DataType.DistributedResource:
@ -462,7 +710,7 @@ class Codec {
static isLocalResource(resource, connection) {
if (resource instanceof DistributedResource)
if (resource.connection == connection)
if (resource._p.connection == connection)
return true;
return false;
@ -477,58 +725,47 @@ static isLocalResource(resource, connection) {
}
static compareResource(previous, next, connection) {
if (next == null)
return ResourceComparisonResult.Null;
if (next == previous)
else if (next == previous)
return ResourceComparisonResult.Same;
if (Codec.isLocalResource(next, connection))
else if (Codec.isLocalResource(next, connection))
return ResourceComparisonResult.Local;
if (previous == null)
else
return ResourceComparisonResult.Distributed;
if (previous.instance.template.classId.valueOf() == next.instance.template.classId.valueOf())
return ResourceComparisonResult.DistributedSameClass;
return ResourceComparisonResult.Distributed;
}
static composeResourceArray(resources, connection, prependLength = false) {
if (resources == null || resources.length == 0 || !(resources instanceof ResourceArray))
return new DC(0);
var rt = new BinaryList();
var comparsion = Codec.compareResource(null, resources[0], connection);
if (resources == null || resources.length == 0)// || !(resources instanceof ResourceArray))
return prependLength ? new DC(4) : new DC(0);
rt.addUint8(comparsion);
var rt = new BinaryList();
var comparsion = Codec.compareResource(null, resources[0], connection);
if (comparsion == ResourceComparisonResult.Local)
rt.addUint32(resources[0].id);
else if (comparsion == ResourceComparisonResult.Distributed) {
rt.addUint8Array(resources[0].instance.template.classId.value);
rt.addUint32(resources[0].instance.id);
}
rt.addUint8(comparsion);
for (var i = 1; i < resources.length; i++) {
comparsion = Codec.compareResource(resources[i - 1], resources[i], connection);
rt.addUint8(comparsion);
if (comparsion == ResourceComparisonResult.Local)
rt.addUint32(resources[0].id);
else if (comparsion == ResourceComparisonResult.Distributed) {
rt.addUint8Array(resources[0].instance.template.classId.value);
rt.addUint32(resources[0].instance.id);
}
else if (comparsion == ResourceComparisonResult.DistributedSameClass) {
rt.addUint32(resources[0].instance.id);
}
}
if (comparsion == ResourceComparisonResult.Local)
rt.addUint32(resources[0]._p.instanceId);
else if (comparsion == ResourceComparisonResult.Distributed)
rt.addUint32(resources[0].instance.id);
if (prependLength)
rt.addUint32(0, rt.length);
for (var i = 1; i < resources.Length; i++)
{
comparsion = Codec.compareResource(resources[i - 1], resources[i], connection);
rt.addUint8(comparsion);
if (comparsion == ResourceComparisonResult.Local)
rt.addUint32(resources[i]._p.instanceId);
else if (comparsion == ResourceComparisonResult.Distributed)
rt.addUint32(resources[i].instance.id);
}
return rt.toArray();
if (prependLength)
rt.addUint32(rt.length, 0);
return rt.toArray();
}
@ -619,4 +856,83 @@ static getDataType(value) {
return DataType.Void;
}
}
/// <summary>
/// Parse an array of structures
/// </summary>
/// <param name="data">Bytes array</param>
/// <param name="offset">Zero-indexed offset</param>
/// <param name="length">Number of bytes to parse</param>
/// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end</param>
/// <returns>Array of structures</returns>
static parseStructureArray(data, offset, length, connection)
{
var reply = new AsyncBag();
if (length == 0)
{
reply.seal();
return reply;
}
var end = offset + length;
var result = data[offset++];
var previous = null;
//var previousKeys = [];
//var previousTypes = [];
var metadata = {keys: null, types: null};
if (result == StructureComparisonResult.Null)
previous = new AsyncReply(null);
else if (result == StructureComparisonResult.Structure)
{
var cs = data.getUint32(offset);
offset += 4;
previous = this.parseStructure(data, offset, cs, connection, metadata);
offset += cs;
}
reply.add(previous);
while (offset < end)
{
result = data[offset++];
if (result == StructureComparisonResult.Null)
previous = new AsyncReply(null);
else if (result == StructureComparisonResult.Structure)
{
var cs = data.getUint32(offset);
offset += 4;
previous = this.parseStructure(data, offset, cs, connection, metadata);
offset += cs;
}
else if (result == StructureComparisonResult.StructureSameKeys)
{
var cs = data.getUint32(offset);
offset += 4;
previous = this.parseStructure(data, offset, cs, connection, metadata, metadata.keys);
offset += cs;
}
else if (result == StructureComparisonResult.StructureSameTypes)
{
var cs = data.getUint32(offset);
offset += 4;
previous = this.parseStructure(data, offset, cs, connection, metadata, metadata.keys, metadata.types);
offset += cs;
}
reply.add(previous);
}
reply.seal();
return reply;
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2017-2018 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 10/11/2018.
*/
"use strict";
class CustomResourceEvent
{
constructor(issuer, receivers, params)
{
this.issuer = issuer;
this.receivers = receivers;
this.params = params;
}
}

View File

@ -24,8 +24,10 @@
* Created by Ahmed Zamil on 25/07/2017.
*/
var UNIX_EPOCH = 621355968000000000;
var TWO_PWR_32 = (1 << 16) * (1 << 16);
"use strict";
const UNIX_EPOCH = 621355968000000000;
const TWO_PWR_32 = (1 << 16) * (1 << 16);
class DC extends Uint8Array// extends DataView // Data Converter
{
@ -155,7 +157,17 @@ class DC extends Uint8Array// extends DataView // Data Converter
return new DC(rt);
}
static stringArrayToBytes(values)
{
var list = new BinaryList();
for(var i = 0; i < values.length; i++)
{
var s = DC.stringToBytes(values[i]);
list.addUint32(s.length).addUint8Array(s);
}
return list.toArray();
}
append(src, offset, length)
{
@ -438,7 +450,7 @@ class DC extends Uint8Array// extends DataView // Data Converter
getDateTime(offset)
{
var ticks = this.getUint64(offset);
return new Date(Math.round((ticks-DCStatic.UNIX_EPOCH)/10000));
return new Date(Math.round((ticks-UNIX_EPOCH)/10000));
}
getDateTimeArray(offset)
@ -451,7 +463,7 @@ class DC extends Uint8Array// extends DataView // Data Converter
getGuid(offset)
{
return new Guid(this.getUint8Array(offset, 16));
return new Guid(this.clip(offset, 16));
/*
var d = this.getUint8Array(offset, 16);

View File

@ -23,7 +23,11 @@
/**
* Created by Ahmed Zamil on 25/07/2017.
*/
DataType = {
"use strict";
const DataType =
{
Void: 0x0,
//Variant,
Bool: 1,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2017-2018 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 27/10/2018.
*/
"use strict";
class DistributedPropertyContext
{
constructor(p1, p2)
{
if(arguments.length == 1)
{
this.method = p1;
}
else if (arguments.length == 2)
{
this.connection = p1;
this.value = p2;
}
}
}

View File

@ -24,18 +24,17 @@
* Created by Ahmed Zamil on 25/07/2017.
*/
"use strict";
class DistributedResource extends IResource
{
destroy()
{
this.destroyed = true;
this._emit("destroy");
this._emit("destroy", this);
}
constructor(connection, template, instanceId, age)
constructor(connection, instanceId, age, link)
{
super();
@ -44,20 +43,38 @@ class DistributedResource extends IResource
connection: connection,
instanceId: instanceId,
age: age,
template: template
link: link,
properties: []
};
}
_serialize()
{
var props = [];
for (var i = 0; i < this._p.properties.length; i++)
props.push(new PropertyValue(this._p.properties[i],
this.instance.getAge(i),
this.instance.getModificationDate(i)));
return props;
}
_attached(properties)
{
if (this._isAttached)
return false;
else
{
this._p.properties = properties;
this._p.ages = new Uint32Array(properties.length);
//this.events = [];//new [this.template.events.length];
{
for(var i = 0; i < properties.length; i++)
{
this.instance.setAge(i, properties[i].age);
this.instance.setModificationDate(i, properties[i].date);
this._p.properties.push(properties[i].value);
}
this._p.isAttached = true;
var self = this;
@ -83,15 +100,15 @@ class DistributedResource extends IResource
};
};
for(var i = 0; i < this._p.template.functions.length; i++)
for(var i = 0; i < this.instance.template.functions.length; i++)
{
var ft = this._p.template.functions[i];
var ft = this.instance.template.functions[i];
this[ft.name] = makeFunc(ft.index);
}
for(var i = 0; i < this._p.template.properties.length; i++)
for(var i = 0; i < this.instance.template.properties.length; i++)
{
var pt = this._p.template.properties[i];
var pt = this.instance.template.properties[i];
Object.defineProperty(this, pt.name, {
get: makeGetter(pt.index),
@ -107,18 +124,21 @@ class DistributedResource extends IResource
_emitEventByIndex(index, args)
{
var et = this._p.template.getEventTemplateByIndex(index);
this._emit(et.name, args);
this.instance.emitResourceEvent(et.name, null, args);
var et = this.instance.template.getEventTemplateByIndex(index);
this._emitArgs(et.name, args);
this.instance._emitResourceEvent(null, null, et.name, args);
}
_invoke(index, args) {
if (this.destroyed)
throw new Exception("Trying to access destroyed object");
if (index >= this._p.template.functions.length)
if (index >= this.instance.template.functions.length)
throw new Exception("Function index is incorrect");
return this._p.connection.sendInvoke(this._p.instanceId, index, args);
/*
var reply = new AsyncReply();
var parameters = Codec.composeVarArray(args, this._p.connection, true);
@ -135,7 +155,7 @@ class DistributedResource extends IResource
return reply;
*/
}
@ -147,12 +167,11 @@ class DistributedResource extends IResource
}
_updatePropertyByIndex(index, value)
{
var pt = this._p.template.getPropertyTemplateByIndex(index);
var pt = this.instance.template.getPropertyTemplateByIndex(index);
this._p.properties[index] = value;
this.instance.modified(pt.name, value);
this.instance.emitModification(pt, value);
}
_set(index, value)
@ -165,15 +184,15 @@ class DistributedResource extends IResource
var parameters = Codec.compose(value, this._p.connection);
var self = this;
this._p.connection.sendRequest(IIPPacketAction.SetProperty,
BL().addUint32(self._p.instanceId).addUint8(index).addUint8Array(parameters))
this._p.connection.sendRequest(IIPPacketAction.SetProperty)
.addUint32(self._p.instanceId).addUint8(index).addUint8Array(parameters)
.done()
.then(function(res)
{
// not really needed, server will always send property modified, this only happens if the programmer forgot to emit in property setter
//Update(index, value);
self._p.properties[index] = value;
reply.trigger(null);
// nothing to do here
});
});
return reply;
}

View File

@ -23,7 +23,10 @@
/**
* Created by Ahmed Zamil on 25/07/2017.
*/
var DistributedResourceQueueItemType =
"use strict";
const DistributedResourceQueueItemType =
{
Propery: 0,
Event: 1

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 24/08/2017.
*/
"use strict";
class EventTemplate extends MemberTemplate
{

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 27/08/2017.
*/
"use strict";
class FunctionTemplate extends MemberTemplate {
compose() {
var name = super.compose();
@ -32,12 +34,12 @@ class FunctionTemplate extends MemberTemplate {
if (this.expansion != null) {
var exp = DC.stringToBytes(this.expansion);
return rt.addUint8(0x10 | (IsVoid ? 0x8 : 0x0))
return rt.addUint8(0x10 | (this.isVoid ? 0x8 : 0x0))
.addUint32(exp.length).addUint8Array(exp)
.addUint8(name.length).addUint8Array(name).toArray();
}
else
return rt.addUint8(IsVoid ? 0x8 : 0x0).addUint8(name.length).addUint8Array(name).toArray();
return rt.addUint8(this.isVoid ? 0x8 : 0x0).addUint8(name.length).addUint8Array(name).toArray();
}

View File

@ -23,6 +23,9 @@
/**
* Created by Ahmed Zamil on 02/09/2017.
*/
"use strict";
class Guid
{
constructor(dc)

View File

@ -23,6 +23,9 @@
/**
* Created by Ahmed Zamil on 31/08/2017.
*/
"use strict";
class IDestructible extends IEventHandler
{
destroy()

View File

@ -23,6 +23,7 @@
/**
* Created by Ahmed Zamil on 30/08/2017.
*/
"use strict";
class IEventHandler
{
@ -42,19 +43,32 @@ class IEventHandler
var args = Array.prototype.slice.call(arguments, 1);
if (this._events[event])
for(var i = 0; i < this._events[event].length; i++)
if (this._events[event][i].apply(this, args))
if (this._events[event][i].f.apply(this._events[event][i].i, args))
return true;
return false;
}
on(event, fn)
_emitArgs(event, args)
{
event = event.toLowerCase();
if (this._events[event])
for(var i = 0; i < this._events[event].length; i++)
if (this._events[event][i].f.apply(this._events[event][i].i, args))
return true;
return this;
}
on(event, fn, issuer)
{
if (!(fn instanceof Function))
return this;
event = event.toLowerCase();
// add
if (!this._events[event])
this._events[event] = [];
this._events[event].push(fn);
this._events[event].push({f: fn, i: issuer == null ? this: issuer});
return this;
}
@ -65,9 +79,13 @@ class IEventHandler
{
if (fn)
{
var index = this._events[event].indexOf(fn);
if (index > -1)
this._events[event].splice(index, 1);
for(var i = 0; i < this._events[event].length; i++)
if (this._events[event][i].f == fn)
this._events[event].splice(i--, 1);
//var index = this._events[event].indexOf(fn);
//if (index > -1)
//this._events[event].splice(index, 1);
}
else
{

View File

@ -23,7 +23,10 @@
/**
* Created by Ahmed Zamil on 25/07/2017.
*/
var IIPAuthPacketCommand =
"use strict";
const IIPAuthPacketCommand =
{
Action: 0,
Declare: 1,
@ -31,7 +34,7 @@ var IIPAuthPacketCommand =
Error: 3
};
var IIPAuthPacketAction =
const IIPAuthPacketAction =
{
// Authenticate
AuthenticateHash: 0,
@ -41,7 +44,7 @@ var IIPAuthPacketAction =
};
var IIPAuthPacketMethod =
const IIPAuthPacketMethod =
{
None: 0,
Certificate: 1,

View File

@ -24,27 +24,43 @@
* Created by Ahmed Zamil on 25/07/2017.
*/
"use strict";
var IIPPacketCommand =
const IIPPacketCommand =
{
Event: 0,
Request: 1,
Reply: 2,
Error: 3
Report: 3
};
var IIPPacketEvent =
const IIPPacketReport =
{
ManagementError: 0,
ExecutionError: 1,
ProgressReport: 0x8,
ChunkStream: 0x9
};
const IIPPacketEvent =
{
// Event Manage
ResourceReassigned : 0,
ResourceDestroyed: 1,
ChildAdded: 2,
ChildRemoved: 3,
Renamed: 4,
// Event Invoke
PropertyUpdated : 0x10,
EventOccured: 0x11
EventOccurred: 0x11,
// Attribute
AttributesUpdated: 0x18
};
var IIPPacketAction =
const IIPPacketAction =
{
// Request Manage
AttachResource: 0,
@ -52,25 +68,35 @@ var IIPPacketAction =
DetachResource: 2,
CreateResource: 3,
DeleteResource: 4,
AddChild: 5,
RemoveChild: 6,
RenameResource: 7,
// Request Inquire
TemplateFromClassName: 0x8,
TemplateFromClassId: 0x9,
TemplateFromResourceLink: 0xA,
TemplateFromResourceId: 0xB,
ResourceIdFromResourceLink: 0xC,
TemplateFromClassName: 8,
TemplateFromClassId: 9,
TemplateFromResourceId: 10,
QueryLink: 11,
ResourceHistory: 12,
ResourceChildren: 13,
ResourceParents: 14,
// Request Invoke
InvokeFunction: 0x10,
GetProperty: 0x11,
GetPropertyIfModified: 0x12,
SetProperty: 0x13
InvokeFunction: 16,
GetProperty: 17,
GetPropertyIfModified: 18,
SetProperty: 19,
// Request Attribute
GetAllAttributes: 24,
UpdateAllAttributes: 25,
ClearAllAttributes: 26,
GetAttributes: 27,
UpdateAttributes: 28,
ClearAttributes: 29
};
class IIPPacket
{
constructor()
@ -91,13 +117,14 @@ class IIPPacket
this.methodName = "";
this.callbackId = 0;
this.dataLengthNeeded = 0;
this.originalOffset = 0;
}
notEnough(offset, ends, needed)
{
if (offset + needed > ends)
{
this.dataLengthNeeded = needed - (ends - offset);
this.dataLengthNeeded = needed - (ends - this.originalOffset);
return true;
}
else
@ -106,7 +133,7 @@ class IIPPacket
parse(data, offset, ends)
{
var oOffset = offset;
this.originalOffset = offset;
if (this.notEnough(offset, ends, 1))
return -this.dataLengthNeeded;
@ -123,6 +150,16 @@ class IIPPacket
this.resourceId = data.getUint32(offset);
offset += 4;
}
else if (this.command == IIPPacketCommand.Report)
{
this.report = (data.getUint8(offset++) & 0x3f);
if (this.notEnough(offset, ends, 4))
return -this.dataLengthNeeded;
this.callbackId = data.getUint32(offset);
offset += 4;
}
else
{
this.action = (data.getUint8(offset++) & 0x3f);
@ -149,6 +186,30 @@ class IIPPacket
{
// nothing to parse
}
else if (this.event == IIPPacketEvent.ChildAdded
|| this.event == IIPPacketEvent.ChildRemoved)
{
if (this.notEnough(offset, ends, 4))
return -this.dataLengthNeeded;
this.childId = data.getUint32(offset);
offset += 4;
}
else if(this.event == IIPPacketEvent.Renamed)
{
if (this.notEnough(offset, ends, 2))
return -this.dataLengthNeeded;
var cl = data.getUint16(offset);
offset += 2;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
this.content = data.clip(offset, cl);
offset += cl;
}
else if (this.event == IIPPacketEvent.PropertyUpdated)
{
if (this.notEnough(offset, ends, 2))
@ -182,7 +243,7 @@ class IIPPacket
offset += size;
}
}
else if (this.event == IIPPacketEvent.EventOccured)
else if (this.event == IIPPacketEvent.EventOccurred)
{
if (this.notEnough(offset, ends, 5))
return -this.dataLengthNeeded;
@ -195,6 +256,22 @@ class IIPPacket
this.content = data.clip(offset, cl);
offset += cl;
}
// Attribute
else if (this.event == IIPPacketEvent.AttributesUpdated)
{
if (this.notEnough(offset, ends, 4))
return -this.dataLengthNeeded;
var cl = data.getUint32(offset);
offset += 4;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
this.content = data.clip(offset, cl);
offset += cl;
}
}
else if (this.command == IIPPacketCommand.Request)
{
@ -208,14 +285,14 @@ class IIPPacket
}
else if (this.action == IIPPacketAction.ReattachResource)
{
if (this.notEnough(offset, ends, 8))
if (this.notEnough(offset, ends, 12))
return -this.dataLengthNeeded;
this.resourceId = data.getUint32(offset);
offset += 4;
this.resourceAge = data.getUint32(offset);
offset += 4;
this.resourceAge = data.getUint64(offset);
offset += 8;
}
else if (this.action == IIPPacketAction.DetachResource)
{
@ -228,16 +305,21 @@ class IIPPacket
}
else if (this.action == IIPPacketAction.CreateResource)
{
if (this.notEnough(offset, ends, 1))
return -this.dataLengthNeeded;
if (this.notEnough(offset, ends, 12))
return -dataLengthNeeded;
var cl = data.getUint8(offset++);
this.storeId = data.getUint32(offset);
offset += 4;
this.resourceId = data.getUint32(offset);
offset += 4;
var cl = data.getUint32(offset);
offset += 4;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
return -dataLengthNeeded;
this.className = data.getString(offset, cl);
offset += cl;
this.content = data.clip(offset, cl);
}
else if (this.action == IIPPacketAction.DeleteResource)
{
@ -247,6 +329,37 @@ class IIPPacket
this.resourceId = data.getUint32(offset);
offset += 4;
}
else if (this.action == IIPPacketAction.AddChild
|| this.action == IIPPacketAction.RemoveChild)
{
if (this.notEnough(offset, ends, 8))
return -this.dataLengthNeeded;
this.resourceId = data.getUint32(offset);
offset += 4;
this.childId = data.getUint32(offset);
offset += 4;
}
else if (this.action == IIPPacketAction.RenameResource)
{
if (this.notEnough(offset, ends, 6))
return -this.dataLengthNeeded;
this.resourceId = data.getUint32(offset);
offset += 4;
var cl = data.getUint16(offset);
offset += 2;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
this.content = data.clip(offset, cl);
offset += cl;
}
else if (this.action == IIPPacketAction.TemplateFromClassName)
{
@ -270,20 +383,6 @@ class IIPPacket
this.classId = data.getGuid(offset);
offset += 16;
}
else if (this.action == IIPPacketAction.TemplateFromResourceLink)
{
if (this.notEnough(offset, ends, 2))
return -this.dataLengthNeeded;
var cl = data.getUint16(offset);
offset += 2;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
this.resourceLink = data.getString(offset, cl);
offset += cl;
}
else if (this.action == IIPPacketAction.TemplateFromResourceId)
{
if (this.notEnough(offset, ends, 4))
@ -292,7 +391,7 @@ class IIPPacket
this.resourceId = data.getUint32(offset);
offset += 4;
}
else if (this.action == IIPPacketAction.ResourceIdFromResourceLink)
else if (this.action == IIPPacketAction.QueryLink)
{
if (this.notEnough(offset, ends, 2))
return -this.dataLengthNeeded;
@ -306,6 +405,30 @@ class IIPPacket
this.resourceLink = data.getString(offset, cl);
offset += cl;
}
else if (this.action == IIPPacketAction.ResourceChildren
|| this.action == IIPPacketAction.ResourceParents)
{
if (this.notEnough(offset, ends, 4))
return -this.dataLengthNeeded;
this.resourceId = data.getUint32(offset);
offset += 4;
}
else if (this.action == IIPPacketAction.ResourceHistory)
{
if (this.notEnough(offset, ends, 20))
return -this.dataLengthNeeded;
this.resourceId = data.getUint32(offset);
offset += 4;
this.fromDate = data.getDateTime(offset);
offset += 8;
this.toDate = data.getDateTime(offset);
offset += 8;
}
else if (this.action == IIPPacketAction.InvokeFunction)
{
if (this.notEnough(offset, ends, 9))
@ -347,8 +470,8 @@ class IIPPacket
this.methodIndex = data[offset++];
this.resourceAge = data.getUint32(offset);
offset += 4;
this.resourceAge = data.getUint64(offset);
offset += 8;
}
else if (this.action == IIPPacketAction.SetProperty)
@ -388,6 +511,28 @@ class IIPPacket
offset += size;
}
}
// Attribute
else if (this.action == IIPPacketAction.UpdateAllAttributes
|| this.action == IIPPacketAction.GetAttributes
|| this.action == IIPPacketAction.UpdateAttributes
|| this.action == IIPPacketAction.ClearAttributes)
{
if (this.notEnough(offset, ends, 8))
return -this.dataLengthNeeded;
this.resourceId = data.getUint32(offset);
offset += 4;
var cl = data.getUint32(offset);
offset += 4;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
this.content = data.clip(offset, cl);
offset += cl;
}
}
else if (this.command == IIPPacketCommand.Reply)
{
@ -400,8 +545,8 @@ class IIPPacket
this.classId = data.getGuid(offset);
offset += 16;
this.resourceAge = data.getUint32(offset);
offset += 4;
this.resourceAge = data.getUint64(offset);
offset += 8;
var cl = data.getUint16(offset);
offset+=2;
@ -433,9 +578,6 @@ class IIPPacket
if (this.notEnough(offset, ends, 20))
return -this.dataLengthNeeded;
this.classId = data.GetGuid(offset);
offset += 16;
this.resourceId = data.getUint32(offset);
offset += 4;
@ -446,8 +588,14 @@ class IIPPacket
}
else if (this.action == IIPPacketAction.TemplateFromClassName
|| this.action == IIPPacketAction.TemplateFromClassId
|| this.action == IIPPacketAction.TemplateFromResourceLink
|| this.action == IIPPacketAction.TemplateFromResourceId)
|| this.action == IIPPacketAction.TemplateFromResourceId
|| this.action == IIPPacketAction.QueryLink
|| this.action == IIPPacketAction.ResourceChildren
|| this.action == IIPPacketAction.ResourceParents
|| this.action == IIPPacketAction.ResourceHistory
// Attribute
|| this.action == IIPPacketAction.GetAllAttributes
|| this.action == IIPPacketAction.GetAttributes)
{
if (this.notEnough(offset, ends, 4))
return -this.dataLengthNeeded;
@ -461,20 +609,6 @@ class IIPPacket
this.content = data.clip(offset, cl);
offset += cl;
}
else if (this.action == IIPPacketAction.ResourceIdFromResourceLink)
{
if (this.notEnough(offset, ends, 24))
return -this.dataLengthNeeded;
this.classId = data.getGuid(offset);
offset += 16;
this.resourceId = data.getUint32(offset);
offset += 4;
this.resourceAge = data.getUint32(offset);
offset += 4;
}
else if (this.action == IIPPacketAction.InvokeFunction
|| this.action == IIPPacketAction.GetProperty
|| this.action == IIPPacketAction.GetPropertyIfModified)
@ -513,32 +647,76 @@ class IIPPacket
// nothing to do
}
}
else if (this.command == IIPPacketCommand.Error)
else if (this.command == IIPPacketCommand.Report)
{
// Error
if (this.notEnough(offset, ends, 4))
return -this.dataLengthNeeded;
if (this.report == IIPPacketReport.ManagementError)
{
if (this.notEnough(offset, ends, 2))
return -this.dataLengthNeeded;
this.callbackId = data.getUint32(offset);
this.errorCode = data.getUint16(offset);
offset += 2;
}
else if (this.report == IIPPacketReport.ExecutionError)
{
if (this.notEnough(offset, ends, 2))
return -this.dataLengthNeeded;
if (this.notEnough(offset, ends, 1))
return -this.dataLengthNeeded;
this.errorCode = data.getUint16(offset);
offset += 2;
this.errorCode = data.getUint8(offset++);
if (this.notEnough(offset, ends, 2))
return -this.dataLengthNeeded;
if (this.notEnough(offset, ends, 4))
return -this.dataLengthNeeded;
var cl = data.getUint16(offset);
offset += 2;
var cl = data.getUint32(offset);
offset += 4;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
this.errorMessage = data.getString(offset, cl);
offset += cl;
}
else if (this.report == IIPPacketReport.ProgressReport)
{
if (this.notEnough(offset, ends, 8))
return -this.dataLengthNeeded;
this.errorMessage = data.getString(offset, cl);
offset += cl;
this.progressValue = data.getInt32(offset);
offset += 4;
this.progressMax = data.getInt32(offset);
offset += 4;
}
else if (this.report == IIPPacketReport.ChunkStream)
{
var dt = data.getUint8(offset++);
var size = DataType.sizeOf(dt);
if (size < 0)
{
if (this.notEnough(offset, ends, 4))
return -this.dataLengthNeeded;
var cl = data.getUint32(offset);
offset += 4;
if (this.notEnough(offset, ends, cl))
return -this.dataLengthNeeded;
this.content = data.clip(offset - 5, cl + 5);
offset += cl;
}
else
{
if (this.notEnough(offset, ends, size))
return -this.dataLengthNeeded;
this.content = data.clip(offset - 1, size + 1);
offset += size;
}
}
}
return offset - oOffset;
return offset - this.originalOffset;
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.
*/
/**
* Created by Ahmed Zamil on 16/11/2017.
*/
"use strict";
const ActionType =
{
Attach: 0,
Delete: 1,
Execute: 2,
GetProperty: 3,
SetProperty: 4,
CreateResource: 5,
UpdateAttributes: 6,
InquireAttributes: 7,
AddParent: 8,
RemoveParent: 9,
AddChild: 10,
RemoveChild: 11,
Rename: 12,
ReceiveEvent: 13
};
const Ruling = {
Denied: 0,
Allowed: 1,
DontCare: 2,
};
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 or property to check for permission.</param>
/// <returns>Allowed or denined.</returns>
applicable(resource, session, action, member, inquirer)
{
}
initialize(settings, resource)
{
}
get settings()
{
}
}

View File

@ -24,7 +24,9 @@
* Created by Ahmed Zamil on 25/07/2017.
*/
var ResourceTrigger =
"use strict";
const ResourceTrigger =
{
Loaded : 0,
Initialize: 1,

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 25/07/2017.
*/
"use strict";
class IStore extends IResource {
get(path) {
@ -37,6 +39,21 @@ class IStore extends IResource {
}
record(resource, propertyName, value, age, dateTime)
{
}
getRecord(resource, fromDate, toDate)
{
}
remove(resource)
{
}
constructor()
{
super();

View File

@ -23,22 +23,77 @@
/**
* Created by Ahmed Zamil on 29/08/2017.
*/
"use strict";
class Instance extends IEventHandler
{
getAge(index)
{
if (index < this.ages.Count)
if (index < this.ages.length)
return this.ages[index];
else
return 0;
}
setAge(index, value)
{
if (index < this.ages.length)
{
this.ages[index] = value;
if (value > this.instanceAge)
this.instanceAge = value;
}
}
getModificationDate(index)
{
if (index < this.modificationDates.length)
return this.modificationDates[index];
else
return new Date(0);
}
setModificationDate(index, value)
{
if (index < this.modificationDates.length)
{
this.modificationDates[index] = value;
if (value > this.instanceModificationDate)
this.instanceModificationDate = value;
}
}
loadProperty(name, age, modificationDate, value)
{
var pt = this.template.getPropertyTemplateByName(name);
if (pt == null)
return false;
this.resource[name] = value;
this.setAge(pt.index, age);
this.setModificationDate(pt.index, modificationDate);
return true;
}
deserialize(properties)
{
for(var i = 0; i < this.template.properties.length; i++)
this.resource[this.template.properties[i].name] = properties[i];
for (var i = 0; i < properties.length; i++)
{
var pt = this.template.GetPropertyTemplateByIndex(i);
if (pt != null)
{
var pv = properties[i];
this.loadProperty(pt.name, pv.age, pv.date, pv.value);
}
}
return true;
}
@ -47,8 +102,10 @@ class Instance extends IEventHandler
var props = [];
for (var i = 0; i < this.template.properties.length; i++)
props.push(this.resource[this.template.properties[i].name]);
props.push(new PropertyValue(this.resource[this.template.properties[i].name],
this.ages[this.template.properties[i].index],
this.modificationDates[this.template.properties[i].index]));
return props;
}
@ -57,25 +114,38 @@ class Instance extends IEventHandler
return resource instanceof Storable;
}
emitModification(pt, value)
{
this.instanceAge++;
modified(propertyName = null, newValue = null, oldValue = null)
var now = new Date();
this.ages[pt.index] = this.instanceAge;
this.modificationDates[pt.index] = now;
if (pt.recordable)
this.store.record(this.resource, pt.name, value, this.ages[pt.index], now);
super._emit("ResourceModified", this.resource, pt.name, value);
this.resource._emit("modified", pt.name, value);
}
modified(propertyName = null)
{
if (propertyName == null)
propertyName = modified.caller.name;
if (newValue == null)
var val = {};
if (this.getPropertyValue(propertyName, val))
{
var val = {};
if (this.getPropertyValue(propertyName, val))
super._emit("ResourceModified", this.resource, propertyName, val.value, oldValue);
var pt = this.template.getPropertyTemplateByName(propertyName);
this.emitModification(pt, val.value)
}
else
super._emit("ResourceModified", this.resource, propertyName, newValue, oldValue);
}
emitResourceEvent(name, receivers, args)
_emitResourceEvent(issuer, receivers, name, args)
{
super._emit("ResourceEventOccured", this.resource, name, receivers, args);
super._emit("ResourceEventOccurred", this.resource, issuer, receivers, name, args);
}
getPropertyValue(name, resultObject)
@ -92,7 +162,7 @@ class Instance extends IEventHandler
constructor(id, name, resource, store)
constructor(id, name, resource, store, customTemplate = null, age = 0)
{
super();
@ -101,8 +171,14 @@ class Instance extends IEventHandler
this.id = id;
this.name = name;
this.instanceAge = age;
this.instanceModificationDate = new Date(0);
this.children = new AutoList();
this.parents = new AutoList();
this.managers = new AutoList();
this.attributes = new KeyList();
var self = this;
@ -119,24 +195,157 @@ class Instance extends IEventHandler
self._emit("ResourceDestroyed", sender);
});
this.template = Warehouse.getTemplateByType(this.resource.constructor);
if (customTemplate != null)
this.template = customTemplate;
else
this.template = Warehouse.getTemplateByType(this.resource.constructor);
// set ages
this.ages = new Uint32Array(this.template.properties.length);
this.ages = [];
this.modificationDates = [];
for(var i = 0; i < this.template.properties.length; i++)
{
this.ages.push(0);
this.modificationDates.push(new Date(0));
}
// connect events
var makeHandler = function(name, receivers, args)
{
return new function(receivers, args)
{
self.emitResourceEvent(name, receivers, args);
};
};
for (var i = 0; i < this.template.events.length; i++)
this.resource.on(this.template.events[i].name, makeHandler(this.template.events[i].name));
this.resource.on(this.template.events[i].name, this._makeHandler(this.template.events[i].name));
}
}
_makeHandler(name)
{
var self = this;
return function(args)
{
if (args instanceof CustomResourceEvent)
self._emitResourceEvent(args.issuer, args.receivers, name, args.params);
else
self._emitResourceEvent(null, null, name, args);
};
}
/// <summary>
/// Check for permission.
/// </summary>
/// <param name="session">Caller sessions.</param>
/// <param name="action">Action type</param>
/// <param name="member">Function or property to check for permission.</param>
/// <returns>Ruling.</returns>
applicable(session, action, member, inquirer)
{
for (var i = 0; i < this.managers.length; i++)
{
var r = this.managers.item(i).applicable(this.resource, session, action, member, inquirer);
if (r != Ruling.DontCare)
return r;
}
return Ruling.DontCare;
}
removeAttributes(attributes = null)
{
if (attributes == null)
this.attributes.clear();
else
{
for(var i = 0; i < attributes.length; i++)
this.attributes.remove(attributes[i]);
}
return true;
}
getAttributes(attributes = null)
{
var st = new Structure();
if (attributes == null)
{
attributes = this.attributes.keys.slice(0);
attributes.push("managers");
}
for(var i = 0; i < attributes.length; i++)
{
var attr = attributes[i];
if (attr == "name")
st["name"] = this.name;
else if (attr == "managers")
{
var mngrs = new StructureArray();
for(var j = 0; j < this.managers.length; j++)
{
var manager = this.managers.item(j);
var sm = new Structure();
sm["type"] = manager.constructor.name;
sm["settings"] = manager.settings;
mngrs.push(sm);
}
st["managers"] = mngrs;
}
else
st[attr] = this.attributes.item(attr);
}
return st;
}
setAttributes(attributes, clearAttributes = false)
{
if (clearAttributes)
this.attributes.clear();
for (var attr in attributes)
if (attr == "name")
this.name = attributes[attr];
else if (attr == "managers")
{
this.managers.clear();
var mngrs = attributes[attr];
for (var i = 0; i < mngrs.length; i++)
{
var mngr = mngrs[i];
var type = window[mngr];
var settings = mngr["settings"];
var manager = new (Function.prototype.bind.apply(type));
if (manager instanceof IPermissionsManager)
{
manager.initialize(settings, this.resource);
this.managers.add(manager);
}
else
return false;
}
}
else
{
this.attributes.set(attr, attributes[attr]);
}
return true;
}
}

115
src/KeyList.js Normal file
View File

@ -0,0 +1,115 @@
/*
* 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.
*/
/**
* Created by Ahmed Zamil on 06/11/2017.
*/
"use strict";
class KeyList
{
constructor()
{
this.keys = [];
this.values = [];
}
at(index)
{
return this.values[index];
}
item(key)
{
for(var i = 0; i < this.keys.length; i++)
if (this.keys[i] == key)
return this.values[i];
}
get(key)
{
for(var i = 0; i < this.keys.length; i++)
if (this.keys[i] == key)
return this.values[i];
}
_item_destroyed(sender)
{
for(var i = 0; i < this.values.length; i++)
if (sender == this.values[i])
{
this.removeAt(i);
break;
}
}
add(key, value)
{
this.remove(key);
if (value instanceof IDestructible)
value.on("destroy", this._item_destroyed, this);
this.keys.push(key);
this.values.push(value);
}
contains(key)
{
for(var i = 0; i < this.keys.length; i++)
if (this.keys[i] == key)
return true;
return false;
}
set(key, value)
{
this.remove(key);
this.add(key, value);
}
remove(key)
{
for(var i = 0; i < this.keys.length; i++)
if (key == this.keys[i])
{
this.removeAt(i);
break;
}
}
removeAt(index)
{
if (this.values[index] instanceof IDestructible)
this.values[index].off("destroy", this._item_destroyed);
this.keys.splice(index, 1);
this.values.splice(index, 1);
}
get length()
{
return this.keys.length;
}
}

View File

@ -24,8 +24,9 @@
* Created by Ahmed Zamil on 24/08/2017.
*/
"use strict";
var MemberType = {
const MemberType = {
Function: 0,
Property: 1,
Event: 2

75
src/MemoryStore.js Normal file
View File

@ -0,0 +1,75 @@
/*
* 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.
*/
/**
* Created by Ahmed Zamil on 12/11/2017.
*/
"use strict";
class MemoryStore extends IStore
{
constructor()
{
super();
this.resources = [];
}
put(resource)
{
this.resources[resource.instance.id] = resource;
}
retrive(id)
{
if (this.resources[resource.instance.id])
return new AsyncReply(this.resources[resource.instance.id]);
else
return new AsyncReply(null);
}
get(resource)
{
return new AsyncReply(null);
}
link(resource)
{
if (resource.instance.store == this)
return this.instance.name + "/" + resource.instance.id;
}
trigger(trigger)
{
return new AsyncReply(true);
}
record(resource, propertyName, value, age, dateTime)
{
}
getRecord(resource, fromDate, toDate)
{
}
}

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 01/09/2017.
*/
"use strict";
class NetworkBuffer {
constructor() {
this.neededDataLength = 0;

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 26/08/2017.
*/
"use strict";
class NotModified
{

View File

@ -24,13 +24,14 @@
* Created by Ahmed Zamil on 27/08/2017.
*/
var PropertyPermission = {
"use strict";
const PropertyPermission = {
Read: 1,
Write: 2,
ReadWrite: 3
};
class PropertyTemplate extends MemberTemplate
{
@ -44,12 +45,13 @@ class PropertyTemplate extends MemberTemplate
{
var name = super.compose();
var rt = new BinaryList();
var pv = (this.permission >> 1) | (this.recordable ? 1 : 0);
if (this.writeExpansion != null && this.readExpansion != null)
{
var rexp = DC.stringToBytes(this.readExpansion);
var wexp = DC.stringToBytes(this.writeExpansion);
return rt.addUint8(0x38 | this.permission)
return rt.addUint8(0x38 | pv)
.addUint32(wexp.length)
.addUint8Array(wexp)
.addUint32(rexp.length)
@ -60,7 +62,7 @@ class PropertyTemplate extends MemberTemplate
else if (this.writeExpansion != null)
{
var wexp = DC.stringToBytes(this.writeExpansion);
return rt.addUint8(0x30 | this.permission)
return rt.addUint8(0x30 | pv)
.addUint32(wexp.length)
.addUint8Array(wexp)
.addUint8(name.length)
@ -69,14 +71,14 @@ class PropertyTemplate extends MemberTemplate
else if (this.readExpansion != null)
{
var rexp = DC.stringToBytes(this.readExpansion);
return rt.addUint8(0x28 | this.permission)
return rt.addUint8(0x28 | pv)
.addUint32(rexp.length)
.addUint8Array(rexp)
.addUint8(name.length)
.addUint8Array(name).toArray();
}
else
return rt.addUint8(0x20 | this.permission)
return rt.addUint8(0x20 | pv)
.addUint32(name.length)
.addUint8Array(name).toArray();
}

37
src/PropertyValue.js Normal file
View File

@ -0,0 +1,37 @@
/*
* 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.
*/
/**
* Created by Ahmed Zamil on 06/11/2017.
*/
"use strict";
class PropertyValue
{
constructor(value, age, date)
{
this.value = value;
this.age = age;
this.date = date;
}
}

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 26/08/2017.
*/
"use strict";
class ResourceArray extends Array
{
push(value)

View File

@ -20,18 +20,9 @@
* SOFTWARE.
*/
class ResourceTemplate {
"use strict";
getMemberTemplate(member) {
if (member instanceof MethodInfo)
return this.getFunctionTemplate(member.name);
else if (member instanceof EventInfo)
return this.getEventTemplate(member.name);
else if (member instanceof PropertyInfo)
return this.getPropertyTemplate(member.name);
else
return null;
}
class ResourceTemplate {
getEventTemplateByName(eventName) {
for (var i = 0; i < this.events.length; i++)
@ -107,7 +98,7 @@ class ResourceTemplate {
// set guid
this.className = template.namespace + "." + type.prototype.constructor.name;
this.classId = (new DC(sha256.arrayBuffer(this.className))).getGuid(0);
this.classId = SHA256.compute(DC.stringToBytes(this.className)).getGuid(0);
//byte currentIndex = 0;
@ -117,6 +108,7 @@ class ResourceTemplate {
pt.index = i;
pt.readExpansion = template.properties[i].read;
pt.writeExpansion = template.properties[i].write;
pt.recordable = template.properties[i].recordable;
this.properties.push(pt);
}
@ -224,6 +216,7 @@ class ResourceTemplate {
pt.index = propertyIndex++;
var readExpansion = ((data.getUint8(offset) & 0x8) == 0x8);
var writeExpansion = ((data.getUint8(offset) & 0x10) == 0x10);
pt.recordable = ((data.getUint8(offset) & 1) == 1);
pt.permission = ((data.getUint8(offset++) >> 1) & 0x3);
pt.name = data.getString(offset + 1, data.getUint8(offset));// Encoding.ASCII.getString(data, (int)offset + 1, data.getUint8(offset));
offset += data.getUint8(offset) + 1;

177
src/SHA256.js Normal file
View File

@ -0,0 +1,177 @@
/*
* 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.
*/
/**
* Created by Ahmed Zamil on 25/12/2017.
* Ref: https://en.wikipedia.org/wiki/SHA-2
*/
class SHA256
{
static RROT(n, d)
{
return (n >>> d)|(n << (32 - d));
}
static compute(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):
const hash = new Uint32Array([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):
const k = new Uint32Array([
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
var 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 Uint8Array(paddingLength);
paddingBytes[0] = 0x80;
var data = new DC(BL().addUint8Array(msg).addUint8Array(paddingBytes).addUint64(L).toArray());
// 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 Uint32Array(64);
for(var i = 0; i < 16; i++)
w[i] = data.getInt32(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) ^ (w[i-15] >>> 3);
var s1 = SHA256.RROT(w[i-2], 17) ^ SHA256.RROT(w[i-2], 19) ^ (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);
var temp2 = S0 + maj;
h = g;
g = f;
f = e;
e = (d + temp1) >>> 0;
d = c;
c = b;
b = a;
a = (temp1 + temp2) >>> 0;
}
// Add the compressed chunk to the current hash value:
hash[0] = (hash[0] + a) >>> 0;
hash[1] = (hash[1] + b) >>> 0;
hash[2] = (hash[2] + c) >>> 0;
hash[3] = (hash[3] + d) >>> 0;
hash[4] = (hash[4] + e) >>> 0;
hash[5] = (hash[5] + f) >>> 0;
hash[6] = (hash[6] + g) >>> 0;
hash[7] = (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

@ -24,16 +24,20 @@
* Created by Ahmed Zamil on 02/09/2017.
*/
"use strict";
class SendList extends BinaryList
{
constructor(connection)
constructor(connection, doneReply)
{
super();
this.connection = connection;
this.reply = doneReply;
}
done()
{
this.connection.send(this.toArray());
return this.reply;
}
}

41
src/Session.js Normal file
View File

@ -0,0 +1,41 @@
/*
* 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.
*/
/**
* Created by Ahmed Zamil on 16/11/2017.
*/
"use strict";
class Session
{
constructor(localAuthentication, remoteAuthentication)
{
this.localAuthentication = localAuthentication;
this.remoteAuthentication = remoteAuthentication;
this.id = null;
this.creation = null;
this.modification = null;
}
}

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 26/08/2017.
*/
"use strict";
class Structure
{
getKeys() {

View File

@ -24,6 +24,8 @@
* Created by Ahmed Zamil on 06/09/2017.
*/
"use strict";
class StructureArray extends Array
{
push(value)

View File

@ -23,33 +23,112 @@
/**
* Created by Ahmed Zamil on 25/07/2017.
*/
var Warehouse = {
stores: [],
resources: {},
resourceCounter: 0,
templates: {},
"use strict";
new(type, name, store = null, parent = null)
class Warehouse
{
static new(type, name, store = null, parent = null, manager = null)
{
var res = type();
Warehouse.put(res, name, store, parent);
Warehouse.put(res, name, store, parent, null, 0, manager);
return res;
},
}
get: function(id)
static get(id)
{
if (Warehouse.resources[id])
return new AsyncReply(Warehouse.resources[id]);
if (Number.isInteger(id))
{
//if (Warehouse.resources.contains(id))
return new AsyncReply(Warehouse.resources.item(id));
//else
// return null;
}
else
return null;
},
{
var p = id.split('/');
var res = null;
put: function(resource, name, store, parent){
resource.instance = new Instance(Warehouse.resourceCounter++, name, resource, store);
for(var s = 0; s < this.stores.length; s++)
{
var d = this.stores.at(s);
if (p[0] == d.instance.name)
{
var i = 1;
res = d;
while(p.length > i)
{
var si = i;
for (var r = 0; r < res.instance.children.length; r++)
if (res.instance.children.item(r).instance.name == p[i])
{
i++;
res = res.instance.children.item(r);
break;
}
if (si == i)
// not found, ask the store
return d.get(id.substring(p[0].length + 1));
}
return new AsyncReply(res);
}
}
return new AsyncReply(null);
}
}
static remove(resource)
{
if (Warehouse.resources.contains(resource.instance.id))
Warehouse.resources.remove(resource.instance.id);
else
return false;
if (resource instanceof IStore)
{
Warehouse.stores.remove(resource);
// remove all objects associated with the store
var toBeRemoved = null;
for (var i = 0; i < Warehouse.resources.length; i++)
{
var o = Warehouse.resources.at(i);
if (o.instance.store == resource)
{
if (toBeRemoved == null)
toBeRemoved = [];
toBeRemoved.push(o);
}
}
if (toBeRemoved != null)
for(var i = 0; i < toBeRemoved.length; i++)
Warehouse.remove(toBeRemoved[i]);
}
if (resource.instance.store != null)
resource.instance.store.remove(resource);
resource.destroy();
return true;
}
static put(resource, name, store, parent, customTemplate = null, age = 0, manager = null){
resource.instance = new Instance(Warehouse.resourceCounter++, name, resource, store, customTemplate, age);
//resource.instance.children.on("add", Warehouse._onChildrenAdd).on("remove", Warehouse._onChildrenRemove);
//resource.instance.parents.on("add", Warehouse._onParentsAdd).on("remove", Warehouse._onParentsRemove);
if (manager != null)
resource.instance.managers.add(manager);
if (parent)
{
parent.instance.children.add(resource);
@ -61,69 +140,101 @@ get: function(id)
}
if (resource instanceof IStore)
Warehouse.stores.push(resource);
Warehouse.stores.add(resource);
else
store.put(resource);
Warehouse.resources[resource.instance.id] = resource;
},
Warehouse.resources.add(resource.instance.id, resource);
}
_onParentsRemove: function(value)
static _onParentsRemove(value)
{
if (value.instance.children.contains(value))
value.instance.children.remove(value);
},
}
_onParentsAdd: function(value)
static _onParentsAdd(value)
{
if (!value.instance.children.contains(value))
value.instance.children.add(value);
},
}
_onChildrenRemove: function(value)
static _onChildrenRemove(value)
{
if (value.instance.parents.contains(value))
value.instance.parents.remove(value);
},
}
_onChildrenAdd: function(value)
static _onChildrenAdd(value)
{
if (!value.instance.parents.contains(value))
value.instance.parents.add(value);
},
}
putTemplate: function(template)
static putTemplate(template)
{
if (Warehouse.templates[template.classId])
Warehouse.templates[template.classId] = template;
},
Warehouse.templates.add(template.classId.valueOf(), template);
}
getTemplateByType: function(type)
static getTemplateByType(type)
{
// loaded ?
for (var t in Warehouse.templates)
if (Warehouse.templates[t].className == typeof(type))
return t;
for (var i = 0; i < Warehouse.templates.length; i++)
if (Warehouse.templates.at(i).className == typeof(type))
return Warehouse.templates.at(i);
var template = new ResourceTemplate(type);
Warehouse.templates[template.classId] = template;
Warehouse.templates.add(template.classId.valueOf(), template);
return template;
},
getTemplateByClassId: function(classId)
{
if (Warehouse.templates[classId])
return new AsyncReply(Warehouse.templates[classId]);
return null;
},
getTemplateByClassName: function(className)
{
for(var t in Warehouse.templates)
if (Warehouse.templates[t].className == className)
return new AsyncReply(t);
return null;
}
};
static getTemplateByClassId(classId)
{
var template = Warehouse.templates.item(classId);
return new AsyncReply(template);
}
static getTemplateByClassName(className)
{
for(var i = 0; i < Warehouse.templates.length; i++)
if (Warehouse.templates.at(i).className == className)
return new AsyncReply(Warehouse.templates.at(i));
return new AsyncReply(null);
}
static _qureyIn(path, index, resources)
{
var rt = [];
if (index == path.length - 1)
{
if (path[index] == "")
for(var i = 0; i < resources.length; i++)
rt.push(resources.at(i));
else
for(var i = 0; i < resources.length; i++)
if (resources.at(i).instance.name == path[index])
rt.push(resources.at(i));
}
else
for(var i = 0; i < resources.length; i++)
if (resources.at(i).instance.name == path[index])
rt = rt.concat(Warehouse._qureyIn(path, index+1, resources.at(i).instance.children));
return rt;
}
static query(path)
{
var p = path.split('/');
return new AsyncReply(Warehouse._qureyIn(p, 0, Warehouse.stores));
}
}
// Initialize
Warehouse.stores = new AutoList();
Warehouse.resources = new KeyList();
Warehouse.resourceCounter = 0;
Warehouse.templates = new KeyList();