From 999eec603ea62056f599761b90c7a0510336cdd9 Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Thu, 22 Nov 2007 19:01:53 +0000 Subject: Created a client driven packet throttler. The sim now respects the client's network throttle settings but does sanity checks to avoid too little(nothing gets sent) or too much(the sim crashes) data. * Consider this experimental.. however, it looks very promising. --- .../ClientStack/ClientView.ProcessPackets.cs | 247 +++++++++++++++++++-- 1 file changed, 234 insertions(+), 13 deletions(-) (limited to 'OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs') diff --git a/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs b/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs index 7f762b6..93c12a6 100644 --- a/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs +++ b/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs @@ -781,12 +781,9 @@ namespace OpenSim.Region.ClientStack } break; - #endregion - - #region unimplemented handlers case PacketType.AgentThrottle: - - //OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; @@ -803,7 +800,7 @@ namespace OpenSim.Region.ClientStack //Agent Throttle Block contains 7 single floatingpoint values. int j = 0; - + // Some Systems may be big endian... // it might be smart to do this check more often... if (!BitConverter.IsLittleEndian) @@ -813,22 +810,22 @@ namespace OpenSim.Region.ClientStack // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_ // bytes // Convert to integer, since.. the full fp space isn't used. - tResend = (int)BitConverter.ToSingle(throttle, j); + tResend = (int)BitConverter.ToSingle(throttle, j); j += singlefloat; - tLand = (int)BitConverter.ToSingle(throttle, j); + tLand = (int)BitConverter.ToSingle(throttle, j); j += singlefloat; - tWind = (int)BitConverter.ToSingle(throttle, j); + tWind = (int)BitConverter.ToSingle(throttle, j); j += singlefloat; - tCloud = (int)BitConverter.ToSingle(throttle, j); + tCloud = (int)BitConverter.ToSingle(throttle, j); j += singlefloat; - tTask = (int)BitConverter.ToSingle(throttle, j); + tTask = (int)BitConverter.ToSingle(throttle, j); j += singlefloat; - tTexture = (int)BitConverter.ToSingle(throttle, j); + tTexture = (int)BitConverter.ToSingle(throttle, j); j += singlefloat; tAsset = (int)BitConverter.ToSingle(throttle, j); tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset; - OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet AgentThrottle - Got throttle:resendbytes=" + tResend + + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "Client AgentThrottle - Got throttle:resendbytes=" + tResend + " landbytes=" + tLand + " windbytes=" + tWind + " cloudbytes=" + tCloud + @@ -836,9 +833,233 @@ namespace OpenSim.Region.ClientStack " texturebytes=" + tTexture + " Assetbytes=" + tAsset + " Allbytes=" + tall); + // Total Sanity + // Make sure that the client sent sane total values. + + // If the client didn't send acceptable values.... + // Scale the clients values down until they are acceptable. + + if (tall <= throttleOutboundMax) + { + // Sanity + // Making sure the client sends sane values + // This gives us a measure of control of the comms + // Check Max of Type + // Then Check Min of type + + // Resend throttle + if (tResend <= ResendthrottleMAX) + ResendthrottleOutbound = tResend; + + if (tResend < ResendthrottleMin) + ResendthrottleOutbound = ResendthrottleMin; + + // Land throttle + if (tLand <= LandthrottleMax) + LandthrottleOutbound = tLand; + + if (tLand < LandthrottleMin) + LandthrottleOutbound = LandthrottleMin; + + // Wind throttle + if (tWind <= WindthrottleMax) + WindthrottleOutbound = tWind; + + if (tWind < WindthrottleMin) + WindthrottleOutbound = WindthrottleMin; + + // Cloud throttle + if (tCloud <= CloudthrottleMax) + CloudthrottleOutbound = tCloud; + + if (tCloud < CloudthrottleMin) + CloudthrottleOutbound = CloudthrottleMin; + + // Task throttle + if (tTask <= TaskthrottleMax) + TaskthrottleOutbound = tTask; + + if (tTask < TaskthrottleMin) + TaskthrottleOutbound = TaskthrottleMin; + + // Texture throttle + if (tTexture <= TexturethrottleMax) + TexturethrottleOutbound = tTexture; + + if (tTexture < TexturethrottleMin) + TexturethrottleOutbound = TexturethrottleMin; + + //Asset throttle + if (tAsset <= AssetthrottleMax) + AssetthrottleOutbound = tAsset; + + if (tAsset < AssetthrottleMin) + AssetthrottleOutbound = AssetthrottleMin; + + OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "Using:resendbytes=" + ResendthrottleOutbound + + " landbytes=" + LandthrottleOutbound + + " windbytes=" + WindthrottleOutbound + + " cloudbytes=" + CloudthrottleOutbound + + " taskbytes=" + TaskthrottleOutbound + + " texturebytes=" + TexturethrottleOutbound + + " Assetbytes=" + AssetthrottleOutbound + + " Allbytes=" + tall); + } + else + { + // The client didn't send acceptable values.. + // so it's our job now to turn them into acceptable values + // We're going to first scale the values down + // After that we're going to check if the scaled values are sane + + // We're going to be dividing by a user value.. so make sure + // we don't get a divide by zero error. + if (tall > 0) + { + // Find out the percentage of all communications + // the client requests for each type. We'll keep resend at + // it's client recommended level (won't scale it down) + // unless it's beyond sane values itself. + + if (tResend <= ResendthrottleMAX) + { + // This is nexted because we only want to re-set the values + // the packet throttler uses once. + + if (tResend >= ResendthrottleMin) + { + ResendthrottleOutbound = tResend; + } + else + { + ResendthrottleOutbound = ResendthrottleMin; + } + } + else + { + ResendthrottleOutbound = ResendthrottleMAX; + } + + + // Getting Percentages of communication for each type of data + float LandPercent = (float)(tLand / tall); + float WindPercent = (float)(tWind / tall); + float CloudPercent = (float)(tCloud / tall); + float TaskPercent = (float)(tTask / tall); + float TexturePercent = (float)(tTexture / tall); + float AssetPercent = (float)(tAsset / tall); + + // Okay.. now we've got the percentages of total communication. + // Apply them to a new max total + + int tLandResult = (int)(LandPercent * throttleOutboundMax); + int tWindResult = (int)(WindPercent * throttleOutboundMax); + int tCloudResult = (int)(CloudPercent * throttleOutboundMax); + int tTaskResult = (int)(TaskPercent * throttleOutboundMax); + int tTextureResult = (int)(TexturePercent * throttleOutboundMax); + int tAssetResult = (int)(AssetPercent * throttleOutboundMax); + + // Now we have to check our scaled values for sanity + + // Check Max of Type + // Then Check Min of type + + // Land throttle + if (tLandResult <= LandthrottleMax) + LandthrottleOutbound = tLandResult; + + if (tLandResult < LandthrottleMin) + LandthrottleOutbound = LandthrottleMin; + + // Wind throttle + if (tWindResult <= WindthrottleMax) + WindthrottleOutbound = tWindResult; + + if (tWindResult < WindthrottleMin) + WindthrottleOutbound = WindthrottleMin; + + // Cloud throttle + if (tCloudResult <= CloudthrottleMax) + CloudthrottleOutbound = tCloudResult; + + if (tCloudResult < CloudthrottleMin) + CloudthrottleOutbound = CloudthrottleMin; + + // Task throttle + if (tTaskResult <= TaskthrottleMax) + TaskthrottleOutbound = tTaskResult; + + if (tTaskResult < TaskthrottleMin) + TaskthrottleOutbound = TaskthrottleMin; + + // Texture throttle + if (tTextureResult <= TexturethrottleMax) + TexturethrottleOutbound = tTextureResult; + + if (tTextureResult < TexturethrottleMin) + TexturethrottleOutbound = TexturethrottleMin; + + //Asset throttle + if (tAssetResult <= AssetthrottleMax) + AssetthrottleOutbound = tAssetResult; + + if (tAssetResult < AssetthrottleMin) + AssetthrottleOutbound = AssetthrottleMin; + + OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "Using:resendbytes=" + ResendthrottleOutbound + + " landbytes=" + LandthrottleOutbound + + " windbytes=" + WindthrottleOutbound + + " cloudbytes=" + CloudthrottleOutbound + + " taskbytes=" + TaskthrottleOutbound + + " texturebytes=" + TexturethrottleOutbound + + " Assetbytes=" + AssetthrottleOutbound + + " Allbytes=" + tall); + + } + else + { + + // The client sent a stupid value.. + // We're going to set the throttles to the minimum possible + ResendthrottleOutbound = ResendthrottleMin; + LandthrottleOutbound = LandthrottleMin; + WindthrottleOutbound = WindthrottleMin; + CloudthrottleOutbound = CloudthrottleMin; + TaskthrottleOutbound = TaskthrottleMin; + TexturethrottleOutbound = TexturethrottleMin; + AssetthrottleOutbound = AssetthrottleMin; + OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "ClientSentBadThrottle Using:resendbytes=" + ResendthrottleOutbound + + " landbytes=" + LandthrottleOutbound + + " windbytes=" + WindthrottleOutbound + + " cloudbytes=" + CloudthrottleOutbound + + " taskbytes=" + TaskthrottleOutbound + + " texturebytes=" + TexturethrottleOutbound + + " Assetbytes=" + AssetthrottleOutbound + + " Allbytes=" + tall); + } + + } + // Reset Client Throttles + // This has the effect of 'wiggling the slider + // causes prim and stuck textures that didn't download to download + + ResendthrottleSentPeriod = 0; + LandthrottleSentPeriod = 0; + WindthrottleSentPeriod = 0; + CloudthrottleSentPeriod = 0; + TaskthrottleSentPeriod = 0; + AssetthrottleSentPeriod = 0; + TexturethrottleSentPeriod = 0; + + //Yay, we've finally handled the agent Throttle packet! + break; + + #endregion + + #region unimplemented handlers case PacketType.StartPingCheck: // Send the client the ping response back // Pass the same PingID in the matching packet -- cgit v1.1