aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorTeravus Ovares2007-11-22 19:01:53 +0000
committerTeravus Ovares2007-11-22 19:01:53 +0000
commit999eec603ea62056f599761b90c7a0510336cdd9 (patch)
tree436e7a97ec06ab22b2378d24c5feb5296cfd7a6a /OpenSim
parent* removed erroneous comments (diff)
downloadopensim-SC-999eec603ea62056f599761b90c7a0510336cdd9.zip
opensim-SC-999eec603ea62056f599761b90c7a0510336cdd9.tar.gz
opensim-SC-999eec603ea62056f599761b90c7a0510336cdd9.tar.bz2
opensim-SC-999eec603ea62056f599761b90c7a0510336cdd9.tar.xz
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.
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/IClientAPI.cs4
-rw-r--r--OpenSim/Region/ClientStack/ClientView.PacketQueue.cs50
-rw-r--r--OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs247
-rw-r--r--OpenSim/Region/ClientStack/ClientView.cs158
4 files changed, 437 insertions, 22 deletions
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 05adf22..2c82d97 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -62,7 +62,9 @@ namespace OpenSim.Framework
62 Cloud = 3, 62 Cloud = 3,
63 Task = 4, 63 Task = 4,
64 Texture = 5, 64 Texture = 5,
65 Asset = 6 65 Asset = 6,
66 Unknown = 7,
67 Back = 8
66 } 68 }
67 69
68 /// <summary> 70 /// <summary>
diff --git a/OpenSim/Region/ClientStack/ClientView.PacketQueue.cs b/OpenSim/Region/ClientStack/ClientView.PacketQueue.cs
index 179d02a..3ce3d8c 100644
--- a/OpenSim/Region/ClientStack/ClientView.PacketQueue.cs
+++ b/OpenSim/Region/ClientStack/ClientView.PacketQueue.cs
@@ -40,6 +40,17 @@ namespace OpenSim.Region.ClientStack
40 public partial class ClientView 40 public partial class ClientView
41 { 41 {
42 protected BlockingQueue<QueItem> PacketQueue; 42 protected BlockingQueue<QueItem> PacketQueue;
43
44 protected Queue<QueItem> IncomingPacketQueue;
45 protected Queue<QueItem> OutgoingPacketQueue;
46 protected Queue<QueItem> ResendOutgoingPacketQueue;
47 protected Queue<QueItem> LandOutgoingPacketQueue;
48 protected Queue<QueItem> WindOutgoingPacketQueue;
49 protected Queue<QueItem> CloudOutgoingPacketQueue;
50 protected Queue<QueItem> TaskOutgoingPacketQueue;
51 protected Queue<QueItem> TextureOutgoingPacketQueue;
52 protected Queue<QueItem> AssetOutgoingPacketQueue;
53
43 protected Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>(); 54 protected Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
44 protected Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>(); 55 protected Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
45 56
@@ -213,7 +224,39 @@ namespace OpenSim.Region.ClientStack
213 QueItem item = new QueItem(); 224 QueItem item = new QueItem();
214 item.Packet = NewPack; 225 item.Packet = NewPack;
215 item.Incoming = false; 226 item.Incoming = false;
216 PacketQueue.Enqueue(item); 227 item.throttleType = throttlePacketType; // Packet throttle type
228 switch (throttlePacketType)
229 {
230 case ThrottleOutPacketType.Resend:
231 ResendOutgoingPacketQueue.Enqueue(item);
232 break;
233 case ThrottleOutPacketType.Texture:
234 TextureOutgoingPacketQueue.Enqueue(item);
235 break;
236 case ThrottleOutPacketType.Task:
237 TaskOutgoingPacketQueue.Enqueue(item);
238 break;
239 case ThrottleOutPacketType.Land:
240 LandOutgoingPacketQueue.Enqueue(item);
241 break;
242 case ThrottleOutPacketType.Asset:
243 AssetOutgoingPacketQueue.Enqueue(item);
244 break;
245 case ThrottleOutPacketType.Cloud:
246 CloudOutgoingPacketQueue.Enqueue(item);
247 break;
248 case ThrottleOutPacketType.Wind:
249 WindOutgoingPacketQueue.Enqueue(item);
250 break;
251
252 default:
253
254 // Acknowledgements and other such stuff should go directly to the blocking Queue
255 // Throttling them may and likely 'will' be problematic
256 PacketQueue.Enqueue(item);
257 break;
258 }
259 //OutgoingPacketQueue.Enqueue(item);
217 } 260 }
218 261
219 # region Low Level Packet Methods 262 # region Low Level Packet Methods
@@ -228,7 +271,7 @@ namespace OpenSim.Region.ClientStack
228 ack_it.Packets[0].ID = Pack.Header.Sequence; 271 ack_it.Packets[0].ID = Pack.Header.Sequence;
229 ack_it.Header.Reliable = false; 272 ack_it.Header.Reliable = false;
230 273
231 OutPacket(ack_it, ThrottleOutPacketType.Task); 274 OutPacket(ack_it, ThrottleOutPacketType.Unknown);
232 } 275 }
233 /* 276 /*
234 if (Pack.Header.Reliable) 277 if (Pack.Header.Reliable)
@@ -289,7 +332,7 @@ namespace OpenSim.Region.ClientStack
289 } 332 }
290 333
291 acks.Header.Reliable = false; 334 acks.Header.Reliable = false;
292 OutPacket(acks, ThrottleOutPacketType.Task); 335 OutPacket(acks, ThrottleOutPacketType.Unknown);
293 336
294 PendingAcks.Clear(); 337 PendingAcks.Clear();
295 } 338 }
@@ -314,6 +357,7 @@ namespace OpenSim.Region.ClientStack
314 357
315 public Packet Packet; 358 public Packet Packet;
316 public bool Incoming; 359 public bool Incoming;
360 public ThrottleOutPacketType throttleType;
317 } 361 }
318 362
319 #endregion 363 #endregion
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
781 } 781 }
782 break; 782 break;
783 783
784 #endregion
785
786 #region unimplemented handlers
787 case PacketType.AgentThrottle: 784 case PacketType.AgentThrottle:
788 785
789 //OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); 786 OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString());
790 787
791 AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; 788 AgentThrottlePacket atpack = (AgentThrottlePacket)Pack;
792 789
@@ -803,7 +800,7 @@ namespace OpenSim.Region.ClientStack
803 800
804 //Agent Throttle Block contains 7 single floatingpoint values. 801 //Agent Throttle Block contains 7 single floatingpoint values.
805 int j = 0; 802 int j = 0;
806 803
807 // Some Systems may be big endian... 804 // Some Systems may be big endian...
808 // it might be smart to do this check more often... 805 // it might be smart to do this check more often...
809 if (!BitConverter.IsLittleEndian) 806 if (!BitConverter.IsLittleEndian)
@@ -813,22 +810,22 @@ namespace OpenSim.Region.ClientStack
813 // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_ 810 // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_
814 // bytes 811 // bytes
815 // Convert to integer, since.. the full fp space isn't used. 812 // Convert to integer, since.. the full fp space isn't used.
816 tResend = (int)BitConverter.ToSingle(throttle, j); 813 tResend = (int)BitConverter.ToSingle(throttle, j);
817 j += singlefloat; 814 j += singlefloat;
818 tLand = (int)BitConverter.ToSingle(throttle, j); 815 tLand = (int)BitConverter.ToSingle(throttle, j);
819 j += singlefloat; 816 j += singlefloat;
820 tWind = (int)BitConverter.ToSingle(throttle, j); 817 tWind = (int)BitConverter.ToSingle(throttle, j);
821 j += singlefloat; 818 j += singlefloat;
822 tCloud = (int)BitConverter.ToSingle(throttle, j); 819 tCloud = (int)BitConverter.ToSingle(throttle, j);
823 j += singlefloat; 820 j += singlefloat;
824 tTask = (int)BitConverter.ToSingle(throttle, j); 821 tTask = (int)BitConverter.ToSingle(throttle, j);
825 j += singlefloat; 822 j += singlefloat;
826 tTexture = (int)BitConverter.ToSingle(throttle, j); 823 tTexture = (int)BitConverter.ToSingle(throttle, j);
827 j += singlefloat; 824 j += singlefloat;
828 tAsset = (int)BitConverter.ToSingle(throttle, j); 825 tAsset = (int)BitConverter.ToSingle(throttle, j);
829 826
830 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset; 827 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset;
831 OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet AgentThrottle - Got throttle:resendbytes=" + tResend + 828 OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "Client AgentThrottle - Got throttle:resendbytes=" + tResend +
832 " landbytes=" + tLand + 829 " landbytes=" + tLand +
833 " windbytes=" + tWind + 830 " windbytes=" + tWind +
834 " cloudbytes=" + tCloud + 831 " cloudbytes=" + tCloud +
@@ -836,9 +833,233 @@ namespace OpenSim.Region.ClientStack
836 " texturebytes=" + tTexture + 833 " texturebytes=" + tTexture +
837 " Assetbytes=" + tAsset + 834 " Assetbytes=" + tAsset +
838 " Allbytes=" + tall); 835 " Allbytes=" + tall);
836 // Total Sanity
837 // Make sure that the client sent sane total values.
838
839 // If the client didn't send acceptable values....
840 // Scale the clients values down until they are acceptable.
841
842 if (tall <= throttleOutboundMax)
843 {
844 // Sanity
845 // Making sure the client sends sane values
846 // This gives us a measure of control of the comms
847 // Check Max of Type
848 // Then Check Min of type
849
850 // Resend throttle
851 if (tResend <= ResendthrottleMAX)
852 ResendthrottleOutbound = tResend;
853
854 if (tResend < ResendthrottleMin)
855 ResendthrottleOutbound = ResendthrottleMin;
856
857 // Land throttle
858 if (tLand <= LandthrottleMax)
859 LandthrottleOutbound = tLand;
860
861 if (tLand < LandthrottleMin)
862 LandthrottleOutbound = LandthrottleMin;
863
864 // Wind throttle
865 if (tWind <= WindthrottleMax)
866 WindthrottleOutbound = tWind;
867
868 if (tWind < WindthrottleMin)
869 WindthrottleOutbound = WindthrottleMin;
870
871 // Cloud throttle
872 if (tCloud <= CloudthrottleMax)
873 CloudthrottleOutbound = tCloud;
874
875 if (tCloud < CloudthrottleMin)
876 CloudthrottleOutbound = CloudthrottleMin;
877
878 // Task throttle
879 if (tTask <= TaskthrottleMax)
880 TaskthrottleOutbound = tTask;
881
882 if (tTask < TaskthrottleMin)
883 TaskthrottleOutbound = TaskthrottleMin;
884
885 // Texture throttle
886 if (tTexture <= TexturethrottleMax)
887 TexturethrottleOutbound = tTexture;
888
889 if (tTexture < TexturethrottleMin)
890 TexturethrottleOutbound = TexturethrottleMin;
891
892 //Asset throttle
893 if (tAsset <= AssetthrottleMax)
894 AssetthrottleOutbound = tAsset;
895
896 if (tAsset < AssetthrottleMin)
897 AssetthrottleOutbound = AssetthrottleMin;
898
899 OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "Using:resendbytes=" + ResendthrottleOutbound +
900 " landbytes=" + LandthrottleOutbound +
901 " windbytes=" + WindthrottleOutbound +
902 " cloudbytes=" + CloudthrottleOutbound +
903 " taskbytes=" + TaskthrottleOutbound +
904 " texturebytes=" + TexturethrottleOutbound +
905 " Assetbytes=" + AssetthrottleOutbound +
906 " Allbytes=" + tall);
907 }
908 else
909 {
910 // The client didn't send acceptable values..
911 // so it's our job now to turn them into acceptable values
912 // We're going to first scale the values down
913 // After that we're going to check if the scaled values are sane
914
915 // We're going to be dividing by a user value.. so make sure
916 // we don't get a divide by zero error.
917 if (tall > 0)
918 {
919 // Find out the percentage of all communications
920 // the client requests for each type. We'll keep resend at
921 // it's client recommended level (won't scale it down)
922 // unless it's beyond sane values itself.
923
924 if (tResend <= ResendthrottleMAX)
925 {
926 // This is nexted because we only want to re-set the values
927 // the packet throttler uses once.
928
929 if (tResend >= ResendthrottleMin)
930 {
931 ResendthrottleOutbound = tResend;
932 }
933 else
934 {
935 ResendthrottleOutbound = ResendthrottleMin;
936 }
937 }
938 else
939 {
940 ResendthrottleOutbound = ResendthrottleMAX;
941 }
942
943
944 // Getting Percentages of communication for each type of data
945 float LandPercent = (float)(tLand / tall);
946 float WindPercent = (float)(tWind / tall);
947 float CloudPercent = (float)(tCloud / tall);
948 float TaskPercent = (float)(tTask / tall);
949 float TexturePercent = (float)(tTexture / tall);
950 float AssetPercent = (float)(tAsset / tall);
951
952 // Okay.. now we've got the percentages of total communication.
953 // Apply them to a new max total
954
955 int tLandResult = (int)(LandPercent * throttleOutboundMax);
956 int tWindResult = (int)(WindPercent * throttleOutboundMax);
957 int tCloudResult = (int)(CloudPercent * throttleOutboundMax);
958 int tTaskResult = (int)(TaskPercent * throttleOutboundMax);
959 int tTextureResult = (int)(TexturePercent * throttleOutboundMax);
960 int tAssetResult = (int)(AssetPercent * throttleOutboundMax);
961
962 // Now we have to check our scaled values for sanity
963
964 // Check Max of Type
965 // Then Check Min of type
966
967 // Land throttle
968 if (tLandResult <= LandthrottleMax)
969 LandthrottleOutbound = tLandResult;
970
971 if (tLandResult < LandthrottleMin)
972 LandthrottleOutbound = LandthrottleMin;
973
974 // Wind throttle
975 if (tWindResult <= WindthrottleMax)
976 WindthrottleOutbound = tWindResult;
977
978 if (tWindResult < WindthrottleMin)
979 WindthrottleOutbound = WindthrottleMin;
980
981 // Cloud throttle
982 if (tCloudResult <= CloudthrottleMax)
983 CloudthrottleOutbound = tCloudResult;
984
985 if (tCloudResult < CloudthrottleMin)
986 CloudthrottleOutbound = CloudthrottleMin;
987
988 // Task throttle
989 if (tTaskResult <= TaskthrottleMax)
990 TaskthrottleOutbound = tTaskResult;
991
992 if (tTaskResult < TaskthrottleMin)
993 TaskthrottleOutbound = TaskthrottleMin;
994
995 // Texture throttle
996 if (tTextureResult <= TexturethrottleMax)
997 TexturethrottleOutbound = tTextureResult;
998
999 if (tTextureResult < TexturethrottleMin)
1000 TexturethrottleOutbound = TexturethrottleMin;
1001
1002 //Asset throttle
1003 if (tAssetResult <= AssetthrottleMax)
1004 AssetthrottleOutbound = tAssetResult;
1005
1006 if (tAssetResult < AssetthrottleMin)
1007 AssetthrottleOutbound = AssetthrottleMin;
1008
1009 OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "Using:resendbytes=" + ResendthrottleOutbound +
1010 " landbytes=" + LandthrottleOutbound +
1011 " windbytes=" + WindthrottleOutbound +
1012 " cloudbytes=" + CloudthrottleOutbound +
1013 " taskbytes=" + TaskthrottleOutbound +
1014 " texturebytes=" + TexturethrottleOutbound +
1015 " Assetbytes=" + AssetthrottleOutbound +
1016 " Allbytes=" + tall);
1017
1018 }
1019 else
1020 {
1021
1022 // The client sent a stupid value..
1023 // We're going to set the throttles to the minimum possible
1024 ResendthrottleOutbound = ResendthrottleMin;
1025 LandthrottleOutbound = LandthrottleMin;
1026 WindthrottleOutbound = WindthrottleMin;
1027 CloudthrottleOutbound = CloudthrottleMin;
1028 TaskthrottleOutbound = TaskthrottleMin;
1029 TexturethrottleOutbound = TexturethrottleMin;
1030 AssetthrottleOutbound = AssetthrottleMin;
1031 OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "ClientSentBadThrottle Using:resendbytes=" + ResendthrottleOutbound +
1032 " landbytes=" + LandthrottleOutbound +
1033 " windbytes=" + WindthrottleOutbound +
1034 " cloudbytes=" + CloudthrottleOutbound +
1035 " taskbytes=" + TaskthrottleOutbound +
1036 " texturebytes=" + TexturethrottleOutbound +
1037 " Assetbytes=" + AssetthrottleOutbound +
1038 " Allbytes=" + tall);
1039 }
1040
1041 }
1042 // Reset Client Throttles
1043 // This has the effect of 'wiggling the slider
1044 // causes prim and stuck textures that didn't download to download
1045
1046 ResendthrottleSentPeriod = 0;
1047 LandthrottleSentPeriod = 0;
1048 WindthrottleSentPeriod = 0;
1049 CloudthrottleSentPeriod = 0;
1050 TaskthrottleSentPeriod = 0;
1051 AssetthrottleSentPeriod = 0;
1052 TexturethrottleSentPeriod = 0;
1053
1054 //Yay, we've finally handled the agent Throttle packet!
839 1055
840 1056
1057
841 break; 1058 break;
1059
1060 #endregion
1061
1062 #region unimplemented handlers
842 case PacketType.StartPingCheck: 1063 case PacketType.StartPingCheck:
843 // Send the client the ping response back 1064 // Send the client the ping response back
844 // Pass the same PingID in the matching packet 1065 // Pass the same PingID in the matching packet
diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs
index 10f880b..411883b 100644
--- a/OpenSim/Region/ClientStack/ClientView.cs
+++ b/OpenSim/Region/ClientStack/ClientView.cs
@@ -87,11 +87,53 @@ namespace OpenSim.Region.ClientStack
87 private int probesWithNoIngressPackets = 0; 87 private int probesWithNoIngressPackets = 0;
88 private int lastPacketsReceived = 0; 88 private int lastPacketsReceived = 0;
89 89
90 90 // 1536000
91 private int throttleOutbound = 262144; // Number of bytes allowed to go out per second. (256kbps per client) 91 private int throttleOutboundMax = 1536000; // Number of bytes allowed to go out per second. (256kbps per client)
92 // TODO: Make this variable. Lower throttle on un-ack. Raise over time? 92 // TODO: Make this variable. Lower throttle on un-ack. Raise over time?
93 private int throttleSentPeriod = 0; // Number of bytes sent this period 93 private int throttleSentPeriod = 0; // Number of bytes sent this period
94 94
95 private int throttleOutbound = 162144; // Number of bytes allowed to go out per second. (256kbps per client)
96 // TODO: Make this variable. Lower throttle on un-ack. Raise over time
97
98 // All throttle times and number of bytes are calculated by dividing by this value
99 private int throttleTimeDivisor = 5;
100
101 private int throttletimems = 1000;
102
103 // Maximum -per type- throttle
104 private int ResendthrottleMAX = 100000;
105 private int LandthrottleMax = 100000;
106 private int WindthrottleMax = 100000;
107 private int CloudthrottleMax = 100000;
108 private int TaskthrottleMax = 800000;
109 private int AssetthrottleMax = 800000;
110 private int TexturethrottleMax = 800000;
111
112 // Minimum -per type- throttle
113 private int ResendthrottleMin = 5000; // setting resendmin to 0 results in mostly dropped packets
114 private int LandthrottleMin = 1000;
115 private int WindthrottleMin = 1000;
116 private int CloudthrottleMin = 1000;
117 private int TaskthrottleMin = 1000;
118 private int AssetthrottleMin = 1000;
119 private int TexturethrottleMin = 1000;
120
121 // Sim default per-client settings.
122 private int ResendthrottleOutbound = 50000;
123 private int ResendthrottleSentPeriod = 0;
124 private int LandthrottleOutbound = 100000;
125 private int LandthrottleSentPeriod = 0;
126 private int WindthrottleOutbound = 10000;
127 private int WindthrottleSentPeriod = 0;
128 private int CloudthrottleOutbound = 5000;
129 private int CloudthrottleSentPeriod = 0;
130 private int TaskthrottleOutbound = 100000;
131 private int TaskthrottleSentPeriod = 0;
132 private int AssetthrottleOutbound = 80000;
133 private int AssetthrottleSentPeriod = 0;
134 private int TexturethrottleOutbound = 100000;
135 private int TexturethrottleSentPeriod = 0;
136
95 private Timer throttleTimer; 137 private Timer throttleTimer;
96 138
97 public ClientView(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, ClientManager clientManager, 139 public ClientView(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, ClientManager clientManager,
@@ -114,14 +156,31 @@ namespace OpenSim.Region.ClientStack
114 156
115 startpos = m_authenticateSessionsHandler.GetPosition(initialcirpack.CircuitCode.Code); 157 startpos = m_authenticateSessionsHandler.GetPosition(initialcirpack.CircuitCode.Code);
116 158
159
160 // While working on this, the BlockingQueue had me fooled for a bit.
161 // The Blocking queue causes the thread to stop until there's something
162 // in it to process. it's an on-purpose threadlock though because
163 // without it, the clientloop will suck up all sim resources.
164
117 PacketQueue = new BlockingQueue<QueItem>(); 165 PacketQueue = new BlockingQueue<QueItem>();
118 166
167 IncomingPacketQueue = new Queue<QueItem>();
168 OutgoingPacketQueue = new Queue<QueItem>();
169 ResendOutgoingPacketQueue = new Queue<QueItem>();
170 LandOutgoingPacketQueue = new Queue<QueItem>();
171 WindOutgoingPacketQueue = new Queue<QueItem>();
172 CloudOutgoingPacketQueue = new Queue<QueItem>();
173 TaskOutgoingPacketQueue = new Queue<QueItem>();
174 TextureOutgoingPacketQueue = new Queue<QueItem>();
175 AssetOutgoingPacketQueue = new Queue<QueItem>();
176
177
119 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); 178 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
120 AckTimer = new Timer(750); 179 AckTimer = new Timer(750);
121 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); 180 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
122 AckTimer.Start(); 181 AckTimer.Start();
123 182
124 throttleTimer = new Timer(1000); 183 throttleTimer = new Timer((int)(throttletimems/throttleTimeDivisor));
125 throttleTimer.Elapsed += new ElapsedEventHandler(throttleTimer_Elapsed); 184 throttleTimer.Elapsed += new ElapsedEventHandler(throttleTimer_Elapsed);
126 throttleTimer.Start(); 185 throttleTimer.Start();
127 186
@@ -133,8 +192,97 @@ namespace OpenSim.Region.ClientStack
133 } 192 }
134 193
135 void throttleTimer_Elapsed(object sender, ElapsedEventArgs e) 194 void throttleTimer_Elapsed(object sender, ElapsedEventArgs e)
136 { 195 {
137 throttleSentPeriod = 0; 196 throttleSentPeriod = 0;
197 ResendthrottleSentPeriod = 0;
198 LandthrottleSentPeriod = 0;
199 WindthrottleSentPeriod = 0;
200 CloudthrottleSentPeriod = 0;
201 TaskthrottleSentPeriod = 0;
202 AssetthrottleSentPeriod = 0;
203 TexturethrottleSentPeriod = 0;
204
205 // I was considering this.. Will an event fire if the thread it's on is blocked?
206
207 // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long
208 // The General overhead of the UDP protocol gets sent to the queue un-throttled by this
209 // so This'll pick up about around the right time.
210
211 int MaxThrottleLoops = 5550; // 50*7 packets can be dequeued at once.
212 int throttleLoops = 0;
213
214 // We're going to dequeue all of the saved up packets until
215 // we've hit the throttle limit or there's no more packets to send
216 while ((throttleSentPeriod <= ((int)(throttleOutbound/throttleTimeDivisor)) &&
217 (ResendOutgoingPacketQueue.Count > 0 ||
218 LandOutgoingPacketQueue.Count > 0 ||
219 WindOutgoingPacketQueue.Count > 0 ||
220 CloudOutgoingPacketQueue.Count > 0 ||
221 TaskOutgoingPacketQueue.Count > 0 ||
222 AssetOutgoingPacketQueue.Count > 0 ||
223 TextureOutgoingPacketQueue.Count > 0)) && throttleLoops <= MaxThrottleLoops)
224 {
225 throttleLoops++;
226 //Now comes the fun part.. we dump all our elements into PacketQueue that we've saved up.
227 if (ResendthrottleSentPeriod <= ((int)(ResendthrottleOutbound/throttleTimeDivisor)) && ResendOutgoingPacketQueue.Count > 0)
228 {
229 QueItem qpack = ResendOutgoingPacketQueue.Dequeue();
230
231 PacketQueue.Enqueue(qpack);
232 throttleSentPeriod += qpack.Packet.ToBytes().Length;
233 ResendthrottleSentPeriod += qpack.Packet.ToBytes().Length;
234 }
235 if (LandthrottleSentPeriod <= ((int)(LandthrottleOutbound/throttleTimeDivisor)) && LandOutgoingPacketQueue.Count > 0)
236 {
237 QueItem qpack = LandOutgoingPacketQueue.Dequeue();
238
239 PacketQueue.Enqueue(qpack);
240 throttleSentPeriod += qpack.Packet.ToBytes().Length;
241 LandthrottleSentPeriod += qpack.Packet.ToBytes().Length;
242 }
243 if (WindthrottleSentPeriod <= ((int)(WindthrottleOutbound/throttleTimeDivisor)) && WindOutgoingPacketQueue.Count > 0)
244 {
245 QueItem qpack = WindOutgoingPacketQueue.Dequeue();
246
247 PacketQueue.Enqueue(qpack);
248 throttleSentPeriod += qpack.Packet.ToBytes().Length;
249 WindthrottleSentPeriod += qpack.Packet.ToBytes().Length;
250 }
251 if (CloudthrottleSentPeriod <= ((int)(CloudthrottleOutbound/throttleTimeDivisor)) && CloudOutgoingPacketQueue.Count > 0)
252 {
253 QueItem qpack = CloudOutgoingPacketQueue.Dequeue();
254
255 PacketQueue.Enqueue(qpack);
256 throttleSentPeriod += qpack.Packet.ToBytes().Length;
257 CloudthrottleSentPeriod += qpack.Packet.ToBytes().Length;
258 }
259 if (TaskthrottleSentPeriod <= ((int)(TaskthrottleOutbound/throttleTimeDivisor)) && TaskOutgoingPacketQueue.Count > 0)
260 {
261 QueItem qpack = TaskOutgoingPacketQueue.Dequeue();
262
263 PacketQueue.Enqueue(qpack);
264 throttleSentPeriod += qpack.Packet.ToBytes().Length;
265 TaskthrottleSentPeriod += qpack.Packet.ToBytes().Length;
266 }
267 if (TexturethrottleSentPeriod <= ((int)(TexturethrottleOutbound/throttleTimeDivisor)) && TextureOutgoingPacketQueue.Count > 0)
268 {
269 QueItem qpack = TextureOutgoingPacketQueue.Dequeue();
270
271 PacketQueue.Enqueue(qpack);
272 throttleSentPeriod += qpack.Packet.ToBytes().Length;
273 TexturethrottleSentPeriod += qpack.Packet.ToBytes().Length;
274 }
275 if (AssetthrottleSentPeriod <= ((int)(AssetthrottleOutbound/throttleTimeDivisor)) && AssetOutgoingPacketQueue.Count > 0)
276 {
277 QueItem qpack = AssetOutgoingPacketQueue.Dequeue();
278
279 PacketQueue.Enqueue(qpack);
280 throttleSentPeriod += qpack.Packet.ToBytes().Length;
281 AssetthrottleSentPeriod += qpack.Packet.ToBytes().Length;
282 }
283
284 }
285
138 } 286 }
139 287
140 public LLUUID SessionId 288 public LLUUID SessionId
@@ -277,7 +425,7 @@ namespace OpenSim.Region.ClientStack
277 else 425 else
278 { 426 {
279 // Throw it back on the queue if it's going to cause us to flood the client 427 // Throw it back on the queue if it's going to cause us to flood the client
280 if (throttleSentPeriod > throttleOutbound) 428 if (throttleSentPeriod > throttleOutboundMax)
281 { 429 {
282 PacketQueue.Enqueue(nextPacket); 430 PacketQueue.Enqueue(nextPacket);
283 MainLog.Instance.Verbose("Client over throttle limit, requeuing packet"); 431 MainLog.Instance.Verbose("Client over throttle limit, requeuing packet");