/// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">Serialized packet data. If the flags or sequence number
 /// need to be updated, they will be injected directly into this binary buffer</param>
 /// <param name="category">Throttling category for this packet</param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method)
 {
     Client        = client;
     Buffer        = buffer;
     Category      = category;
     UnackedMethod = method;
 }
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">Serialized packet data. If the flags or sequence number
 /// need to be updated, they will be injected directly into this binary buffer</param>
 /// <param name="category">Throttling category for this packet</param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method)
 {
     Client = client;
     Buffer = buffer;
     Category = category;
     UnackedMethod = method;
 }
        public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
            {
                allowSplitting = false;
            }

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas       = packet.ToBytesMultiple();
                int      packetCount = datas.Length;

                if (packetCount < 1)
                {
                    m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
                }

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, packet.Type, category);
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(udpClient, data, packet.Type, category);
            }
        }
Exemple #4
0
        /// <summary>
        /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
        /// flag value
        /// </summary>
        /// <param name="i">Throttle category to convert</param>
        /// <returns>Flag representation of the throttle category</returns>
        private static ThrottleOutPacketTypeFlags CategoryToFlag(int i)
        {
            ThrottleOutPacketType category = (ThrottleOutPacketType)i;

            switch (category)
            {
            case ThrottleOutPacketType.Land:
                return(ThrottleOutPacketTypeFlags.Land);    // Terrain data

            case ThrottleOutPacketType.Wind:
                return(ThrottleOutPacketTypeFlags.Wind);    // Wind data

            case ThrottleOutPacketType.Cloud:
                return(ThrottleOutPacketTypeFlags.Cloud);    // Cloud data

            case ThrottleOutPacketType.Task:
                return(ThrottleOutPacketTypeFlags.Task);    // Object updates and everything not on the other categories

            case ThrottleOutPacketType.Texture:
                return(ThrottleOutPacketTypeFlags.Texture);    // Textures data (also impacts http texture and mesh by default)

            case ThrottleOutPacketType.Asset:
                return(ThrottleOutPacketTypeFlags.Asset);    // Non-texture Assets data

            default:
                return(0);
            }
        }
        public int GetLimit(ThrottleOutPacketType type)
        {
            switch (type)
            {
            case ThrottleOutPacketType.Resend:
                return(ResendLimit);

            case ThrottleOutPacketType.Land:
                return(LandLimit);

            case ThrottleOutPacketType.Wind:
                return(WindLimit);

            case ThrottleOutPacketType.Cloud:
                return(CloudLimit);

            case ThrottleOutPacketType.Task:
                return(TaskLimit);

            case ThrottleOutPacketType.Texture:
                return(TextureLimit);

            case ThrottleOutPacketType.Asset:
                return(AssetLimit);

            case ThrottleOutPacketType.State:
                return(StateLimit);

            case ThrottleOutPacketType.AvatarInfo:
                return(AvatarInfoLimit);

            default:
                return(0);
            }
        }
Exemple #6
0
        public int GetRate(ThrottleOutPacketType type)
        {
            switch (type)
            {
            case ThrottleOutPacketType.Resend:
                return(Resend);

            case ThrottleOutPacketType.Land:
                return(Land);

            case ThrottleOutPacketType.Wind:
                return(Wind);

            case ThrottleOutPacketType.Cloud:
                return(Cloud);

            case ThrottleOutPacketType.Task:
                return(Task);

            case ThrottleOutPacketType.Texture:
                return(Texture);

            case ThrottleOutPacketType.Asset:
                return(Asset);

            case ThrottleOutPacketType.Unknown:
            default:
                return(0);
            }
        }
Exemple #7
0
 public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
 {
     ThrottleBytes   = pBytes;
     lastTimeElapsed = Util.EnvironmentTickCount();
     Throttle        = ThrottleOutPacketType.Asset;
     m_scene         = pScene;
     User            = puser;
 }
        /// <summary>
        ///     This is the starting point for sending a simulator packet out to the client
        /// </summary>
        /// <param name="pack">Packet to send</param>
        /// <param name="throttlePacketType">Throttling category for the packet</param>
        /// <param name="doAutomaticSplitting">
        ///     True to automatically split oversized
        ///     packets (the default), or false to disable splitting if the calling code
        ///     handles splitting manually
        /// </param>
        /// <param name="resendMethod">Method that will be called if the packet needs resent</param>
        /// <param name="finishedMethod">Method that will be called when the packet is sent</param>
        void OutPacket(Packet pack, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting,
                       UnackedPacketMethod resendMethod, UnackedPacketMethod finishedMethod)
        {
            if (m_debugPacketLevel > 0 || m_debugPackets.Contains(pack.Type.ToString()))
            {
                bool outputPacket = true;

                if (m_debugPacketLevel <= 255 &&
                    (pack.Type == PacketType.SimStats || pack.Type == PacketType.SimulatorViewerTimeMessage))
                {
                    outputPacket = false;
                }

                if (m_debugPacketLevel <= 200 &&
                    (pack.Type == PacketType.ImagePacket ||
                     pack.Type == PacketType.ImageData ||
                     pack.Type == PacketType.LayerData ||
                     pack.Type == PacketType.CoarseLocationUpdate))
                {
                    outputPacket = false;
                }

                if (m_debugPacketLevel <= 100 &&
                    (pack.Type == PacketType.AvatarAnimation ||
                     pack.Type == PacketType.ViewerEffect))
                {
                    outputPacket = false;
                }

                if (m_debugPacketLevel <= 50 &&
                    (pack.Type == PacketType.ImprovedTerseObjectUpdate ||
                     pack.Type == PacketType.ObjectUpdate))
                {
                    outputPacket = false;
                }

                if (m_debugPacketLevel <= 25 &&
                    pack.Type == PacketType.ObjectPropertiesFamily)
                {
                    outputPacket = false;
                }

                if (m_debugPackets.Contains(pack.Type.ToString()))
                {
                    outputPacket = true;
                }

                if (outputPacket && !m_debugRemovePackets.Contains(pack.Type.ToString()))
                {
                    MainConsole.Instance.DebugFormat("[CLIENT ({1})]: Packet OUT {0}", pack.Type, Name);
                }
            }

            m_udpServer.SendPacket(m_udpClient, pack, throttlePacketType, doAutomaticSplitting, resendMethod,
                                   finishedMethod);
        }
Exemple #9
0
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="server">Reference to the UDP server this client is connected to</param>
        /// <param name="rates">Default throttling rates and maximum throttle limits</param>
        /// <param name="parentThrottle">Parent HTB (hierarchical token bucket)
        /// that the child throttles will be governed by</param>
        /// <param name="circuitCode">Circuit code for this connection</param>
        /// <param name="agentID">AgentID for the connected agent</param>
        /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
        public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
        {
            AgentID        = agentID;
            RemoteEndPoint = remoteEndPoint;
            CircuitCode    = circuitCode;
            m_udpServer    = server;
            if (defaultRTO != 0)
            {
                m_defaultRTO = defaultRTO;
            }
            if (maxRTO != 0)
            {
                m_maxRTO = maxRTO;
            }

            // Create a token bucket throttle for this client that has the scene token bucket as a parent
            m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total);
            // Create an array of token buckets for this clients different throttle categories
            m_throttleCategories = new TokenBucket[(int)ThrottleOutPacketType.Count];

            for (int i = 0; i < (int)ThrottleOutPacketType.Count; i++)
            {
                ThrottleOutPacketType type = (ThrottleOutPacketType)i;

                // Initialize the packet outboxes, where packets sit while they are waiting for tokens
                m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue <OutgoingPacket>();
                // Initialize the token buckets that control the throttling for each category
                m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type));
            }

            TotalRateRequested = STARTPERCLIENTRATE;
            TotalRateMin       = MINPERCLIENTRATE;

            m_throttle.MaxBurst = STARTPERCLIENTRATE;
            m_throttle.DripRate = STARTPERCLIENTRATE;

            MapCatsToPriority[(int)ThrottleOutPacketType.Resend]     = 2;
            MapCatsToPriority[(int)ThrottleOutPacketType.Land]       = 1;
            MapCatsToPriority[(int)ThrottleOutPacketType.Wind]       = 0;
            MapCatsToPriority[(int)ThrottleOutPacketType.Cloud]      = 0;
            MapCatsToPriority[(int)ThrottleOutPacketType.Task]       = 4;
            MapCatsToPriority[(int)ThrottleOutPacketType.Texture]    = 2;
            MapCatsToPriority[(int)ThrottleOutPacketType.Asset]      = 3;
            MapCatsToPriority[(int)ThrottleOutPacketType.Transfer]   = 5;
            MapCatsToPriority[(int)ThrottleOutPacketType.State]      = 5;
            MapCatsToPriority[(int)ThrottleOutPacketType.AvatarInfo] = 6;
            MapCatsToPriority[(int)ThrottleOutPacketType.OutBand]    = 7;

//            m_lastthrottleCategoryChecked = 0;

            // Default the retransmission timeout to three seconds
            RTO = m_defaultRTO;

            // Initialize this to a sane value to prevent early disconnects
            TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
        }
        /// <summary>
        ///     This is the starting point for sending a simulator packet out to the client
        /// </summary>
        /// <param name="packet">Packet to send</param>
        /// <param name="throttlePacketType">Throttling category for the packet</param>
        void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType)
        {
            #region BinaryStats

            LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);

            #endregion BinaryStats

            OutPacket(packet, throttlePacketType, true);
        }
Exemple #11
0
 /// <summary>
 ///     Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">
 ///     Serialized packet data. If the flags or sequence number
 ///     need to be updated, they will be injected directly into this binary buffer
 /// </param>
 /// <param name="category">Throttling category for this packet</param>
 /// <param name="resendMethod">The delegate to be called if this packet is determined to be unacknowledged</param>
 /// <param name="finishedMethod">The delegate to be called when this packet is sent</param>
 /// <param name="packet"></param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer,
                       ThrottleOutPacketType category, UnackedPacketMethod resendMethod,
                       UnackedPacketMethod finishedMethod, Packet packet)
 {
     Client         = client;
     Buffer         = buffer;
     Category       = category;
     UnackedMethod  = resendMethod;
     FinishedMethod = finishedMethod;
     Packet         = packet;
 }
Exemple #12
0
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="server">Reference to the UDP server this client is connected to</param>
        /// <param name="rates">Default throttling rates and maximum throttle limits</param>
        /// <param name="parentThrottle">Parent HTB (hierarchical token bucket)
        /// that the child throttles will be governed by</param>
        /// <param name="circuitCode">Circuit code for this connection</param>
        /// <param name="agentID">AgentID for the connected agent</param>
        /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
        /// <param name="defaultRTO">
        /// Default retransmission timeout for unacked packets.  The RTO will never drop
        /// beyond this number.
        /// </param>
        /// <param name="maxRTO">
        /// The maximum retransmission timeout for unacked packets.  The RTO will never exceed this number.
        /// </param>
        public LLUDPClient(
            LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID,
            IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
        {
            AgentID        = agentID;
            RemoteEndPoint = remoteEndPoint;
            CircuitCode    = circuitCode;
            m_udpServer    = server;
            if (defaultRTO != 0)
            {
                m_defaultRTO = defaultRTO;
            }
            if (maxRTO != 0)
            {
                m_maxRTO = maxRTO;
            }

            ProcessUnackedSends = true;

            // Create a token bucket throttle for this client that has the scene token bucket as a parent
            m_throttleClient
                = new AdaptiveTokenBucket(
                      string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name),
                      parentThrottle, 0, rates.Total, rates.MinimumAdaptiveThrottleRate, rates.AdaptiveThrottlesEnabled);

            // Create an array of token buckets for this clients different throttle categories
            m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];

            m_cannibalrate = rates.CannibalizeTextureRate;

            for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
            {
                ThrottleOutPacketType type = (ThrottleOutPacketType)i;

                // Initialize the packet outboxes, where packets sit while they are waiting for tokens
                m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue <OutgoingPacket>();

                // Initialize the token buckets that control the throttling for each category
                m_throttleCategories[i]
                    = new TokenBucket(
                          string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name),
                          m_throttleClient, rates.GetRate(type), 0);
            }

            // Default the retransmission timeout to one second
            RTO = m_defaultRTO;

            // Initialize this to a sane value to prevent early disconnects
            TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;

            // Initialize the stopwatch for the first set of updates, afterwards
            // the SendPacketStats method will be responsible
            m_statsUpdateStopwatch.Start();
        }
Exemple #13
0
 /// <summary>
 /// Get the number of packets queued for the given throttle type.
 /// </summary>
 /// <returns></returns>
 /// <param name="throttleType"></param>
 public int GetPacketsQueuedCount(ThrottleOutPacketType throttleType)
 {
     if ((int)throttleType > 0)
     {
         return(m_packetOutboxes[(int)throttleType].Count);
     }
     else
     {
         return(0);
     }
 }
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">Serialized packet data. If the flags or sequence number
 /// need to be updated, they will be injected directly into this binary buffer</param>
 /// <param name="category">Throttling category for this packet</param>
 /// <param name="resendMethod">The delegate to be called if this packet is determined to be unacknowledged</param>
 /// <param name="finishedMethod">The delegate to be called when this packet is sent</param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer,
     ThrottleOutPacketType category, UnackedPacketMethod resendMethod,
     UnackedPacketMethod finishedMethod, Packet packet)
 {
     Client = client;
     Buffer = buffer;
     Category = category;
     UnackedMethod = resendMethod;
     FinishedMethod = finishedMethod;
     Packet = packet;
 }
Exemple #15
0
        /// <summary>
        /// Get the number of packets queued for the given throttle type.
        /// </summary>
        /// <returns></returns>
        /// <param name="throttleType"></param>
        public int GetPacketsQueuedCount(ThrottleOutPacketType throttleType)
        {
            int icat = (int)throttleType;

            if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT)
            {
                return(m_packetOutboxes[icat].Count);
            }
            else
            {
                return(0);
            }
        }
Exemple #16
0
        public int GetCatBytesCanSend(ThrottleOutPacketType cat, int timeMS)
        {
            int icat = (int)cat;

            if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT)
            {
                TokenBucket bucket = m_throttleCategories[icat];
                return(bucket.GetCatBytesCanSend(timeMS));
            }
            else
            {
                return(0);
            }
        }
Exemple #17
0
        /// <summary>
        /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
        /// flag value
        /// </summary>
        /// <param name="i">Throttle category to convert</param>
        /// <returns>Flag representation of the throttle category</returns>
        private static ThrottleOutPacketTypeFlags CategoryToFlag(int i)
        {
            ThrottleOutPacketType category = (ThrottleOutPacketType)i;

            /*
             * Land = 1,
             * /// <summary>Wind data</summary>
             * Wind = 2,
             * /// <summary>Cloud data</summary>
             * Cloud = 3,
             * /// <summary>Any packets that do not fit into the other throttles</summary>
             * Task = 4,
             * /// <summary>Texture assets</summary>
             * Texture = 5,
             * /// <summary>Non-texture assets</summary>
             * Asset = 6,
             * /// <summary>Avatar and primitive data</summary>
             * /// <remarks>This is a sub-category of Task</remarks>
             * State = 7,
             */

            switch (category)
            {
            case ThrottleOutPacketType.Land:
                return(ThrottleOutPacketTypeFlags.Land);

            case ThrottleOutPacketType.Wind:
                return(ThrottleOutPacketTypeFlags.Wind);

            case ThrottleOutPacketType.Cloud:
                return(ThrottleOutPacketTypeFlags.Cloud);

            case ThrottleOutPacketType.Task:
                return(ThrottleOutPacketTypeFlags.Task);

            case ThrottleOutPacketType.Texture:
                return(ThrottleOutPacketTypeFlags.Texture);

            case ThrottleOutPacketType.Asset:
                return(ThrottleOutPacketTypeFlags.Asset);

            case ThrottleOutPacketType.State:
                return(ThrottleOutPacketTypeFlags.State);

            default:
                return(0);
            }
        }
Exemple #18
0
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="server">Reference to the UDP server this client is connected to</param>
        /// <param name="rates">Default throttling rates and maximum throttle limits</param>
        /// <param name="parentThrottle">Parent HTB (hierarchical token bucket)
        /// that the child throttles will be governed by</param>
        /// <param name="circuitCode">Circuit code for this connection</param>
        /// <param name="agentID">AgentID for the connected agent</param>
        /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
        /// <param name="defaultRTO">
        /// Default retransmission timeout for unacked packets.  The RTO will never drop
        /// beyond this number.
        /// </param>
        /// <param name="maxRTO">
        /// The maximum retransmission timeout for unacked packets.  The RTO will never exceed this number.
        /// </param>
        public LLUDPClient(
            LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID,
            IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
        {
            AgentID        = agentID;
            RemoteEndPoint = remoteEndPoint;
            CircuitCode    = circuitCode;
            m_udpServer    = server;
            if (defaultRTO != 0)
            {
                m_defaultRTO = defaultRTO;
            }
            if (maxRTO != 0)
            {
                m_maxRTO = maxRTO;
            }

            m_burstTime = rates.BrustTime;
            float m_burst = rates.ClientMaxRate * m_burstTime;

            // Create a token bucket throttle for this client that has the scene token bucket as a parent
            m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.ClientMaxRate, m_burst, rates.AdaptiveThrottlesEnabled);

            // Create an array of token buckets for this clients different throttle categories
            m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];

            m_burst = rates.Total * rates.BrustTime;

            for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
            {
                ThrottleOutPacketType type = (ThrottleOutPacketType)i;

                // Initialize the packet outboxes, where packets sit while they are waiting for tokens
                m_packetOutboxes[i] = new DoubleLocklessQueue <OutgoingPacket>();
                // Initialize the token buckets that control the throttling for each category
                //m_throttleCategories[i] = new TokenBucket(m_throttleClient, rates.GetRate(type), m_burst);
                float rate  = rates.GetRate(type);
                float burst = rate * rates.BrustTime;
                m_throttleCategories[i] = new TokenBucket(m_throttleClient, rate, burst);
            }

            // Default the retransmission timeout to one second
            m_RTO = m_defaultRTO;

            // Initialize this to a sane value to prevent early disconnects
            TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
            m_pingMS = (int)(3.0 * server.TickCountResolution); // so filter doesnt start at 0;
        }
        public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
        {
            // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
            if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
            {
                allowSplitting = false;
            }

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas       = packet.ToBytesMultiple();
                int      packetCount = datas.Length;

                if (packetCount < 1)
                {
                    m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
                }

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    m_scene.ForEachClient(
                        delegate(IClientAPI client)
                    {
                        if (client is LLClientView)
                        {
                            SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
                        }
                    }
                        );
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                m_scene.ForEachClient(
                    delegate(IClientAPI client)
                {
                    if (client is LLClientView)
                    {
                        SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
                    }
                }
                    );
            }
        }
Exemple #20
0
        private void QueuePacket(
            Packet packet, ThrottleOutPacketType throttlePacketType,
            Object id)
        {
            LLQueItem item = new LLQueItem();

            item.Packet       = packet;
            item.Incoming     = false;
            item.throttleType = throttlePacketType;
            item.TickCount    = Environment.TickCount;
            item.Identifier   = id;
            item.Resends      = 0;
            item.Length       = packet.Length;
            item.Sequence     = packet.Header.Sequence;

            m_PacketQueue.Enqueue(item);
            m_PacketsSent++;
        }
Exemple #21
0
        /// <summary>
        /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
        /// flag value
        /// </summary>
        /// <param name="i">Throttle category to convert</param>
        /// <returns>Flag representation of the throttle category</returns>
        private static ThrottleOutPacketTypeFlags CategoryToFlag(int i)
        {
            ThrottleOutPacketType category = (ThrottleOutPacketType)i;

            /*
             * Land = 1,
        /// <summary>Wind data</summary>
        Wind = 2,
        /// <summary>Cloud data</summary>
        Cloud = 3,
        /// <summary>Any packets that do not fit into the other throttles</summary>
        Task = 4,
        /// <summary>Texture assets</summary>
        Texture = 5,
        /// <summary>Non-texture assets</summary>
        Asset = 6,
        /// <summary>Avatar and primitive data</summary>
        /// <remarks>This is a sub-category of Task</remarks>
        State = 7,
             */

            switch (category)
            {
                case ThrottleOutPacketType.Land:
                    return ThrottleOutPacketTypeFlags.Land;
                case ThrottleOutPacketType.Wind:
                    return ThrottleOutPacketTypeFlags.Wind;
                case ThrottleOutPacketType.Cloud:
                    return ThrottleOutPacketTypeFlags.Cloud;
                case ThrottleOutPacketType.Task:
                    return ThrottleOutPacketTypeFlags.Task;
                case ThrottleOutPacketType.Texture:
                    return ThrottleOutPacketTypeFlags.Texture;
                case ThrottleOutPacketType.Asset:
                    return ThrottleOutPacketTypeFlags.Asset;
                case ThrottleOutPacketType.State:
                    return ThrottleOutPacketTypeFlags.State;
                case ThrottleOutPacketType.AvatarInfo:
                    return ThrottleOutPacketTypeFlags.AvatarInfo;
                default:
                    return 0;
            }
        }
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="server">Reference to the UDP server this client is connected to</param>
        /// <param name="rates">Default throttling rates and maximum throttle limits</param>
        /// <param name="parentThrottle">Parent HTB (hierarchical token bucket)
        /// that the child throttles will be governed by</param>
        /// <param name="circuitCode">Circuit code for this connection</param>
        /// <param name="agentID">AgentID for the connected agent</param>
        /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
        /// <param name="defaultRTO">
        /// Default retransmission timeout for unacked packets.  The RTO will never drop
        /// beyond this number.
        /// </param>
        /// <param name="maxRTO">
        /// The maximum retransmission timeout for unacked packets.  The RTO will never exceed this number.
        /// </param>
        public LLUDPClient(
            LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID,
            IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
        {
            AgentID        = agentID;
            RemoteEndPoint = remoteEndPoint;
            CircuitCode    = circuitCode;
            m_udpServer    = server;
            if (defaultRTO != 0)
            {
                m_defaultRTO = defaultRTO;
            }
            if (maxRTO != 0)
            {
                m_maxRTO = maxRTO;
            }

            // Create a token bucket throttle for this client that has the scene token bucket as a parent
            m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled);
            // Create a token bucket throttle for the total categary with the client bucket as a throttle
            m_throttleCategory = new TokenBucket(m_throttleClient, 0);
            // Create an array of token buckets for this clients different throttle categories
            m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];

            m_cannibalrate = rates.CannibalizeTextureRate;

            for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
            {
                ThrottleOutPacketType type = (ThrottleOutPacketType)i;

                // Initialize the packet outboxes, where packets sit while they are waiting for tokens
                m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue <OutgoingPacket>();
                // Initialize the token buckets that control the throttling for each category
                m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
            }

            // Default the retransmission timeout to one second
            RTO = m_defaultRTO;

            // Initialize this to a sane value to prevent early disconnects
            TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
        }
Exemple #23
0
        public void OutPacket(
            Packet packet, ThrottleOutPacketType throttlePacketType,
            Object id)
        {
            // Call the load balancer's hook. If this is not active here
            // we defer to the sim server this client is actually connected
            // to. Packet drop notifies will not be triggered in this
            // configuration!
            //

            packet.Header.Sequence = 0;

            lock (m_NeedAck)
            {
                DropResend(id);

                AddAcks(ref packet);
                QueuePacket(packet, throttlePacketType, id);
            }
        }
Exemple #24
0
        public int GetRate(ThrottleOutPacketType type)
        {
            switch (type)
            {
            case ThrottleOutPacketType.Resend:
                return(Resend);

            case ThrottleOutPacketType.Land:
                return(Land);

            case ThrottleOutPacketType.Wind:
                return(Wind);

            case ThrottleOutPacketType.Cloud:
                return(Cloud);

            case ThrottleOutPacketType.Task:
                return(Task);

            case ThrottleOutPacketType.Texture:
                return(Texture);

            case ThrottleOutPacketType.Asset:
                return(Asset);

            case ThrottleOutPacketType.Transfer:
                return(Transfer);

            case ThrottleOutPacketType.State:
                return(State);

            case ThrottleOutPacketType.AvatarInfo:
                return(AvatarInfo);

            default:
                return(0);
            }
        }
Exemple #25
0
        private void QueuePacket(
                Packet packet, ThrottleOutPacketType throttlePacketType,
                Object id)
        {
            LLQueItem item = new LLQueItem();
            item.Packet = packet;
            item.Incoming = false;
            item.throttleType = throttlePacketType;
            item.TickCount = Environment.TickCount;
            item.Identifier = id;
            item.Resends = 0;
            item.Length = packet.Length;
            item.Sequence = packet.Header.Sequence;

            m_PacketQueue.Enqueue(item);
            m_PacketsSent++;
        }
        public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType 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(udpClient.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("[LLUDPSERVER]: 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)
                {
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
                else
                {
                    bufferSize = dataLength;
                    buffer     = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

                    // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                    //     type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);

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

            #endregion Queue or Send
        }
Exemple #27
0
 // Send one packet. This actually doesn't send anything, it queues
 // it. Designed to be fire-and-forget, but there is an optional
 // notifier.
 //
 public void OutPacket(
     Packet packet, ThrottleOutPacketType throttlePacketType)
 {
     OutPacket(packet, throttlePacketType, null);
 }
Exemple #28
0
 /// <summary>
 /// Get the number of packets queued for the given throttle type.
 /// </summary>
 /// <returns></returns>
 /// <param name="throttleType"></param>
 public int GetPacketsQueuedCount(ThrottleOutPacketType throttleType)
 {
     if ((int)throttleType > 0)
         return m_packetOutboxes[(int)throttleType].Count;
     else
         return 0;
 }
Exemple #29
0
        /// <summary>
        /// Start the process of sending a packet to the client.
        /// </summary>
        /// <param name="udpClient"></param>
        /// <param name="packet"></param>
        /// <param name="category"></param>
        /// <param name="allowSplitting"></param>
        /// <param name="method">
        /// The method to call if the packet is not acked by the client.  If null, then a standard
        /// resend of the packet is done.
        /// </param>
        public virtual void SendPacket(
            LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount < 1)
                    m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, packet.Type, category, method);
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(udpClient, data, packet.Type, category, method);
            }

            PacketPool.Instance.ReturnPacket(packet);

            m_dataPresentEvent.Set();
        }
Exemple #30
0
 public int GetLimit(ThrottleOutPacketType type)
 {
     switch (type)
     {
         case ThrottleOutPacketType.Resend:
             return ResendLimit;
         case ThrottleOutPacketType.Land:
             return LandLimit;
         case ThrottleOutPacketType.Wind:
             return WindLimit;
         case ThrottleOutPacketType.Cloud:
             return CloudLimit;
         case ThrottleOutPacketType.Task:
             return TaskLimit;
         case ThrottleOutPacketType.Texture:
             return TextureLimit;
         case ThrottleOutPacketType.Asset:
             return AssetLimit;
         case ThrottleOutPacketType.Transfer:
             return TransferLimit;
         case ThrottleOutPacketType.State:
             return StateLimit;
         case ThrottleOutPacketType.AvatarInfo:
             return AvatarInfoLimit;
         default:
             return 0;
     }
 }
        public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents,
                                    bool allowSplitting, UnackedPacketMethod resendMethod,
                                    UnackedPacketMethod finishedMethod)
        {
            // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
            if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) &&
                allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount < 1)
                    MainConsole.Instance.Error("[LLUDP Server]: Failed to split " + packet.Type +
                                               " with estimated length " + packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    ForEachInternalClient(
                        delegate(IClientAPI client)
                            {
                                if (client is LLClientView)
                                    SendPacketData(((LLClientView) client).UDPClient, data, packet, category,
                                                   resendMethod, finishedMethod);
                            }
                        );
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                ForEachInternalClient(
                    delegate(IClientAPI client)
                        {
                            if (client is LLClientView)
                                SendPacketData(((LLClientView) client).UDPClient, data, packet, category, resendMethod,
                                               finishedMethod);
                        }
                    );
            }
        }
 public int GetCatRateMS(ThrottleOutPacketType cat)
     {
     TokenBucket bucket = m_throttleCategories[(int)cat];
     int ratems = (int)(bucket.RequestedDripRate/1000);
     if (ratems <1 ) ratems=1;
     return ratems;
     }
Exemple #33
0
        public void SendPacketData(LLUDPClient udpClient, byte[] data, Packet packet, ThrottleOutPacketType category, UnackedPacketMethod resendMethod, UnackedPacketMethod finishedMethod)
        {
            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 * 2;

            UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.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.Info("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + packet.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)
                {
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
                else
                {
                    bufferSize = dataLength;
                    buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

                    // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                    //     type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, resendMethod, finishedMethod, packet);

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

            #endregion Queue or Send
        }
 /// <summary>
 ///     This is the starting point for sending a simulator packet out to the client
 /// </summary>
 /// <param name="packet">Packet to send</param>
 /// <param name="throttlePacketType">Throttling category for the packet</param>
 /// <param name="doAutomaticSplitting">
 ///     True to automatically split oversized
 ///     packets (the default), or false to disable splitting if the calling code
 ///     handles splitting manually
 /// </param>
 /// <param name="resendMethod">Method that will be called if the packet needs resent</param>
 void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting,
                UnackedPacketMethod resendMethod)
 {
     OutPacket(packet, throttlePacketType, doAutomaticSplitting, resendMethod, null);
 }
Exemple #35
0
        public void OutPacket(
            Packet packet, ThrottleOutPacketType throttlePacketType,
            Object id)
        {
            // Call the load balancer's hook. If this is not active here
            // we defer to the sim server this client is actually connected
            // to. Packet drop notifies will not be triggered in this
            // configuration!
            //

            packet.Header.Sequence = 0;

            lock (m_NeedAck)
            {
                DropResend(id);

                AddAcks(ref packet);
                QueuePacket(packet, throttlePacketType, id);
            }
        }
Exemple #36
0
        public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                //if (packetCount > 1)
                //    m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets");

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, packet.Type, category);
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(udpClient, data, packet.Type, category);
            }
        }
Exemple #37
0
 public int GetRate(ThrottleOutPacketType type)
 {
     switch (type)
     {
         case ThrottleOutPacketType.Resend:
             return Resend;
         case ThrottleOutPacketType.Land:
             return Land;
         case ThrottleOutPacketType.Wind:
             return Wind;
         case ThrottleOutPacketType.Cloud:
             return Cloud;
         case ThrottleOutPacketType.Task:
             return Task;
         case ThrottleOutPacketType.Texture:
             return Texture;
         case ThrottleOutPacketType.Asset:
             return Asset;
         case ThrottleOutPacketType.Transfer:
             return Transfer;
         case ThrottleOutPacketType.State:
             return State;
         case ThrottleOutPacketType.AvatarInfo:
             return AvatarInfo;
         default:
             return 0;
     }
 }
Exemple #38
0
        public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas;
                int[] sizes;

                if (packet.UsesBufferPooling)
                {
                    datas = packet.ToBytesMultiple(_bufferPool, out sizes);
                }
                else
                {
                    datas = packet.ToBytesMultiple();
                    sizes = new int[datas.Length];

                    for (int i = 0; i < datas.Length; i++)
                    {
                        sizes[i] = datas[i].Length;
                    }
                }

                //add up all the sizes of the data going out for this packet. if it is more than MAX_PACKET_SIZE
                //drop it and log it
                long totalSz = 0;
                foreach (int size in sizes)
                {
                    totalSz += size;
                }

                if (totalSz > MAX_PACKET_SIZE)
                {
                    m_log.ErrorFormat("[LLUDPSERVER] Not sending HUGE packet Type:{0}, Size: {1}", packet.Type, totalSz);
                    datas = null;
                    return;
                }

                int packetCount = datas.Length;

                if (packetCount < 1)
                    m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, sizes[i], packet.Type, category, packet.UsesBufferPooling);
                }
            }
            else
            {
                byte[] data;
                int size = 0;
                
                if (packet.UsesBufferPooling)
                {
                    data = packet.ToBytes(_bufferPool, ref size);
                }
                else
                {
                    data = packet.ToBytes();
                    size = data.Length;
                }

                if (size > MAX_PACKET_SIZE)
                {
                    m_log.ErrorFormat("[LLUDPSERVER] Not sending HUGE packet Type:{0}, Size: {1}", packet.Type, size);
                    data = null;
                    return;
                }

                SendPacketData(udpClient, data, size, packet.Type, category, packet.UsesBufferPooling);
            }
        }
 public override void SendPacket(
     LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
 {
     PacketsSent.Add(packet);
 }
        public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting,
            UnackedPacketMethod resendMethod, UnackedPacketMethod finishedMethod)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount < 1)
                    MainConsole.Instance.Error("[LLUDPSERVER]: Failed to split " + packet.Type +
                                               " with estimated length " +
                                               packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, packet, category, resendMethod, finishedMethod);
                    data = null;
                }
                datas = null;
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(udpClient, data, packet, category, resendMethod, finishedMethod);
                data = null;
            }
            packet = null;
        }
Exemple #41
0
 // Send one packet. This actually doesn't send anything, it queues
 // it. Designed to be fire-and-forget, but there is an optional
 // notifier.
 //
 public void OutPacket(
     Packet packet, ThrottleOutPacketType throttlePacketType)
 {
     OutPacket(packet, throttlePacketType, null);
 }
Exemple #42
0
 public int GetLimit(ThrottleOutPacketType type)
 {
     switch (type)
     {
         case ThrottleOutPacketType.Resend:
             return ResendLimit;
         case ThrottleOutPacketType.Land:
             return LandLimit;
         case ThrottleOutPacketType.Wind:
             return WindLimit;
         case ThrottleOutPacketType.Cloud:
             return CloudLimit;
         case ThrottleOutPacketType.Task:
             return TaskLimit;
         case ThrottleOutPacketType.Texture:
             return TextureLimit;
         case ThrottleOutPacketType.Asset:
             return AssetLimit;
         case ThrottleOutPacketType.State:
             return StateLimit;
         case ThrottleOutPacketType.Unknown:
         default:
             return 0;
     }
 }
Exemple #43
0
 public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
 {
     ThrottleBytes = pBytes;
     lastTimeElapsed = Util.EnvironmentTickCount();
     Throttle = ThrottleOutPacketType.Asset;
     m_scene = pScene;
     User = puser;
 }
Exemple #44
0
 public int GetRate(ThrottleOutPacketType type)
 {
     switch (type)
     {
         case ThrottleOutPacketType.Resend:
             return Resend;
         case ThrottleOutPacketType.Land:
             return Land;
         case ThrottleOutPacketType.Wind:
             return Wind;
         case ThrottleOutPacketType.Cloud:
             return Cloud;
         case ThrottleOutPacketType.Task:
             return Task;
         case ThrottleOutPacketType.Texture:
             return Texture;
         case ThrottleOutPacketType.Asset:
             return Asset;
         case ThrottleOutPacketType.Unknown:
         default:
             return 0;
     }
 }
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">Serialized packet data. If the flags or sequence number
 /// need to be updated, they will be injected directly into this binary buffer</param>
 /// <param name="category">Throttling category for this packet</param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category)
 {
     Client   = client;
     Buffer   = buffer;
     Category = category;
 }
Exemple #46
0
        public void SendPacketData(LLUDPClient udpClient, byte[] data, int dataLength, PacketType type, 
            ThrottleOutPacketType category, bool bufferAcquiredFromPool)
        {
            bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
            bool zeroCoded = false;
            byte[] outBuffer = null;

            // Zerocode if needed
            if (doZerocode)
            {
                // 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;

                try
                {
                    //zerocode and return the current buffer to the pool if necessary
                    outBuffer = _bufferPool.LeaseBytes(bufferSize);
                    dataLength = Helpers.ZeroEncode(data, dataLength, outBuffer);
                    zeroCoded = true;

                    if (bufferAcquiredFromPool)
                    {
                        _bufferPool.ReturnBytes(data);
                    }

                    //now the buffer is from a pool most definitely
                    bufferAcquiredFromPool = true;
                }
                catch (IndexOutOfRangeException)
                {
                    //TODO: Throwing an exception here needs to be revisted. I've seen an issue with
                    //70+ avatars where a very common high freq packet hits this code everytime
                    //that packet either needs to be split, or this needs to be revised to not throw
                    //and instead check the buffer size and return an error condition

                    // The packet grew larger than the bufferSize while zerocoding.
                    // Remove the MSG_ZEROCODED flag and send the unencoded data
                    // instead
                    m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
                        " and BufferLength=" + outBuffer.Length + ". Removing MSG_ZEROCODED flag");
                    data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);

                    _bufferPool.ReturnBytes(outBuffer);
                }
            }

            if (! zeroCoded)
            {
                outBuffer = data;
            }

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, outBuffer, (int)category, dataLength, 
                udpClient.RemoteEndPoint, bufferAcquiredFromPool, type);

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

            #endregion Queue or Send
        }
Exemple #47
0
 /// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="client">Reference to the client this packet is destined for</param>
 /// <param name="buffer">Serialized packet data. If the flags or sequence number
 /// need to be updated, they will be injected directly into this binary buffer</param>
 /// <param name="category">Throttling category for this packet</param>
 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category)
 {
     Client = client;
     Buffer = buffer;
     Category = category;
 }
Exemple #48
0
        public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
        {
            // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
            if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount < 1)
                    m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    m_scene.ForEachClient(
                        delegate(IClientAPI client)
                        {
                            if (client is LLClientView)
                                SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
                        }
                    );
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                m_scene.ForEachClient(
                    delegate(IClientAPI client)
                    {
                        if (client is LLClientView)
                            SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
                    }
                );
            }
        }
 /// <summary>
 ///     This is the starting point for sending a simulator packet out to the client
 /// </summary>
 /// <param name="packet">Packet to send</param>
 /// <param name="throttlePacketType">Throttling category for the packet</param>
 /// <param name="doAutomaticSplitting">
 ///     True to automatically split oversized
 ///     packets (the default), or false to disable splitting if the calling code
 ///     handles splitting manually
 /// </param>
 void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
 {
     OutPacket(packet, throttlePacketType, doAutomaticSplitting, null);
 }
Exemple #50
0
        /// <summary>
        /// Start the process of sending a packet to the client.
        /// </summary>
        /// <param name="udpClient"></param>
        /// <param name="data"></param>
        /// <param name="type"></param>
        /// <param name="category"></param>
        /// <param name="method">
        /// The method to call if the packet is not acked by the client.  If null, then a standard
        /// resend of the packet is done.
        /// </param>
        public void SendPacketData(
            LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
        {
            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(udpClient.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("[LLUDPSERVER]: 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)
                {
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
                else
                {
                    bufferSize = dataLength;
                    buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);

                    // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
                    //     type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
                    Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
                }
            }

            buffer.DataLength = dataLength;

            #region Queue or Send

            OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
            // If we were not provided a method for handling unacked, use the UDPServer default method
            outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);

            // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 
            // continue to display the deleted object until relog.  Therefore, we need to always queue a kill object
            // packet so that it isn't sent before a queued update packet.
            bool requestQueue = type == PacketType.KillObject;
            if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue))
                SendPacketFinal(outgoingPacket);

            #endregion Queue or Send
        }
Exemple #51
0
        public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                //if (packetCount > 1)
                //    m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets");

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    m_scene.ForEachClient(
                        delegate(IClientAPI client)
                        {
                            if (client is LLClientView)
                                SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
                        }
                    );
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                m_scene.ForEachClient(
                    delegate(IClientAPI client)
                    {
                        if (client is LLClientView)
                            SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
                    }
                );
            }
        }