diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 99 |
1 files changed, 72 insertions, 27 deletions
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 | { |