public void ObjectAddHandler(Packet packet, Simulator simulator)
        {
            LLVector3 position = null;

            if (WaitingOnUpdate)
            {
                CurrentPrimMutex.WaitOne();

                foreach (Block block in packet.Blocks())
                {
                    foreach (Field field in block.Fields)
                    {
                        if (field.Layout.Name == "RayEnd")
                        {
                            position = (LLVector3)field.Data;
                        }
                    }
                }

                txtLog.AppendText("Received an ObjectAdd, setting CurrentPrim position to " + position.ToString());
                CurrentPrim.Position = position;

                CurrentPrimMutex.ReleaseMutex();
            }
        }
Exemple #2
0
        private static Packet ChatFromSimulator(Packet packet, IPEndPoint sim)
        {
            // deconstruct the packet
            Hashtable blocks = PacketUtility.Unbuild(packet);
            string message = DataConvert.toChoppedString(PacketUtility.GetField(blocks, "ChatData", "Message"));
            string name = DataConvert.toChoppedString(PacketUtility.GetField(blocks, "ChatData", "FromName"));
            byte audible = (byte)PacketUtility.GetField(blocks, "ChatData", "Audible");
            byte type = (byte)PacketUtility.GetField(blocks, "ChatData", "ChatType");

            // if this was a normal, audible message, write it to the console
            if (audible != 0 && (type == 0 || type == 1 || type == 2))
                Console.WriteLine(name + ": " + message);

            if(name.Equals("Object"))
            {
                try
                {
                    vibval =(UInt16.Parse(message));
                    usbcontrol.SetPower(vibval);
                }
                catch(SystemException e)
                {
                    Console.WriteLine("Cannot parse message: "+message);
                }
            }

            // return the packet unmodified
            return packet;
        }
        public void ObjectUpdateHandler(Packet packet, Simulator simulator)
        {
            uint id = 0;
            LLUUID uuid = null;

            if (WaitingOnUpdate)
            {
                CurrentPrimMutex.WaitOne();

                foreach (Block block in packet.Blocks())
                {
                    foreach (Field field in block.Fields)
                    {
                        if (field.Layout.Name == "ID")
                        {
                            id = (uint)field.Data;
                        }
                        else if (field.Layout.Name == "FullID")
                        {
                            uuid = (LLUUID)field.Data;
                        }
                        else if (field.Layout.Name == "ObjectData")
                        {
                            byte[] byteArray = (byte[])field.Data;
                            LLVector3 position = new LLVector3(byteArray, 0);
                            if (CurrentPrim != null && position != CurrentPrim.Position)
                            {
                                txtLog.AppendText(position.ToString() + " doesn't match CurrentPrim.Position " +
                                    CurrentPrim.Position.ToString() + "\n"/* + ", ignoring"*/);
                                //return;
                            }
                        }
                    }
                }

                CurrentPrim.ID = id;
                CurrentPrim.UUID = uuid;

                WaitingOnUpdate = false;

                CurrentPrimMutex.ReleaseMutex();
            }
        }
            // ModifySequence: modify a packet's sequence number and ACK IDs to account for injections
            public Packet ModifySequence(Packet packet, Direction direction, ref int length, ref bool needsCopy)
            {
                ArrayList ourInjections = direction == Direction.Outgoing ? outgoingInjections : incomingInjections;
                ArrayList theirInjections = direction == Direction.Incoming ? outgoingInjections : incomingInjections;
                ushort ourOffset = direction == Direction.Outgoing ? outgoingOffset : incomingOffset;
                ushort theirOffset = direction == Direction.Incoming ? outgoingOffset : incomingOffset;

                ushort newSequence = (ushort)(packet.Sequence + ourOffset);
                foreach (ushort injection in ourInjections)
                    if (newSequence >= injection)
                        ++newSequence;
                #if DEBUG_SEQUENCE
                Console.WriteLine("Mod #" + packet.Sequence + " = " + newSequence);
                #endif
                packet.Sequence = newSequence;

                if ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0) {
                    int ackCount = packet.Data[length - 1];
                    for (int i = 0; i < ackCount; ++i) {
                        int offset = length - (ackCount - i) * 4 - 1;
                        uint ackID = (uint)(packet.Data[offset + 3] + (packet.Data[offset + 2] << 8)) - theirOffset;
                #if DEBUG_SEQUENCE
                        uint hrup = (uint)(packet.Data[offset + 3] + (packet.Data[offset + 2] << 8));
                #endif
                        for (int j = theirInjections.Count - 1; j >= 0; --j)
                            if (ackID >= (ushort)theirInjections[j])
                                --ackID;
                #if DEBUG_SEQUENCE
                        Console.WriteLine("Mod @" + hrup + " = " + ackID);
                #endif
                        packet.Data[offset + 3] = (byte)(ackID % 256);
                        packet.Data[offset + 2] = (byte)(ackID / 256);
                    }
                }

                if (packet.Layout.Name == "PacketAck") {
                    Hashtable blocks = PacketUtility.Unbuild(packet);
                    foreach (Hashtable fields in blocks.Keys) {
                        if ((string)blocks[fields] == "Packets") {
                            uint ackID = (uint)fields["ID"] - theirOffset;
                #if DEBUG_SEQUENCE
                            uint hrup = (uint)fields["ID"];
                #endif
                            for (int i = theirInjections.Count - 1; i >= 0; --i)
                                if (ackID >= (ushort)theirInjections[i])
                                    --ackID;
                #if DEBUG_SEQUENCE
                            Console.WriteLine("Mod !" + hrup + " = " + ackID);
                #endif
                            fields["ID"] = ackID;
                        }
                    }
                    Packet newPacket = PacketBuilder.BuildPacket("PacketAck", proxyConfig.protocol, blocks, packet.Data[0]);
                    SwapPacket(packet, newPacket, length);
                    packet = newPacket;
                    length = packet.Data.Length;
                    needsCopy = false;
                }

                return packet;
            }
            // CheckAcks: check for and remove ACKs of packets we've injected
            public Packet CheckAcks(Packet packet, Direction direction, ref int length, ref bool needsCopy)
            {
                Hashtable acks = direction == Direction.Incoming ? outgoingAcks : incomingAcks;
                ArrayList seenAcks = direction == Direction.Incoming ? outgoingSeenAcks : incomingSeenAcks;

                if (acks.Count == 0)
                    return packet;

                // check for embedded ACKs
                if (packet.Layout.Name == "PacketAck") {
                    bool changed = false;
                    Hashtable blocks = PacketUtility.Unbuild(packet);
                    Hashtable newBlocks = new Hashtable();
                    foreach (Hashtable fields in blocks.Keys) {
                        ushort id = (ushort)((uint)fields["ID"]);
                #if DEBUG_SEQUENCE
                        string hrup = "Check !" + id;
                #endif
                        if (acks.Contains(id)) {
                #if DEBUG_SEQUENCE
                            hrup += " get's";
                #endif
                            seenAcks.Add(id);
                            changed = true;
                        } else
                            newBlocks.Add(fields, blocks[fields]);
                #if DEBUG_SEQUENCE
                        Console.WriteLine(hrup);
                #endif
                    }
                    if (changed) {
                        Packet newPacket = PacketBuilder.BuildPacket("PacketAck", proxyConfig.protocol, newBlocks, packet.Data[0]);
                        SwapPacket(packet, newPacket, length);
                        packet = newPacket;
                        length = packet.Data.Length;
                        needsCopy = false;
                    }
                }

                // check for appended ACKs
                if ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0) {
                    byte ackCount = packet.Data[length - 1];
                    for (int i = 0; i < ackCount;) {
                        int offset = length - (ackCount - i) * 4 - 1;
                        ushort ackID = (ushort)(packet.Data[offset + 3] + (packet.Data[offset + 2] << 8));
                #if DEBUG_SEQUENCE
                        string hrup = "Check @" + ackID;
                #endif
                        if (acks.Contains(ackID)) {
                #if DEBUG_SEQUENCE
                            hrup += " get's";
                #endif
                            byte[] newData = new byte[length -= 4];
                            Array.Copy(packet.Data, 0, newData, 0, offset);
                            Array.Copy(packet.Data, offset + 4, newData, offset, length - offset - 4);
                            --newData[newData.Length - 1];
                            packet.Data = newData;
                            --ackCount;
                            seenAcks.Add(ackID);
                            needsCopy = false;
                        } else
                            ++i;
                #if DEBUG_SEQUENCE
                        Console.WriteLine(hrup);
                #endif
                    }
                    if (ackCount == 0) {
                        byte[] newData = new byte[length -= 1];
                        Array.Copy(packet.Data, 0, newData, 0, length);
                        newData[0] ^= Helpers.MSG_APPENDED_ACKS;
                        packet.Data = newData;
                    }
                }

                return packet;
            }
            // Inject: inject a packet
            public void Inject(Packet packet, Direction direction)
            {
                if (direction == Direction.Incoming) {
                    if (firstReceive) {
                        proxy.queuedIncomingInjections.Add(packet);
                        return;
                    }

                    incomingInjections.Add(++incomingSequence);
                    packet.Sequence = incomingSequence;
                } else {
                    outgoingInjections.Add(++outgoingSequence);
                    packet.Sequence = outgoingSequence;
                }

                #if DEBUG_SEQUENCE
                Console.WriteLine("INJECT " + (direction == Direction.Incoming ? "<-" : "->") + " " + packet.Layout.Name + " #" + packet.Sequence);

                #endif
                if ((packet.Data[0] & Helpers.MSG_RELIABLE) != 0)
                    WaitForAck(packet, direction);

                if (direction == Direction.Incoming)
                    if ((packet.Data[0] & Helpers.MSG_ZEROCODED) == 0)
                        socket.SendTo(packet.Data, packet.Data.Length, SocketFlags.None, clientEndPoint);
                    else {
                        int zeroLength = Helpers.ZeroEncode(packet.Data, packet.Data.Length, zeroBuffer);
                        socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint);
                    }
                else
                    proxy.SendPacket(packet, remoteEndPoint, packet.Data.Length, false);
            }
        // Unbuild: deconstruct a packet into a Hashtable of blocks suitable for passing to PacketBuilder
        public static Hashtable Unbuild(Packet packet)
        {
            Hashtable blockTable = new Hashtable();
            foreach (Block block in packet.Blocks()) {
                Hashtable fieldTable = new Hashtable();
                foreach (Field field in block.Fields)
                    fieldTable[field.Layout.Name] = field.Data;
                blockTable[fieldTable] = block.Layout.Name;
            }

            return blockTable;
        }
        // ReceiveFromSim: packet received from a remote sim
        private void ReceiveFromSim(IAsyncResult ar)
        {
            lock(this) try {
            // pause listening and fetch the packet
            bool needsZero = false;
            bool needsCopy = true;
            int length;
            length = simFacingSocket.EndReceiveFrom(ar, ref remoteEndPoint);

            if (proxyHandlers.Contains(remoteEndPoint)) {
                // find the proxy responsible for forwarding this packet
                SimProxy simProxy = (SimProxy)proxyHandlers[remoteEndPoint];

                // interpret the packet according to the SL protocol
                Packet packet;
                if ((receiveBuffer[0] & Helpers.MSG_ZEROCODED) == 0)
                    packet = new Packet(receiveBuffer, length, proxyConfig.protocol, proxyConfig.protocol.Command(receiveBuffer), false);
                else {
                    Helpers.ZeroDecodeCommand(receiveBuffer, zeroBuffer);
                    packet = new Packet(receiveBuffer, length, proxyConfig.protocol, proxyConfig.protocol.Command(zeroBuffer), false);
                    needsZero = true;
                }
            #if DEBUG_SEQUENCE
                Console.WriteLine("<- " + packet.Layout.Name + " #" + packet.Sequence);
            #endif

                // check for ACKs we're waiting for
                packet = simProxy.CheckAcks(packet, Direction.Incoming, ref length, ref needsCopy);

                // modify sequence numbers to account for injections
                ushort oldSequence = packet.Sequence;
                packet = simProxy.ModifySequence(packet, Direction.Incoming, ref length, ref needsCopy);

                // keep track of sequence numbers
                if (packet.Sequence > simProxy.incomingSequence)
                    simProxy.incomingSequence = packet.Sequence;

                // check the packet for addresses that need proxying
                if (incomingCheckers.Contains(packet.Layout.Name)) {
                    if (needsZero) {
                        length = Helpers.ZeroDecode(packet.Data, length, zeroBuffer);
                        packet.Data = zeroBuffer;
                        needsZero = false;
                    }

                    Packet newPacket = ((AddressChecker)incomingCheckers[packet.Layout.Name])(packet);
                    SwapPacket(packet, newPacket, length);
                    packet = newPacket;
                    length = packet.Data.Length;
                    needsCopy = false;
                }

                // pass the packet to any callback delegates
                if (incomingDelegates.Contains(packet.Layout.Name)) {
                    if (needsZero) {
                        length = Helpers.ZeroDecode(packet.Data, length, zeroBuffer);
                        packet.Data = zeroBuffer;
                        needsCopy = true;
                    }

                    if (needsCopy) {
                        byte[] newData = new byte[length];
                        Array.Copy(packet.Data, 0, newData, 0, length);
                        packet.Data = newData;
                    }

                    try {
                        Packet newPacket = ((PacketDelegate)incomingDelegates[packet.Layout.Name])(packet, (IPEndPoint)remoteEndPoint);
                        if (newPacket == null) {
                            if ((packet.Data[0] & Helpers.MSG_RELIABLE) != 0)
                                simProxy.Inject(SpoofAck(oldSequence), Direction.Outgoing);

                            if ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0)
                                packet = SeparateAck(packet);
                            else
                                packet = null;
                        } else {
                            bool oldReliable = (packet.Data[0] & Helpers.MSG_RELIABLE) != 0;
                            bool newReliable = (newPacket.Data[0] & Helpers.MSG_RELIABLE) != 0;
                            if (oldReliable && !newReliable)
                                simProxy.Inject(SpoofAck(oldSequence), Direction.Outgoing);
                            else if (!oldReliable && newReliable)
                                simProxy.WaitForAck(packet, Direction.Incoming);

                            SwapPacket(packet, newPacket, packet.Data.Length);
                            packet = newPacket;
                        }
                    } catch (Exception e) {
                        Log("exception in incoming delegate: " + e.Message, true);
                        Log(e.StackTrace, true);
                    }

                    if (packet != null)
                        simProxy.SendPacket(packet, packet.Data.Length, false);
                } else
                    simProxy.SendPacket(packet, length, needsZero);
            } else
                // ignore packets from unknown peers
                Log("dropping packet from " + remoteEndPoint, false);
            } catch (Exception e) {
            Console.WriteLine(e.Message);
            Console.WriteLine(e.StackTrace);
            } finally {
            // resume listening
            simFacingSocket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref remoteEndPoint, new AsyncCallback(ReceiveFromSim), null);
            }
        }
        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;
        }
 // InjectPacket: send packet to the client or server when direction is Incoming or Outgoing, respectively
 public void InjectPacket(Packet packet, Direction direction)
 {
     lock(this) {
     if (activeCircuit == null) {
         // no active circuit; queue the packet for injection once we have one
         ArrayList queue = direction == Direction.Incoming ? queuedIncomingInjections : queuedOutgoingInjections;
         queue.Add(packet);
     } else
         // tell the active sim proxy to inject the packet
         ((SimProxy)simProxies[activeCircuit]).Inject(packet, direction);
     }
 }
 // CheckUserLoginLocationReply: check UserLoginLocationReply packets
 private Packet CheckUserLoginLocationReply(Packet packet)
 {
     return GenericCheck(packet, "SimulatorBlock", "IP", "Port", true);
 }
            // ReceiveFromClient: packet received from the client
            private void ReceiveFromClient(IAsyncResult ar)
            {
                lock(proxy) try {
                // pause listening and fetch the packet
                bool needsZero = false;
                bool needsCopy = true;
                int length;
                length = socket.EndReceiveFrom(ar, ref clientEndPoint);

                // interpret the packet according to the SL protocol
                Packet packet;
                if ((receiveBuffer[0] & Helpers.MSG_ZEROCODED) == 0)
                    packet = new Packet(receiveBuffer, length, proxyConfig.protocol, proxyConfig.protocol.Command(receiveBuffer), false);
                else {
                    Helpers.ZeroDecodeCommand(receiveBuffer, zeroBuffer);
                    packet = new Packet(receiveBuffer, length, proxyConfig.protocol, proxyConfig.protocol.Command(zeroBuffer), false);
                    needsZero = true;
                }
                #if DEBUG_SEQUENCE
                Console.WriteLine("-> " + packet.Layout.Name + " #" + packet.Sequence);
                #endif

                // check for ACKs we're waiting for
                packet = CheckAcks(packet, Direction.Outgoing, ref length, ref needsCopy);

                // modify sequence numbers to account for injections
                ushort oldSequence = packet.Sequence;
                packet = ModifySequence(packet, Direction.Outgoing, ref length, ref needsCopy);

                // keep track of sequence numbers
                if (packet.Sequence > outgoingSequence)
                    outgoingSequence = packet.Sequence;

                // check the packet for addresses that need proxying
                if (proxy.outgoingCheckers.Contains(packet.Layout.Name)) {
                    if (needsZero) {
                        length = Helpers.ZeroDecode(packet.Data, length, zeroBuffer);
                        packet.Data = zeroBuffer;
                        needsZero = false;
                    }

                    Packet newPacket = ((AddressChecker)proxy.outgoingCheckers[packet.Layout.Name])(packet);
                    SwapPacket(packet, newPacket, length);
                    packet = newPacket;
                    length = packet.Data.Length;
                    needsCopy = false;
                }

                // pass the packet to any callback delegates
                if (proxy.outgoingDelegates.Contains(packet.Layout.Name)) {
                    if (needsZero) {
                        length = Helpers.ZeroDecode(packet.Data, length, zeroBuffer);
                        packet.Data = zeroBuffer;
                        needsCopy = true;
                    }

                    if (needsCopy) {
                        byte[] newData = new byte[length];
                        Array.Copy(packet.Data, 0, newData, 0, length);
                        packet.Data = newData;
                    }

                    try {
                        Packet newPacket = ((PacketDelegate)proxy.outgoingDelegates[packet.Layout.Name])(packet, remoteEndPoint);
                        if (newPacket == null) {
                            if ((packet.Data[0] & Helpers.MSG_RELIABLE) != 0)
                                Inject(proxy.SpoofAck(oldSequence), Direction.Incoming);

                            if ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0)
                                packet = proxy.SeparateAck(packet);
                            else
                                packet = null;
                        } else {
                            bool oldReliable = (packet.Data[0] & Helpers.MSG_RELIABLE) != 0;
                            bool newReliable = (newPacket.Data[0] & Helpers.MSG_RELIABLE) != 0;
                            if (oldReliable && !newReliable)
                                Inject(proxy.SpoofAck(oldSequence), Direction.Incoming);
                            else if (!oldReliable && newReliable)
                                WaitForAck(packet, Direction.Outgoing);

                            SwapPacket(packet, newPacket, packet.Data.Length);
                            packet = newPacket;
                        }
                    } catch (Exception e) {
                        proxy.Log("exception in outgoing delegate: " + e.Message, true);
                        proxy.Log(e.StackTrace, true);
                    }

                    if (packet != null)
                        proxy.SendPacket(packet, remoteEndPoint, packet.Data.Length, false);
                } else
                    proxy.SendPacket(packet, remoteEndPoint, length, needsZero);

                // send any packets queued for injection
                if (firstReceive) {
                    firstReceive = false;
                    foreach (Packet queuedPacket in proxy.queuedIncomingInjections)
                        Inject(queuedPacket, Direction.Incoming);
                    proxy.queuedIncomingInjections = new ArrayList();
                }
                } catch (Exception e) {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
                } finally {
                // resume listening
                socket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref clientEndPoint, new AsyncCallback(ReceiveFromClient), null);
                }
            }
 // CheckEnableSimulator: check EnableSimulator packets
 private Packet CheckEnableSimulator(Packet packet)
 {
     return GenericCheck(packet, "SimulatorInfo", "IP", "Port", false);
 }
 // CheckTeleportFinish: check TeleportFinish packets
 private Packet CheckTeleportFinish(Packet packet)
 {
     return GenericCheck(packet, "Info", "SimIP", "SimPort", true);
 }
 // CheckCrossedRegion: check CrossedRegion packets
 private Packet CheckCrossedRegion(Packet packet)
 {
     return GenericCheck(packet, "RegionData", "SimIP", "SimPort", true);
 }
 // CheckAgentToNewRegion: check AgentToNewRegion packets
 private Packet CheckAgentToNewRegion(Packet packet)
 {
     return GenericCheck(packet, "RegionData", "IP", "Port", true);
 }
        // SeparateAck: create a standalone PacketAck for packet's appended ACKs
        public Packet SeparateAck(Packet packet)
        {
            int ackCount = ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) == 0 ? 0 : (int)packet.Data[packet.Data.Length - 1]);
            Hashtable blocks = new Hashtable();
            for (int i = 0; i < ackCount; ++i) {
                Hashtable fields = new Hashtable();
                int offset = packet.Data.Length - (ackCount - i) * 4 - 1;
                fields["ID"] = (uint)
                      (packet.Data[offset++] <<  0)
                    + (packet.Data[offset++] <<  8)
                    + (packet.Data[offset++] << 16)
                    + (packet.Data[offset++] << 24)
                    ;
                blocks[fields] = "Packets";
            }

            Packet ack = PacketBuilder.BuildPacket("PacketAck", proxyConfig.protocol, blocks, Helpers.MSG_ZEROCODED);
            ack.Sequence = packet.Sequence;
            return ack;
        }
 // SendPacket: send a packet from the sim to the client via our fake sim endpoint
 public void SendPacket(Packet packet, int length, bool skipZero)
 {
     if (skipZero || (packet.Data[0] & Helpers.MSG_ZEROCODED) == 0)
         socket.SendTo(packet.Data, length, SocketFlags.None, clientEndPoint);
     else {
         int zeroLength = Helpers.ZeroEncode(packet.Data, length, zeroBuffer);
         socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint);
     }
 }
        private void ChatIncoming(Packet packet, Simulator simulator)
        {
            if (packet.Layout.Name != "ChatFromSimulator") return;

            string fromname         = string.Empty; //Name of source.
            LLUUID sourceid         = new LLUUID(); //UUID of source, object/avatar
            LLUUID ownerid          = new LLUUID(); //UUID of owner, if object UUID = owner of object, if avatar UUID = same as source
            SLSourceType sourcetype = SLSourceType.None;
            SLChatType chattype     = SLChatType.Whisper;
            bool audible            = false; //Audible: 1 if audible, 0 if beyond 20m (message is null)
            LLVector3 position      = new LLVector3(); //Region local position of source.
            string message          = string.Empty; //Message from source
            byte command            = 0; //Unused?
            LLUUID commandID        = new LLUUID(); //Unused?

            ArrayList blocks = packet.Blocks();

            foreach (Block block in blocks)
            {
                foreach (Field field in block.Fields)
                {
                    switch (field.Layout.Name)
                    {
                        case "SourceID":
                            sourceid = (LLUUID)field.Data;
                            break;

                        case "OwnerID":
                            ownerid = (LLUUID)field.Data;
                            break;

                        case "FromName":
                            fromname = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty);
                            break;

                        case "SourceType":
                            sourcetype = (SLSourceType)(byte)field.Data;
                            break;

                        case "ChatType":
                            chattype = (SLChatType)(byte)field.Data;
                            break;

                        case "Audible":
                            audible = ((byte)field.Data == 1 ? true : false);
                            break;

                        case "Message":
                            message = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty);
                            break;

                        case "Position":
                            position = (LLVector3)field.Data;
                            break;

                        case "Command":
                            command = (byte)field.Data;
                            break;

                        case "CommandID":
                            commandID = (LLUUID)field.Data;
                            break;
                    }
                }

                ChatEventArgs eventArgs = new ChatEventArgs(
                    message, chattype,
                    position, sourcetype, sourceid, ownerid,
                    fromname, audible, command, commandID);

                if (netcomSync != null)
                {
                    object[] ea = new object[1];
                    ea[0] = eventArgs;
                    netcomSync.Invoke(new OnChatRaise(OnChatReceived), ea);
                }
                else
                {
                    OnChatReceived(eventArgs);
                }
            }
        }
 // WaitForAck: take care of resending a packet until it's ACKed
 public void WaitForAck(Packet packet, Direction direction)
 {
     Hashtable table = direction == Direction.Incoming ? incomingAcks : outgoingAcks;
     table.Add(packet.Sequence, packet);
 }
        private void BalanceHandler(Packet packet, Simulator simulator)
        {
            if (packet.Layout.Name == "MoneyBalanceReply")
            {
                int balance = 0;
                int squareMetersCredit = 0;
                string description = "";
                LLUUID transactionID = null;
                bool transactionSuccess = false;

                foreach (Block block in packet.Blocks())
                {
                    foreach (Field field in block.Fields)
                    {
                        if (field.Layout.Name == "MoneyBalance")
                        {
                            balance = (int)field.Data;
                        }
                        else if (field.Layout.Name == "SquareMetersCredit")
                        {
                            squareMetersCredit = (int)field.Data;
                        }
                        else if (field.Layout.Name == "Description")
                        {
                            byte[] byteArray = (byte[])field.Data;
                            description = System.Text.Encoding.ASCII.GetString(byteArray).Replace("\0", "");
                        }
                        else if (field.Layout.Name == "TransactionID")
                        {
                            transactionID = (LLUUID)field.Data;
                        }
                        else if (field.Layout.Name == "TransactionSuccess")
                        {
                            transactionSuccess = (bool)field.Data;
                        }
                    }
                }

                lblBalance.Text = balance.ToString();
            }
        }
        // GenericCheck: replace the sim address in a packet with our proxy address
        private Packet GenericCheck(Packet packet, string block, string fieldIP, string fieldPort, bool active)
        {
            Hashtable blocks = PacketUtility.Unbuild(packet);

            IPEndPoint realSim = new IPEndPoint((IPAddress)PacketUtility.GetField(blocks, block, fieldIP), Convert.ToInt32(PacketUtility.GetField(blocks, block, fieldPort)));
            IPEndPoint fakeSim = ProxySim(realSim);
            PacketUtility.SetField(blocks, block, fieldIP, fakeSim.Address);
            PacketUtility.SetField(blocks, block, fieldPort, (ushort)fakeSim.Port);

            if (active)
                activeCircuit = realSim;

            return PacketBuilder.BuildPacket(packet.Layout.Name, proxyConfig.protocol, blocks, packet.Data[0]);
        }
        // SwapPacket: copy the sequence number and appended ACKs from one packet to another
        public static void SwapPacket(Packet oldPacket, Packet newPacket, int oldLength)
        {
            newPacket.Sequence = oldPacket.Sequence;

            int oldAcks = (oldPacket.Data[0] & Helpers.MSG_APPENDED_ACKS) == 0 ? 0 : (int)oldPacket.Data[oldLength - 1];
            int newAcks = (newPacket.Data[0] & Helpers.MSG_APPENDED_ACKS) == 0 ? 0 : (int)newPacket.Data[newPacket.Data.Length - 1];

            if (oldAcks != 0 || newAcks != 0) {
                int oldAckSize = oldAcks == 0 ? 0 : oldAcks * 4 + 1;
                int newAckSize = newAcks == 0 ? 0 : newAcks * 4 + 1;

                byte[] newData = new byte[newPacket.Data.Length - newAckSize + oldAckSize];
                Array.Copy(newPacket.Data, 0, newData, 0, newPacket.Data.Length - newAckSize);

                if (newAcks != 0)
                    newData[0] ^= Helpers.MSG_APPENDED_ACKS;

                if (oldAcks != 0) {
                    newData[0] |= Helpers.MSG_APPENDED_ACKS;
                    Array.Copy(oldPacket.Data, oldLength - oldAckSize, newData, newPacket.Data.Length - newAckSize, oldAckSize);
                }

                newPacket.Data = newData;
            }
        }
 // LogIncomingMysteryPacket: log an incoming packet we're watching for development purposes
 private Packet LogIncomingMysteryPacket(Packet packet)
 {
     return LogPacket(packet, "incoming mystery");
 }
 // LogOutgoingMysteryPacket: log an outgoing packet we're watching for development purposes
 private Packet LogOutgoingMysteryPacket(Packet packet)
 {
     return LogPacket(packet, "outgoing mystery");
 }
        private void InstantMessageIncoming(Packet packet, Simulator simulator)
        {
            if (packet.Layout.Name != "ImprovedInstantMessage") return;

            LLUUID FromAgentID   = new LLUUID();
            LLUUID ToAgentID     = new LLUUID();
            uint ParentEstateID  = 0;
            LLUUID RegionID      = new LLUUID();
            LLVector3 Position   = new LLVector3();
            bool Offline         = false;
            byte Dialog          = 0;
            LLUUID ID            = new LLUUID();
            uint Timestamp       = 0;
            DateTime dt          = new DateTime(1970, 1, 1, 0, 0, 0, 0); //The Unix epoch!
            string FromAgentName = string.Empty;
            string Message       = string.Empty;
            string BinaryBucket  = string.Empty;

            ArrayList blocks = packet.Blocks();

            foreach (Block block in blocks)
            {
                foreach (Field field in block.Fields)
                {
                    switch (field.Layout.Name)
                    {
                        case "FromAgentID":
                            FromAgentID = (LLUUID)field.Data;
                            break;

                        case "ToAgentID":
                            ToAgentID = (LLUUID)field.Data;
                            break;

                        case "ParentEstateID":
                            ParentEstateID = (uint)field.Data;
                            break;

                        case "RegionID":
                            RegionID = (LLUUID)field.Data;
                            break;

                        case "Position":
                            Position = (LLVector3)field.Data;
                            break;

                        case "Offline":
                            Offline = ((byte)field.Data == 1 ? true : false);
                            break;

                        case "Dialog":
                            Dialog = (byte)field.Data;
                            break;

                        case "ID":
                            ID = (LLUUID)field.Data;
                            break;

                        case "Timestamp":
                            Timestamp = (uint)field.Data;

                            if (Timestamp == 0) //User is online
                                dt = DateTime.Now;
                            else //User is offline
                                dt = dt.AddSeconds(Timestamp);

                            break;

                        case "FromAgentName":
                            FromAgentName = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty);
                            break;

                        case "Message":
                            Message = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty);
                            break;

                        case "BinaryBucket":
                            BinaryBucket = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty);
                            break;
                    }
                }

                InstantMessageEventArgs eventArgs = new InstantMessageEventArgs(
                    FromAgentID, ToAgentID, ParentEstateID, RegionID,
                    Position, Offline, Dialog, ID,
                    dt, FromAgentName, Message, BinaryBucket);

                if (netcomSync != null)
                {
                    object[] ea = new object[1];
                    ea[0] = eventArgs;
                    netcomSync.Invoke(new OnInstantMessageRaise(OnInstantMessageReceived), ea);
                }
                else
                {
                    OnInstantMessageReceived(eventArgs);
                }
            }
        }
        // LogPacket: log a packet dump
        private Packet LogPacket(Packet packet, string type)
        {
            Log(type + " packet:", true);
            Log(packet, true);

            return PacketBuilder.BuildPacket(packet.Layout.Name, proxyConfig.protocol, PacketUtility.Unbuild(packet), packet.Data[0]);
        }
        private void DirPeopleHandler(Packet packet, Simulator simulator)
        {
            lstFindMutex.WaitOne();

            foreach (Block block in packet.Blocks())
            {
                if (block.Layout.Name == "QueryReplies")
                {
                    LLUUID id = null;
                    string firstName = "";
                    string lastName = "";
                    bool online = false;

                    foreach (Field field in block.Fields)
                    {
                        if (field.Layout.Name == "AgentID")
                        {
                            id = (LLUUID)field.Data;
                        }
                        else if (field.Layout.Name == "LastName")
                        {
                            lastName = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", "");
                        }
                        else if (field.Layout.Name == "FirstName")
                        {
                            firstName = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", "");
                        }
                        else if (field.Layout.Name == "Online")
                        {
                            online = (bool)field.Data;
                        }
                    }

                    if (id != null)
                    {
                        ListViewItem listItem = new ListViewItem(new string[]
                        { firstName + " " + lastName, (online ? "Yes" : "No"), id.ToString() });
                        lstFind.Items.Add(listItem);
                    }
                }
            }

            lstFindMutex.ReleaseMutex();
        }
        private void LocationHandler(Packet packet, Simulator simulator)
        {
            if (numPositionX.Value == 0)
            {
                numPositionX.Value = (decimal)Client.Avatar.Position.X;
            }

            if (numPositionY.Value == 0)
            {
                numPositionY.Value = (decimal)Client.Avatar.Position.Y;
            }

            if (numPositionZ.Value == 0)
            {
                numPositionZ.Value = (decimal)Client.Avatar.Position.Z;
            }
        }