/// <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); } }
/// <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); } }
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); } }
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); }
/// <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); }
/// <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; }
/// <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(); }
/// <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; }
/// <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); } }
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); } }
/// <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); } }
/// <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); } } ); } }
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++; }
/// <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; }
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); } }
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); } }
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 }
// 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); }
/// <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> /// 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(); }
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; }
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); }
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); } }
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; } }
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; }
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; } }
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; }
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 }
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); }
/// <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 }
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); } ); } }