Пример #1
0
        public void ResendUnacked(LLAgent agent)
        {
            //FIXME: Make this an .ini setting
            const int AGENT_TIMEOUT_MS = 1000 * 60;

            // Disconnect an agent if no packets are received for some time
            if (Util.TickCount() - agent.TickLastPacketReceived > AGENT_TIMEOUT_MS)
            {
                m_log.Warn("Ack timeout, disconnecting " + agent.ID);

                ShutdownClient(agent);
                return;
            }

            // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
            List <OutgoingPacket> expiredPackets = agent.NeedAcks.GetExpiredPackets(agent.RTO);

            if (expiredPackets != null)
            {
                //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);

                // Exponential backoff of the retransmission timeout
                agent.BackoffRTO();

                // Resend packets
                for (int i = 0; i < expiredPackets.Count; i++)
                {
                    OutgoingPacket outgoingPacket = expiredPackets[i];

                    //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
                    //    outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);

                    // Set the resent flag
                    outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
                    outgoingPacket.Category       = ThrottleCategory.Resend;

                    // Bump up the resend count on this packet
                    Interlocked.Increment(ref outgoingPacket.ResendCount);
                    Interlocked.Increment(ref m_packetsResent);

                    // Requeue or resend the packet
                    if (!agent.EnqueueOutgoing(outgoingPacket))
                    {
                        SendPacketFinal(outgoingPacket);
                    }
                }
            }
        }
Пример #2
0
        public void SendPacketData(LLAgent agent, byte[] data, PacketType type, ThrottleCategory category)
        {
            int dataLength = data.Length;
            bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
            bool doCopy = true;

            // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
            // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
            // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
            // to accomodate for both common scenarios and provide ample room for ACK appending in both
            int bufferSize = (dataLength > 180)
                ? LLUDPServer.MTU
                : 200;

            UDPPacketBuffer buffer = new UDPPacketBuffer(agent.RemoteEndPoint, bufferSize);

            // Zerocode if needed
            if (doZerocode)
            {
                try
                {
                    dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
                    doCopy = false;
                }
                catch (IndexOutOfRangeException)
                {
                    // The packet grew larger than the bufferSize while zerocoding.
                    // Remove the MSG_ZEROCODED flag and send the unencoded data
                    // instead
                    m_log.Debug("Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
                        " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
                    data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
                }
            }

            // If the packet data wasn't already copied during zerocoding, copy it now
            if (doCopy)
            {
                if (dataLength > buffer.Data.Length)
                {
                    m_log.Error("Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                        type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
                    buffer.Data = new byte[dataLength];
                }

                Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(agent, buffer, category, type);

            if (!agent.EnqueueOutgoing(outgoingPacket))
                SendPacketFinal(outgoingPacket);

            #endregion Queue or Send
        }
Пример #3
0
        public void ResendUnacked(LLAgent agent)
        {
            //FIXME: Make this an .ini setting
            const int AGENT_TIMEOUT_MS = 1000 * 60;

            // Disconnect an agent if no packets are received for some time
            if (Util.TickCount() - agent.TickLastPacketReceived > AGENT_TIMEOUT_MS)
            {
                m_log.Warn("Ack timeout, disconnecting " + agent.ID);

                ShutdownClient(agent);
                return;
            }

            // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
            List<OutgoingPacket> expiredPackets = agent.NeedAcks.GetExpiredPackets(agent.RTO);

            if (expiredPackets != null)
            {
                //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);

                // Exponential backoff of the retransmission timeout
                agent.BackoffRTO();

                // Resend packets
                for (int i = 0; i < expiredPackets.Count; i++)
                {
                    OutgoingPacket outgoingPacket = expiredPackets[i];

                    //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
                    //    outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);

                    // Set the resent flag
                    outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
                    outgoingPacket.Category = ThrottleCategory.Resend;

                    // Bump up the resend count on this packet
                    Interlocked.Increment(ref outgoingPacket.ResendCount);
                    Interlocked.Increment(ref m_packetsResent);

                    // Requeue or resend the packet
                    if (!agent.EnqueueOutgoing(outgoingPacket))
                        SendPacketFinal(outgoingPacket);
                }
            }
        }
Пример #4
0
        public void SendPacketData(LLAgent agent, byte[] data, PacketType type, ThrottleCategory category)
        {
            int  dataLength = data.Length;
            bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
            bool doCopy     = true;

            // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
            // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
            // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
            // to accomodate for both common scenarios and provide ample room for ACK appending in both
            int bufferSize = (dataLength > 180)
                ? LLUDPServer.MTU
                : 200;

            UDPPacketBuffer buffer = new UDPPacketBuffer(agent.RemoteEndPoint, bufferSize);

            // Zerocode if needed
            if (doZerocode)
            {
                try
                {
                    dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
                    doCopy     = false;
                }
                catch (IndexOutOfRangeException)
                {
                    // The packet grew larger than the bufferSize while zerocoding.
                    // Remove the MSG_ZEROCODED flag and send the unencoded data
                    // instead
                    m_log.Debug("Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
                                " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
                    data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
                }
            }

            // If the packet data wasn't already copied during zerocoding, copy it now
            if (doCopy)
            {
                if (dataLength > buffer.Data.Length)
                {
                    m_log.Error("Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                                type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
                    buffer.Data = new byte[dataLength];
                }

                Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(agent, buffer, category, type);

            if (!agent.EnqueueOutgoing(outgoingPacket))
            {
                SendPacketFinal(outgoingPacket);
            }

            #endregion Queue or Send
        }