/// <summary> /// Default constructor /// </summary> /// <param name="parent"> /// Parent bucket if this is a child bucket, or /// null if this is a root bucket /// </param> /// <param name="maxBurst"> /// Maximum size of the bucket in bytes, or /// zero if this bucket has no maximum capacity /// </param> /// <param name="dripRate"> /// Rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full /// </param> public TokenBucket(TokenBucket parent, int maxBurst, int dripRate) { this.parent = parent; MaxBurst = maxBurst; DripRate = dripRate; lastDrip = Environment.TickCount & Int32.MaxValue; }
/// <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"></param> /// <param name="maxRTO"></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, 0); // remember the rates the client requested Rates = new int[(int)ThrottleOutPacketType.Count]; for (int i = 0; i < (int)ThrottleOutPacketType.Count; i++) { PacketsCounts[i] = 0; } //Set the priorities for the different packet types //Higher is more important MapCatsToPriority[(int)ThrottleOutPacketType.Resend] = 7; 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; // Default the retransmission timeout to one second RTO = m_defaultRTO; // Initialize this to a sane value to prevent early disconnects TickLastPacketReceived = Environment.TickCount & int.MaxValue; }
public void SetThrottles(byte[] throttleData) { byte[] adjData; int pos = 0; if (!BitConverter.IsLittleEndian) { byte[] newData = new byte[7 * 4]; Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4); for (int i = 0; i < 7; i++) { Array.Reverse(newData, i * 4, 4); } adjData = newData; } else { adjData = throttleData; } // 0.125f converts from bits to bytes int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); int total = resend + land + wind + cloud + task + texture + asset; // These are subcategories of task that we allocate a percentage to int state = (int)(task * STATE_TASK_PERCENTAGE); task -= state; int transfer = (int)(asset * TRANSFER_ASSET_PERCENTAGE); asset -= transfer; // avatar info comes out from state int avatarinfo = (int)(state * AVATAR_INFO_STATE_PERCENTAGE); state -= avatarinfo; // int total = resend + land + wind + cloud + task + texture + asset + state + avatarinfo; // Make sure none of the throttles are set below our packet MTU, // otherwise a throttle could become permanently clogged Rates[(int)ThrottleOutPacketType.Resend] = resend; Rates[(int)ThrottleOutPacketType.Land] = land; Rates[(int)ThrottleOutPacketType.Wind] = wind; Rates[(int)ThrottleOutPacketType.Cloud] = cloud; Rates[(int)ThrottleOutPacketType.Task] = task + state + avatarinfo; Rates[(int)ThrottleOutPacketType.Texture] = texture; Rates[(int)ThrottleOutPacketType.Asset] = asset + transfer; Rates[(int)ThrottleOutPacketType.State] = state; TotalRateRequested = total; TotalRateMin = (int)(total * 0.1); if (TotalRateMin < MINPERCLIENTRATE) { TotalRateMin = MINPERCLIENTRATE; } total = TotalRateMin; // let it grow slowly //MainConsole.Instance.WarnFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, AvatarInfo={9}, Transfer={10}, TaskFull={11}, Total={12}", // AgentID, resend, land, wind, cloud, task, texture, asset, state, avatarinfo, transfer, task + state + avatarinfo, total); // Update the token buckets with new throttle values TokenBucket bucket = m_throttle; bucket.DripRate = total; bucket.MaxBurst = total; // Reset the packed throttles cached data m_packedThrottles = null; }