예제 #1
0
        /// <summary>
        /// Constructor used for building a packet where the length of the data
        /// is known in advance. This is being phased out in favor of
        /// pre-assembling the data or using PacketBuilder.BuildPacket().
        /// </summary>
        /// <param name="command">The name of the command in the message template</param>
        /// <param name="protocol">A reference to the ProtocolManager instance</param>
        /// <param name="length">The length of the packet data</param>
        public Packet(string command, ProtocolManager protocol, int length)
        {
            Protocol = protocol;
            Data     = new byte[length];
            Layout   = protocol.Command(command);

            if (Layout == null)
            {
                Console.WriteLine("Attempting to build a packet with invalid command \"" + command + "\"");

                // Create an empty Layout
                Layout        = new MapPacket();
                Layout.Blocks = new ArrayList();
                return;
            }

            switch (Layout.Frequency)
            {
            case PacketFrequency.Low:
                // Set the low frequency identifier bits
                byte[] lowHeader = { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
                Array.Copy(lowHeader, 0, Data, 0, 6);

                // Store the packet ID in network order
                Data[6] = (byte)(Layout.ID / 256);
                Data[7] = (byte)(Layout.ID % 256);

                break;

            case PacketFrequency.Medium:
                // Set the medium frequency identifier bits
                byte[] mediumHeader = { 0x00, 0x00, 0x00, 0x00, 0xFF };
                Array.Copy(mediumHeader, 0, Data, 0, 5);
                Data[5] = (byte)Layout.ID;

                break;

            case PacketFrequency.High:
                // Set the high frequency identifier bits
                byte[] highHeader = { 0x00, 0x00, 0x00, 0x00 };
                Array.Copy(highHeader, 0, Data, 0, 4);
                Data[4] = (byte)Layout.ID;

                break;
            }
        }
예제 #2
0
        public static Packet BuildPacket(string name, ProtocolManager protocol, Hashtable blocks, byte flags)
        {
            Hashtable fields;

            byte[] byteArray   = new byte[4096];
            int    length      = 0;
            int    blockCount  = 0;
            int    fieldLength = 0;
            IDictionaryEnumerator blocksEnum;

            MapPacket packetMap = protocol.Command(name);

            // Build the header
            #region Header
            switch (packetMap.Frequency)
            {
            case PacketFrequency.High:
                byteArray[4] = (byte)packetMap.ID;
                length       = 5;
                break;

            case PacketFrequency.Medium:
                byteArray[4] = 0xFF;
                byteArray[5] = (byte)packetMap.ID;
                length       = 6;
                break;

            case PacketFrequency.Low:
                byteArray[4] = 0xFF;
                byteArray[5] = 0xFF;
                byteArray[6] = (byte)(packetMap.ID / 256);
                byteArray[7] = (byte)(packetMap.ID % 256);
                length       = 8;
                break;
            }
            #endregion Header

            foreach (MapBlock blockMap in packetMap.Blocks)
            {
                // If this is a variable count block, count the number of appearances of this block in the
                // passed in Hashtable and prepend a counter byte
                #region VariableSize
                if (blockMap.Count == -1)
                {
                    blockCount = 0;

                    // Count the number of this type of block in the blocks Hashtable
                    blocksEnum = blocks.GetEnumerator();

                    while (blocksEnum.MoveNext())
                    {
                        if ((string)blocksEnum.Value == blockMap.Name)
                        {
                            blockCount++;
                        }
                    }

                    if (blockCount > 255)
                    {
                        throw new Exception("Trying to put more than 255 blocks in a variable block");
                    }

                    // Prepend the blocks with a count
                    byteArray[length] = (byte)blockCount;
                    length++;
                }
                #endregion VariableSize

                // Reset blockCount
                blockCount = 0;

                // Check for blocks of this type in the Hashtable
                #region BuildBlock
                blocksEnum = blocks.GetEnumerator();

                while (blocksEnum.MoveNext())
                {
                    if ((string)blocksEnum.Value == blockMap.Name)
                    {
                        // Found a match of this block
                        if ((blockMap.Count == -1 && blockCount < 255) || blockCount < blockMap.Count)
                        {
                            blockCount++;

                            #region TryBlockTypecast
                            try
                            {
                                fields = (Hashtable)blocksEnum.Key;
                            }
                            catch (Exception e)
                            {
                                throw new Exception("A block Hashtable did not contain a fields Hashtable", e);
                            }
                            #endregion TryBlockTypecast

                            foreach (MapField fieldMap in blockMap.Fields)
                            {
                                if (fields.ContainsKey(fieldMap.Name))
                                {
                                    object field = fields[fieldMap.Name];

                                    #region AddField
                                    switch (fieldMap.Type)
                                    {
                                    case FieldType.U8:
                                        byteArray[length++] = (byte)field;
                                        break;

                                    case FieldType.U16:
                                        ushort fieldUShort = (ushort)field;
                                        byteArray[length++] = (byte)(fieldUShort % 256);
                                        fieldUShort       >>= 8;
                                        byteArray[length++] = (byte)(fieldUShort % 256);
                                        break;

                                    case FieldType.U32:
                                        uint fieldUInt = (uint)field;
                                        byteArray[length++] = (byte)(fieldUInt % 256);
                                        fieldUInt         >>= 8;
                                        byteArray[length++] = (byte)(fieldUInt % 256);
                                        fieldUInt         >>= 8;
                                        byteArray[length++] = (byte)(fieldUInt % 256);
                                        fieldUInt         >>= 8;
                                        byteArray[length++] = (byte)(fieldUInt % 256);
                                        break;

                                    case FieldType.U64:
                                        // FIXME: Apply endianness patch
                                        Array.Copy(((U64)field).GetBytes(), 0, byteArray, length, 8);
                                        length += 8;
                                        break;

                                    case FieldType.S8:
                                        byteArray[length++] = (byte)((sbyte)field);
                                        break;

                                    case FieldType.S16:
                                        // FIXME: Apply endianness patch
                                        Array.Copy(BitConverter.GetBytes((short)field), 0, byteArray, length, 2);
                                        length += 2;
                                        break;

                                    case FieldType.S32:
                                        // FIXME: Apply endianness patch
                                        Array.Copy(BitConverter.GetBytes((int)field), 0, byteArray, length, 4);
                                        length += 4;
                                        break;

                                    case FieldType.S64:
                                        // FIXME: Apply endianness patch
                                        Array.Copy(BitConverter.GetBytes((long)field), 0, byteArray, length, 8);
                                        length += 8;
                                        break;

                                    case FieldType.F32:
                                        Array.Copy(BitConverter.GetBytes((float)field), 0, byteArray, length, 4);
                                        length += 4;
                                        break;

                                    case FieldType.F64:
                                        Array.Copy(BitConverter.GetBytes((double)field), 0, byteArray, length, 8);
                                        length += 8;
                                        break;

                                    case FieldType.LLUUID:
                                        Array.Copy(((LLUUID)field).Data, 0, byteArray, length, 16);
                                        length += 16;
                                        break;

                                    case FieldType.BOOL:
                                        byteArray[length] = (byte)((bool)field == true ? 1 : 0);
                                        length++;
                                        break;

                                    case FieldType.LLVector3:
                                        Array.Copy(((LLVector3)field).GetBytes(), 0, byteArray, length, 12);
                                        length += 12;
                                        break;

                                    case FieldType.LLVector3d:
                                        Array.Copy(((LLVector3d)field).GetBytes(), 0, byteArray, length, 24);
                                        length += 24;
                                        break;

                                    case FieldType.LLVector4:
                                        Array.Copy(((LLVector4)field).GetBytes(), 0, byteArray, length, 16);
                                        length += 16;
                                        break;

                                    case FieldType.LLQuaternion:
                                        Array.Copy(((LLQuaternion)field).GetBytes(), 0, byteArray, length, 16);
                                        length += 16;
                                        break;

                                    case FieldType.IPADDR:
                                        Array.Copy(((IPAddress)field).GetAddressBytes(), 0, byteArray, length, 4);
                                        length += 4;
                                        break;

                                    case FieldType.IPPORT:
                                        ushort fieldIPPort = (ushort)field;
                                        byteArray[length + 1] = (byte)(fieldIPPort % 256);
                                        fieldIPPort         >>= 8;
                                        byteArray[length]     = (byte)(fieldIPPort % 256);
                                        length += 2;
                                        break;

                                    case FieldType.Variable:
                                        if (field.GetType().IsArray)
                                        {
                                            // Assume this is a byte array
                                            fieldLength = ((byte[])field).Length;
                                        }
                                        else
                                        {
                                            // Assume this is a string, add 1 for the null terminator
                                            fieldLength = ((string)field).Length + 1;
                                        }

                                        if (fieldMap.Count == 1)
                                        {
                                            if (fieldLength > 255)
                                            {
                                                throw new Exception("Variable byte field longer than 255 characters");
                                            }

                                            byteArray[length] = (byte)(fieldLength);
                                            length++;
                                        }
                                        else if (fieldMap.Count == 2)
                                        {
                                            if (fieldLength > 1024)
                                            {
                                                throw new Exception("Variable byte field longer than 1024 characters");
                                            }

                                            byteArray[length++] = (byte)(fieldLength % 256);
                                            byteArray[length++] = (byte)(fieldLength / 256);
                                        }
                                        else
                                        {
                                            throw new Exception("Variable field with an unknown count, protocol map error");
                                        }

                                        if (field.GetType().IsArray)
                                        {
                                            // Assume this is a byte array
                                            Array.Copy((byte[])field, 0, byteArray, length, fieldLength);
                                        }
                                        else
                                        {
                                            // Assume this is a string, add 1 for the null terminator
                                            byte[] stringBytes = System.Text.Encoding.UTF8.GetBytes((string)field);
                                            Array.Copy(stringBytes, 0, byteArray, length, stringBytes.Length);
                                            fieldLength = stringBytes.Length + 1;
                                        }

                                        length += fieldLength;

                                        break;

                                    case FieldType.Fixed:
                                        Array.Copy((byte[])field, 0, byteArray, length, fieldMap.Count);
                                        length += fieldMap.Count;
                                        break;

                                    default:
                                        throw new Exception("Unhandled FieldType");
                                    }
                                    #endregion AddField
                                }
                                else
                                {
                                    // This field wasn't passed in, create an empty version
                                    #region EmptyField
                                    if (fieldMap.Type == FieldType.Variable)
                                    {
                                        // Just set the counter to zero and move on
                                        if (fieldMap.Count == 2)
                                        {
                                            length += 2;
                                        }
                                        else
                                        {
                                            if (fieldMap.Count != 1)
                                            {
                                                throw new Exception("Variable length field has an invalid Count");
                                            }

                                            length++;
                                        }
                                    }
                                    else if (fieldMap.Type == FieldType.Fixed)
                                    {
                                        length += fieldMap.Count;
                                    }
                                    else
                                    {
                                        length += (int)protocol.TypeSizes[fieldMap.Type];
                                    }
                                    #endregion EmptyField
                                }
                            }
                        }
                        else
                        {
                            throw new Exception("Too many blocks");
                        }
                    }
                }
                #endregion BuildBlock

                // If this is a fixed count block and it doesn't appear in the Hashtable passed in, create
                // empty filler blocks
                #region EmptyBlock
                if (blockCount == 0 && blockMap.Count != -1)
                {
                    for (int i = 0; i < blockMap.Count; ++i)
                    {
                        foreach (MapField field in blockMap.Fields)
                        {
                            if (field.Type == FieldType.Variable)
                            {
                                length++;
                            }
                            else
                            {
                                length += (int)protocol.TypeSizes[field.Type];
                            }
                        }
                    }
                }
                #endregion EmptyBlock
            }

            Packet packet = new Packet(byteArray, length, protocol);
            packet.Data[0] = flags;
            return(packet);
        }
예제 #3
0
 /// <summary>
 /// Constructor used to build a Packet object from incoming data.
 /// </summary>
 /// <param name="data">Byte array containing the full UDP payload</param>
 /// <param name="length">Length of the actual data in the byte array</param>
 /// <param name="protocol">A reference to the ProtocolManager instance</param>
 public Packet(byte[] data, int length, ProtocolManager protocol)
     : this(data, length, protocol, protocol.Command(data), true)
 {
 }
예제 #4
0
        public static Packet BuildPacket(string name, ProtocolManager protocol, Hashtable blocks, byte flags)
        {
            Hashtable fields;
            byte[] byteArray = new byte[4096];
            int length = 0;
            int blockCount = 0;
            int fieldLength = 0;
            IDictionaryEnumerator blocksEnum;

            MapPacket packetMap = protocol.Command(name);

            // Build the header
            #region Header
            switch (packetMap.Frequency)
            {
                case PacketFrequency.High:
                    byteArray[4] = (byte)packetMap.ID;
                    length = 5;
                    break;
                case PacketFrequency.Medium:
                    byteArray[4] = 0xFF;
                    byteArray[5] = (byte)packetMap.ID;
                    length = 6;
                    break;
                case PacketFrequency.Low:
                    byteArray[4] = 0xFF;
                    byteArray[5] = 0xFF;
                    byteArray[6] = (byte)(packetMap.ID / 256);
                    byteArray[7] = (byte)(packetMap.ID % 256);
                    length = 8;
                    break;
            }
            #endregion Header

            foreach (MapBlock blockMap in packetMap.Blocks)
            {
                // If this is a variable count block, count the number of appearances of this block in the
                // passed in Hashtable and prepend a counter byte
                #region VariableSize
                if (blockMap.Count == -1)
                {
                    blockCount = 0;

                    // Count the number of this type of block in the blocks Hashtable
                    blocksEnum = blocks.GetEnumerator();

                    while (blocksEnum.MoveNext())
                    {
                        if ((string)blocksEnum.Value == blockMap.Name)
                        {
                            blockCount++;
                        }
                    }

                    if (blockCount > 255)
                    {
                        throw new Exception("Trying to put more than 255 blocks in a variable block");
                    }

                    // Prepend the blocks with a count
                    byteArray[length] = (byte)blockCount;
                    length++;
                }
                #endregion VariableSize

                // Reset blockCount
                blockCount = 0;

                // Check for blocks of this type in the Hashtable
                #region BuildBlock
                blocksEnum = blocks.GetEnumerator();

                while (blocksEnum.MoveNext())
                {
                    if ((string)blocksEnum.Value == blockMap.Name)
                    {
                        // Found a match of this block
                        if ((blockMap.Count == -1 && blockCount < 255) || blockCount < blockMap.Count)
                        {
                            blockCount++;

                            #region TryBlockTypecast
                            try
                            {
                                fields = (Hashtable)blocksEnum.Key;
                            }
                            catch (Exception e)
                            {
                                throw new Exception("A block Hashtable did not contain a fields Hashtable", e);
                            }
                            #endregion TryBlockTypecast

                            foreach (MapField fieldMap in blockMap.Fields)
                            {
                                if (fields.ContainsKey(fieldMap.Name))
                                {
                                    object field = fields[fieldMap.Name];

                                    #region AddField
                                    switch (fieldMap.Type)
                                    {
                                        case FieldType.U8:
                                            byteArray[length++] = (byte)field;
                                            break;
                                        case FieldType.U16:
                                            ushort fieldUShort = (ushort)field;
                                            byteArray[length++] = (byte)(fieldUShort % 256);
                                            fieldUShort >>= 8;
                                            byteArray[length++] = (byte)(fieldUShort % 256);
                                            break;
                                        case FieldType.U32:
                                            uint fieldUInt = (uint)field;
                                            byteArray[length++] = (byte)(fieldUInt % 256);
                                            fieldUInt >>= 8;
                                            byteArray[length++] = (byte)(fieldUInt % 256);
                                            fieldUInt >>= 8;
                                            byteArray[length++] = (byte)(fieldUInt % 256);
                                            fieldUInt >>= 8;
                                            byteArray[length++] = (byte)(fieldUInt % 256);
                                            break;
                                        case FieldType.U64:
                                            // FIXME: Apply endianness patch
                                            Array.Copy(((U64)field).GetBytes(), 0, byteArray, length, 8);
                                            length += 8;
                                            break;
                                        case FieldType.S8:
                                            byteArray[length++] = (byte)((sbyte)field);
                                            break;
                                        case FieldType.S16:
                                            // FIXME: Apply endianness patch
                                            Array.Copy(BitConverter.GetBytes((short)field), 0, byteArray, length, 2);
                                            length += 2;
                                            break;
                                        case FieldType.S32:
                                            // FIXME: Apply endianness patch
                                            Array.Copy(BitConverter.GetBytes((int)field), 0, byteArray, length, 4);
                                            length += 4;
                                            break;
                                        case FieldType.S64:
                                            // FIXME: Apply endianness patch
                                            Array.Copy(BitConverter.GetBytes((long)field), 0, byteArray, length, 8);
                                            length += 8;
                                            break;
                                        case FieldType.F32:
                                            Array.Copy(BitConverter.GetBytes((float)field), 0, byteArray, length, 4);
                                            length += 4;
                                            break;
                                        case FieldType.F64:
                                            Array.Copy(BitConverter.GetBytes((double)field), 0, byteArray, length, 8);
                                            length += 8;
                                            break;
                                        case FieldType.LLUUID:
                                            Array.Copy(((LLUUID)field).Data, 0, byteArray, length, 16);
                                            length += 16;
                                            break;
                                        case FieldType.BOOL:
                                            byteArray[length] = (byte)((bool)field == true ? 1 : 0);
                                            length++;
                                            break;
                                        case FieldType.LLVector3:
                                            Array.Copy(((LLVector3)field).GetBytes(), 0, byteArray, length, 12);
                                            length += 12;
                                            break;
                                        case FieldType.LLVector3d:
                                            Array.Copy(((LLVector3d)field).GetBytes(), 0, byteArray, length, 24);
                                            length += 24;
                                            break;
                                        case FieldType.LLVector4:
                                            Array.Copy(((LLVector4)field).GetBytes(), 0, byteArray, length, 16);
                                            length += 16;
                                            break;
                                        case FieldType.LLQuaternion:
                                            Array.Copy(((LLQuaternion)field).GetBytes(), 0, byteArray, length, 16);
                                            length += 16;
                                            break;
                                        case FieldType.IPADDR:
                                            Array.Copy(((IPAddress)field).GetAddressBytes(), 0, byteArray, length, 4);
                                            length += 4;
                                            break;
                                        case FieldType.IPPORT:
                                            ushort fieldIPPort = (ushort)field;
                                            byteArray[length + 1] = (byte)(fieldIPPort % 256);
                                            fieldIPPort >>= 8;
                                            byteArray[length] = (byte)(fieldIPPort % 256);
                                            length += 2;
                                            break;
                                        case FieldType.Variable:
                                            if (field.GetType().IsArray)
                                            {
                                                // Assume this is a byte array
                                                fieldLength = ((byte[])field).Length;
                                            }
                                            else
                                            {
                                                // Assume this is a string, add 1 for the null terminator
                                                fieldLength = ((string)field).Length + 1;
                                            }

                                            if (fieldMap.Count == 1)
                                            {
                                                if (fieldLength > 255)
                                                {
                                                    throw new Exception("Variable byte field longer than 255 characters");
                                                }

                                                byteArray[length] = (byte)(fieldLength);
                                                length++;
                                            }
                                            else if (fieldMap.Count == 2)
                                            {
                                                if (fieldLength > 1024)
                                                {
                                                    throw new Exception("Variable byte field longer than 1024 characters");
                                                }

                                                byteArray[length++] = (byte)(fieldLength % 256);
                                                byteArray[length++] = (byte)(fieldLength / 256);
                                            }
                                            else
                                            {
                                                throw new Exception("Variable field with an unknown count, protocol map error");
                                            }

                                            if (field.GetType().IsArray)
                                            {
                                                // Assume this is a byte array
                                                Array.Copy((byte[])field, 0, byteArray, length, fieldLength);
                                            }
                                            else
                                            {
                                                // Assume this is a string, add 1 for the null terminator
                                                byte[] stringBytes = System.Text.Encoding.UTF8.GetBytes((string)field);
                                                Array.Copy(stringBytes, 0, byteArray, length, stringBytes.Length);
                                                fieldLength = stringBytes.Length + 1;
                                            }

                                            length += fieldLength;

                                            break;
                                        case FieldType.Fixed:
                                            Array.Copy((byte[])field, 0, byteArray, length, fieldMap.Count);
                                            length += fieldMap.Count;
                                            break;
                                        default:
                                            throw new Exception("Unhandled FieldType");
                                    }
                                    #endregion AddField
                                }
                                else
                                {
                                    // This field wasn't passed in, create an empty version
                                    #region EmptyField
                                    if (fieldMap.Type == FieldType.Variable)
                                    {
                                        // Just set the counter to zero and move on
                                        if (fieldMap.Count == 2)
                                        {
                                            length += 2;
                                        }
                                        else
                                        {
                                            if (fieldMap.Count != 1)
                                            {
                                                throw new Exception("Variable length field has an invalid Count");
                                            }

                                            length++;
                                        }
                                    }
                                    else if (fieldMap.Type == FieldType.Fixed)
                                    {
                                        length += fieldMap.Count;
                                    }
                                    else
                                    {
                                        length += (int)protocol.TypeSizes[fieldMap.Type];
                                    }
                                    #endregion EmptyField
                                }
                            }
                        }
                        else
                        {
                            throw new Exception("Too many blocks");
                        }
                    }
                }
                #endregion BuildBlock

                // If this is a fixed count block and it doesn't appear in the Hashtable passed in, create
                // empty filler blocks
                #region EmptyBlock
                if (blockCount == 0 && blockMap.Count != -1)
                {
                    for (int i = 0; i < blockMap.Count; ++i)
                    {
                        foreach (MapField field in blockMap.Fields)
                        {
                            if (field.Type == FieldType.Variable)
                            {
                                length++;
                            }
                            else
                            {
                                length += (int)protocol.TypeSizes[field.Type];
                            }
                        }
                    }
                }
                #endregion EmptyBlock
            }

            Packet packet = new Packet(byteArray, length, protocol);
            packet.Data[0] = flags;
            return packet;
        }
예제 #5
0
 /// <summary>
 /// Constructor used to build a Packet object from incoming data.
 /// </summary>
 /// <param name="data">Byte array containing the full UDP payload</param>
 /// <param name="length">Length of the actual data in the byte array</param>
 /// <param name="protocol">A reference to the ProtocolManager instance</param>
 public Packet(byte[] data, int length, ProtocolManager protocol)
     : this(data, length, protocol, protocol.Command(data), true)
 {
 }
예제 #6
0
        /// <summary>
        /// Constructor used for building a packet where the length of the data
        /// is known in advance. This is being phased out in favor of 
        /// pre-assembling the data or using PacketBuilder.BuildPacket().
        /// </summary>
        /// <param name="command">The name of the command in the message template</param>
        /// <param name="protocol">A reference to the ProtocolManager instance</param>
        /// <param name="length">The length of the packet data</param>
        public Packet(string command, ProtocolManager protocol, int length)
        {
            Protocol = protocol;
            Data = new byte[length];
            Layout = protocol.Command(command);

            if (Layout == null)
            {
                Console.WriteLine("Attempting to build a packet with invalid command \"" + command + "\"");

                // Create an empty Layout
                Layout = new MapPacket();
                Layout.Blocks = new ArrayList();
                return;
            }

            switch (Layout.Frequency)
            {
                case PacketFrequency.Low:
                    // Set the low frequency identifier bits
                    byte[] lowHeader = {0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF};
                    Array.Copy(lowHeader, 0, Data, 0, 6);

                    // Store the packet ID in network order
                    Data[6] = (byte)(Layout.ID / 256);
                    Data[7] = (byte)(Layout.ID % 256);

                    break;
                case PacketFrequency.Medium:
                    // Set the medium frequency identifier bits
                    byte[] mediumHeader = {0x00, 0x00, 0x00, 0x00, 0xFF};
                    Array.Copy(mediumHeader, 0, Data, 0, 5);
                    Data[5] = (byte)Layout.ID;

                    break;
                case PacketFrequency.High:
                    // Set the high frequency identifier bits
                    byte[] highHeader = {0x00, 0x00, 0x00, 0x00};
                    Array.Copy(highHeader, 0, Data, 0, 4);
                    Data[4] = (byte)Layout.ID;

                    break;
            }
        }