Esempio n. 1
0
        /// <summary>
        ///    Unserializes the fields of an object from a binary reader.
        /// </summary>
        /// <param name="writer">Writer to unpack fields into.</param>
        /// <param name="obj">Object to unpack fields of.</param>
        private void UnPackObjectFields(BinaryReader reader, object obj)
        {
            // Write in field values.
            FieldInfo[] properties = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            // Order fields by names in alphabetical order.
            properties = properties.OrderBy(j => j.Name).ToArray();

            // Read number of fields.
            byte fieldCount = reader.ReadByte();
            if (properties.Length != fieldCount)
            {
                throw new IndexOutOfRangeException("Packet contains an invalid number of fields.");
            }

            // Read in fields hash and check if its correct.
            byte realHash = reader.ReadByte();
            PearsonHash hash = new PearsonHash();
            foreach (FieldInfo field in properties)
            {
                byte[] bytes = StringHelper.StringToByteArray(field.Name);
                hash.AddBuffer(bytes, 0, bytes.Length);
            }

            // Check hash is correct.
            if (hash.Calculate() != realHash)
            {
                throw new FormatException("Packet structure appears to be different from packet class.");
            }

            for (int i = 0; i < fieldCount; i++)
            {
                PacketPackedFieldType fieldType = (PacketPackedFieldType)reader.ReadByte();
                FieldInfo field                 = properties[i];
                Type realFieldType              = field.FieldType;

                // Is array or normal?
                if (((byte)fieldType & (byte)PacketPackedFieldType.Array) != 0)
                {
                    // Is field an array.
                    if (realFieldType.IsArray != true)
                    {
                        throw new FormatException("Packet contains invalid field data type.");
                    }

                    // Strip "Array" from field type.
                    fieldType = (PacketPackedFieldType)(((byte)fieldType) & ~((int)PacketPackedFieldType.Array));

                    // Read in array.
                    Type elementType        = realFieldType.GetElementType();
                    int arrayDimensions     = reader.ReadByte();
                    Array array            = null;
                    int[] arrayLengths      = new int[arrayDimensions];
                    int[] arrayLowerBounds  = new int[arrayDimensions];

                    // Read in array lengths.
                    for (int l = 0; l < arrayDimensions; l++)
                    {
                        arrayLengths[l] = reader.ReadInt32();
                        arrayLowerBounds[l] = 0;
                    }

                    // Create the array.
                    array = Array.CreateInstance(elementType, arrayLengths, arrayLowerBounds);

                    if (fieldType == PacketPackedFieldType.Null)
                    {
                        array = null;
                    }
                    else if (fieldType == PacketPackedFieldType.String)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(string))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            if (reader.ReadBoolean() == true)
                            {
                                array.SetValue(reader.ReadString(), val.Indicies);
                            }
                            else
                            {
                                array.SetValue(null, val.Indicies);
                            }
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Byte)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(byte))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadByte(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.UShort)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(ushort))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadUInt16(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Short)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(short))
                        {
                            throw new IndexOutOfRangeException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadInt16(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.UInt)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(uint))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadUInt32(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Bool)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(bool))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadBoolean(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Int)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(int))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadInt32(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.ULong)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(ulong))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadUInt64(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Long)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(long))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadInt64(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Float)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(float))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadSingle(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Double)
                    {
                        // Is field correct data type.
                        if (elementType != typeof(double))
                        {
                            throw new IndexOutOfRangeException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            array.SetValue(reader.ReadDouble(), val.Indicies);
                        }
                    }
                    else if (fieldType == PacketPackedFieldType.Struct)
                    {
                        // Is field correct data type.
                        if (elementType.IsValueType != true && elementType.IsClass != true)
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        // Write in values.
                        MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                        foreach (MultiDimensionArrayIteratorValue val in iterator)
                        {
                            if (reader.ReadBoolean() == true)
                            {
                                object structResult = Activator.CreateInstance(elementType);//FormatterServices.GetUninitializedObject(realFieldType);
                                UnPackObjectFields(reader, structResult);
                                array.SetValue(structResult, val.Indicies);
                            }
                            else
                            {
                                array.SetValue(null, val.Indicies);
                            }
                        }
                    }
                    else
                    {
                        throw new FormatException("Packet contains invalid field data type.");
                    }

                    // Set the field value.
                    field.SetValue(obj, array);
                }
                else
                {
                    if (fieldType == PacketPackedFieldType.Null)
                    {
                        // Is field correct data type.
                        if (realFieldType.IsByRef == false && realFieldType.IsValueType == false && realFieldType.IsClass == false)
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, null);
                    }
                    else if (fieldType == PacketPackedFieldType.String)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(string))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadString());
                    }
                    else if (fieldType == PacketPackedFieldType.Byte)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(byte))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadByte());
                    }
                    else if (fieldType == PacketPackedFieldType.UShort)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(ushort))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadUInt16());
                    }
                    else if (fieldType == PacketPackedFieldType.Short)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(short))
                        {
                            throw new IndexOutOfRangeException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadInt16());
                    }
                    else if (fieldType == PacketPackedFieldType.UInt)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(uint))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadUInt32());
                    }
                    else if (fieldType == PacketPackedFieldType.Bool)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(bool))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadBoolean());
                    }
                    else if (fieldType == PacketPackedFieldType.Int)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(int))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadInt32());
                    }
                    else if (fieldType == PacketPackedFieldType.ULong)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(ulong))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadUInt64());
                    }
                    else if (fieldType == PacketPackedFieldType.Long)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(long))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadInt64());
                    }
                    else if (fieldType == PacketPackedFieldType.Float)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(float))
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadSingle());
                    }
                    else if (fieldType == PacketPackedFieldType.Double)
                    {
                        // Is field correct data type.
                        if (realFieldType != typeof(double))
                        {
                            throw new IndexOutOfRangeException("Packet contains invalid field data type.");
                        }

                        field.SetValue(obj, reader.ReadDouble());
                    }
                    else if (fieldType == PacketPackedFieldType.Struct)
                    {
                        // Is field correct data type.
                        if (realFieldType.IsValueType != true && realFieldType.IsClass != true)
                        {
                            throw new FormatException("Packet contains invalid field data type.");
                        }

                        object structResult = null;
                        if (reader.ReadBoolean() == true)
                        {
                            structResult = Activator.CreateInstance(realFieldType); //FormatterServices.GetUninitializedObject(realFieldType); //
                            UnPackObjectFields(reader, structResult);
                        }
                        field.SetValue(obj, structResult);
                    }
                    else
                    {
                        throw new FormatException("Packet contains invalid field data type.");
                    }
                }
            }
        }
Esempio n. 2
0
        /*
        static double _noneTime = 0.0f;
        static int _noneSize = 0;

        static int _encodeSize = 0;
        static double _encodeTime = 0.0f;
        static int  _encodeCompressSize = 0;
        static double _encodeCompressTime = 0.0f;
        static int  _encodeCompressEncryptSize = 0;
        static double _encodeCompressEncryptTime = 0.0f;
          static int   _compressSize = 0;
        static double _compressTime = 0.0f;
           static int  _compressEncryptSize = 0;
        static double _compressEncryptTime = 0.0f;
          static int   _encryptSize = 0;
        static double _encryptTime = 0.0f;
        static int _encryptEncodeSize = 0;
        static double _encryptEncodeTime = 0.0f;

        static int _packetCounter = 0;
        */
        /// <summary>
        ///     Serializes this packet to a byte buffer than can be recreated by calling FromBuffer.
        /// </summary>
        /// <param name="inReplyTo">If not null this packet is marked as a reply to another packet.</param>
        /// <param name="cryptor">The encryption class to encrypt the buffer with.</param>
        /// <param name="compressor">Compressor used to compress the packet.</param>
        /// <param name="encoder">Encoder used for delta-encoding of packets.</param>
        /// <returns>Byte buffer conversion of packet.</returns>
        public byte[] ToBuffer(Packet inReplyTo, StreamEncryptor cryptor, StreamCompressor compressor, StreamDeltaEncoder encoder)
        {
            byte[] data = CreatePayload();

            // Data cannot be larger than a ushort.
            if (data.Length >= ushort.MaxValue)
            {
                throw new InvalidDataException("Packets cannot be larger than a ushort's max value.");
            }

            // Work out checksum of unmodified payload.
            PearsonHash hash = new PearsonHash();
            hash.AddBuffer(data, 0, data.Length);
            byte dataChecksum = hash.Calculate();

            // Mangle our data based ready for transport.
            data = MangleData(data, encoder, compressor, cryptor);

            // DEBUG TIMING
            /*
            HighPerformanceTimer timer = new HighPerformanceTimer();

            StreamEncryptor tmp_cryptor = cryptor == null ? null : cryptor.Clone();
            StreamCompressor tmp_compressor = new StreamCompressor();
            StreamDeltaEncoder tmp_encoder = encoder == null ? null : encoder.Clone();

            byte[] tmp = CreatePayload();
            timer.Start();
            _noneSize += MangleData(tmp, null, null, null).Length;
            _noneTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encodeSize += MangleData(tmp, tmp_encoder, null, null).Length;
            _encodeTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encodeCompressSize += MangleData(tmp, tmp_encoder, tmp_compressor, null).Length;
            _encodeCompressTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encodeCompressEncryptSize += MangleData(tmp, tmp_encoder, tmp_compressor, tmp_cryptor).Length;
            _encodeCompressEncryptTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _compressSize += MangleData(tmp, null, tmp_compressor, null).Length;
            _compressTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _compressEncryptSize += MangleData(tmp, null, tmp_compressor, tmp_cryptor).Length;
            _compressEncryptTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encryptSize += MangleData(tmp, null, null, tmp_cryptor).Length;
            _encryptTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encryptEncodeSize += MangleData(tmp, tmp_encoder, null, tmp_cryptor).Length;
            _encryptEncodeTime += timer.Stop();

            _packetCounter++;
            if (_packetCounter >= 100000)
            {
                System.Console.WriteLine("DONE!");
            }
             * */
            // DEBUG TIMING

            // Write in data checksum.
            byte[] buffer = new byte[HEADER_SIZE + data.Length];
            buffer[0] = dataChecksum;

            // Write in payload size.
            byte[] bytes = BitConverter.GetBytes((ushort)data.Length);
            buffer[1] = bytes[0];
            buffer[2] = bytes[1];

            // Write in class hash.
            bytes = BitConverter.GetBytes(this.GetType().FullName.GetHashCode());
            buffer[3] = bytes[0];
            buffer[4] = bytes[1];
            buffer[5] = bytes[2];
            buffer[6] = bytes[3];

            // Write in a reply-to-packet-id.
            bytes = BitConverter.GetBytes(inReplyTo == null ? 0 : inReplyTo.PacketID);
            buffer[7] = bytes[0];
            buffer[8] = bytes[1];

            // Write in payload.
            for (int i = 0; i < data.Length; i++)
            {
                buffer[HEADER_SIZE + i] = data[i];
            }

            return buffer;
        }
Esempio n. 3
0
        /// <summary>
        ///     Serializes the fields of an object into a binary writer.
        /// </summary>
        /// <param name="writer">Writer to pack fields into.</param>
        /// <param name="obj">Object to pack fields of.</param>
        private void PackObjectFields(BinaryWriter writer, object obj)
        {
            // Write in field values.
            FieldInfo[] properties = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            // Order fields by names in alphabetical order.
            properties = properties.OrderBy(j => j.Name).ToArray();

            // Write number of fields.
            if (properties.Length >= 255)
            {
                throw new IndexOutOfRangeException("Packet can only have a maximum of 255 public fields.");
            }
            writer.Write((byte)properties.Length);

            // Write in hash code of fields.
            PearsonHash hash = new PearsonHash();
            foreach (FieldInfo field in properties)
            {
                byte[] bytes = StringHelper.StringToByteArray(field.Name);
                hash.AddBuffer(bytes, 0, bytes.Length);
            }
            writer.Write((byte)hash.Calculate());

            // Write in the fields!
            foreach (FieldInfo field in properties)
            {
                Type fieldType    = field.FieldType;
                object fieldValue = field.GetValue(obj);

                // Null.
                if (fieldValue == null)
                {
                    writer.Write((byte)PacketPackedFieldType.Null);
                }

                // String.
                else if (fieldType == typeof(string))
                {
                    writer.Write((byte)PacketPackedFieldType.String);
                    writer.Write((string)fieldValue);
                }

                // Integer types.
                else if (fieldType == typeof(byte))
                {
                    writer.Write((byte)PacketPackedFieldType.Byte);
                    writer.Write((byte)fieldValue);
                }
                else if (fieldType == typeof(ushort))
                {
                    writer.Write((byte)PacketPackedFieldType.UShort);
                    writer.Write((ushort)fieldValue);
                }
                else if (fieldType == typeof(short))
                {
                    writer.Write((byte)PacketPackedFieldType.Short);
                    writer.Write((short)fieldValue);
                }
                else if (fieldType == typeof(uint))
                {
                    writer.Write((byte)PacketPackedFieldType.UInt);
                    writer.Write((uint)fieldValue);
                }
                else if (fieldType == typeof(int))
                {
                    writer.Write((byte)PacketPackedFieldType.Int);
                    writer.Write((int)fieldValue);
                }
                else if (fieldType == typeof(bool))
                {
                    writer.Write((byte)PacketPackedFieldType.Bool);
                    writer.Write((bool)fieldValue);
                }
                else if (fieldType == typeof(ulong))
                {
                    writer.Write((byte)PacketPackedFieldType.ULong);
                    writer.Write((ulong)fieldValue);
                }
                else if (fieldType == typeof(long))
                {
                    writer.Write((byte)PacketPackedFieldType.Long);
                    writer.Write((long)fieldValue);
                }

                // Floating point types.
                else if (fieldType == typeof(float))
                {
                    writer.Write((byte)PacketPackedFieldType.Float);
                    writer.Write((float)fieldValue);
                }
                else if (fieldType == typeof(double))
                {
                    writer.Write((byte)PacketPackedFieldType.Double);
                    writer.Write((double)fieldValue);
                }

                // Other types of data.
                else
                {
                    // An array.
                    if (fieldType.IsArray)
                    {
                        Array array      = ((Array)fieldValue);
                        Type elementType = fieldType.GetElementType();

                        // Null
                        if (array == null)
                        {
                            writer.Write((byte)(PacketPackedFieldType.Null | PacketPackedFieldType.Array));
                            writer.Write((byte)0);
                        }

                        // String.
                        else if (elementType == typeof(string))
                        {
                            writer.Write((byte)(PacketPackedFieldType.String | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write(val.Value != null);
                                if (val.Value != null)
                                {
                                    writer.Write((string)val.Value);
                                }
                            }
                        }

                        // Integer types.
                        else if (elementType == typeof(byte))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Byte | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((byte)val.Value);
                            }
                        }
                        else if (elementType == typeof(ushort))
                        {
                            writer.Write((byte)(PacketPackedFieldType.UShort | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((ushort)val.Value);
                            }
                        }
                        else if (elementType == typeof(short))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Short | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((short)val.Value);
                            }
                        }
                        else if (elementType == typeof(uint))
                        {
                            writer.Write((byte)(PacketPackedFieldType.UInt | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((uint)val.Value);
                            }
                        }
                        else if (elementType == typeof(bool))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Bool | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((bool)val.Value);
                            }
                        }
                        else if (elementType == typeof(int))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Int | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((int)val.Value);
                            }
                        }
                        else if (elementType == typeof(ulong))
                        {
                            writer.Write((byte)(PacketPackedFieldType.ULong | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((ulong)val.Value);
                            }
                        }
                        else if (elementType == typeof(long))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Long | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((long)val.Value);
                            }
                        }

                        // Floating point types.
                        else if (elementType == typeof(float))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Float | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((float)val.Value);
                            }
                        }
                        else if (elementType == typeof(double))
                        {
                            writer.Write((byte)(PacketPackedFieldType.Double | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write((double)val.Value);
                            }
                        }

                        // Structs maybe?
                        else if (elementType.IsValueType == true || elementType.IsClass == true)
                        {
                            writer.Write((byte)(PacketPackedFieldType.Struct | PacketPackedFieldType.Array));
                            writer.Write((byte)fieldType.GetArrayRank());

                            // Write in dimension lengths.
                            for (int rank = 0; rank < fieldType.GetArrayRank(); rank++)
                            {
                                int length = array.GetLength(rank);
                                writer.Write((int)length);
                            }

                            // Write in values.
                            MultiDimensionArrayIterator iterator = new MultiDimensionArrayIterator(array);
                            foreach (MultiDimensionArrayIteratorValue val in iterator)
                            {
                                writer.Write(val.Value != null);
                                if (val.Value != null)
                                {
                                    PackObjectFields(writer, val.Value);
                                }
                            }
                        }

                        // Invalid data type.
                        else
                        {
                            throw new IndexOutOfRangeException("Packet contains an invalid data type for packing '" + elementType.Name + "'.");
                        }
                    }

                    // Structs maybe?
                    else if (fieldType.IsValueType == true || fieldType.IsClass == true)
                    {
                        writer.Write((byte)PacketPackedFieldType.Struct);
                        writer.Write(fieldValue != null);
                        PackObjectFields(writer, fieldValue);
                    }

                    // Invalid data type.
                    else
                    {
                        throw new IndexOutOfRangeException("Packet contains an invalid data type for packing '" + fieldType.Name + "'.");
                    }
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        ///     Finishes the job that FromHeader starts, decrypts and parses the packet payload.
        ///     
        ///     Be aware that for the sake of speed, decryption of the data will be done
        ///     in-place - the value of buffer will be in its decrypted form when this
        ///     function returns!
        /// </summary>
        /// <returns>True if successful, or false if payload is invalid (and thus packet is too).</returns>
        /// <param name="cryptor">The encryption class to decrypt the buffer with.</param>
        /// <param name="compressor">Compressor used to decompress the packet.</param>
        /// <param name="encoder">Encoder used for delta-deencoding of packets.</param>
        /// <param name="buffer">Buffer to construct packet from.</param>
        public bool RecievePayload(byte[] buffer, StreamEncryptor cryptor, StreamCompressor compressor, StreamDeltaEncoder encoder)
        {
            try
            {
                // Decrypt the payload.
                cryptor.DecryptInPlace(buffer);

                // Decompress payload.
                buffer = compressor.Decompress(buffer);

                // Delta un-encode.
                encoder.DecodeInPlace(buffer, GetType().FullName.GetHashCode());
            }
            catch (Exception)
            {
                Logger.Error("Recieved packet with invalid data. Dropping packet.", LoggerVerboseLevel.Normal);
                return false;
            }

            // Check that the checksum is correct.
            PearsonHash hash = new PearsonHash();
            hash.AddBuffer(buffer, 0, buffer.Length);
            int bufferChecksum = hash.Calculate();

            if (bufferChecksum != m_checksum)
            {
                Logger.Error("Recieved packet with invalid checksum, got {0}, expected {1}. Dropping packet.", LoggerVerboseLevel.Normal, bufferChecksum, m_checksum);
                return false;
            }

            // Parse the payload!
            return ParsePayload(buffer);
        }