public static AsyncReply TupleParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence) { var results = new AsyncBag <object>(); var rt = new AsyncReply(); var tupleSize = data[offset++]; length--; var types = new List <Type>(); for (var i = 0; i < tupleSize; i++) { var(cs, rep) = RepresentationType.Parse(data, offset); types.Add(rep.GetRuntimeType()); offset += cs; length -= cs; } while (length > 0) { var(cs, reply) = Codec.Parse(data, offset, connection, requestSequence); results.Add(reply); if (cs > 0) { offset += (uint)cs; length -= (uint)cs; } else { throw new Exception("Error while parsing structured data"); } } results.Seal(); results.Then(ar => { if (ar.Length == 2) { var type = typeof(ValueTuple <,>).MakeGenericType(types.ToArray()); rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1])); } else if (ar.Length == 3) { var type = typeof(ValueTuple <, ,>).MakeGenericType(types.ToArray()); rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2])); } else if (ar.Length == 4) { var type = typeof(ValueTuple <, , ,>).MakeGenericType(types.ToArray()); rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3])); } }); return(rt); }
public static (TransmissionTypeIdentifier, byte[]) EnumComposer(object value, DistributedConnection connection) { if (value == null) { return(TransmissionTypeIdentifier.Null, new byte[0]); } var template = Warehouse.GetTemplateByType(value.GetType()); var intVal = Convert.ChangeType(value, (value as Enum).GetTypeCode()); var ct = template.Constants.FirstOrDefault(x => x.Value.Equals(intVal)); if (ct == null) { return(TransmissionTypeIdentifier.Null, new byte[0]); } var rt = new List <byte>(); rt.AddRange(template.ClassId.ToByteArray()); rt.Add(ct.Index); return(TransmissionTypeIdentifier.Enum, rt.ToArray()); }
/// <summary> /// Compose a structure into an array of bytes /// </summary> /// <param name="value">Structure to compose</param> /// <param name="connection">DistributedConnection is required in case an item in the structure is at the other end</param> /// <param name="includeKeys">Whether to include the structure keys</param> /// <param name="includeTypes">Whether to include each item DataType</param> /// <param name="prependLength">If true, prepend the length as UInt32 at the beginning of the returned bytes array</param> /// <returns>Array of bytes in the network byte order</returns> public static byte[] ComposeStructure(Structure value, DistributedConnection connection, bool includeKeys = true, bool includeTypes = true, bool prependLength = false) { var rt = new BinaryList(); if (includeKeys) { foreach (var i in value) { var key = DC.ToBytes(i.Key); rt.Append((byte)key.Length, key, Compose(i.Value, connection)); } } else { foreach (var i in value) { rt.Append(Compose(i.Value, connection, includeTypes)); } } if (prependLength) { rt.Insert(0, rt.Length); } return(rt.ToArray()); }
public static (TransmissionTypeIdentifier, byte[]) TupleComposer(object value, DistributedConnection connection) { if (value == null) { return(TransmissionTypeIdentifier.Null, new byte[0]); } var rt = new List <byte>(); var fields = value.GetType().GetFields(); var list = fields.Select(x => x.GetValue(value)).ToArray(); var types = fields.Select(x => RepresentationType.FromType(x.FieldType).Compose()).ToArray(); rt.Add((byte)list.Length); foreach (var t in types) { rt.AddRange(t); } var composed = ArrayComposer(list, connection); if (composed == null) { return(TransmissionTypeIdentifier.Null, new byte[0]); } else { rt.AddRange(composed); return(TransmissionTypeIdentifier.Tuple, rt.ToArray()); } }
public static AsyncReply TypedListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence) { var rt = new AsyncBag <object>(); // get the type var(hdrCs, rep) = RepresentationType.Parse(data, offset); offset += hdrCs; length -= hdrCs; var runtimeType = rep.GetRuntimeType(); rt.ArrayType = runtimeType; while (length > 0) { var(cs, reply) = Codec.Parse(data, offset, connection, requestSequence); rt.Add(reply); if (cs > 0) { offset += (uint)cs; length -= (uint)cs; } else { throw new Exception("Error while parsing structured data"); } } rt.Seal(); return(rt); }
/// <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> public static byte[] ComposePropertyValue(PropertyValue propertyValue, DistributedConnection connection)//, bool includeAge = true) { // age, date, value //if (includeAge) return(BinaryList.ToBytes(propertyValue.Age, propertyValue.Date, Compose(propertyValue.Value, connection))); //else // return BinaryList.ToBytes(propertyValue.Date, Compose(propertyValue.Value, connection)); }
/// <summary> /// Compose a resource /// </summary> /// <param name="resource">Resource to compose.</param> /// <param name="connection">DistributedConnection is required to check locality.</param> /// <returns>Array of bytes in the network byte order.</returns> public static byte[] ComposeResource(IResource resource, DistributedConnection connection) { if (IsLocalResource(resource, connection)) { return(DC.ToBytes((resource as DistributedResource).Id)); } else { return(BinaryList.ToBytes(resource.Instance.Template.ClassId, resource.Instance.Id)); } }
/// <summary> /// Get DataType array of a given Structure /// </summary> /// <param name="structure">Structure to get its DataTypes</param> /// <param name="connection">Distributed connection is required in case a type is at the other end</param> private static DataType[] GetStructureDateTypes(Structure structure, DistributedConnection connection) { var keys = structure.GetKeys(); var types = new DataType[keys.Length]; for (var i = 0; i < keys.Length; i++) { types[i] = Codec.GetDataType(structure[keys[i]], connection); } return(types); }
// public DistributedResourceStack Stack //{ // get { return stack; } //} /// <summary> /// Create a new distributed resource. /// </summary> /// <param name="connection">Connection responsible for the distributed resource.</param> /// <param name="template">Resource template.</param> /// <param name="instanceId">Instance Id given by the other end.</param> /// <param name="age">Resource age.</param> public DistributedResource(DistributedConnection connection, uint instanceId, ulong age, string link) { this.link = link; this.connection = connection; this.instanceId = instanceId; //this.Instance.Template = template; //this.Instance.Age = age; //this.template = template; //this.age = age; }
/// <summary> /// Check if a resource is local to a given connection. /// </summary> /// <param name="resource">Resource to check.</param> /// <param name="connection">DistributedConnection to check if the resource is local to it.</param> /// <returns>True, if the resource owner is the given connection, otherwise False.</returns> static bool IsLocalResource(IResource resource, DistributedConnection connection) { if (resource is DistributedResource) { if ((resource as DistributedResource).Connection == connection) { return(true); } } return(false); }
/// <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> /// //, bool includeAge = true public static byte[] ComposePropertyValueArray(PropertyValue[] array, DistributedConnection connection, bool prependLength = false) { var rt = new List <byte>(); for (var i = 0; i < array.Length; i++) { rt.AddRange(ComposePropertyValue(array[i], connection)); } if (prependLength) { rt.InsertRange(0, DC.ToBytes(rt.Count)); } return(rt.ToArray()); }
public static AsyncReply TypedMapParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence) { // get key type var(keyCs, keyRepType) = RepresentationType.Parse(data, offset); offset += keyCs; length -= keyCs; var(valueCs, valueRepType) = RepresentationType.Parse(data, offset); offset += valueCs; length -= valueCs; var map = (IMap)Activator.CreateInstance(typeof(Map <,>).MakeGenericType(keyRepType.GetRuntimeType(), valueRepType.GetRuntimeType())); var rt = new AsyncReply(); var results = new AsyncBag <object>(); while (length > 0) { var(cs, reply) = Codec.Parse(data, offset, connection, requestSequence); results.Add(reply); if (cs > 0) { offset += (uint)cs; length -= (uint)cs; } else { throw new Exception("Error while parsing structured data"); } } results.Seal(); results.Then(ar => { for (var i = 0; i < ar.Length; i += 2) { map.Add(ar[i], ar[i + 1]); } rt.Trigger(map); }); return(rt); }
public static byte[] ArrayComposer(IEnumerable value, DistributedConnection connection) { if (value == null) { return(null); } var rt = new List <byte>(); foreach (var i in value) { rt.AddRange(Codec.Compose(i, connection)); } return(rt.ToArray()); }
public static byte[] HistoryComposer(KeyList <PropertyTemplate, PropertyValue[]> history, DistributedConnection connection, bool prependLength = false) { //@TODO:Test var rt = new BinaryList(); for (var i = 0; i < history.Count; i++) { rt.AddUInt8(history.Keys.ElementAt(i).Index) .AddUInt8Array(Codec.Compose(history.Values.ElementAt(i), connection)); } if (prependLength) { rt.InsertInt32(0, rt.Length); } return(rt.ToArray()); }
/// <summary> /// Compose an array of resources /// </summary> /// <param name="resources">Array of resources.</param> /// <param name="connection">DistributedConnection is required to check locality.</param> /// <param name="prependLength">If True, prepend the length of the output at the beginning.</param> /// <returns>Array of bytes in the network byte order.</returns> public static byte[] ComposeResourceArray(IResource[] resources, DistributedConnection connection, bool prependLength = false) { if (resources == null || resources?.Length == 0) { return prependLength ? new byte[] { 0, 0, 0, 0 } } : new byte[0]; var rt = new BinaryList(); var comparsion = Compare(null, resources[0], connection); rt.Append((byte)comparsion); if (comparsion == ResourceComparisonResult.Local) { rt.Append((resources[0] as DistributedResource).Id); } else if (comparsion == ResourceComparisonResult.Distributed) { rt.Append(resources[0].Instance.Id); } for (var i = 1; i < resources.Length; i++) { comparsion = Compare(resources[i - 1], resources[i], connection); rt.Append((byte)comparsion); if (comparsion == ResourceComparisonResult.Local) { rt.Append((resources[i] as DistributedResource).Id); } else if (comparsion == ResourceComparisonResult.Distributed) { rt.Append(resources[i].Instance.Id); } } if (prependLength) { rt.Insert(0, rt.Length); } return(rt.ToArray()); }
/// <summary> /// Parse a value /// </summary> /// <param name="data">Bytes array</param> /// <param name="offset">Zero-indexed offset.</param> /// <param name="size">Output the number of bytes parsed</param> /// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end.</param> /// <param name="dataType">DataType, in case the data is not prepended with DataType</param> /// <returns>Value</returns> public static (uint, AsyncReply) Parse(byte[] data, uint offset, DistributedConnection connection, uint[] requestSequence, TransmissionType?dataType = null) { uint len = 0; if (dataType == null) { (var longLen, dataType) = TransmissionType.Parse(data, offset, (uint)data.Length); len = (uint)longLen; offset = dataType.Value.Offset; } else { len = (uint)dataType.Value.ContentLength; } var tt = dataType.Value; if (tt.Class == TransmissionTypeClass.Fixed) { return(len, FixedParsers[tt.Exponent][tt.Index](data, dataType.Value.Offset, (uint)tt.ContentLength, connection, requestSequence));
/// <summary> /// Compose an array of structures into an array of bytes /// </summary> /// <param name="structures">Array of Structure to compose</param> /// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end</param> /// <param name="prependLength">If true, prepend the length as UInt32 at the beginning of the returned bytes array</param> /// <returns>Array of bytes in the network byte order</returns> public static byte[] ComposeStructureArray(Structure[] structures, DistributedConnection connection, bool prependLength = false) { if (structures == null || structures?.Length == 0) { return prependLength ? new byte[] { 0, 0, 0, 0 } } : new byte[0]; var rt = new BinaryList(); var comparsion = StructureComparisonResult.Structure; rt.Append((byte)comparsion); rt.Append(ComposeStructure(structures[0], connection, true, true, true)); for (var i = 1; i < structures.Length; i++) { comparsion = Compare(structures[i - 1], structures[i], connection); rt.Append((byte)comparsion); if (comparsion == StructureComparisonResult.Structure) { rt.Append(ComposeStructure(structures[i], connection, true, true, true)); } else if (comparsion == StructureComparisonResult.StructureSameKeys) { rt.Append(ComposeStructure(structures[i], connection, false, true, true)); } else if (comparsion == StructureComparisonResult.StructureSameTypes) { rt.Append(ComposeStructure(structures[i], connection, false, false, true)); } } if (prependLength) { rt.Insert(0, rt.Length); } return(rt.ToArray()); }
public override bool Execute(HTTPConnection sender) { if (sender.Request.Filename.StartsWith("/iip/")) { // find the service var path = sender.Request.Filename.Substring(5);// sender.Request.Query["path"]; Warehouse.Get(path).Then((r) => { if (r is DistributedServer) { var httpServer = sender.Parent; var iipServer = r as DistributedServer; var tcpSocket = sender.Unassign(); if (tcpSocket == null) { return; } var wsSocket = new WSSocket(tcpSocket); httpServer.RemoveConnection(sender); //httpServer.Connections.Remove(sender); var iipConnection = new DistributedConnection(); // iipConnection.OnReady += IipConnection_OnReady; // iipConnection.Server = iipServer; // iipConnection.Assign(wsSocket); iipServer.AddConnection(iipConnection); iipConnection.Assign(wsSocket); wsSocket.Begin(); } }); return(true); } return(false); }
//public static (TransmissionTypeIdentifier, byte[]) ListComposerFromArray(dynamic value, DistributedConnection connection) //{ // var rt = new List<byte>(); // var array = (object[])value; // for (var i = 0; i < array.Length; i++) // rt.AddRange(Codec.Compose(array[i], connection)); // return (TransmissionTypeIdentifier.List, rt.ToArray()); //} public static (TransmissionTypeIdentifier, byte[]) ListComposer(object value, DistributedConnection connection) { var rt = ArrayComposer((IEnumerable)value, connection); if (rt == null) { return(TransmissionTypeIdentifier.Null, new byte[0]); } else { return(TransmissionTypeIdentifier.List, rt); } //var rt = new List<byte>(); //var list = (IEnumerable)value;// ((List<object>)value); //foreach (var o in list) // rt.AddRange(Codec.Compose(o, connection)); //return (TransmissionTypeIdentifier.List, rt.ToArray()); }
public static AsyncReply RecordListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence) { var rt = new AsyncBag <IRecord>(); while (length > 0) { var(cs, reply) = Codec.Parse(data, offset, connection, requestSequence); rt.Add(reply); if (cs > 0) { offset += (uint)cs; length -= (uint)cs; } else { throw new Exception("Error while parsing structured data"); } } rt.Seal(); return(rt); }
public override AsyncReply <bool> Execute(HTTPConnection sender) { if (sender.IsWebsocketRequest()) { if (Server == null) { return(new AsyncReply <bool>(false)); } var tcpSocket = sender.Unassign(); if (tcpSocket == null) { return(new AsyncReply <bool>(false)); } var httpServer = sender.Parent; var wsSocket = new WSocket(tcpSocket); httpServer.Remove(sender); var iipConnection = new DistributedConnection(); Server.Add(iipConnection); iipConnection.Assign(wsSocket); wsSocket.Begin(); return(new AsyncReply <bool>(true)); } return(new AsyncReply <bool>(false)); /* * if (sender.Request.Filename.StartsWith("/iip/")) * { * // find the service * var path = sender.Request.Filename.Substring(5);// sender.Request.Query["path"]; * * * Warehouse.Get(path).Then((r) => * { * if (r is DistributedServer) * { * var httpServer = sender.Parent; * var iipServer = r as DistributedServer; * var tcpSocket = sender.Unassign(); * if (tcpSocket == null) * return; * * var wsSocket = new WSSocket(tcpSocket); * httpServer.RemoveConnection(sender); * * //httpServer.Connections.Remove(sender); * var iipConnection = new DistributedConnection(); * // iipConnection.OnReady += IipConnection_OnReady; * // iipConnection.Server = iipServer; * // iipConnection.Assign(wsSocket); * * iipServer.AddConnection(iipConnection); * iipConnection.Assign(wsSocket); * wsSocket.Begin(); * } * }); * * return true; * } * * return false; */ }
private void IipConnection_OnReady(DistributedConnection sender) { Warehouse.Put(sender.RemoteUsername, sender, null, sender.Server).Wait(); }
public static unsafe AsyncReply Int128Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence) { fixed(byte *ptr = &data[offset]) return(new AsyncReply <decimal>(*(decimal *)ptr)); }
public static unsafe AsyncReply UInt16Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence) { fixed(byte *ptr = &data[offset]) return(new AsyncReply <ushort>(*(ushort *)ptr)); }
public static AsyncReply <KeyList <PropertyTemplate, PropertyValue[]> > HistoryParser(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection, uint[] requestSequence) { //var count = (int)toAge - (int)fromAge; var list = new KeyList <PropertyTemplate, PropertyValue[]>(); var reply = new AsyncReply <KeyList <PropertyTemplate, PropertyValue[]> >(); var bagOfBags = new AsyncBag <PropertyValue[]>(); 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, Endian.Little); offset += 4; var(len, pv) = PropertyValueParser(data, offset, connection, requestSequence); bagOfBags.Add(pv);// ParsePropertyValueArray(data, offset, cs, connection)); offset += len; } bagOfBags.Seal(); bagOfBags.Then(x => { for (var i = 0; i < list.Count; i++) { list[list.Keys.ElementAt(i)] = x[i]; } reply.Trigger(list); }); return(reply); }
public static (uint, AsyncReply <PropertyValue>) PropertyValueParser(byte[] data, uint offset, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true) { var reply = new AsyncReply <PropertyValue>(); var age = data.GetUInt64(offset, Endian.Little); offset += 8; DateTime date = data.GetDateTime(offset, Endian.Little); offset += 8; var(valueSize, results) = Codec.Parse(data, offset, connection, requestSequence); results.Then(value => { reply.Trigger(new PropertyValue(value, age, date)); }); return(16 + valueSize, reply); }
public static AsyncReply Char8Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence) { return(new AsyncReply <char>((char)data[offset])); }
public abstract AsyncReply <IResource[]> Query(string path, DistributedConnection sender);
public MyChildResource(DistributedConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) { }
public static unsafe AsyncReply Float64Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence) { fixed(byte *ptr = &data[offset]) return(new AsyncReply <double>(*(double *)ptr)); }