mirror of
https://github.com/esiur/esiur-js.git
synced 2025-05-06 12:32:58 +00:00
2063 lines
78 KiB
JavaScript
2063 lines
78 KiB
JavaScript
/*
|
|
* 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/07/2017.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
import IStore from '../../Resource/IStore.js';
|
|
import Session from '../../Security/Authority/Session.js';
|
|
import Authentication from '../../Security/Authority/Authentication.js';
|
|
import AuthenticationType from "../../Security/Authority/AuthenticationType.js";
|
|
|
|
import SHA256 from '../../Security/Integrity/SHA256.js';
|
|
import { BL, DC } from '../../Data/DataConverter.js';
|
|
import SendList from '../SendList.js';
|
|
|
|
import AsyncReply from '../../Core/AsyncReply.js';
|
|
import Codec from '../../Data/Codec.js';
|
|
import NetworkBuffer from '../Sockets/NetworkBuffer.js';
|
|
import KeyList from '../../Data/KeyList.js';
|
|
import AsyncQueue from '../../Core/AsyncQueue.js';
|
|
import Warehouse from '../../Resource/Warehouse.js';
|
|
|
|
import IIPAuthPacket from "../Packets/IIPAuthPacket.js";
|
|
import IIPPacket from "../Packets/IIPPacket.js";
|
|
import IIPAuthPacketAction from "../Packets/IIPAuthPacketAction.js";
|
|
import IIPAuthPacketCommand from "../Packets/IIPAuthPacketCommand.js";
|
|
import AuthenticationMethod from "../../Security/Authority/AuthenticationMethod.js";
|
|
|
|
import IIPPacketAction from "../Packets/IIPPacketAction.js";
|
|
import IIPPacketCommand from "../Packets/IIPPacketCommand.js";
|
|
import IIPPacketEvent from "../Packets/IIPPacketEvent.js";
|
|
import IIPPacketReport from "../Packets//IIPPacketReport.js";
|
|
|
|
import ErrorType from "../../Core/ErrorType.js";
|
|
import ProgressType from "../../Core/ProgressType.js";
|
|
import ExceptionCode from "../../Core/ExceptionCode.js";
|
|
|
|
import DistributedResource from './DistributedResource.js';
|
|
import ResourceTemplate from '../../Resource/Template/ResourceTemplate.js';
|
|
|
|
import DistributedResourceQueueItem from './DistributedResourceQueueItem.js';
|
|
import DistributedResourceQueueItemType from './DistributedResourceQueueItemType.js';
|
|
|
|
import DistributedPropertyContext from './DistributedPropertyContext.js';
|
|
import { ResourceTrigger } from '../../Resource/IResource.js';
|
|
|
|
import Ruling from '../../Security/Permissions/Ruling.js';
|
|
import ActionType from '../../Security/Permissions/ActionType.js';
|
|
import AsyncException from '../../Core/AsyncException.js';
|
|
|
|
export default class DistributedConnection extends IStore {
|
|
|
|
|
|
send(data) {
|
|
|
|
if (this.holdSending) {
|
|
//console.log("hold ", data.length);
|
|
this.sendBuffer.writeAll(data);
|
|
}
|
|
else
|
|
//console.log("Send", data.length);
|
|
this.socket.send(data.buffer);
|
|
}
|
|
|
|
sendParams(doneReply) {
|
|
return new SendList(this, doneReply);
|
|
}
|
|
|
|
generateNonce(length) {
|
|
var rt = new Uint8Array(length);
|
|
for (var i = 0; i < length; i++)
|
|
rt[i] = Math.random() * 255;
|
|
|
|
return rt;
|
|
}
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
//Instance.Name = Global.GenerateCode(12);
|
|
|
|
//this.hostType = AuthenticationType.Client;
|
|
//this.domain = domain;
|
|
//this.localUsername = username;
|
|
|
|
//this._register("ready");
|
|
//this._register("error");
|
|
this._register("close");
|
|
|
|
this.session = new Session(new Authentication(AuthenticationType.Client), new Authentication(AuthenticationType.Host));
|
|
|
|
this.packet = new IIPPacket();
|
|
this.authPacket = new IIPAuthPacket();
|
|
|
|
this.resources = new KeyList();//{};
|
|
this.templates = new KeyList();
|
|
this.requests = new KeyList();// {};
|
|
//this.pathRequests = new KeyList();// {};
|
|
this.templateRequests = new KeyList();
|
|
this.resourceRequests = new KeyList();// {};
|
|
this.callbackCounter = 0;
|
|
|
|
this.queue = new AsyncQueue();
|
|
|
|
this.queue.then(function (x) {
|
|
if (x.type == DistributedResourceQueueItemType.Event) {
|
|
x.resource._emitEventByIndex(x.index, x.value);
|
|
}
|
|
else {
|
|
x.resource._updatePropertyByIndex(x.index, x.value);
|
|
}
|
|
});
|
|
|
|
this.localNonce = this.generateNonce(32);// new Uint8Array(32);
|
|
//window.crypto.getRandomValues(this.localNonce);
|
|
|
|
// declare (Credentials -> No Auth, No Enctypt)
|
|
//this.socket.onerror = function(event)
|
|
//{
|
|
// self.close(event);
|
|
//};
|
|
}
|
|
|
|
|
|
|
|
processPacket(msg, offset, ends, data) {
|
|
|
|
|
|
var authPacket = this.authPacket;
|
|
|
|
if (this.ready) {
|
|
var packet = new IIPPacket();
|
|
|
|
var rt = packet.parse(msg, offset, ends);
|
|
if (rt <= 0) {
|
|
data.holdFor(msg, offset, ends - offset, -rt);
|
|
return ends;
|
|
}
|
|
else {
|
|
offset += rt;
|
|
|
|
try {
|
|
if (packet.command == IIPPacketCommand.Event) {
|
|
switch (packet.event) {
|
|
case IIPPacketEvent.ResourceReassigned:
|
|
this.IIPEventResourceReassigned(packet.resourceId, packet.newResourceId);
|
|
break;
|
|
case IIPPacketEvent.ResourceDestroyed:
|
|
this.IIPEventResourceDestroyed(packet.resourceId);
|
|
break;
|
|
case IIPPacketEvent.PropertyUpdated:
|
|
this.IIPEventPropertyUpdated(packet.resourceId, packet.methodIndex, packet.content);
|
|
break;
|
|
case IIPPacketEvent.EventOccurred:
|
|
this.IIPEventEventOccurred(packet.resourceId, packet.methodIndex, packet.content);
|
|
break;
|
|
|
|
case IIPPacketEvent.ChildAdded:
|
|
this.IIPEventChildAdded(packet.resourceId, packet.childId);
|
|
break;
|
|
case IIPPacketEvent.ChildRemoved:
|
|
this.IIPEventChildRemoved(packet.resourceId, packet.childId);
|
|
break;
|
|
case IIPPacketEvent.Renamed:
|
|
this.IIPEventRenamed(packet.resourceId, packet.content);
|
|
break;
|
|
case IIPPacketEvent.AttributesUpdated:
|
|
this.IIPEventAttributesUpdated(packet.resourceId, packet.content);
|
|
break;
|
|
|
|
}
|
|
}
|
|
else if (packet.command == IIPPacketCommand.Request) {
|
|
switch (packet.action) {
|
|
|
|
// Manage
|
|
case IIPPacketAction.AttachResource:
|
|
this.IIPRequestAttachResource(packet.callbackId, packet.resourceId);
|
|
break;
|
|
case IIPPacketAction.ReattachResource:
|
|
this.IIPRequestReattachResource(packet.callbackId, packet.resourceId, packet.resourceAge);
|
|
break;
|
|
case IIPPacketAction.DetachResource:
|
|
this.IIPRequestDetachResource(packet.callbackId, packet.resourceId);
|
|
break;
|
|
case IIPPacketAction.CreateResource:
|
|
this.IIPRequestCreateResource(packet.callbackId, packet.storeId, packet.resourceId, packet.content);
|
|
break;
|
|
case IIPPacketAction.DeleteResource:
|
|
this.IIPRequestDeleteResource(packet.callbackId, packet.resourceId);
|
|
break;
|
|
case IIPPacketAction.AddChild:
|
|
this.IIPRequestAddChild(packet.callbackId, packet.resourceId, packet.childId);
|
|
break;
|
|
case IIPPacketAction.RemoveChild:
|
|
this.IIPRequestRemoveChild(packet.callbackId, packet.resourceId, packet.childId);
|
|
break;
|
|
case IIPPacketAction.RenameResource:
|
|
this.IIPRequestRenameResource(packet.callbackId, packet.resourceId, packet.content);
|
|
break;
|
|
|
|
// Inquire
|
|
case IIPPacketAction.TemplateFromClassName:
|
|
this.IIPRequestTemplateFromClassName(packet.callbackId, packet.className);
|
|
break;
|
|
case IIPPacketAction.TemplateFromClassId:
|
|
this.IIPRequestTemplateFromClassId(packet.callbackId, packet.classId);
|
|
break;
|
|
case IIPPacketAction.TemplateFromResourceId:
|
|
this.IIPRequestTemplateFromResourceId(packet.callbackId, packet.resourceId);
|
|
break;
|
|
case IIPPacketAction.QueryLink:
|
|
this.IIPRequestQueryResources(packet.callbackId, packet.resourceLink);
|
|
break;
|
|
case IIPPacketAction.ResourceChildren:
|
|
this.IIPRequestResourceChildren(packet.callbackId, packet.resourceId);
|
|
break;
|
|
case IIPPacketAction.ResourceParents:
|
|
this.IIPRequestResourceParents(packet.callbackId, packet.resourceId);
|
|
break;
|
|
case IIPPacketAction.ResourceHistory:
|
|
this.IIPRequestInquireResourceHistory(packet.callbackId, packet.resourceId, packet.fromDate, packet.toDate);
|
|
break;
|
|
|
|
// Invoke
|
|
case IIPPacketAction.InvokeFunctionArrayArguments:
|
|
this.IIPRequestInvokeFunctionArrayArguments(packet.callbackId, packet.resourceId, packet.methodIndex, packet.content);
|
|
break;
|
|
case IIPPacketAction.InvokeFunctionNamedArguments:
|
|
this.IIPRequestInvokeFunctionNamedArguments(packet.callbackId, packet.resourceId, packet.methodIndex, packet.content);
|
|
break;
|
|
case IIPPacketAction.GetProperty:
|
|
this.IIPRequestGetProperty(packet.callbackId, packet.resourceId, packet.methodIndex);
|
|
break;
|
|
case IIPPacketAction.GetPropertyIfModified:
|
|
this.IIPRequestGetPropertyIfModifiedSince(packet.callbackId, packet.resourceId, packet.methodIndex, packet.resourceAge);
|
|
break;
|
|
case IIPPacketAction.SetProperty:
|
|
this.IIPRequestSetProperty(packet.callbackId, packet.resourceId, packet.methodIndex, packet.content);
|
|
break;
|
|
case IIPPacketAction.ResourceHistory:
|
|
this.IIPRequestInquireResourceHistory(packet.callbackId, packet.resourceId, packet.fromDate, packet.toDate);
|
|
break;
|
|
case IIPPacketAction.QueryLink:
|
|
this.IIPRequestQueryResources(packet.callbackId, packet.resourceLink);
|
|
break;
|
|
|
|
// Attribute
|
|
case IIPPacketAction.GetAllAttributes:
|
|
this.IIPRequestGetAttributes(packet.callbackId, packet.resourceId, packet.content, true);
|
|
break;
|
|
case IIPPacketAction.UpdateAllAttributes:
|
|
this.IIPRequestUpdateAttributes(packet.callbackId, packet.resourceId, packet.content, true);
|
|
break;
|
|
case IIPPacketAction.ClearAllAttributes:
|
|
this.IIPRequestClearAttributes(packet.callbackId, packet.resourceId, packet.content, true);
|
|
break;
|
|
case IIPPacketAction.GetAttributes:
|
|
this.IIPRequestGetAttributes(packet.callbackId, packet.resourceId, packet.content, false);
|
|
break;
|
|
case IIPPacketAction.UpdateAttributes:
|
|
this.IIPRequestUpdateAttributes(packet.callbackId, packet.resourceId, packet.content, false);
|
|
break;
|
|
case IIPPacketAction.ClearAttributes:
|
|
this.IIPRequestClearAttributes(packet.callbackId, packet.resourceId, packet.content, false);
|
|
break;
|
|
|
|
}
|
|
}
|
|
else if (packet.command == IIPPacketCommand.Reply) {
|
|
switch (packet.action) {
|
|
case IIPPacketAction.AttachResource:
|
|
this.IIPReply(packet.callbackId, packet.classId, packet.resourceAge, packet.resourceLink, packet.content);
|
|
break;
|
|
case IIPPacketAction.ReattachResource:
|
|
this.IIPReply(packet.callbackId, packet.resourceAge, packet.content);
|
|
break;
|
|
case IIPPacketAction.DetachResource:
|
|
this.IIPReply(packet.callbackId);
|
|
break;
|
|
case IIPPacketAction.CreateResource:
|
|
this.IIPReply(packet.callbackId, packet.resourceId);
|
|
break;
|
|
case IIPPacketAction.DeleteResource:
|
|
case IIPPacketAction.AddChild:
|
|
case IIPPacketAction.RemoveChild:
|
|
case IIPPacketAction.RenameResource:
|
|
this.IIPReply(packet.callbackId);
|
|
break;
|
|
case IIPPacketAction.TemplateFromClassName:
|
|
case IIPPacketAction.TemplateFromClassId:
|
|
case IIPPacketAction.TemplateFromResourceId:
|
|
this.IIPReply(packet.callbackId, ResourceTemplate.parse(packet.content));
|
|
break;
|
|
|
|
case IIPPacketAction.QueryLink:
|
|
case IIPPacketAction.ResourceChildren:
|
|
case IIPPacketAction.ResourceParents:
|
|
case IIPPacketAction.ResourceHistory:
|
|
this.IIPReply(packet.callbackId, packet.content);
|
|
break;
|
|
|
|
case IIPPacketAction.InvokeFunctionArrayArguments:
|
|
case IIPPacketAction.InvokeFunctionNamedArguments:
|
|
this.IIPReplyInvoke(packet.callbackId, packet.content);
|
|
break;
|
|
|
|
case IIPPacketAction.GetProperty:
|
|
this.IIPReply(packet.callbackId, packet.content);
|
|
break;
|
|
case IIPPacketAction.GetPropertyIfModified:
|
|
this.IIPReply(packet.callbackId, packet.content);
|
|
break;
|
|
case IIPPacketAction.SetProperty:
|
|
this.IIPReply(packet.callbackId);
|
|
break;
|
|
|
|
// Attribute
|
|
case IIPPacketAction.GetAllAttributes:
|
|
case IIPPacketAction.GetAttributes:
|
|
this.IIPReply(packet.callbackId, packet.content);
|
|
break;
|
|
|
|
case IIPPacketAction.UpdateAllAttributes:
|
|
case IIPPacketAction.UpdateAttributes:
|
|
case IIPPacketAction.ClearAllAttributes:
|
|
case IIPPacketAction.ClearAttributes:
|
|
this.IIPReply(packet.callbackId);
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
else if (packet.command == IIPPacketCommand.Report) {
|
|
switch (packet.report) {
|
|
case IIPPacketReport.ManagementError:
|
|
this.IIPReportError(packet.callbackId, ErrorType.Management, packet.errorCode, null);
|
|
break;
|
|
case IIPPacketReport.ExecutionError:
|
|
this.IIPReportError(packet.callbackId, ErrorType.Exception, packet.errorCode, packet.errorMessage);
|
|
break;
|
|
case IIPPacketReport.ProgressReport:
|
|
this.IIPReportProgress(packet.callbackId, ProgressType.Execution, packet.progressValue, packet.progressMax);
|
|
break;
|
|
case IIPPacketReport.ChunkStream:
|
|
this.IIPReportChunk(packet.callbackId, packet.content);
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
} catch (ex) {
|
|
console.log("Esiur Error ", ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
else {
|
|
var rt = authPacket.parse(msg, offset, ends);
|
|
|
|
|
|
if (rt <= 0) {
|
|
data.holdAllFor(msg, ends - rt);
|
|
return ends;
|
|
}
|
|
else {
|
|
offset += rt;
|
|
|
|
if (this.session.localAuthentication.type == AuthenticationType.Host) {
|
|
if (authPacket.command == IIPAuthPacketCommand.Declare) {
|
|
if (authPacket.remoteMethod == AuthenticationMethod.credentials
|
|
&& authPacket.localMethod == AuthenticationMethod.None) {
|
|
this.session.remoteAuthentication.username = authPacket.remoteUsername;
|
|
this.remoteNonce = authPacket.remoteNonce;
|
|
this.domain = authPacket.domain;
|
|
this.sendParams().addUint8(0xa0).addUint8Array(this.localNonce).done();
|
|
}
|
|
}
|
|
else if (authPacket.command == IIPAuthPacketCommand.Action) {
|
|
if (authPacket.action == IIPAuthPacketAction.AuthenticateHash) {
|
|
var remoteHash = authPacket.hash;
|
|
|
|
this.server.membership.getPassword(this.session.remoteAuthentication.username, this.domain).then(function (pw) {
|
|
if (pw != null) {
|
|
|
|
//var hash = new DC(sha256.arrayBuffer(BL().addString(pw).addUint8Array(remoteNonce).addUint8Array(this.localNonce).toArray()));
|
|
var hash = SHA256.compute(BL().addString(pw).addUint8Array(remoteNonce).addUint8Array(this.localNonce).toDC());
|
|
|
|
|
|
if (hash.sequenceEqual(remoteHash)) {
|
|
// send our hash
|
|
//var localHash = new DC(sha256.arrayBuffer((new BinaryList()).addUint8Array(this.localNonce).addUint8Array(remoteNonce).addUint8Array(pw).toArray()));
|
|
var localHash = SHA256.compute(BL().addUint8Array(this.localNonce).addUint8Array(remoteNonce).addUint8Array(pw).toDC());
|
|
this.sendParams().addUint8(0).addUint8Array(localHash).done();
|
|
|
|
this.readyToEstablish = true;
|
|
}
|
|
else {
|
|
// incorrect password
|
|
this.sendParams().addUint8(0xc0)
|
|
.addInt32(ExceptionCode.AccessDenied)
|
|
.addUint16(13)
|
|
.addString("Access Denied")
|
|
.done();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
else if (authPacket.action == IIPAuthPacketAction.NewConnection) {
|
|
if (readyToEstablish) {
|
|
this.session.id = this.generateNonce(32);// new DC(32);
|
|
//window.crypto.getRandomValues(this.session.id);
|
|
|
|
this.sendParams().addUint8(0x28).addUint8Array(this.session.id).done();
|
|
this.ready = true;
|
|
|
|
this.openReply.trigger(this);
|
|
this.openReply = null;
|
|
//this._emit("ready", this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (this.session.localAuthentication.type == AuthenticationType.Client) {
|
|
if (authPacket.command == IIPAuthPacketCommand.Acknowledge) {
|
|
this.remoteNonce = authPacket.remoteNonce;
|
|
|
|
// send our hash
|
|
|
|
var localHash = SHA256.compute(BL().addUint8Array(this.localPasswordOrToken)
|
|
.addUint8Array(this.localNonce)
|
|
.addUint8Array(this.remoteNonce).toDC());
|
|
|
|
this.sendParams().addUint8(0).addUint8Array(localHash).done();
|
|
}
|
|
else if (authPacket.command == IIPAuthPacketCommand.Action) {
|
|
if (authPacket.action == IIPAuthPacketAction.AuthenticateHash) {
|
|
|
|
var remoteHash = SHA256.compute(BL().addUint8Array(this.remoteNonce)
|
|
.addUint8Array(this.localNonce)
|
|
.addUint8Array(this.localPasswordOrToken).toDC());
|
|
|
|
|
|
if (remoteHash.sequenceEqual(authPacket.hash)) {
|
|
// send establish request
|
|
this.sendParams().addUint8(0x20).addUint16(0).done();
|
|
}
|
|
else {
|
|
this.sendParams().addUint8(0xc0)
|
|
.addUint32(ExceptionCode.ChallengeFailed)
|
|
.addUint16(16)
|
|
.addString("Challenge Failed")
|
|
.done();
|
|
}
|
|
}
|
|
else if (authPacket.action == IIPAuthPacketAction.ConnectionEstablished) {
|
|
this.session.id = authPacket.sessionId;
|
|
this.ready = true;
|
|
this.openReply.trigger(this);
|
|
this.openReply = null;
|
|
|
|
//this._emit("ready", this);
|
|
}
|
|
}
|
|
else if (authPacket.command == IIPAuthPacketCommand.Error) {
|
|
this.openReply.triggerError(1, authPacket.errorCode, authPacket.errorMessage);
|
|
this.openReply = null;
|
|
//this._emit("error", this, authPacket.errorCode, authPacket.errorMessage);
|
|
this.close();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
|
|
//if (offset < ends)
|
|
// this.processPacket(msg, offset, ends, data);
|
|
}
|
|
|
|
receive(data) {
|
|
var msg = data.read();
|
|
var offset = 0;
|
|
var ends = msg.length;
|
|
var packet = this.packet;
|
|
|
|
//console.log("Data");
|
|
|
|
while (offset < ends) {
|
|
offset = this.processPacket(msg, offset, ends, data);
|
|
}
|
|
}
|
|
|
|
close(event) {
|
|
|
|
this.ready = false;
|
|
this.readyToEstablish = false;
|
|
|
|
try
|
|
{
|
|
this.requests.values.forEach((x) => x.triggerError(new AsyncException(ErrorType.Management, 0, "Connection closed")));
|
|
this.resourceRequests.values.forEach((x) => x.triggerError(new AsyncException(ErrorType.Management, 0, "Connection closed")));
|
|
this.templateRequests.values.forEach((x) => x.triggerError(new AsyncException(ErrorType.Management, 0, "Connection closed")));
|
|
}
|
|
catch(ex)
|
|
{
|
|
// unhandled error
|
|
}
|
|
|
|
this.resources.values.forEach((x) => x._suspend());
|
|
|
|
this.requests.clear();
|
|
this.resourceRequests.clear();
|
|
this.templateRequests.clear();
|
|
|
|
// Warehouse.remove(this);
|
|
|
|
if (this.socket.readyState != this.socket.CLOSED) {
|
|
this.socket.close();
|
|
}
|
|
|
|
this._emit("close", event);
|
|
}
|
|
|
|
async reconnect() {
|
|
try {
|
|
if (await this.connect()) {
|
|
try {
|
|
var bag = new AsyncBag();
|
|
|
|
for (var i = 0; i < this.resources.keys.length; i++) {
|
|
var index = this.resources.keys[i];
|
|
bag.add(this.fetch(index));
|
|
}
|
|
|
|
bag.seal();
|
|
await bag;
|
|
}
|
|
catch (ex) {
|
|
console.log(ex);
|
|
}
|
|
}
|
|
}
|
|
catch (ex) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
hold() {
|
|
this.holdSending = true;
|
|
}
|
|
|
|
unhold() {
|
|
if (this.holdSending) {
|
|
this.holdSending = false;
|
|
|
|
var msg = this.sendBuffer.read();
|
|
|
|
if (msg == null || msg.length == 0)
|
|
return;
|
|
|
|
this.socket.send(msg);
|
|
}
|
|
}
|
|
|
|
trigger(trigger) {
|
|
if (trigger == ResourceTrigger.Open) {
|
|
var { domain = null,
|
|
secure = false,
|
|
username = "guest",
|
|
password = "",
|
|
checkInterval = 30,
|
|
connectionTimeout = 600,
|
|
revivingTime = 120,
|
|
tokenIndex = 0,
|
|
token = null,
|
|
debug = false } = this.instance.attributes.toObject();
|
|
|
|
|
|
this.debug = debug;
|
|
this.checkInterval = checkInterval * 1000; // check every 30 seconds
|
|
this.connectionTimeout = connectionTimeout * 1000; // 10 minutes (4 pings failed)
|
|
this.revivingTime = revivingTime * 1000; // 2 minutes
|
|
|
|
|
|
var host = this.instance.name.split(':');
|
|
|
|
var address = host[0];
|
|
var port = parseInt(host[1]);
|
|
|
|
if (token != null)
|
|
{
|
|
var tk = DC.stringToBytes(token);
|
|
return this.connect(secure, AuthenticationMethod.token, address, port, null, tokenIndex, tk, domain);
|
|
}
|
|
else
|
|
{
|
|
var pw = DC.stringToBytes(password);
|
|
return this.connect(secure, AuthenticationMethod.credentials, address, port, username, null, pw, domain);
|
|
}
|
|
}
|
|
|
|
return new AsyncReply(true);
|
|
}
|
|
|
|
|
|
connect(secure, method, hostname, port, username, tokenIndex, passwordOrToken, domain) {
|
|
this.openReply = new AsyncReply();
|
|
|
|
|
|
if (secure !== undefined) {
|
|
|
|
this.session.localAuthentication.method = method;
|
|
this.session.localAuthentication.tokenIndex = tokenIndex;
|
|
|
|
this.session.localAuthentication.domain = domain;
|
|
this.session.localAuthentication.username = username;
|
|
this.localPasswordOrToken = passwordOrToken;
|
|
|
|
//this.url = `ws${secure ? 's' : ''}://${this.instance.name}`;
|
|
this.url = `ws${secure ? 's' : ''}://${hostname}:${port}`;
|
|
}
|
|
|
|
//this.debug = debug;
|
|
this.totalReceived = 0;
|
|
this.totalSent = 0;
|
|
|
|
this.lastAction = Date.now();
|
|
|
|
this.socket = new WebSocket(this.url, "iip");
|
|
this.socket.binaryType = "arraybuffer";
|
|
this.socket.connection = this;
|
|
this.socket.networkBuffer = new NetworkBuffer();
|
|
this.sendBuffer = new NetworkBuffer();
|
|
|
|
var un = DC.stringToBytes(this.session.localAuthentication.username);
|
|
var dmn = DC.stringToBytes(this.session.localAuthentication.domain);
|
|
var self = this;
|
|
|
|
this.socket.onopen = function () {
|
|
var bl = BL();
|
|
bl.addUint8(0x60).addUint8(dmn.length).addUint8Array(dmn).addUint8Array(self.localNonce).addUint8(un.length).addUint8Array(un);
|
|
self.send(bl.toArray());
|
|
};
|
|
|
|
this.socket.onmessage = function (msg) {
|
|
|
|
//console.log("Rec", msg.data.byteLength);
|
|
|
|
this.networkBuffer.writeAll(msg.data);
|
|
|
|
self.lastAction = new Date();
|
|
|
|
self.hold();
|
|
while (this.networkBuffer.available > 0 && !this.networkBuffer.protected) {
|
|
// try
|
|
// {
|
|
self.receive(this.networkBuffer);
|
|
// }
|
|
// catch(e)
|
|
//{
|
|
// console.log(e);
|
|
//}
|
|
}
|
|
|
|
self.unhold();
|
|
|
|
};
|
|
|
|
this.socket.onclose = function (event) {
|
|
if (this.connection.openReply) {
|
|
this.connection.openReply.triggerError(0, 0, "Host not reachable");
|
|
this.connection.openReply = null;
|
|
}
|
|
|
|
self.close(event);
|
|
};
|
|
|
|
return this.openReply;
|
|
}
|
|
|
|
reconnect() {
|
|
|
|
}
|
|
|
|
put(resource) {
|
|
this.resources.add(parseInt(resource.instance.name), resource);
|
|
return true;
|
|
}
|
|
|
|
remove(resource) {
|
|
// nothing to do (IStore interface)
|
|
}
|
|
|
|
// Protocol Implementation
|
|
sendRequest(action) {
|
|
var reply = new AsyncReply();
|
|
this.callbackCounter++;
|
|
this.requests.set(this.callbackCounter, reply);
|
|
return this.sendParams(reply).addUint8(0x40 | action).addUint32(this.callbackCounter);
|
|
}
|
|
|
|
sendDetachRequest(instanceId)
|
|
{
|
|
try
|
|
{
|
|
return this.sendRequest(IIPPacketAction.DetachResource).addUint32(instanceId).done();
|
|
}
|
|
catch(ex)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
sendInvokeByArrayArguments(instanceId, index, parameters) {
|
|
var reply = new AsyncReply();
|
|
|
|
var pb = Codec.composeVarArray(parameters, this, true);
|
|
|
|
this.callbackCounter++;
|
|
this.sendParams()
|
|
.addUint8(0x40 | IIPPacketAction.InvokeFunctionArrayArguments)
|
|
.addUint32(this.callbackCounter)
|
|
.addUint32(instanceId)
|
|
.addUint8(index)
|
|
.addUint8Array(pb)
|
|
.done();
|
|
|
|
this.requests.set(this.callbackCounter, reply);
|
|
|
|
return reply;
|
|
}
|
|
|
|
sendInvokeByNamedArguments(instanceId, index, parameters) {
|
|
var reply = new AsyncReply();
|
|
|
|
var pb = Codec.composeStructure(parameters, this, true, true, true);
|
|
|
|
this.callbackCounter++;
|
|
this.sendParams()
|
|
.addUint8(0x40 | IIPPacketAction.InvokeFunctionNamedArguments)
|
|
.addUint32(this.callbackCounter)
|
|
.addUint32(instanceId)
|
|
.addUint8(index)
|
|
.addUint8Array(pb)
|
|
.done();
|
|
|
|
this.requests.set(this.callbackCounter, reply);
|
|
|
|
return reply;
|
|
}
|
|
|
|
|
|
sendError(type, callbackId, errorCode, errorMessage = "") {
|
|
var msg = DC.stringToBytes(errorMessage);
|
|
if (type == ErrorType.Management)
|
|
this.sendParams()
|
|
.addUint8(0xC0 | IIPPacketReport.ManagementError)
|
|
.addUint32(callbackId)
|
|
.addUint16(errorCode)
|
|
.done();
|
|
else if (type == ErrorType.Exception)
|
|
this.sendParams()
|
|
.addUint8(0xC0 | IIPPacketReport.ExecutionError)
|
|
.addUint32(callbackId)
|
|
.addUint16(errorCode)
|
|
.addUint16(msg.length)
|
|
.addUint8Array(msg)
|
|
.done();
|
|
}
|
|
|
|
sendProgress(callbackId, value, max) {
|
|
this.sendParams()
|
|
.addUint8(0xC0 | IIPPacketReport.ProgressReport)
|
|
.addUint32(callbackId)
|
|
.addInt32(value)
|
|
.addInt32(max)
|
|
.done();
|
|
}
|
|
|
|
sendChunk(callbackId, chunk) {
|
|
var c = Codec.compose(chunk, this, true);
|
|
this.sendParams()
|
|
.addUint8(0xC0 | IIPPacketReport.ChunkStream)
|
|
.addUint32(callbackId)
|
|
.addUint8Array(c)
|
|
.done();
|
|
}
|
|
|
|
IIPReply(callbackId) {
|
|
|
|
var results = Array.prototype.slice.call(arguments, 1);
|
|
var req = this.requests.item(callbackId);
|
|
this.requests.remove(callbackId);
|
|
req.trigger(results);
|
|
}
|
|
|
|
IIPReplyInvoke(callbackId, result) {
|
|
|
|
var req = this.requests.item(callbackId);
|
|
|
|
if (req != null) {
|
|
|
|
this.requests.remove(callbackId);
|
|
|
|
Codec.parse(result, 0, {}, this).then(function (rt) {
|
|
req.trigger(rt);
|
|
});
|
|
}
|
|
}
|
|
|
|
IIPReportError(callbackId, errorType, errorCode, errorMessage) {
|
|
var req = this.requests.item(callbackId);
|
|
if (req != null)
|
|
{
|
|
this.requests.remove(callbackId);
|
|
req.triggerError(errorType, errorCode, errorMessage);
|
|
}
|
|
}
|
|
|
|
IIPReportProgress(callbackId, type, value, max) {
|
|
var req = this.requests.item(callbackId);
|
|
if (req != null)
|
|
req.triggerProgress(type, value, max);
|
|
}
|
|
|
|
IIPReportChunk(callbackId, data) {
|
|
var req = this.requests.item(callbackId);
|
|
if (req != null) {
|
|
Codec.parse(data, 0, {}, this).then(function (x) {
|
|
req.triggerChunk(x);
|
|
});
|
|
}
|
|
}
|
|
|
|
IIPEventResourceReassigned(resourceId, newResourceId) {
|
|
|
|
}
|
|
|
|
IIPEventResourceDestroyed(resourceId) {
|
|
if (this.resources.item(resourceId)) {
|
|
var r = this.resources.item(resourceId);
|
|
this.resources.remove(resourceId);
|
|
r.destroy();
|
|
}
|
|
}
|
|
|
|
IIPEventPropertyUpdated(resourceId, index, content) {
|
|
|
|
let self = this;
|
|
|
|
this.fetch(resourceId).then(function (r) {
|
|
|
|
let pt = r.instance.template.getPropertyTemplateByIndex(index);
|
|
|
|
if (pt == null)
|
|
return; // ft found, fi not found, this should never happen
|
|
|
|
// push to the queue to gaurantee serialization
|
|
let item = new AsyncReply();
|
|
self.queue.add(item);
|
|
|
|
Codec.parse(content, 0, {}, self).then(function (args) {
|
|
item.trigger(new DistributedResourceQueueItem(r, DistributedResourceQueueItemType.Propery, args, index));
|
|
}).error(function (ex) {
|
|
self.queue.remove(item);
|
|
console.log("Esiur Property Error", ex);
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
IIPEventEventOccurred(resourceId, index, content) {
|
|
var self = this;
|
|
|
|
this.fetch(resourceId).then(function (r) {
|
|
let et = r.instance.template.getEventTemplateByIndex(index);
|
|
|
|
if (et == null)
|
|
return; // ft found, fi not found, this should never happen
|
|
|
|
// push to the queue to guarantee serialization
|
|
var item = new AsyncReply();
|
|
self.queue.add(item);
|
|
|
|
Codec.parseVarArray(content, 0, content.length, self).then(function (args) {
|
|
item.trigger(new DistributedResourceQueueItem(r, DistributedResourceQueueItemType.Event, args, index));
|
|
|
|
}).error(function (ex) {
|
|
self.queue.remove(item);
|
|
console.log("Esiur Event Error", ex);
|
|
});
|
|
});
|
|
}
|
|
|
|
IIPEventChildAdded(resourceId, childId) {
|
|
var self = this;
|
|
|
|
this.fetch(resourceId).then(function (parent) {
|
|
self.fetch(childId).then(function (child) {
|
|
parent.instance.children.add(child);
|
|
});
|
|
});
|
|
}
|
|
|
|
IIPEventChildRemoved(resourceId, childId) {
|
|
var self = this;
|
|
|
|
this.fetch(resourceId).then(function (parent) {
|
|
self.fetch(childId).then(function (child) {
|
|
parent.instance.children.remove(child);
|
|
});
|
|
});
|
|
}
|
|
|
|
IIPEventRenamed(resourceId, name) {
|
|
this.fetch(resourceId).then(function (resource) {
|
|
resource.instance.attributes.set("name", name.getString(0, name.length));
|
|
});
|
|
}
|
|
|
|
|
|
IIPEventAttributesUpdated(resourceId, attributes) {
|
|
var self = this;
|
|
|
|
this.fetch(resourceId).then(function (resource) {
|
|
var attrs = attributes.getStringArray(0, attributes.length);
|
|
|
|
self.getAttributes(resource, attrs).then(function (s) {
|
|
resource.instance.setAttributes(s);
|
|
});
|
|
});
|
|
}
|
|
|
|
sendReply(action, callbackId) {
|
|
return this.sendParams().addUint8(0x80 | action).addUint32(callbackId);
|
|
}
|
|
|
|
sendEvent(evt) {
|
|
return this.sendParams().addUint8(evt);
|
|
}
|
|
|
|
IIPRequestAttachResource(callback, resourceId) {
|
|
|
|
//var sl = this.sendParams();
|
|
var self = this;
|
|
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null) {
|
|
|
|
if (r.instance.applicable(self.session, ActionType.Attach, null) == Ruling.Denied) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.AttachDenied);
|
|
return;
|
|
}
|
|
|
|
// reply ok
|
|
|
|
var link = DC.stringToBytes(r.instance.link);
|
|
|
|
if (r instanceof DistributedResource)
|
|
self.sendReply(IIPPacketAction.AttachResource, callback)
|
|
.addUint8Array(r.instance.template.classId.value)
|
|
.addUint64(r.instance.age)
|
|
.addUint16(link.length)
|
|
.addUint8Array(link)
|
|
.addUint8Array(Codec.composePropertyValueArray(r._serialize(), self, true))
|
|
.done();
|
|
else
|
|
self.sendReply(IIPPacketAction.AttachResource, callback)
|
|
.addUint8Array(r.instance.template.classId.value)
|
|
.addUint64(r.instance.age)
|
|
.addUint16(link.length)
|
|
.addUint8Array(link)
|
|
.addUint8Array(Codec.composePropertyValueArray(r.instance.serialize(), self, true))
|
|
.done();
|
|
|
|
r.instance.on("ResourceEventOccurred", self.instance_eventOccurred, self);
|
|
r.instance.on("ResourceModified", self.instance_propertyModified, self);
|
|
r.instance.on("ResourceDestroyed", self.instance_resourceDestroyed, self);
|
|
|
|
}
|
|
else {
|
|
// reply failed
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestReattachResource(callback, resourceId, resourceAge) {
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (res != null) {
|
|
r.instance.on("ResourceEventOccurred", self.instance_eventOccurred, self);
|
|
r.instance.on("ResourceModified", self.instance_propertyModified, self);
|
|
r.instance.on("ResourceDestroyed", self.instance_resourceDestroyed, self);
|
|
// reply ok
|
|
self.sendReply(IIPPacketAction.ReattachResource, callback)
|
|
.addUint64(r.instance.age)
|
|
.addUint8Array(Codec.composePropertyValueArray(r.instance.serialize(), self, true))
|
|
.done();
|
|
}
|
|
else {
|
|
// reply failed
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestDetachResource(callback, resourceId) {
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null) {
|
|
r.instance.off("ResourceEventOccurred", self.instance_eventOccurred);
|
|
r.instance.off("ResourceModified", self.instance_propertyModified);
|
|
r.instance.off("ResourceDestroyed", self.instance_resourceDestroyed);
|
|
|
|
// reply ok
|
|
self.sendReply(IIPPacketAction.DetachResource, callback).done();
|
|
}
|
|
else {
|
|
// reply failed
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestCreateResource(callback, storeId, parentId, content) {
|
|
var self = this;
|
|
Warehouse.getById(storeId).then(function (store) {
|
|
if (store == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.StoreNotFound);
|
|
return;
|
|
}
|
|
|
|
if (!(store instanceof IStore)) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceIsNotStore);
|
|
return;
|
|
}
|
|
|
|
// check security
|
|
if (store.instance.applicable(self.session, ActionType.CreateResource, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.CreateDenied);
|
|
return;
|
|
}
|
|
|
|
Warehouse.getById(parentId).then(function (parent) {
|
|
|
|
// check security
|
|
|
|
if (parent != null)
|
|
if (parent.instance.applicable(self.session, ActionType.AddChild, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.AddChildDenied);
|
|
return;
|
|
}
|
|
|
|
var offset = 0;
|
|
|
|
var className = content.getString(offset + 1, content[0]);
|
|
offset += 1 + content[0];
|
|
|
|
var nameLength = content.getUint16(offset);
|
|
offset += 2;
|
|
var name = content.getString(offset, nameLength);
|
|
|
|
var cl = content.getUint32(offset);
|
|
offset += 4;
|
|
|
|
var type = window[className];
|
|
|
|
if (type == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ClassNotFound);
|
|
return;
|
|
}
|
|
|
|
Codec.parseVarArray(content, offset, cl, self).then(function (parameters) {
|
|
offset += cl;
|
|
cl = content.getUint32(offset);
|
|
Codec.parseStructure(content, offset, cl, self).then(function (attributes) {
|
|
offset += cl;
|
|
cl = content.length - offset;
|
|
|
|
Codec.parseStructure(content, offset, cl, self).then(function (values) {
|
|
|
|
|
|
var resource = new (Function.prototype.bind.apply(type, values));
|
|
|
|
Warehouse.put(resource, name, store, parent).then(function(ok){
|
|
self.sendReply(IIPPacketAction.CreateResource, callback)
|
|
.addUint32(resource.Instance.Id)
|
|
.done();
|
|
}).error(function(ex){
|
|
// send some error
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.AddToStoreFailed);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
IIPRequestDeleteResource(callback, resourceId) {
|
|
var self = this;
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
if (r.instance.store.instance.applicable(session, ActionType.Delete, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.DeleteDenied);
|
|
return;
|
|
}
|
|
|
|
if (Warehouse.remove(r))
|
|
self.sendReply(IIPPacketAction.DeleteResource, callback).done();
|
|
else
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.DeleteFailed);
|
|
});
|
|
}
|
|
|
|
IIPRequestTemplateFromClassName(callback, className) {
|
|
|
|
var self = this;
|
|
|
|
Warehouse.getTemplateByClassName(className).then(function (t) {
|
|
if (t != null)
|
|
self.sendReply(IIPPacketAction.TemplateFromClassName, callback)
|
|
.addUint32(t.content.length)
|
|
.addUint8Array(t.content)
|
|
.done();
|
|
else {
|
|
// reply failed
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.TemplateNotFound);
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestTemplateFromClassId(callback, classId) {
|
|
var self = this;
|
|
Warehouse.getTemplateByClassId(classId).then(function (t) {
|
|
if (t != null)
|
|
self.sendReply(IIPPacketAction.TemplateFromClassId, callback)
|
|
.addUint32(t.content.length)
|
|
.addUint8Array(t.content)
|
|
.done();
|
|
else {
|
|
// reply failed
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.TemplateNotFound);
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestTemplateFromResourceId(callback, resourceId) {
|
|
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null)
|
|
self.sendReply(IIPPacketAction.TemplateFromResourceId, callback)
|
|
.addUint32(r.instance.template.content.length)
|
|
.addUint8Array(r.instance.template.content)
|
|
.done();
|
|
else {
|
|
// reply failed
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.TemplateNotFound);
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestInvokeFunctionArrayArguments(callback, resourceId, index, content) {
|
|
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null) {
|
|
Codec.parseVarArray(content, 0, content.length, self).then(function (args) {
|
|
var ft = r.instance.template.getFunctionTemplateByIndex(index);
|
|
if (ft != null) {
|
|
if (r instanceof DistributedResource) {
|
|
var rt = r._invokeByArrayArguments(index, args);
|
|
if (rt != null) {
|
|
rt.then(function (res) {
|
|
self.sendReply(IIPPacketAction.InvokeFunctionArrayArguments, callback)
|
|
.addUint8Array(Codec.compose(res, self))
|
|
.done();
|
|
});
|
|
}
|
|
else {
|
|
// function not found on a distributed object
|
|
}
|
|
}
|
|
else {
|
|
|
|
var fi = r[ft.name];
|
|
|
|
if (r.instance.applicable(self.session, ActionType.Execute, ft) == Ruling.Denied) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.InvokeDenied);
|
|
return;
|
|
}
|
|
|
|
if (fi instanceof Function) {
|
|
args.push(self);
|
|
|
|
var rt = fi.apply(r, args);
|
|
|
|
function* itt() {
|
|
|
|
};
|
|
|
|
// Is iterator ?
|
|
if (rt[Symbol.iterator] instanceof Function) {
|
|
for (let v of rt)
|
|
self.sendChunk(callback, v);
|
|
|
|
self.sendReply(IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments, callback)
|
|
.addUint8(DataType.Void)
|
|
.done();
|
|
}
|
|
else if (rt instanceof AsyncReply) {
|
|
rt.then(function (res) {
|
|
self.sendReply(IIPPacketAction.InvokeFunctionArrayArguments, callback)
|
|
.addUint8Array(Codec.compose(res, self))
|
|
.done();
|
|
});
|
|
}
|
|
else {
|
|
self.sendReply(IIPPacketAction.InvokeFunctionArrayArguments, callback)
|
|
.addUint8Array(Codec.compose(rt, self))
|
|
.done();
|
|
}
|
|
}
|
|
else {
|
|
// ft found, fi not found, this should never happen
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// no function at this index
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
// no resource with this id
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
IIPRequestInvokeFunctionNamedArguments(callback, resourceId, index, content) {
|
|
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null) {
|
|
Codec.parseStructure(content, 0, content.length, self).then(function (namedArgs) {
|
|
var ft = r.instance.template.getFunctionTemplateByIndex(index);
|
|
if (ft != null) {
|
|
if (r instanceof DistributedResource) {
|
|
var rt = r._invokeByNamedArguments(index, namedArgs);
|
|
if (rt != null) {
|
|
rt.then(function (res) {
|
|
self.sendReply(IIPPacketAction.InvokeFunctionNamedArguments, callback)
|
|
.addUint8Array(Codec.compose(res, self))
|
|
.done();
|
|
});
|
|
}
|
|
else {
|
|
// function not found on a distributed object
|
|
}
|
|
}
|
|
else {
|
|
|
|
var fi = r[ft.name];
|
|
|
|
if (r.instance.applicable(self.session, ActionType.Execute, ft) == Ruling.Denied) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.InvokeDenied);
|
|
return;
|
|
}
|
|
|
|
if (fi instanceof Function) {
|
|
|
|
var pi = ResourceTemplate.getFunctionParameters(fi);
|
|
var args = new Array(pi.length);
|
|
|
|
for (var i = 0; i < pi.length; i++) {
|
|
if (namedArgs[pi[i]] !== undefined)
|
|
args[i] = namedArgs[pi[i]];
|
|
}
|
|
|
|
// pass this to the last argument if it is undefined
|
|
if (args[args.length - 1] === undefined)
|
|
args[args.length - 1] = self;
|
|
|
|
var rt = fi.apply(r, args);
|
|
|
|
// Is iterator ?
|
|
if (rt[Symbol.iterator] instanceof Function) {
|
|
for (let v of rt)
|
|
self.sendChunk(callback, v);
|
|
|
|
self.sendReply(IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments, callback)
|
|
.addUint8(DataType.Void)
|
|
.done();
|
|
}
|
|
else if (rt instanceof AsyncReply) {
|
|
rt.then(function (res) {
|
|
self.sendReply(IIPPacketAction.InvokeFunctionNamedArguments, callback)
|
|
.addUint8Array(Codec.compose(res, self))
|
|
.done();
|
|
});
|
|
}
|
|
else {
|
|
self.sendReply(IIPPacketAction.InvokeFunctionNamedArguments, callback)
|
|
.addUint8Array(Codec.compose(rt, self))
|
|
.done();
|
|
}
|
|
}
|
|
else {
|
|
// ft found, fi not found, this should never happen
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// no function at this index
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
// no resource with this id
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestGetProperty(callback, resourceId, index) {
|
|
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null) {
|
|
var pt = r.instance.template.getFunctionTemplateByIndex(index);
|
|
if (pt != null) {
|
|
if (r instanceof DistributedResource) {
|
|
self.sendReply(IIPPacketAction.GetProperty, callback)
|
|
.addUint8Array(Codec.compose(r._get(pt.index), self))
|
|
.done();
|
|
}
|
|
else {
|
|
var pv = r[pt.name];
|
|
self.sendReply(IIPPacketAction.GetProperty)
|
|
.addUint8Array(Codec.compose(pv, self))
|
|
.done();
|
|
}
|
|
}
|
|
else {
|
|
// pt not found
|
|
}
|
|
}
|
|
else {
|
|
// resource not found
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestGetPropertyIfModifiedSince(callback, resourceId, index, age) {
|
|
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null) {
|
|
var pt = r.instance.template.getFunctionTemplateByIndex(index);
|
|
if (pt != null) {
|
|
if (r.instance.getAge(index) > age) {
|
|
var pv = r[pt.name];
|
|
self.sendReply(IIPPacketAction.GetPropertyIfModified, callback)
|
|
.addUint8Array(Codec.compose(pv, self))
|
|
.done();
|
|
}
|
|
else {
|
|
self.sendReply(IIPPacketAction.GetPropertyIfModified, callback)
|
|
.addUint8(DataType.NotModified)
|
|
.done();
|
|
}
|
|
}
|
|
else {
|
|
// pt not found
|
|
}
|
|
}
|
|
else {
|
|
// resource not found
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestSetProperty(callback, resourceId, index, content) {
|
|
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null) {
|
|
|
|
|
|
var pt = r.instance.template.getPropertyTemplateByIndex(index);
|
|
if (pt != null) {
|
|
Codec.parse(content, 0, {}, this).then(function (value) {
|
|
if (r instanceof DistributedResource) {
|
|
// propagation
|
|
r._set(index, value).then(function (x) {
|
|
self.sendReply(IIPPacketAction.SetProperty, callback)
|
|
.done();
|
|
}).error(function (x) {
|
|
self.sendError(x.type, callback, x.code, x.message)
|
|
.done();
|
|
});
|
|
}
|
|
else {
|
|
if (r.instance.applicable(self.session, ActionType.SetProperty, pt) == Ruling.Denied) {
|
|
self.sendError(AsyncReply.ErrorType.Exception, callback, ExceptionCode.SetPropertyDenied);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
if (r[pt.name] instanceof DistributedPropertyContext)
|
|
value = new DistributedPropertyContext(this, value);
|
|
|
|
r[pt.name] = value;
|
|
self.sendReply(IIPPacketAction.SetProperty, callback).done();
|
|
}
|
|
catch (ex) {
|
|
self.sendError(AsyncReply.ErrorType.Exception, callback, 0, ex.toString()).done();
|
|
}
|
|
}
|
|
|
|
});
|
|
}
|
|
else {
|
|
// property not found
|
|
self.sendError(AsyncReply.ErrorType.Management, callback, ExceptionCode.PropertyNotFound).done();
|
|
}
|
|
}
|
|
else {
|
|
// resource not found
|
|
self.sendError(AsyncReply.ErrorType.Management, callback, ExceptionCode.PropertyNotFound).done();
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestInquireResourceHistory(callback, resourceId, fromDate, toDate) {
|
|
var self = this;
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r != null) {
|
|
r.instance.store.getRecord(r, fromDate, toDate).then(function (results) {
|
|
var history = Codec.composeHistory(results, self, true);
|
|
self.sendReply(IIPPacketAction.ResourceHistory, callback)
|
|
.addUint8Array(history)
|
|
.done();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
IIPRequestQueryResources(callback, resourceLink) {
|
|
var self = this;
|
|
|
|
Warehouse.query(resourceLink).then(function (resources) {
|
|
|
|
var list = resources.filter(function (r) { return r.instance.applicable(self.session, ActionType.Attach, null) != Ruling.Denied });
|
|
|
|
if (list.length == 0)
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
else
|
|
self.sendReply(IIPPacketAction.QueryLink, callback)
|
|
.addUint8Array(Codec.composeResourceArray(list, self, true))
|
|
.done();
|
|
});
|
|
}
|
|
|
|
create(store, parent, className, parameters, attributes, values) {
|
|
var reply = new AsyncReply();
|
|
var sb = DC.stringToBytes(className);
|
|
|
|
var pkt = BL().addUint32(store.instance.id)
|
|
.addUint32(parent.instance.id)
|
|
.addUint32(sb.length)
|
|
.addUint8Array(sb)
|
|
.addUint8Array(Codec.composeVarArray(parameters, this, true))
|
|
.addUint8Array(Codec.composeStructure(attributes, this, true, true, true))
|
|
.addUint8Array(Codec.composeStructure(values, this));
|
|
|
|
pkt.addUint32(pkt.length, 8);
|
|
|
|
this.sendRequest(IIPPacket.IIPPacketAction.CreateResource).addUint8Array(pkt.ToArray()).done().then(function (args) {
|
|
var rid = args[0];
|
|
|
|
self.fetch(rid).then(function (r) {
|
|
reply.trigger(r);
|
|
});
|
|
|
|
});
|
|
|
|
return reply;
|
|
}
|
|
|
|
query(resourceLink) {
|
|
var reply = new AsyncReply();
|
|
var self = this;
|
|
|
|
var sb = DC.stringToBytes(resourceLink);
|
|
|
|
this.sendRequest(IIPPacketAction.QueryLink)
|
|
.addUint16(sb.length)
|
|
.addUint8Array(sb)
|
|
.done()
|
|
.then(function (args) {
|
|
Codec.parseResourceArray(args[0], 0, args[0].length, self).then(function (resources) {
|
|
reply.trigger(resources);
|
|
});
|
|
}).error(function (ex) {
|
|
reply.triggerError(ex);
|
|
});
|
|
|
|
return reply;
|
|
}
|
|
|
|
getTemplate(classId) {
|
|
if (this.templates.contains(classId))
|
|
return new AsyncReply(this.templates.item(classId));
|
|
else if (this.templateRequests.contains(classId))
|
|
return this.templateRequests.item(classId);
|
|
|
|
var reply = new AsyncReply();
|
|
this.templateRequests.add(classId.valueOf(), reply);
|
|
|
|
var self = this;
|
|
|
|
this.sendRequest(IIPPacketAction.TemplateFromClassId)
|
|
.addUint8Array(classId.value)
|
|
.done()
|
|
.then(function (rt) {
|
|
self.templateRequests.remove(classId);
|
|
self.templates.add(rt[0].classId.valueOf(), rt[0]);
|
|
Warehouse.putTemplate(rt[0]);
|
|
reply.trigger(rt[0]);
|
|
});
|
|
|
|
return reply;
|
|
}
|
|
|
|
// IStore interface
|
|
get(path) {
|
|
|
|
var rt = new AsyncReply();
|
|
|
|
this.query(path).then(function (ar) {
|
|
if (ar != null && ar.length > 0)
|
|
rt.trigger(ar[0]);
|
|
else
|
|
rt.trigger(null);
|
|
}).error(function (ex) { rt.triggerError(ex); });
|
|
|
|
return rt;
|
|
|
|
/*
|
|
if (this.pathRequests[path])
|
|
return this.pathRequests[path];
|
|
|
|
var reply = new AsyncReply();
|
|
this.pathRequests[path] = reply;
|
|
|
|
var bl = new BinaryList();
|
|
bl.addString(path);
|
|
bl.addUint16(bl.length, 0);
|
|
|
|
var link = data.get
|
|
var self = this;
|
|
|
|
this.sendRequest(IIPPacketAction.ResourceIdFromResourceLink)
|
|
.addUint16(.then(function (rt) {
|
|
delete self.pathRequests[path];
|
|
|
|
self.fetch(rt[1]).then(function (r) {
|
|
reply.trigger(r);
|
|
});
|
|
});
|
|
|
|
|
|
return reply;
|
|
*/
|
|
}
|
|
|
|
retrieve(iid) {
|
|
|
|
let r = this.resources.item(iid);
|
|
|
|
return new AsyncReply(r);
|
|
|
|
//for (var r in this.resources)
|
|
// if (this.resources[r].instance.id == iid)
|
|
// return new AsyncReply(r);
|
|
//return new AsyncReply(null);
|
|
}
|
|
|
|
// Get a resource from the other end
|
|
fetch(id) {
|
|
|
|
let resource = this.resources.item(id);
|
|
let request = this.resourceRequests.item(id);
|
|
|
|
if (request != null) {
|
|
|
|
if (resource != null)
|
|
// dig for dead locks // or not
|
|
return new AsyncReply(resource);
|
|
else
|
|
return request;
|
|
}
|
|
else if (resource != null && !resource._p.suspended) {
|
|
return new AsyncReply(resource);
|
|
}
|
|
|
|
var reply = new AsyncReply();
|
|
|
|
this.resourceRequests.set(id, reply);
|
|
|
|
var self = this;
|
|
|
|
this.sendRequest(IIPPacketAction.AttachResource)
|
|
.addUint32(id)
|
|
.done()
|
|
.then(function (rt) {
|
|
|
|
let dr = resource || new DistributedResource(self, id, rt[1], rt[2]);
|
|
|
|
self.getTemplate(rt[0]).then(function (tmp) {
|
|
|
|
// ClassId, ResourceAge, ResourceLink, Content
|
|
if (resource == null)
|
|
{
|
|
Warehouse.put(dr, id.toString(), self, null, tmp).then(function(ok){
|
|
Codec.parsePropertyValueArray(rt[3], 0, rt[3].length, self).then(function (ar) {
|
|
dr._attach(ar);
|
|
self.resourceRequests.remove(id);
|
|
reply.trigger(dr);
|
|
});
|
|
}).error(function(ex){
|
|
reply.triggerError(ex);
|
|
});
|
|
}
|
|
else
|
|
{
|
|
Codec.parsePropertyValueArray(rt[3], 0, rt[3].length, self).then(function (ar) {
|
|
dr._attach(ar);
|
|
self.resourceRequests.remove(id);
|
|
reply.trigger(dr);
|
|
}).error(function(ex){
|
|
reply.triggerError(ex);
|
|
});
|
|
}
|
|
}).error(function(ex){
|
|
reply.triggerError(ex);
|
|
});
|
|
}).error(function(ex){
|
|
reply.triggerError(ex);
|
|
});
|
|
|
|
return reply;
|
|
}
|
|
|
|
getRecord(resource, fromDate, toDate) {
|
|
if (resource instanceof DistributedResource) {
|
|
|
|
if (resource._p.connection != this)
|
|
return new AsyncReply(null);
|
|
|
|
var reply = new AsyncReply();
|
|
|
|
var self = this;
|
|
|
|
this.sendRequest(IIPPacketAction.ResourceHistory)
|
|
.addUint32(resource._p.instanceId)
|
|
.addDateTime(fromDate).addDateTime(toDate)
|
|
.done()
|
|
.then(function (rt) {
|
|
Codec.parseHistory(rt[0], 0, rt[0].length, resource, self).then(function (history) {
|
|
reply.trigger(history);
|
|
});
|
|
});
|
|
|
|
return reply;
|
|
}
|
|
else
|
|
return new AsyncReply(null);
|
|
}
|
|
|
|
instance_resourceDestroyed(resource) {
|
|
// compose the packet
|
|
this.sendEvent(IIPPacketEvent.ResourceDestroyed)
|
|
.addUint32(resource.instance.id)
|
|
.done();
|
|
}
|
|
|
|
instance_propertyModified(resource, name, newValue) {
|
|
var pt = resource.instance.template.getPropertyTemplateByName(name);
|
|
|
|
if (pt == null)
|
|
return;
|
|
|
|
this.sendEvent(IIPPacketEvent.PropertyUpdated)
|
|
.addUint32(resource.instance.id)
|
|
.addUint8(pt.index)
|
|
.addUint8Array(Codec.compose(newValue, this))
|
|
.done();
|
|
}
|
|
|
|
instance_eventOccurred(resource, issuer, receivers, name, args) {
|
|
var et = resource.instance.template.getEventTemplateByName(name);
|
|
|
|
if (et == null)
|
|
return;
|
|
|
|
if (receivers != null)
|
|
if (receivers.indexOf(this.session) < 0)
|
|
return;
|
|
|
|
if (resource.instance.applicable(this.session, ActionType.ReceiveEvent, et, issuer) == Ruling.Denied)
|
|
return;
|
|
|
|
// compose the packet
|
|
this.sendEvent(IIPPacketEvent.EventOccurred)
|
|
.addUint32(resource.instance.id)
|
|
.addUint8(et.index)
|
|
.addUint8Array(Codec.composeVarArray(args, this, true))
|
|
.done();
|
|
|
|
}
|
|
|
|
|
|
|
|
IIPRequestAddChild(callback, parentId, childId) {
|
|
var self = this;
|
|
Warehouse.getById(parentId).then(function (parent) {
|
|
if (parent == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
Warehouse.getById(childId).then(function (child) {
|
|
if (child == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
if (parent.instance.applicable(self.session, ActionType.AddChild, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.AddChildDenied);
|
|
return;
|
|
}
|
|
|
|
if (child.instance.applicable(self.session, ActionType.AddParent, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.AddParentDenied);
|
|
return;
|
|
}
|
|
|
|
parent.instance.children.add(child);
|
|
|
|
self.sendReply(IIPPacketAction.AddChild, callback)
|
|
.done();
|
|
//child.Instance.Parents
|
|
});
|
|
|
|
});
|
|
}
|
|
|
|
IIPRequestRemoveChild(callback, parentId, childId) {
|
|
var self = this;
|
|
|
|
Warehouse.getById(parentId).then(function (parent) {
|
|
if (parent == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
Warehouse.getById(childId).then(function (child) {
|
|
if (child == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
if (parent.instance.applicable(self.session, ActionType.RemoveChild, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.AddChildDenied);
|
|
return;
|
|
}
|
|
|
|
if (child.instance.applicable(self.session, ActionType.RemoveParent, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.AddParentDenied);
|
|
return;
|
|
}
|
|
|
|
parent.instance.children.remove(child);
|
|
|
|
self.sendReply(IIPPacketAction.RemoveChild, callback)
|
|
.done();
|
|
//child.Instance.Parents
|
|
});
|
|
|
|
});
|
|
}
|
|
|
|
IIPRequestRenameResource(callback, resourceId, name) {
|
|
var self = this;
|
|
Warehouse.getById(resourceId).then(function (resource) {
|
|
if (resource == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
if (resource.instance.applicable(self.session, ActionType.Rename, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.RenameDenied);
|
|
return;
|
|
}
|
|
|
|
resource.instance.name = name.getString(0, name.length);
|
|
self.sendReply(IIPPacketAction.RenameResource, callback)
|
|
.done();
|
|
});
|
|
}
|
|
|
|
IIPRequestResourceChildren(callback, resourceId) {
|
|
var self = this;
|
|
Warehouse.getById(resourceId).then(function (resource) {
|
|
if (resource == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
self.sendReply(IIPPacketAction.ResourceChildren, callback)
|
|
.addUint8Array(Codec.composeResourceArray(resource.instance.children.toArray(), this, true))
|
|
.done();
|
|
|
|
});
|
|
}
|
|
|
|
IIPRequestResourceParents(callback, resourceId) {
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (resource) {
|
|
if (resource == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
self.sendReply(IIPPacketAction.ResourceParents, callback)
|
|
.addUint8Array(Codec.composeResourceArray(resource.instance.parents.toArray(), this, true))
|
|
.done();
|
|
});
|
|
}
|
|
|
|
IIPRequestClearAttributes(callback, resourceId, attributes, all = false) {
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
if (r.instance.store.instance.applicable(self.session, ActionType.UpdateAttributes, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.UpdateAttributeDenied);
|
|
return;
|
|
}
|
|
|
|
var attrs = [];
|
|
|
|
if (!all)
|
|
attrs = attributes.getStringArray(0, attributes.length);
|
|
|
|
if (r.instance.removeAttributes(attrs))
|
|
self.sendReply(all ? IIPPacketAction.ClearAllAttributes : IIPPacketAction.ClearAttributes, callback)
|
|
.done();
|
|
else
|
|
self.sendError(AsyncReply.ErrorType.Management, callback, ExceptionCode.UpdateAttributeFailed);
|
|
|
|
});
|
|
}
|
|
|
|
IIPRequestUpdateAttributes(callback, resourceId, attributes, clearAttributes = false) {
|
|
var self = this;
|
|
|
|
Warehouse.getById(resourceId).then(function (r) {
|
|
if (r == null) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
|
|
return;
|
|
}
|
|
|
|
if (r.instance.store.instance.applicable(self.session, ActionType.UpdateAttributes, null) != Ruling.Allowed) {
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.UpdateAttributeDenied);
|
|
return;
|
|
}
|
|
|
|
Codec.parseStructure(attributes, 0, attributes.length, this).then(function (attrs) {
|
|
if (r.instance.setAttributes(attrs, clearAttributes))
|
|
self.sendReply(clearAttributes ? IIPPacketAction.ClearAllAttributes : IIPPacketAction.ClearAttributes,
|
|
callback)
|
|
.done();
|
|
else
|
|
self.sendError(ErrorType.Management, callback, ExceptionCode.UpdateAttributeFailed);
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
getChildren(resource) {
|
|
if (resource._p.connection != this)
|
|
return new AsyncReply(null);
|
|
|
|
var rt = new AsyncReply();
|
|
var self = this;
|
|
|
|
this.sendRequest(IIPPacketAction.ResourceChildren)
|
|
.addUint32(resource._p.instanceId)
|
|
.done()
|
|
.then(function (d) {
|
|
|
|
Codec.parseResourceArray(d, 0, d.length, self).then(function (resources) {
|
|
rt.trigger(resources);
|
|
}).error(function (ex) { rt.triggerError(ex); });
|
|
});
|
|
|
|
return rt;
|
|
}
|
|
|
|
getParents(resource) {
|
|
if (resource._p.connection != this)
|
|
return new AsyncReply(null);
|
|
|
|
var rt = new AsyncReply();
|
|
var self = this;
|
|
|
|
this.sendRequest(IIPPacketAction.ResourceParents)
|
|
.addUint32(resource._p.instanceId)
|
|
.done()
|
|
.then(function (d) {
|
|
Codec.parseResourceArray(d, 0, d.length, this).then(function (resources) {
|
|
rt.trigger(resources);
|
|
}).error(function (ex) { rt.triggerError(ex); });
|
|
});
|
|
|
|
return rt;
|
|
}
|
|
|
|
removeAttributes(resource, attributes = null) {
|
|
if (resource._p.connection != this)
|
|
return new AsyncReply(null);
|
|
|
|
var rt = new AsyncReply();
|
|
|
|
if (attributes == null)
|
|
this.sendRequest(IIPPacketAction.ClearAllAttributes)
|
|
.addUint32(resource._p.instanceId)
|
|
.done()
|
|
.then(function (ar) {
|
|
rt.trigger(true);
|
|
}).error(function (ex) { rt.triggerError(ex); });
|
|
else {
|
|
var attrs = DC.stringArrayToBytes(attributes);
|
|
this.sendRequest(IIPPacketAction.ClearAttributes)
|
|
.addUint32(resource.instance.id)
|
|
.addUint32(attrs.length)
|
|
.addUint8Array(attrs)
|
|
.done()
|
|
.then(function (ar) {
|
|
rt.trigger(true);
|
|
}).error(function (ex) { rt.triggerError(ex); });
|
|
}
|
|
|
|
return rt;
|
|
}
|
|
|
|
setAttributes(resource, attributes, clearAttributes = false) {
|
|
if (resource._p.connection != this)
|
|
return new AsyncReply(null);
|
|
|
|
var rt = new AsyncReply();
|
|
|
|
this.sendRequest(clearAttributes ? IIPPacketAction.UpdateAllAttributes : IIPPacketAction.UpdateAttributes)
|
|
.addUint32(resource._p.instanceId)
|
|
.addUint8Array(Codec.composeStructure(attributes, this, true, true, true))
|
|
.done()
|
|
.then(function (ar) {
|
|
rt.trigger(true);
|
|
}).error(function (ex) { rt.triggerError(ex); });
|
|
|
|
return rt;
|
|
}
|
|
|
|
getAttributes(resource, attributes = null) {
|
|
if (resource._p.connection != this)
|
|
return new AsyncReply(null);
|
|
|
|
var rt = new AsyncReply();
|
|
var self = this;
|
|
|
|
if (attributes == null) {
|
|
this.sendRequest(IIPPacketAction.GetAllAttributes)
|
|
.addUint32(resource._p.instanceId)
|
|
.done()
|
|
.then(function (ar) {
|
|
Codec.parseStructure(ar[0], 0, ar[0].length, this).then(function (st) {
|
|
for (var a in st)
|
|
resource.instance.attributes.set(a, st[a]);
|
|
rt.trigger(st);
|
|
}).error(function (ex) { rt.triggerError(ex); });
|
|
});
|
|
}
|
|
else {
|
|
var attrs = DC.stringArrayToBytes(attributes);
|
|
this.sendRequest(IIPPacketAction.GetAttributes)
|
|
.addUint32(resource._p.instanceId)
|
|
.addUint32(attrs.length)
|
|
.addUint8Array(attrs)
|
|
.done()
|
|
.then(function (ar) {
|
|
Codec.parseStructure(ar[0], 0, ar[0].length, self).then(function (st) {
|
|
for (var a in st)
|
|
resource.instance.attributes.set(a, st[a]);
|
|
rt.trigger(st);
|
|
}).error(function (ex) { rt.triggerError(ex); });
|
|
});
|
|
}
|
|
|
|
return rt;
|
|
}
|
|
|
|
}
|