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/LLClientView.cs190
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs27
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs107
3 files changed, 200 insertions, 124 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 0ba76ec..f6a7a0c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -346,15 +346,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
346 protected int m_terrainCheckerCount; 346 protected int m_terrainCheckerCount;
347 protected uint m_agentFOVCounter; 347 protected uint m_agentFOVCounter;
348 348
349 // These numbers are guesses at a decent tradeoff between responsiveness
350 // of the interest list and throughput. Lower is more responsive, higher
351 // is better throughput
352 protected int m_primTerseUpdatesPerPacket = 25;
353 protected int m_primFullUpdatesPerPacket = 100;
354 protected int m_avatarTerseUpdatesPerPacket = 10;
355 /// <summary>Number of texture packets to put on the queue each time the
356 /// OnQueueEmpty event is triggered for the texture category</summary>
357 protected int m_textureSendLimit = 20;
358 protected IAssetService m_assetService; 349 protected IAssetService m_assetService;
359 private IHyperAssetService m_hyperAssets; 350 private IHyperAssetService m_hyperAssets;
360 351
@@ -827,7 +818,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
827 for (int i = x1; i <= x2; i++) 818 for (int i = x1; i <= x2; i++)
828 SendLayerData(i, y1, map); 819 SendLayerData(i, y1, map);
829 820
830 // Column 821 // Column
831 for (int j = y1 + 1; j <= y2; j++) 822 for (int j = y1 + 1; j <= y2; j++)
832 SendLayerData(x2, j, map); 823 SendLayerData(x2, j, map);
833 824
@@ -2114,12 +2105,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2114 public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks) 2105 public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks)
2115 { 2106 {
2116 ViewerEffectPacket packet = (ViewerEffectPacket)PacketPool.Instance.GetPacket(PacketType.ViewerEffect); 2107 ViewerEffectPacket packet = (ViewerEffectPacket)PacketPool.Instance.GetPacket(PacketType.ViewerEffect);
2117 packet.Effect = effectBlocks; 2108 packet.Header.Reliable = false;
2109 packet.Header.Zerocoded = true;
2118 2110
2119 packet.AgentData.AgentID = AgentId; 2111 packet.AgentData.AgentID = AgentId;
2120 packet.AgentData.SessionID = SessionId; 2112 packet.AgentData.SessionID = SessionId;
2121 packet.Header.Reliable = false; 2113
2122 packet.Header.Zerocoded = true; 2114 packet.Effect = effectBlocks;
2115
2123 OutPacket(packet, ThrottleOutPacketType.State); 2116 OutPacket(packet, ThrottleOutPacketType.State);
2124 } 2117 }
2125 2118
@@ -3333,7 +3326,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3333 3326
3334 lock (m_avatarTerseUpdates.SyncRoot) 3327 lock (m_avatarTerseUpdates.SyncRoot)
3335 { 3328 {
3336 int count = Math.Min(m_avatarTerseUpdates.Count, m_avatarTerseUpdatesPerPacket); 3329 int count = Math.Min(m_avatarTerseUpdates.Count, m_udpServer.AvatarTerseUpdatesPerPacket);
3337 if (count == 0) 3330 if (count == 0)
3338 return; 3331 return;
3339 3332
@@ -3418,7 +3411,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3418 3411
3419 lock (m_primFullUpdates.SyncRoot) 3412 lock (m_primFullUpdates.SyncRoot)
3420 { 3413 {
3421 int count = Math.Min(m_primFullUpdates.Count, m_primFullUpdatesPerPacket); 3414 int count = Math.Min(m_primFullUpdates.Count, m_udpServer.PrimFullUpdatesPerPacket);
3422 if (count == 0) 3415 if (count == 0)
3423 return; 3416 return;
3424 3417
@@ -3462,7 +3455,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3462 3455
3463 lock (m_primTerseUpdates.SyncRoot) 3456 lock (m_primTerseUpdates.SyncRoot)
3464 { 3457 {
3465 int count = Math.Min(m_primTerseUpdates.Count, m_primTerseUpdatesPerPacket); 3458 int count = Math.Min(m_primTerseUpdates.Count, m_udpServer.PrimTerseUpdatesPerPacket);
3466 if (count == 0) 3459 if (count == 0)
3467 return; 3460 return;
3468 3461
@@ -3585,7 +3578,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3585 void ProcessTextureRequests() 3578 void ProcessTextureRequests()
3586 { 3579 {
3587 if (m_imageManager != null) 3580 if (m_imageManager != null)
3588 m_imageManager.ProcessImageQueue(m_textureSendLimit); 3581 m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
3589 } 3582 }
3590 3583
3591 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 3584 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
@@ -4167,6 +4160,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4167 4160
4168 pack.Data = dataBlock; 4161 pack.Data = dataBlock;
4169 } 4162 }
4163 else
4164 {
4165 pack.Data = new ParcelObjectOwnersReplyPacket.DataBlock[0];
4166 }
4170 pack.Header.Zerocoded = true; 4167 pack.Header.Zerocoded = true;
4171 this.OutPacket(pack, ThrottleOutPacketType.Task); 4168 this.OutPacket(pack, ThrottleOutPacketType.Task);
4172 } 4169 }
@@ -4434,6 +4431,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4434 protected virtual void RegisterLocalPacketHandlers() 4431 protected virtual void RegisterLocalPacketHandlers()
4435 { 4432 {
4436 AddLocalPacketHandler(PacketType.LogoutRequest, Logout); 4433 AddLocalPacketHandler(PacketType.LogoutRequest, Logout);
4434 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate);
4437 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); 4435 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect);
4438 AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); 4436 AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached);
4439 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); 4437 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate);
@@ -4446,6 +4444,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4446 4444
4447 #region Packet Handlers 4445 #region Packet Handlers
4448 4446
4447 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
4448 {
4449 if (OnAgentUpdate != null)
4450 {
4451 bool update = false;
4452 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
4453
4454 #region Packet Session and User Check
4455 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId)
4456 return false;
4457 #endregion
4458
4459 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
4460
4461 // We can only check when we have something to check
4462 // against.
4463
4464 if (lastarg != null)
4465 {
4466 update =
4467 (
4468 (x.BodyRotation != lastarg.BodyRotation) ||
4469 (x.CameraAtAxis != lastarg.CameraAtAxis) ||
4470 (x.CameraCenter != lastarg.CameraCenter) ||
4471 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
4472 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
4473 (x.ControlFlags != lastarg.ControlFlags) ||
4474 (x.Far != lastarg.Far) ||
4475 (x.Flags != lastarg.Flags) ||
4476 (x.State != lastarg.State) ||
4477 (x.HeadRotation != lastarg.HeadRotation) ||
4478 (x.SessionID != lastarg.SessionID) ||
4479 (x.AgentID != lastarg.AgentID)
4480 );
4481 }
4482 else
4483 update = true;
4484
4485 // These should be ordered from most-likely to
4486 // least likely to change. I've made an initial
4487 // guess at that.
4488
4489 if (update)
4490 {
4491 AgentUpdateArgs arg = new AgentUpdateArgs();
4492 arg.AgentID = x.AgentID;
4493 arg.BodyRotation = x.BodyRotation;
4494 arg.CameraAtAxis = x.CameraAtAxis;
4495 arg.CameraCenter = x.CameraCenter;
4496 arg.CameraLeftAxis = x.CameraLeftAxis;
4497 arg.CameraUpAxis = x.CameraUpAxis;
4498 arg.ControlFlags = x.ControlFlags;
4499 arg.Far = x.Far;
4500 arg.Flags = x.Flags;
4501 arg.HeadRotation = x.HeadRotation;
4502 arg.SessionID = x.SessionID;
4503 arg.State = x.State;
4504 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
4505 lastarg = arg; // save this set of arguments for nexttime
4506 if (handlerAgentUpdate != null)
4507 OnAgentUpdate(this, arg);
4508
4509 handlerAgentUpdate = null;
4510 }
4511 }
4512
4513 return true;
4514 }
4515
4449 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) 4516 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack)
4450 { 4517 {
4451 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack; 4518 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack;
@@ -5631,77 +5698,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5631 5698
5632 break; 5699 break;
5633 5700
5634 case PacketType.AgentUpdate:
5635 if (OnAgentUpdate != null)
5636 {
5637 bool update = false;
5638 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5639
5640 #region Packet Session and User Check
5641 if (m_checkPackets)
5642 {
5643 if (agenUpdate.AgentData.SessionID != SessionId ||
5644 agenUpdate.AgentData.AgentID != AgentId)
5645 break;
5646 }
5647 #endregion
5648
5649 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
5650
5651 // We can only check when we have something to check
5652 // against.
5653
5654 if (lastarg != null)
5655 {
5656 update =
5657 (
5658 (x.BodyRotation != lastarg.BodyRotation) ||
5659 (x.CameraAtAxis != lastarg.CameraAtAxis) ||
5660 (x.CameraCenter != lastarg.CameraCenter) ||
5661 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5662 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5663 (x.ControlFlags != lastarg.ControlFlags) ||
5664 (x.Far != lastarg.Far) ||
5665 (x.Flags != lastarg.Flags) ||
5666 (x.State != lastarg.State) ||
5667 (x.HeadRotation != lastarg.HeadRotation) ||
5668 (x.SessionID != lastarg.SessionID) ||
5669 (x.AgentID != lastarg.AgentID)
5670 );
5671 }
5672 else
5673 update = true;
5674
5675 // These should be ordered from most-likely to
5676 // least likely to change. I've made an initial
5677 // guess at that.
5678
5679 if (update)
5680 {
5681 AgentUpdateArgs arg = new AgentUpdateArgs();
5682 arg.AgentID = x.AgentID;
5683 arg.BodyRotation = x.BodyRotation;
5684 arg.CameraAtAxis = x.CameraAtAxis;
5685 arg.CameraCenter = x.CameraCenter;
5686 arg.CameraLeftAxis = x.CameraLeftAxis;
5687 arg.CameraUpAxis = x.CameraUpAxis;
5688 arg.ControlFlags = x.ControlFlags;
5689 arg.Far = x.Far;
5690 arg.Flags = x.Flags;
5691 arg.HeadRotation = x.HeadRotation;
5692 arg.SessionID = x.SessionID;
5693 arg.State = x.State;
5694 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5695 lastarg = arg; // save this set of arguments for nexttime
5696 if (handlerAgentUpdate != null)
5697 OnAgentUpdate(this, arg);
5698
5699 handlerAgentUpdate = null;
5700 }
5701
5702 }
5703 break;
5704
5705 case PacketType.AgentAnimation: 5701 case PacketType.AgentAnimation:
5706 AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; 5702 AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
5707 5703
@@ -6762,11 +6758,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6762 if (OnRequestTexture != null) 6758 if (OnRequestTexture != null)
6763 { 6759 {
6764 TextureRequestArgs args = new TextureRequestArgs(); 6760 TextureRequestArgs args = new TextureRequestArgs();
6765 args.RequestedAssetID = imageRequest.RequestImage[i].Image; 6761
6766 args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; 6762 RequestImagePacket.RequestImageBlock block = imageRequest.RequestImage[i];
6767 args.PacketNumber = imageRequest.RequestImage[i].Packet; 6763
6768 args.Priority = imageRequest.RequestImage[i].DownloadPriority; 6764 args.RequestedAssetID = block.Image;
6765 args.DiscardLevel = block.DiscardLevel;
6766 args.PacketNumber = block.Packet;
6767 args.Priority = block.DownloadPriority;
6769 args.requestSequence = imageRequest.Header.Sequence; 6768 args.requestSequence = imageRequest.Header.Sequence;
6769
6770 // NOTE: This is not a built in part of the LLUDP protocol, but we double the
6771 // priority of avatar textures to get avatars rezzing in faster than the
6772 // surrounding scene
6773 if ((ImageType)block.Type == ImageType.Baked)
6774 args.Priority *= 2.0f;
6775
6770 //handlerTextureRequest = OnRequestTexture; 6776 //handlerTextureRequest = OnRequestTexture;
6771 6777
6772 //if (handlerTextureRequest != null) 6778 //if (handlerTextureRequest != null)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index a9bc7d2..84a4959 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -304,8 +304,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
304 304
305 int total = resend + land + wind + cloud + task + texture + asset + state; 305 int total = resend + land + wind + cloud + task + texture + asset + state;
306 306
307 m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}", 307 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}",
308 AgentID, resend, land, wind, cloud, task, texture, asset, state, total); 308 // AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
309 309
310 // Update the token buckets with new throttle values 310 // Update the token buckets with new throttle values
311 TokenBucket bucket; 311 TokenBucket bucket;
@@ -372,7 +372,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
372 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 372 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
373 TokenBucket bucket = m_throttleCategories[category]; 373 TokenBucket bucket = m_throttleCategories[category];
374 374
375 if (m_throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) 375 if (bucket.RemoveTokens(packet.Buffer.DataLength))
376 { 376 {
377 // Enough tokens were removed from the bucket, the packet will not be queued 377 // Enough tokens were removed from the bucket, the packet will not be queued
378 return false; 378 return false;
@@ -497,16 +497,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
497 SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r; 497 SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r;
498 } 498 }
499 499
500 RTO = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR)); 500 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
501 501
502 // Clamp the retransmission timeout to manageable values 502 // Clamp the retransmission timeout to manageable values
503 RTO = Utils.Clamp(RTO, 3000, 10000); 503 rto = Utils.Clamp(RTO, 3000, 60000);
504
505 RTO = rto;
504 506
505 //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + 507 //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
506 // RTTVAR + " based on new RTT of " + r + "ms"); 508 // RTTVAR + " based on new RTT of " + r + "ms");
507 } 509 }
508 510
509 /// <summary> 511 /// <summary>
512 /// Exponential backoff of the retransmission timeout, per section 5.5
513 /// of RFC 2988
514 /// </summary>
515 public void BackoffRTO()
516 {
517 // Reset SRTT and RTTVAR, we assume they are bogus since things
518 // didn't work out and we're backing off the timeout
519 SRTT = 0.0f;
520 RTTVAR = 0.0f;
521
522 // Double the retransmission timeout
523 RTO = Math.Min(RTO * 2, 60000);
524 }
525
526 /// <summary>
510 /// Does an early check to see if this queue empty callback is already 527 /// Does an early check to see if this queue empty callback is already
511 /// running, then asynchronously firing the event 528 /// running, then asynchronously firing the event
512 /// </summary> 529 /// </summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index a9f4b2c..74d3262 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -98,6 +98,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
98 98
99 /// <summary>The measured resolution of Environment.TickCount</summary> 99 /// <summary>The measured resolution of Environment.TickCount</summary>
100 public readonly float TickCountResolution; 100 public readonly float TickCountResolution;
101 /// <summary>Number of terse prim updates to put on the queue each time the
102 /// OnQueueEmpty event is triggered for updates</summary>
103 public readonly int PrimTerseUpdatesPerPacket;
104 /// <summary>Number of terse avatar updates to put on the queue each time the
105 /// OnQueueEmpty event is triggered for updates</summary>
106 public readonly int AvatarTerseUpdatesPerPacket;
107 /// <summary>Number of full prim updates to put on the queue each time the
108 /// OnQueueEmpty event is triggered for updates</summary>
109 public readonly int PrimFullUpdatesPerPacket;
110 /// <summary>Number of texture packets to put on the queue each time the
111 /// OnQueueEmpty event is triggered for textures</summary>
112 public readonly int TextureSendLimit;
101 113
102 /// <summary>Handlers for incoming packets</summary> 114 /// <summary>Handlers for incoming packets</summary>
103 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 115 //PacketEventDictionary packetEvents = new PacketEventDictionary();
@@ -172,6 +184,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
172 m_asyncPacketHandling = config.GetBoolean("async_packet_handling", false); 184 m_asyncPacketHandling = config.GetBoolean("async_packet_handling", false);
173 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); 185 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
174 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); 186 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
187
188 PrimTerseUpdatesPerPacket = config.GetInt("PrimTerseUpdatesPerPacket", 25);
189 AvatarTerseUpdatesPerPacket = config.GetInt("AvatarTerseUpdatesPerPacket", 10);
190 PrimFullUpdatesPerPacket = config.GetInt("PrimFullUpdatesPerPacket", 100);
191 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
192 }
193 else
194 {
195 PrimTerseUpdatesPerPacket = 25;
196 AvatarTerseUpdatesPerPacket = 10;
197 PrimFullUpdatesPerPacket = 100;
198 TextureSendLimit = 20;
175 } 199 }
176 200
177 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps); 201 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps);
@@ -187,14 +211,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
187 211
188 base.Start(m_recvBufferSize, m_asyncPacketHandling); 212 base.Start(m_recvBufferSize, m_asyncPacketHandling);
189 213
190 // Start the incoming packet processing thread 214 // Start the packet processing threads
191 Thread incomingThread = new Thread(IncomingPacketHandler); 215 Watchdog.StartThread(IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false);
192 incomingThread.Name = "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")"; 216 Watchdog.StartThread(OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false);
193 incomingThread.Start();
194
195 Thread outgoingThread = new Thread(OutgoingPacketHandler);
196 outgoingThread.Name = "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")";
197 outgoingThread.Start();
198 } 217 }
199 218
200 public new void Stop() 219 public new void Stop()
@@ -243,7 +262,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
243 for (int i = 0; i < packetCount; i++) 262 for (int i = 0; i < packetCount; i++)
244 { 263 {
245 byte[] data = datas[i]; 264 byte[] data = datas[i];
246 m_scene.ClientManager.ForEach( 265 m_scene.ForEachClient(
247 delegate(IClientAPI client) 266 delegate(IClientAPI client)
248 { 267 {
249 if (client is LLClientView) 268 if (client is LLClientView)
@@ -255,7 +274,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
255 else 274 else
256 { 275 {
257 byte[] data = packet.ToBytes(); 276 byte[] data = packet.ToBytes();
258 m_scene.ClientManager.ForEach( 277 m_scene.ForEachClient(
259 delegate(IClientAPI client) 278 delegate(IClientAPI client)
260 { 279 {
261 if (client is LLClientView) 280 if (client is LLClientView)
@@ -412,6 +431,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
412 { 431 {
413 m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); 432 m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
414 433
434 // Exponential backoff of the retransmission timeout
435 udpClient.BackoffRTO();
436
415 // Resend packets 437 // Resend packets
416 for (int i = 0; i < expiredPackets.Count; i++) 438 for (int i = 0; i < expiredPackets.Count; i++)
417 { 439 {
@@ -548,27 +570,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
548 // UseCircuitCode handling 570 // UseCircuitCode handling
549 if (packet.Type == PacketType.UseCircuitCode) 571 if (packet.Type == PacketType.UseCircuitCode)
550 { 572 {
551 Util.FireAndForget( 573 m_log.Debug("[LLUDPSERVER]: Handling UseCircuitCode packet from " + buffer.RemoteEndPoint);
552 delegate(object o) 574 object[] array = new object[] { buffer, packet };
553 {
554 IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
555 575
556 // Begin the process of adding the client to the simulator 576 if (m_asyncPacketHandling)
557 AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint); 577 Util.FireAndForget(HandleUseCircuitCode, array);
578 else
579 HandleUseCircuitCode(array);
558 580
559 // Acknowledge the UseCircuitCode packet
560 SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
561 }
562 );
563 return; 581 return;
564 } 582 }
565 583
566 // Determine which agent this packet came from 584 // Determine which agent this packet came from
567 IClientAPI client; 585 IClientAPI client;
568 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView)) 586 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
569 { 587 {
570 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + 588 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
571 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients");
572 return; 589 return;
573 } 590 }
574 591
@@ -670,6 +687,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
670 packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); 687 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
671 } 688 }
672 689
690 private void HandleUseCircuitCode(object o)
691 {
692 object[] array = (object[])o;
693 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
694 UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1];
695
696 IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
697
698 // Begin the process of adding the client to the simulator
699 AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint);
700
701 // Acknowledge the UseCircuitCode packet
702 SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
703 }
704
673 private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber) 705 private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
674 { 706 {
675 PacketAckPacket ack = new PacketAckPacket(); 707 PacketAckPacket ack = new PacketAckPacket();
@@ -731,8 +763,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
731 { 763 {
732 // Create the LLUDPClient 764 // Create the LLUDPClient
733 LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); 765 LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint);
766 IClientAPI existingClient;
734 767
735 if (!m_scene.ClientManager.ContainsKey(agentID)) 768 if (!m_scene.TryGetClient(agentID, out existingClient))
736 { 769 {
737 // Create the LLClientView 770 // Create the LLClientView
738 LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 771 LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
@@ -752,7 +785,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
752 { 785 {
753 // Remove this client from the scene 786 // Remove this client from the scene
754 IClientAPI client; 787 IClientAPI client;
755 if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client)) 788 if (m_scene.TryGetClient(udpClient.AgentID, out client))
756 client.Close(); 789 client.Close();
757 } 790 }
758 791
@@ -768,6 +801,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
768 { 801 {
769 IncomingPacket incomingPacket = null; 802 IncomingPacket incomingPacket = null;
770 803
804 // HACK: This is a test to try and rate limit packet handling on Mono.
805 // If it works, a more elegant solution can be devised
806 if (Util.FireAndForgetCount() < 2)
807 {
808 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping");
809 Thread.Sleep(30);
810 }
811
771 if (packetInbox.Dequeue(100, ref incomingPacket)) 812 if (packetInbox.Dequeue(100, ref incomingPacket))
772 Util.FireAndForget(ProcessInPacket, incomingPacket); 813 Util.FireAndForget(ProcessInPacket, incomingPacket);
773 } 814 }
@@ -775,11 +816,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
775 { 816 {
776 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 817 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
777 } 818 }
819
820 Watchdog.UpdateThread();
778 } 821 }
779 822
780 if (packetInbox.Count > 0) 823 if (packetInbox.Count > 0)
781 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets"); 824 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets");
782 packetInbox.Clear(); 825 packetInbox.Clear();
826
827 Watchdog.RemoveThread();
783 } 828 }
784 829
785 private void OutgoingPacketHandler() 830 private void OutgoingPacketHandler()
@@ -788,6 +833,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
788 // on to en-US to avoid number parsing issues 833 // on to en-US to avoid number parsing issues
789 Culture.SetCurrentCulture(); 834 Culture.SetCurrentCulture();
790 835
836 // Typecast the function to an Action<IClientAPI> once here to avoid allocating a new
837 // Action generic every round
838 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
839
791 while (base.IsRunning) 840 while (base.IsRunning)
792 { 841 {
793 try 842 try
@@ -836,18 +885,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
836 885
837 // Handle outgoing packets, resends, acknowledgements, and pings for each 886 // Handle outgoing packets, resends, acknowledgements, and pings for each
838 // client. m_packetSent will be set to true if a packet is sent 887 // client. m_packetSent will be set to true if a packet is sent
839 m_scene.ClientManager.ForEachSync(ClientOutgoingPacketHandler); 888 m_scene.ForEachClient(clientPacketHandler, false);
840 889
841 // If nothing was sent, sleep for the minimum amount of time before a 890 // If nothing was sent, sleep for the minimum amount of time before a
842 // token bucket could get more tokens 891 // token bucket could get more tokens
843 if (!m_packetSent) 892 if (!m_packetSent)
844 Thread.Sleep((int)TickCountResolution); 893 Thread.Sleep((int)TickCountResolution);
894
895 Watchdog.UpdateThread();
845 } 896 }
846 catch (Exception ex) 897 catch (Exception ex)
847 { 898 {
848 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); 899 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
849 } 900 }
850 } 901 }
902
903 Watchdog.RemoveThread();
851 } 904 }
852 905
853 private void ClientOutgoingPacketHandler(IClientAPI client) 906 private void ClientOutgoingPacketHandler(IClientAPI client)
@@ -897,7 +950,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
897 } 950 }
898 951
899 // Make sure this client is still alive 952 // Make sure this client is still alive
900 if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client)) 953 if (m_scene.TryGetClient(udpClient.AgentID, out client))
901 { 954 {
902 try 955 try
903 { 956 {