diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 190 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | 27 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 99 |
3 files changed, 192 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..e3233da 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 | ||
@@ -775,11 +808,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
775 | { | 808 | { |
776 | m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); | 809 | m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); |
777 | } | 810 | } |
811 | |||
812 | Watchdog.UpdateThread(); | ||
778 | } | 813 | } |
779 | 814 | ||
780 | if (packetInbox.Count > 0) | 815 | if (packetInbox.Count > 0) |
781 | m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets"); | 816 | m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets"); |
782 | packetInbox.Clear(); | 817 | packetInbox.Clear(); |
818 | |||
819 | Watchdog.RemoveThread(); | ||
783 | } | 820 | } |
784 | 821 | ||
785 | private void OutgoingPacketHandler() | 822 | private void OutgoingPacketHandler() |
@@ -788,6 +825,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
788 | // on to en-US to avoid number parsing issues | 825 | // on to en-US to avoid number parsing issues |
789 | Culture.SetCurrentCulture(); | 826 | Culture.SetCurrentCulture(); |
790 | 827 | ||
828 | // Typecast the function to an Action<IClientAPI> once here to avoid allocating a new | ||
829 | // Action generic every round | ||
830 | Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; | ||
831 | |||
791 | while (base.IsRunning) | 832 | while (base.IsRunning) |
792 | { | 833 | { |
793 | try | 834 | try |
@@ -836,18 +877,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
836 | 877 | ||
837 | // Handle outgoing packets, resends, acknowledgements, and pings for each | 878 | // Handle outgoing packets, resends, acknowledgements, and pings for each |
838 | // client. m_packetSent will be set to true if a packet is sent | 879 | // client. m_packetSent will be set to true if a packet is sent |
839 | m_scene.ClientManager.ForEachSync(ClientOutgoingPacketHandler); | 880 | m_scene.ForEachClient(clientPacketHandler, false); |
840 | 881 | ||
841 | // If nothing was sent, sleep for the minimum amount of time before a | 882 | // If nothing was sent, sleep for the minimum amount of time before a |
842 | // token bucket could get more tokens | 883 | // token bucket could get more tokens |
843 | if (!m_packetSent) | 884 | if (!m_packetSent) |
844 | Thread.Sleep((int)TickCountResolution); | 885 | Thread.Sleep((int)TickCountResolution); |
886 | |||
887 | Watchdog.UpdateThread(); | ||
845 | } | 888 | } |
846 | catch (Exception ex) | 889 | catch (Exception ex) |
847 | { | 890 | { |
848 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); | 891 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); |
849 | } | 892 | } |
850 | } | 893 | } |
894 | |||
895 | Watchdog.RemoveThread(); | ||
851 | } | 896 | } |
852 | 897 | ||
853 | private void ClientOutgoingPacketHandler(IClientAPI client) | 898 | private void ClientOutgoingPacketHandler(IClientAPI client) |
@@ -897,7 +942,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
897 | } | 942 | } |
898 | 943 | ||
899 | // Make sure this client is still alive | 944 | // Make sure this client is still alive |
900 | if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client)) | 945 | if (m_scene.TryGetClient(udpClient.AgentID, out client)) |
901 | { | 946 | { |
902 | try | 947 | try |
903 | { | 948 | { |