mirror of
				https://github.com/esiur/esiur-js.git
				synced 2025-10-29 17:10:30 +00:00 
			
		
		
		
	IIP v3.3
This commit is contained in:
		| @@ -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
									
								
							
							
						
						
									
										88
									
								
								src/AsyncException.js
									
									
									
									
									
										Normal 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; | ||||
|      } | ||||
|  } | ||||
| @@ -22,6 +22,9 @@ | ||||
| /** | ||||
|  * Created by Ahmed Zamil on 25/07/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class AsyncQueue extends AsyncReply | ||||
| { | ||||
|  | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										50
									
								
								src/Authentication.js
									
									
									
									
									
										Normal 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; | ||||
|     } | ||||
| } | ||||
| @@ -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) | ||||
|   | ||||
| @@ -24,6 +24,8 @@ | ||||
|  * Created by Ahmed Zamil on 05/09/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class AutoMap extends IEventHandler | ||||
| { | ||||
|     constructor() | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
							
								
								
									
										426
									
								
								src/Codec.js
									
									
									
									
									
								
							
							
						
						
									
										426
									
								
								src/Codec.js
									
									
									
									
									
								
							| @@ -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; | ||||
|         } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										37
									
								
								src/CustomResourceEvent.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/CustomResourceEvent.js
									
									
									
									
									
										Normal 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; | ||||
|     } | ||||
| } | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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
											
										
									
								
							
							
								
								
									
										43
									
								
								src/DistributedPropertyContext.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/DistributedPropertyContext.js
									
									
									
									
									
										Normal 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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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; | ||||
|     } | ||||
|   | ||||
| @@ -23,7 +23,10 @@ | ||||
| /** | ||||
|  * Created by Ahmed Zamil on 25/07/2017. | ||||
|  */ | ||||
| var DistributedResourceQueueItemType = | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| const DistributedResourceQueueItemType = | ||||
|     { | ||||
|         Propery: 0, | ||||
|         Event: 1 | ||||
|   | ||||
| @@ -24,6 +24,8 @@ | ||||
|  * Created by Ahmed Zamil on 24/08/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class EventTemplate extends MemberTemplate | ||||
| { | ||||
|  | ||||
|   | ||||
| @@ -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(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -23,6 +23,9 @@ | ||||
| /** | ||||
|  * Created by Ahmed Zamil on 02/09/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class Guid | ||||
| { | ||||
|     constructor(dc) | ||||
|   | ||||
| @@ -23,6 +23,9 @@ | ||||
| /** | ||||
|  * Created by Ahmed Zamil on 31/08/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class IDestructible extends IEventHandler | ||||
| { | ||||
|     destroy() | ||||
|   | ||||
| @@ -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 | ||||
|             { | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
							
								
								
									
										346
									
								
								src/IIPPacket.js
									
									
									
									
									
								
							
							
						
						
									
										346
									
								
								src/IIPPacket.js
									
									
									
									
									
								
							| @@ -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; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								src/IPermissionsManager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/IPermissionsManager.js
									
									
									
									
									
										Normal 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() | ||||
|     { | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -24,7 +24,9 @@ | ||||
|  * Created by Ahmed Zamil on 25/07/2017. | ||||
|  */ | ||||
|  | ||||
| var ResourceTrigger = | ||||
| "use strict";   | ||||
|  | ||||
| const ResourceTrigger = | ||||
| { | ||||
|     Loaded : 0, | ||||
|         Initialize: 1, | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
							
								
								
									
										265
									
								
								src/Instance.js
									
									
									
									
									
								
							
							
						
						
									
										265
									
								
								src/Instance.js
									
									
									
									
									
								
							| @@ -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
									
								
							
							
						
						
									
										115
									
								
								src/KeyList.js
									
									
									
									
									
										Normal 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; | ||||
|      } | ||||
|  } | ||||
| @@ -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
									
								
							
							
						
						
									
										75
									
								
								src/MemoryStore.js
									
									
									
									
									
										Normal 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) | ||||
|      { | ||||
|  | ||||
|      } | ||||
|  } | ||||
| @@ -24,6 +24,8 @@ | ||||
|  * Created by Ahmed Zamil on 01/09/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class NetworkBuffer { | ||||
|     constructor() { | ||||
|         this.neededDataLength = 0; | ||||
|   | ||||
| @@ -24,6 +24,8 @@ | ||||
|  * Created by Ahmed Zamil on 26/08/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class NotModified | ||||
| { | ||||
|  | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										37
									
								
								src/PropertyValue.js
									
									
									
									
									
										Normal 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; | ||||
|      } | ||||
|  } | ||||
| @@ -24,6 +24,8 @@ | ||||
|  * Created by Ahmed Zamil on 26/08/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class ResourceArray extends Array | ||||
| { | ||||
|     push(value) | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										177
									
								
								src/SHA256.js
									
									
									
									
									
										Normal 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(); | ||||
|      } | ||||
| } | ||||
| @@ -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
									
								
							
							
						
						
									
										41
									
								
								src/Session.js
									
									
									
									
									
										Normal 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; | ||||
|     } | ||||
| } | ||||
| @@ -24,6 +24,8 @@ | ||||
|  * Created by Ahmed Zamil on 26/08/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class Structure | ||||
| { | ||||
|     getKeys() { | ||||
|   | ||||
| @@ -24,6 +24,8 @@ | ||||
|  * Created by Ahmed Zamil on 06/09/2017. | ||||
|  */ | ||||
|  | ||||
| "use strict";   | ||||
|  | ||||
| class StructureArray extends Array | ||||
| { | ||||
|     push(value) | ||||
|   | ||||
							
								
								
									
										217
									
								
								src/Warehouse.js
									
									
									
									
									
								
							
							
						
						
									
										217
									
								
								src/Warehouse.js
									
									
									
									
									
								
							| @@ -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(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user