Пример #1
0
        public static OSD GetLLSD(Packet packet)
        {
            OSDMap body = new OSDMap();
            Type type = packet.GetType();

            foreach (FieldInfo field in type.GetFields())
            {
                if (field.IsPublic)
                {
                    Type blockType = field.FieldType;

                    if (blockType.IsArray)
                    {
                        object blockArray = field.GetValue(packet);
                        Array array = (Array)blockArray;
                        OSDArray blockList = new OSDArray(array.Length);
                        IEnumerator ie = array.GetEnumerator();

                        while (ie.MoveNext())
                        {
                            object block = ie.Current;
                            blockList.Add(BuildLLSDBlock(block));
                        }

                        body[field.Name] = blockList;
                    }
                    else
                    {
                        object block = field.GetValue(packet);
                        body[field.Name] = BuildLLSDBlock(block);
                    }
                }
            }

            return body;
        }
Пример #2
0
        /// <summary>
        /// Sends a packet directly to the simulator without queuing
        /// </summary>
        /// <param name="packet">Packet to be sent</param>
        /// <param name="setSequence">True to set the sequence number, false to
        /// leave it as is</param>
        public void SendPacketUnqueued(Packet packet, bool setSequence)
        {
            byte[] buffer;
            int bytes;

            // Set sequence implies that this is not a resent packet
            if (setSequence)
            {
                // Reset to zero if we've hit the upper sequence number limit
                Interlocked.CompareExchange(ref Sequence, 0, Settings.MAX_SEQUENCE);
                // Increment and fetch the current sequence number
                packet.Header.Sequence = (uint)Interlocked.Increment(ref Sequence);

                if (packet.Header.Reliable)
                {
                    // Wrap this packet in a struct to track timeouts and resends
                    NetworkManager.OutgoingPacket outgoing = new NetworkManager.OutgoingPacket(this, packet, true);
                    // Keep track of when this packet was first sent out (right now)
                    outgoing.TickCount = Environment.TickCount;

                    // Add this packet to the list of ACK responses we are waiting on from the server
                    lock (NeedAck)
                    {
                        NeedAck[packet.Header.Sequence] = outgoing;
                    }

                    if (packet.Header.Resent)
                    {
                        // This packet has already been sent out once, strip any appended ACKs
                        // off it and reinsert them into the outgoing ACK queue under the
                        // assumption that this packet will continually be rejected from the
                        // server or that the appended ACKs are possibly making the delivery fail
                        if (packet.Header.AckList.Length > 0)
                        {
                            Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
                                packet.Header.Sequence, packet.GetType()));

                            lock (PendingAcks)
                            {
                                foreach (uint sequence in packet.Header.AckList)
                                {
                                    if (!PendingAcks.ContainsKey(sequence))
                                        PendingAcks[sequence] = sequence;
                                }
                            }

                            packet.Header.AppendedAcks = false;
                            packet.Header.AckList = new uint[0];
                        }

                        // Update the sent time for this packet
                        SetResentTime(packet.Header.Sequence);
                    }
                    else
                    {
                        // This packet is not a resend, check if the conditions are favorable
                        // to ACK appending
                        if (packet.Type != PacketType.PacketAck &&
                            packet.Type != PacketType.LogoutRequest)
                        {
                            lock (PendingAcks)
                            {
                                if (PendingAcks.Count > 0 &&
                                    PendingAcks.Count < Client.Settings.MAX_APPENDED_ACKS)
                                {
                                    // Append all of the queued up outgoing ACKs to this packet
                                    packet.Header.AckList = new uint[PendingAcks.Count];

                                    for (int i = 0; i < PendingAcks.Count; i++)
                                        packet.Header.AckList[i] = PendingAcks.Values[i];

                                    PendingAcks.Clear();
                                    packet.Header.AppendedAcks = true;
                                }
                            }
                        }
                    }
                }
                else if (packet.Header.AckList.Length > 0)
                {
                    // Sanity check for ACKS appended on an unreliable packet, this is bad form
                    Logger.Log("Sending appended ACKs on an unreliable packet", Helpers.LogLevel.Warning);
                }
            }

            // Serialize the packet
            buffer = packet.ToBytes();
            bytes = buffer.Length;
            Stats.SentBytes += (ulong)bytes;
            ++Stats.SentPackets;

            UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint);

            // Zerocode if needed
            if (packet.Header.Zerocoded)
                bytes = Helpers.ZeroEncode(buffer, bytes, buf.Data);
            else
                Buffer.BlockCopy(buffer, 0, buf.Data, 0, bytes);

            buf.DataLength = bytes;

            AsyncBeginSend(buf);
        }
Пример #3
0
        /// <summary>
        /// Creates a formatted string containing the values of a Packet
        /// </summary>
        /// <param name="packet">The Packet</param>
        /// <returns>A formatted string of values of the nested items in the Packet object</returns>
        public static string PacketToString(Packet packet)
        {
            StringBuilder result = new StringBuilder();

            result.AppendFormat("Packet Type: {0} http://lib.openmetaverse.co/wiki/{0} http://wiki.secondlife.com/wiki/{0}" + Environment.NewLine, packet.Type);
            result.AppendLine("[Packet Header]");
            // payload
            result.AppendFormat("Sequence: {0}" + Environment.NewLine, packet.Header.Sequence);
            result.AppendFormat(" Options: {0}" + Environment.NewLine, InterpretOptions(packet.Header));
            result.AppendLine();

            result.AppendLine("[Packet Payload]");

            FieldInfo[] fields = packet.GetType().GetFields();

            for (int i = 0; i < fields.Length; i++)
            {
                // we're not interested in any of these here
                if (fields[i].Name == "Type" || fields[i].Name == "Header" || fields[i].Name == "HasVariableBlocks")
                    continue;

                if (fields[i].FieldType.IsArray)
                {
                    result.AppendFormat("{0,30} []" + Environment.NewLine, "-- " + fields[i].Name + " --");
                    RecursePacketArray(fields[i], packet, ref result);
                }
                else
                {
                    result.AppendFormat("{0,30}" + Environment.NewLine, "-- " + fields[i].Name + " --");
                    RecursePacketField(fields[i], packet, ref result);
                }
            }
            return result.ToString();
        }
Пример #4
0
        /// <summary>
        /// Parse a packet into human readable formatted key/value pairs
        /// </summary>
        /// <param name="packet">the Packet to parse</param>
        /// <returns>A string containing the packet block name, and key/value pairs of the data fields</returns>
        public static string PacketToString(Packet packet)
        {
            StringBuilder result = new StringBuilder();

            foreach(FieldInfo packetField in packet.GetType().GetFields())
            {
                object packetDataObject = packetField.GetValue(packet);

                result.AppendFormat("-- {0} --" + System.Environment.NewLine, packetField.Name);

                foreach(FieldInfo packetValueField in packetField.GetValue(packet).GetType().GetFields())
                {
                    result.AppendFormat("{0}: {1}" + System.Environment.NewLine, 
                        packetValueField.Name, packetValueField.GetValue(packetDataObject));
                }

                // handle blocks that are arrays
                if (packetDataObject.GetType().IsArray)
                {
                    foreach (object nestedArrayRecord in packetDataObject as Array)
                    {
                        foreach (FieldInfo packetArrayField in nestedArrayRecord.GetType().GetFields())
                        {
                            result.AppendFormat("{0} {1}" + System.Environment.NewLine, 
                                packetArrayField.Name, packetArrayField.GetValue(nestedArrayRecord));
                        }
                    }
                }
                else
                {
                    // handle non array data blocks
                    foreach (PropertyInfo packetPropertyField in packetField.GetValue(packet).GetType().GetProperties())
                    {
                        // Handle fields named "Data" specifically, this is generally binary data, we'll display it as hex values
                        if (packetPropertyField.PropertyType.Equals(typeof(System.Byte[])) 
                            && packetPropertyField.Name.Equals("Data"))
                        {
                            result.AppendFormat("{0}: {1}" + System.Environment.NewLine,
                                packetPropertyField.Name, 
                                Utils.BytesToHexString((byte[])packetPropertyField.GetValue(packetDataObject, null), packetPropertyField.Name));
                        }
                        // decode bytes into strings
                        else if (packetPropertyField.PropertyType.Equals(typeof(System.Byte[])))
                        {
                            result.AppendFormat("{0}: {1}" + System.Environment.NewLine, 
                                packetPropertyField.Name, 
                                Utils.BytesToString((byte[])packetPropertyField.GetValue(packetDataObject, null)));
                        }
                        else
                        {
                            result.AppendFormat("{0}: {1}" + System.Environment.NewLine, 
                                packetPropertyField.Name, packetPropertyField.GetValue(packetDataObject, null));
                        }
                    }
                }
            }
            return result.ToString();
        }
Пример #5
0
        public void SendPacket(Packet packet, bool setSequence)
        {
            byte[] buffer;
            int bytes;

            // Keep track of when this packet was sent out
            packet.TickCount = Environment.TickCount;

            if (setSequence)
            {
                // Reset to zero if we've hit the upper sequence number limit
                Interlocked.CompareExchange(ref currentSequence, 0, 0xFFFFFF);
                // Increment and fetch the current sequence number
                uint sequence = (uint)Interlocked.Increment(ref currentSequence);
                packet.Header.Sequence = sequence;

                if (packet.Header.Reliable)
                {
                    // Add this packet to the list of ACK responses we are waiting on from the client
                    lock (needAcks)
                        needAcks[sequence] = packet;

                    if (packet.Header.Resent)
                    {
                        // This packet has already been sent out once, strip any appended ACKs
                        // off it and reinsert them into the outgoing ACK queue under the 
                        // assumption that this packet will continually be rejected from the
                        // client or that the appended ACKs are possibly making the delivery fail
                        if (packet.Header.AckList.Length > 0)
                        {
                            Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
                                packet.Header.Sequence, packet.GetType()));

                            lock (pendingAcks)
                            {
                                foreach (uint ack in packet.Header.AckList)
                                {
                                    if (!pendingAcks.ContainsKey(ack))
                                        pendingAcks[ack] = ack;
                                }
                            }

                            packet.Header.AppendedAcks = false;
                            packet.Header.AckList = new uint[0];
                        }
                    }
                    else
                    {
                        // This packet is not a resend, check if the conditions are favorable
                        // to ACK appending
                        if (packet.Type != PacketType.PacketAck)
                        {
                            lock (pendingAcks)
                            {
                                if (pendingAcks.Count > 0 &&
                                    pendingAcks.Count < 10)
                                {
                                    // Append all of the queued up outgoing ACKs to this packet
                                    packet.Header.AckList = new uint[pendingAcks.Count];

                                    for (int i = 0; i < pendingAcks.Count; i++)
                                        packet.Header.AckList[i] = pendingAcks.Values[i];

                                    pendingAcks.Clear();
                                    packet.Header.AppendedAcks = true;
                                }
                            }
                        }
                    }
                }
                else if (packet.Header.AckList.Length > 0)
                {
                    // Sanity check for ACKS appended on an unreliable packet, this is bad form
                    Logger.Log("Sending appended ACKs on an unreliable packet", Helpers.LogLevel.Warning);
                }
            }

            // Serialize the packet
            buffer = packet.ToBytes();
            bytes = buffer.Length;
            //Stats.SentBytes += (ulong)bytes;
            //++Stats.SentPackets;

            UDPPacketBuffer buf;

            // Zerocode if needed
            if (packet.Header.Zerocoded)
            {
                buf = new UDPPacketBuffer(address, true, false);

                bytes = Helpers.ZeroEncode(buffer, bytes, buf.Data);
                buf.DataLength = bytes;
            }
            else
            {
                buf = new UDPPacketBuffer(address, false, false);

                buf.Data = buffer;
                buf.DataLength = bytes;
            }

            udpServer.AsyncBeginSend(buf);
        }