aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs187
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs10
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs26
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs66
5 files changed, 192 insertions, 100 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index e9e2dca..9dd6663 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
@@ -202,6 +202,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 m_stopPacket = TexturePacketCount(); 202 m_stopPacket = TexturePacketCount();
203 } 203 }
204 204
205 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
206 if (m_stopPacket == 1 && Layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
207
205 m_currentPacket = StartPacket; 208 m_currentPacket = StartPacket;
206 } 209 }
207 } 210 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index c59eedf..ac4be4d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -334,11 +334,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
334// protected HashSet<uint> m_attachmentsSent; 334// protected HashSet<uint> m_attachmentsSent;
335 335
336 private int m_moneyBalance; 336 private int m_moneyBalance;
337 private bool m_deliverPackets = true;
337 private int m_animationSequenceNumber = 1; 338 private int m_animationSequenceNumber = 1;
338 private bool m_SendLogoutPacketWhenClosing = true; 339 private bool m_SendLogoutPacketWhenClosing = true;
339 private AgentUpdateArgs lastarg; 340 private AgentUpdateArgs lastarg;
340 private bool m_IsActive = true; 341 private bool m_IsActive = true;
341 private bool m_IsLoggingOut = false; 342 private bool m_IsLoggingOut = false;
343 private bool m_IsPresenceReady = false;
342 344
343 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 345 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
344 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 346 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -361,6 +363,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
361 363
362 private Timer m_propertiesPacketTimer; 364 private Timer m_propertiesPacketTimer;
363 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>(); 365 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
366 private List<Packet> m_pendingPackets;
364 367
365 #endregion Class Members 368 #endregion Class Members
366 369
@@ -376,6 +379,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
376 get { return m_startpos; } 379 get { return m_startpos; }
377 set { m_startpos = value; } 380 set { m_startpos = value; }
378 } 381 }
382 public bool DeliverPackets
383 {
384 get { return m_deliverPackets; }
385 set {
386 m_deliverPackets = value;
387 m_udpClient.m_deliverPackets = value;
388 }
389 }
379 public UUID AgentId { get { return m_agentId; } } 390 public UUID AgentId { get { return m_agentId; } }
380 public UUID ActiveGroupId { get { return m_activeGroupID; } } 391 public UUID ActiveGroupId { get { return m_activeGroupID; } }
381 public string ActiveGroupName { get { return m_activeGroupName; } } 392 public string ActiveGroupName { get { return m_activeGroupName; } }
@@ -401,6 +412,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
401 get { return m_IsActive; } 412 get { return m_IsActive; }
402 set { m_IsActive = value; } 413 set { m_IsActive = value; }
403 } 414 }
415
404 public bool IsLoggingOut 416 public bool IsLoggingOut
405 { 417 {
406 get { return m_IsLoggingOut; } 418 get { return m_IsLoggingOut; }
@@ -464,18 +476,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
464 476
465 #region Client Methods 477 #region Client Methods
466 478
479
467 /// <summary> 480 /// <summary>
468 /// Shut down the client view 481 /// Shut down the client view
469 /// </summary> 482 /// </summary>
470 public void Close() 483 public void Close()
471 { 484 {
485 Close(true);
486 }
487
488 /// <summary>
489 /// Shut down the client view
490 /// </summary>
491 public void Close(bool sendStop)
492 {
472 m_log.DebugFormat( 493 m_log.DebugFormat(
473 "[CLIENT]: Close has been called for {0} attached to scene {1}", 494 "[CLIENT]: Close has been called for {0} attached to scene {1}",
474 Name, m_scene.RegionInfo.RegionName); 495 Name, m_scene.RegionInfo.RegionName);
475 496
476 // Send the STOP packet 497 if (sendStop)
477 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 498 {
478 OutPacket(disable, ThrottleOutPacketType.Unknown); 499 // Send the STOP packet
500 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
501 OutPacket(disable, ThrottleOutPacketType.Unknown);
502 }
479 503
480 IsActive = false; 504 IsActive = false;
481 505
@@ -1041,6 +1065,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1041 public virtual void SendLayerData(float[] map) 1065 public virtual void SendLayerData(float[] map)
1042 { 1066 {
1043 Util.FireAndForget(DoSendLayerData, map); 1067 Util.FireAndForget(DoSendLayerData, map);
1068
1069 // Send it sync, and async. It's not that much data
1070 // and it improves user experience just so much!
1071 DoSendLayerData(map);
1044 } 1072 }
1045 1073
1046 /// <summary> 1074 /// <summary>
@@ -1053,16 +1081,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1053 1081
1054 try 1082 try
1055 { 1083 {
1056 //for (int y = 0; y < 16; y++) 1084 for (int y = 0; y < 16; y++)
1057 //{ 1085 {
1058 // for (int x = 0; x < 16; x++) 1086 for (int x = 0; x < 16; x+=4)
1059 // { 1087 {
1060 // SendLayerData(x, y, map); 1088 SendLayerPacket(x, y, map);
1061 // } 1089 }
1062 //} 1090 }
1063
1064 // Send LayerData in a spiral pattern. Fun!
1065 SendLayerTopRight(map, 0, 0, 15, 15);
1066 } 1091 }
1067 catch (Exception e) 1092 catch (Exception e)
1068 { 1093 {
@@ -1070,51 +1095,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1070 } 1095 }
1071 } 1096 }
1072 1097
1073 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1074 {
1075 // Row
1076 for (int i = x1; i <= x2; i++)
1077 SendLayerData(i, y1, map);
1078
1079 // Column
1080 for (int j = y1 + 1; j <= y2; j++)
1081 SendLayerData(x2, j, map);
1082
1083 if (x2 - x1 > 0)
1084 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1085 }
1086
1087 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1088 {
1089 // Row in reverse
1090 for (int i = x2; i >= x1; i--)
1091 SendLayerData(i, y2, map);
1092
1093 // Column in reverse
1094 for (int j = y2 - 1; j >= y1; j--)
1095 SendLayerData(x1, j, map);
1096
1097 if (x2 - x1 > 0)
1098 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1099 }
1100
1101 /// <summary> 1098 /// <summary>
1102 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1099 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1103 /// </summary> 1100 /// </summary>
1104 /// <param name="map">heightmap</param> 1101 /// <param name="map">heightmap</param>
1105 /// <param name="px">X coordinate for patches 0..12</param> 1102 /// <param name="px">X coordinate for patches 0..12</param>
1106 /// <param name="py">Y coordinate for patches 0..15</param> 1103 /// <param name="py">Y coordinate for patches 0..15</param>
1107 // private void SendLayerPacket(float[] map, int y, int x) 1104 private void SendLayerPacket(int x, int y, float[] map)
1108 // { 1105 {
1109 // int[] patches = new int[4]; 1106 int[] patches = new int[4];
1110 // patches[0] = x + 0 + y * 16; 1107 patches[0] = x + 0 + y * 16;
1111 // patches[1] = x + 1 + y * 16; 1108 patches[1] = x + 1 + y * 16;
1112 // patches[2] = x + 2 + y * 16; 1109 patches[2] = x + 2 + y * 16;
1113 // patches[3] = x + 3 + y * 16; 1110 patches[3] = x + 3 + y * 16;
1114 1111
1115 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1112 float[] heightmap = (map.Length == 65536) ?
1116 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1113 map :
1117 // } 1114 LLHeightFieldMoronize(map);
1115
1116 try
1117 {
1118 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1119 OutPacket(layerpack, ThrottleOutPacketType.Land);
1120 }
1121 catch
1122 {
1123 for (int px = x ; px < x + 4 ; px++)
1124 SendLayerData(px, y, map);
1125 }
1126 }
1118 1127
1119 /// <summary> 1128 /// <summary>
1120 /// Sends a specified patch to a client 1129 /// Sends a specified patch to a client
@@ -1134,7 +1143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1134 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1143 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1135 layerpack.Header.Reliable = true; 1144 layerpack.Header.Reliable = true;
1136 1145
1137 OutPacket(layerpack, ThrottleOutPacketType.Land); 1146 OutPacket(layerpack, ThrottleOutPacketType.Task);
1138 } 1147 }
1139 catch (Exception e) 1148 catch (Exception e)
1140 { 1149 {
@@ -2206,6 +2215,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2206 OutPacket(sound, ThrottleOutPacketType.Task); 2215 OutPacket(sound, ThrottleOutPacketType.Task);
2207 } 2216 }
2208 2217
2218 public void SendTransferAbort(TransferRequestPacket transferRequest)
2219 {
2220 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2221 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2222 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2223 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2224 OutPacket(abort, ThrottleOutPacketType.Task);
2225 }
2226
2209 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2227 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2210 { 2228 {
2211 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2229 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3467,6 +3485,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3467 /// </summary> 3485 /// </summary>
3468 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3486 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3469 { 3487 {
3488 if (entity is SceneObjectPart)
3489 {
3490 SceneObjectPart e = (SceneObjectPart)entity;
3491 SceneObjectGroup g = e.ParentGroup;
3492 if (g.RootPart.Shape.State > 30) // HUD
3493 if (g.OwnerID != AgentId)
3494 return; // Don't send updates for other people's HUDs
3495 }
3496
3470 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3497 double priority = m_prioritizer.GetUpdatePriority(this, entity);
3471 3498
3472 lock (m_entityUpdates.SyncRoot) 3499 lock (m_entityUpdates.SyncRoot)
@@ -3487,6 +3514,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3487 EntityUpdate update; 3514 EntityUpdate update;
3488 while (updatesThisCall < maxUpdates && m_entityUpdates.TryDequeue(out update)) 3515 while (updatesThisCall < maxUpdates && m_entityUpdates.TryDequeue(out update))
3489 { 3516 {
3517 // If we have sent a kill packet for this object
3518 // drop any updates on the floor
3519 if (update.Entity is SceneObjectPart)
3520 {
3521 SceneObjectPart part = (SceneObjectPart)update.Entity;
3522 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3523 continue;
3524 }
3525
3490 ++updatesThisCall; 3526 ++updatesThisCall;
3491 3527
3492 #region UpdateFlags to packet type conversion 3528 #region UpdateFlags to packet type conversion
@@ -3909,6 +3945,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3909 { 3945 {
3910 m_propertiesPacketTimer.Stop(); 3946 m_propertiesPacketTimer.Stop();
3911 3947
3948 if (m_propertiesBlocks.Count == 0)
3949 return;
3950
3912 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 3951 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
3913 3952
3914 int index = 0; 3953 int index = 0;
@@ -4899,6 +4938,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4899 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 4938 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
4900 (x.CameraUpAxis != lastarg.CameraUpAxis) || 4939 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
4901 (x.ControlFlags != lastarg.ControlFlags) || 4940 (x.ControlFlags != lastarg.ControlFlags) ||
4941 (x.ControlFlags != 0) ||
4902 (x.Far != lastarg.Far) || 4942 (x.Far != lastarg.Far) ||
4903 (x.Flags != lastarg.Flags) || 4943 (x.Flags != lastarg.Flags) ||
4904 (x.State != lastarg.State) || 4944 (x.State != lastarg.State) ||
@@ -5270,7 +5310,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5270 args.Channel = ch; 5310 args.Channel = ch;
5271 args.From = String.Empty; 5311 args.From = String.Empty;
5272 args.Message = Utils.BytesToString(msg); 5312 args.Message = Utils.BytesToString(msg);
5273 args.Type = ChatTypeEnum.Shout; 5313 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5274 args.Position = new Vector3(); 5314 args.Position = new Vector3();
5275 args.Scene = Scene; 5315 args.Scene = Scene;
5276 args.Sender = this; 5316 args.Sender = this;
@@ -11151,18 +11191,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11151 } 11191 }
11152 11192
11153 /// <summary> 11193 /// <summary>
11194 /// This processes packets which have accumulated while the presence was still in the process of initialising.
11195 /// </summary>
11196 public void ProcessPendingPackets()
11197 {
11198 m_IsPresenceReady = true;
11199 if (m_pendingPackets == null)
11200 return;
11201 foreach (Packet p in m_pendingPackets)
11202 {
11203 ProcessInPacket(p);
11204 }
11205 m_pendingPackets.Clear();
11206 }
11207
11208 /// <summary>
11154 /// Entryway from the client to the simulator. All UDP packets from the client will end up here 11209 /// Entryway from the client to the simulator. All UDP packets from the client will end up here
11155 /// </summary> 11210 /// </summary>
11156 /// <param name="Pack">OpenMetaverse.packet</param> 11211 /// <param name="Pack">OpenMetaverse.packet</param>
11157 public void ProcessInPacket(Packet Pack) 11212 public void ProcessInPacket(Packet Pack)
11158 { 11213 {
11159 if (m_debugPacketLevel >= 255) 11214 if (!m_IsPresenceReady)
11160 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); 11215 {
11216 if (m_pendingPackets == null)
11217 {
11218 m_pendingPackets = new List<Packet>();
11219 }
11220 m_pendingPackets.Add(Pack);
11221 }
11222 else
11223 {
11224 if (m_debugPacketLevel >= 255)
11225 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type);
11161 11226
11162 if (!ProcessPacketMethod(Pack)) 11227 if (!ProcessPacketMethod(Pack))
11163 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); 11228 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type);
11164 11229
11165 PacketPool.Instance.ReturnPacket(Pack); 11230 PacketPool.Instance.ReturnPacket(Pack);
11231 }
11166 } 11232 }
11167 11233
11168 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 11234 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -11399,7 +11465,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11399 11465
11400// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11466// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11401 11467
11468
11469 //Note, the bool returned from the below function is useless since it is always false.
11402 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11470 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11471
11403 } 11472 }
11404 11473
11405 /// <summary> 11474 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 6232c48..eebbfa5 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -149,6 +149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
149 149
150 private int m_defaultRTO = 3000; 150 private int m_defaultRTO = 3000;
151 private int m_maxRTO = 60000; 151 private int m_maxRTO = 60000;
152 public bool m_deliverPackets = true;
152 153
153 /// <summary> 154 /// <summary>
154 /// Default constructor 155 /// Default constructor
@@ -389,6 +390,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
389 if (category >= 0 && category < m_packetOutboxes.Length) 390 if (category >= 0 && category < m_packetOutboxes.Length)
390 { 391 {
391 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 392 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
393
394 if (m_deliverPackets == false)
395 {
396 queue.Enqueue(packet);
397 return true;
398 }
399
392 TokenBucket bucket = m_throttleCategories[category]; 400 TokenBucket bucket = m_throttleCategories[category];
393 401
394 if (bucket.RemoveTokens(packet.Buffer.DataLength)) 402 if (bucket.RemoveTokens(packet.Buffer.DataLength))
@@ -419,6 +427,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
419 /// <returns>True if any packets were sent, otherwise false</returns> 427 /// <returns>True if any packets were sent, otherwise false</returns>
420 public bool DequeueOutgoing() 428 public bool DequeueOutgoing()
421 { 429 {
430 if (m_deliverPackets == false) return false;
431
422 OutgoingPacket packet; 432 OutgoingPacket packet;
423 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 433 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
424 TokenBucket bucket; 434 TokenBucket bucket;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 1b81105..3b63bcd 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -899,7 +899,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
899 client.OnLogout += LogoutHandler; 899 client.OnLogout += LogoutHandler;
900 900
901 // Start the IClientAPI 901 // Start the IClientAPI
902 client.Start(); 902 // Spin it off so that it doesn't clog up the LLUDPServer
903
904 //First, and very importantly:
905 //
906 //Set our DeliverPackets flag in the client to *false*
907 //this will prevent us from missing important messages
908 //before the modules are bound
909 client.DeliverPackets = false;
910
911 Util.FireAndForget(
912 delegate
913 {
914 try
915 {
916 client.Start();
917 }
918 finally
919 {
920 //Now, release the hounds. er, packets.
921 client.DeliverPackets = true;
922 }
923 }
924 );
903 } 925 }
904 else 926 else
905 { 927 {
@@ -915,7 +937,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
915 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 937 if (m_scene.TryGetClient(udpClient.AgentID, out client))
916 { 938 {
917 client.IsLoggingOut = true; 939 client.IsLoggingOut = true;
918 client.Close(); 940 client.Close(false);
919 } 941 }
920 } 942 }
921 943
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index bdbd284..91e3d20 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -133,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
133 this.parent = parent; 133 this.parent = parent;
134 MaxBurst = maxBurst; 134 MaxBurst = maxBurst;
135 DripRate = dripRate; 135 DripRate = dripRate;
136 lastDrip = Environment.TickCount & Int32.MaxValue; 136 lastDrip = Environment.TickCount;
137 } 137 }
138 138
139 /// <summary> 139 /// <summary>
@@ -144,40 +144,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
144 /// the bucket, otherwise false</returns> 144 /// the bucket, otherwise false</returns>
145 public bool RemoveTokens(int amount) 145 public bool RemoveTokens(int amount)
146 { 146 {
147 bool dummy;
148 return RemoveTokens(amount, out dummy);
149 }
150
151 /// <summary>
152 /// Remove a given number of tokens from the bucket
153 /// </summary>
154 /// <param name="amount">Number of tokens to remove from the bucket</param>
155 /// <param name="dripSucceeded">True if tokens were added to the bucket
156 /// during this call, otherwise false</param>
157 /// <returns>True if the requested number of tokens were removed from
158 /// the bucket, otherwise false</returns>
159 public bool RemoveTokens(int amount, out bool dripSucceeded)
160 {
161 if (maxBurst == 0) 147 if (maxBurst == 0)
162 { 148 {
163 dripSucceeded = true;
164 return true; 149 return true;
165 } 150 }
166 151
167 dripSucceeded = Drip(); 152 if (amount > maxBurst)
168
169 if (content - amount >= 0)
170 { 153 {
171 if (parent != null && !parent.RemoveTokens(amount)) 154 throw new Exception("amount " + amount + " exceeds maxBurst " + maxBurst);
172 return false; 155 }
173 156
174 content -= amount; 157 Drip();
175 return true; 158
159 if (content < amount)
160 {
161 return false;
176 } 162 }
177 else 163
164 if (parent != null && !parent.RemoveTokens(amount))
178 { 165 {
179 return false; 166 return false;
180 } 167 }
168
169 content -= amount;
170 return true;
181 } 171 }
182 172
183 /// <summary> 173 /// <summary>
@@ -193,25 +183,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 content = maxBurst; 183 content = maxBurst;
194 return true; 184 return true;
195 } 185 }
196 else
197 {
198 int now = Environment.TickCount & Int32.MaxValue;
199 int deltaMS = now - lastDrip;
200 186
201 if (deltaMS <= 0) 187 int now = Environment.TickCount;
202 { 188 int deltaMS = now - lastDrip;
203 if (deltaMS < 0) 189 lastDrip = now;
204 lastDrip = now;
205 return false;
206 }
207 190
208 int dripAmount = deltaMS * tokensPerMS; 191 if (deltaMS <= 0)
209 192 {
210 content = Math.Min(content + dripAmount, maxBurst); 193 return false;
211 lastDrip = now; 194 }
212 195
213 return true; 196 long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content;
197 if (dripAmount > maxBurst)
198 {
199 dripAmount = maxBurst;
214 } 200 }
201 content = (int)dripAmount;
202 return true;
215 } 203 }
216 } 204 }
217} 205}