diff options
author | John Hurliman | 2009-10-13 14:50:03 -0700 |
---|---|---|
committer | John Hurliman | 2009-10-13 14:50:03 -0700 |
commit | 23a334b9f54a1ef5df3b503c165e7b76b746a2b1 (patch) | |
tree | 93003db47fcd77af4085c0c49cbc1f2f0293b5eb /OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |
parent | * Unregister event handlers in LLUDPServer when a client logs out and disconn... (diff) | |
download | opensim-SC-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.zip opensim-SC-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.gz opensim-SC-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.bz2 opensim-SC-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.xz |
* Rewrote ClientManager to remove Lindenisms from OpenSim core, improve performance by removing locks, and replace LLUDPClientCollection
* Removed the confusing (and LL-specific) shutdowncircuit parameter from IClientAPI.Close()
* Updated the LLUDP code to only use ClientManager instead of trying to synchronize ClientManager and m_clients
* Remove clients asynchronously since it is a very slow operation (including a 2000ms sleep)
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 163 |
1 files changed, 84 insertions, 79 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 04c9cb1..8ec143a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | |||
@@ -96,7 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
96 | /// <summary>Incoming packets that are awaiting handling</summary> | 96 | /// <summary>Incoming packets that are awaiting handling</summary> |
97 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | 97 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); |
98 | /// <summary></summary> | 98 | /// <summary></summary> |
99 | private UDPClientCollection m_clients = new UDPClientCollection(); | 99 | //private UDPClientCollection m_clients = new UDPClientCollection(); |
100 | /// <summary>Bandwidth throttle for this UDP server</summary> | 100 | /// <summary>Bandwidth throttle for this UDP server</summary> |
101 | private TokenBucket m_throttle; | 101 | private TokenBucket m_throttle; |
102 | /// <summary>Bandwidth throttle rates for this UDP server</summary> | 102 | /// <summary>Bandwidth throttle rates for this UDP server</summary> |
@@ -181,23 +181,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
181 | return x == m_location; | 181 | return x == m_location; |
182 | } | 182 | } |
183 | 183 | ||
184 | public void RemoveClient(LLUDPClient udpClient) | ||
185 | { | ||
186 | m_log.Debug("[LLUDPSERVER]: Removing LLUDPClient for " + udpClient.AgentID); | ||
187 | |||
188 | // Shut down the IClientAPI and remove it from the scene | ||
189 | IClientAPI client; | ||
190 | if (m_scene.ClientManager.TryGetClient(udpClient.CircuitCode, out client)) | ||
191 | { | ||
192 | client.Close(false); | ||
193 | m_scene.ClientManager.Remove(udpClient.CircuitCode); | ||
194 | } | ||
195 | |||
196 | // Shut down the LLUDPClient and remove it from the list of UDP clients | ||
197 | udpClient.Shutdown(); | ||
198 | m_clients.Remove(udpClient.RemoteEndPoint); | ||
199 | } | ||
200 | |||
201 | public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) | 184 | public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) |
202 | { | 185 | { |
203 | // CoarseLocationUpdate packets cannot be split in an automated way | 186 | // CoarseLocationUpdate packets cannot be split in an automated way |
@@ -215,17 +198,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
215 | for (int i = 0; i < packetCount; i++) | 198 | for (int i = 0; i < packetCount; i++) |
216 | { | 199 | { |
217 | byte[] data = datas[i]; | 200 | byte[] data = datas[i]; |
218 | m_clients.ForEach( | 201 | m_scene.ClientManager.ForEach( |
219 | delegate(LLUDPClient client) | 202 | delegate(IClientAPI client) |
220 | { SendPacketData(client, data, packet.Type, category); }); | 203 | { |
204 | if (client is LLClientView) | ||
205 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | ||
206 | } | ||
207 | ); | ||
221 | } | 208 | } |
222 | } | 209 | } |
223 | else | 210 | else |
224 | { | 211 | { |
225 | byte[] data = packet.ToBytes(); | 212 | byte[] data = packet.ToBytes(); |
226 | m_clients.ForEach( | 213 | m_scene.ClientManager.ForEach( |
227 | delegate(LLUDPClient client) | 214 | delegate(IClientAPI client) |
228 | { SendPacketData(client, data, packet.Type, category); }); | 215 | { |
216 | if (client is LLClientView) | ||
217 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); | ||
218 | } | ||
219 | ); | ||
229 | } | 220 | } |
230 | } | 221 | } |
231 | 222 | ||
@@ -475,7 +466,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
475 | //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; } | 466 | //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; } |
476 | //catch (Exception) { } | 467 | //catch (Exception) { } |
477 | 468 | ||
478 | LLUDPClient client = null; | 469 | LLUDPClient udpClient = null; |
479 | Packet packet = null; | 470 | Packet packet = null; |
480 | int packetEnd = buffer.DataLength - 1; | 471 | int packetEnd = buffer.DataLength - 1; |
481 | IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; | 472 | IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; |
@@ -512,30 +503,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
512 | } | 503 | } |
513 | 504 | ||
514 | // Determine which agent this packet came from | 505 | // Determine which agent this packet came from |
515 | if (!m_clients.TryGetValue(address, out client)) | 506 | IClientAPI client; |
507 | if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView)) | ||
516 | { | 508 | { |
517 | m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + | 509 | m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + |
518 | " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_clients.Count + " clients"); | 510 | " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients"); |
519 | return; | 511 | return; |
520 | } | 512 | } |
521 | 513 | ||
514 | udpClient = ((LLClientView)client).UDPClient; | ||
515 | |||
522 | #endregion Packet to Client Mapping | 516 | #endregion Packet to Client Mapping |
523 | 517 | ||
524 | // Stats tracking | 518 | // Stats tracking |
525 | Interlocked.Increment(ref client.PacketsReceived); | 519 | Interlocked.Increment(ref udpClient.PacketsReceived); |
526 | 520 | ||
527 | #region ACK Receiving | 521 | #region ACK Receiving |
528 | 522 | ||
529 | int now = Environment.TickCount; | 523 | int now = Environment.TickCount; |
530 | client.TickLastPacketReceived = now; | 524 | udpClient.TickLastPacketReceived = now; |
531 | 525 | ||
532 | // Handle appended ACKs | 526 | // Handle appended ACKs |
533 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) | 527 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) |
534 | { | 528 | { |
535 | lock (client.NeedAcks.SyncRoot) | 529 | lock (udpClient.NeedAcks.SyncRoot) |
536 | { | 530 | { |
537 | for (int i = 0; i < packet.Header.AckList.Length; i++) | 531 | for (int i = 0; i < packet.Header.AckList.Length; i++) |
538 | AcknowledgePacket(client, packet.Header.AckList[i], now, packet.Header.Resent); | 532 | AcknowledgePacket(udpClient, packet.Header.AckList[i], now, packet.Header.Resent); |
539 | } | 533 | } |
540 | } | 534 | } |
541 | 535 | ||
@@ -544,10 +538,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
544 | { | 538 | { |
545 | PacketAckPacket ackPacket = (PacketAckPacket)packet; | 539 | PacketAckPacket ackPacket = (PacketAckPacket)packet; |
546 | 540 | ||
547 | lock (client.NeedAcks.SyncRoot) | 541 | lock (udpClient.NeedAcks.SyncRoot) |
548 | { | 542 | { |
549 | for (int i = 0; i < ackPacket.Packets.Length; i++) | 543 | for (int i = 0; i < ackPacket.Packets.Length; i++) |
550 | AcknowledgePacket(client, ackPacket.Packets[i].ID, now, packet.Header.Resent); | 544 | AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent); |
551 | } | 545 | } |
552 | } | 546 | } |
553 | 547 | ||
@@ -556,27 +550,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
556 | #region ACK Sending | 550 | #region ACK Sending |
557 | 551 | ||
558 | if (packet.Header.Reliable) | 552 | if (packet.Header.Reliable) |
559 | client.PendingAcks.Enqueue(packet.Header.Sequence); | 553 | udpClient.PendingAcks.Enqueue(packet.Header.Sequence); |
560 | 554 | ||
561 | // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, | 555 | // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, |
562 | // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove | 556 | // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove |
563 | // 2*MTU bytes from the value and send ACKs, and finally add the local value back to | 557 | // 2*MTU bytes from the value and send ACKs, and finally add the local value back to |
564 | // client.BytesSinceLastACK. Lockless thread safety | 558 | // client.BytesSinceLastACK. Lockless thread safety |
565 | int bytesSinceLastACK = Interlocked.Exchange(ref client.BytesSinceLastACK, 0); | 559 | int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); |
566 | bytesSinceLastACK += buffer.DataLength; | 560 | bytesSinceLastACK += buffer.DataLength; |
567 | if (bytesSinceLastACK > Packet.MTU * 2) | 561 | if (bytesSinceLastACK > Packet.MTU * 2) |
568 | { | 562 | { |
569 | bytesSinceLastACK -= Packet.MTU * 2; | 563 | bytesSinceLastACK -= Packet.MTU * 2; |
570 | SendAcks(client); | 564 | SendAcks(udpClient); |
571 | } | 565 | } |
572 | Interlocked.Add(ref client.BytesSinceLastACK, bytesSinceLastACK); | 566 | Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK); |
573 | 567 | ||
574 | #endregion ACK Sending | 568 | #endregion ACK Sending |
575 | 569 | ||
576 | #region Incoming Packet Accounting | 570 | #region Incoming Packet Accounting |
577 | 571 | ||
578 | // Check the archive of received reliable packet IDs to see whether we already received this packet | 572 | // Check the archive of received reliable packet IDs to see whether we already received this packet |
579 | if (packet.Header.Reliable && !client.PacketArchive.TryEnqueue(packet.Header.Sequence)) | 573 | if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence)) |
580 | { | 574 | { |
581 | if (packet.Header.Resent) | 575 | if (packet.Header.Resent) |
582 | m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); | 576 | m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); |
@@ -593,7 +587,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
593 | if (packet.Type != PacketType.PacketAck) | 587 | if (packet.Type != PacketType.PacketAck) |
594 | { | 588 | { |
595 | // Inbox insertion | 589 | // Inbox insertion |
596 | packetInbox.Enqueue(new IncomingPacket(client, packet)); | 590 | packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); |
597 | } | 591 | } |
598 | } | 592 | } |
599 | 593 | ||
@@ -613,31 +607,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
613 | 607 | ||
614 | private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) | 608 | private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) |
615 | { | 609 | { |
610 | UUID agentID = useCircuitCode.CircuitCode.ID; | ||
611 | UUID sessionID = useCircuitCode.CircuitCode.SessionID; | ||
612 | uint circuitCode = useCircuitCode.CircuitCode.Code; | ||
613 | |||
616 | if (m_scene.RegionStatus != RegionStatus.SlaveScene) | 614 | if (m_scene.RegionStatus != RegionStatus.SlaveScene) |
617 | { | 615 | { |
618 | if (!m_clients.ContainsKey(remoteEndPoint)) | 616 | AuthenticateResponse sessionInfo; |
617 | if (IsClientAuthorized(useCircuitCode, out sessionInfo)) | ||
619 | { | 618 | { |
620 | AuthenticateResponse sessionInfo; | 619 | AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo); |
621 | if (IsClientAuthorized(useCircuitCode, out sessionInfo)) | ||
622 | { | ||
623 | UUID agentID = useCircuitCode.CircuitCode.ID; | ||
624 | UUID sessionID = useCircuitCode.CircuitCode.SessionID; | ||
625 | uint circuitCode = useCircuitCode.CircuitCode.Code; | ||
626 | |||
627 | AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo); | ||
628 | } | ||
629 | else | ||
630 | { | ||
631 | // Don't create circuits for unauthorized clients | ||
632 | m_log.WarnFormat( | ||
633 | "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", | ||
634 | useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint); | ||
635 | } | ||
636 | } | 620 | } |
637 | else | 621 | else |
638 | { | 622 | { |
639 | // Ignore repeated UseCircuitCode packets | 623 | // Don't create circuits for unauthorized clients |
640 | m_log.Debug("[LLUDPSERVER]: Ignoring UseCircuitCode for already established circuit " + useCircuitCode.CircuitCode.Code); | 624 | m_log.WarnFormat( |
625 | "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", | ||
626 | useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint); | ||
641 | } | 627 | } |
642 | } | 628 | } |
643 | else | 629 | else |
@@ -652,17 +638,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
652 | // Create the LLUDPClient | 638 | // Create the LLUDPClient |
653 | LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); | 639 | LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); |
654 | 640 | ||
655 | // Create the LLClientView | 641 | if (!m_scene.ClientManager.ContainsKey(agentID)) |
656 | LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | 642 | { |
657 | clientApi.OnLogout += LogoutHandler; | 643 | // Create the LLClientView |
658 | clientApi.OnConnectionClosed += ConnectionClosedHandler; | 644 | LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
645 | client.OnLogout += LogoutHandler; | ||
646 | client.OnConnectionClosed += ConnectionClosedHandler; | ||
659 | 647 | ||
660 | // Start the IClientAPI | 648 | m_scene.ClientManager.Add(agentID, remoteEndPoint, client); |
661 | m_scene.ClientManager.Add(circuitCode, clientApi); | ||
662 | clientApi.Start(); | ||
663 | 649 | ||
664 | // Add the new client to our list of tracked clients | 650 | // Start the IClientAPI |
665 | m_clients.Add(udpClient.RemoteEndPoint, udpClient); | 651 | m_scene.ClientManager.Add(agentID, remoteEndPoint, client); |
652 | client.Start(); | ||
653 | } | ||
654 | else | ||
655 | { | ||
656 | m_log.Debug("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from " + udpClient.AgentID); | ||
657 | } | ||
658 | } | ||
659 | |||
660 | private void RemoveClient(LLUDPClient udpClient) | ||
661 | { | ||
662 | // Remove this client from the scene ClientManager | ||
663 | IClientAPI client; | ||
664 | if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client)) | ||
665 | Util.FireAndForget(delegate(object o) { client.Close(); }); | ||
666 | } | 666 | } |
667 | 667 | ||
668 | private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) | 668 | private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) |
@@ -740,20 +740,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
740 | elapsed500MS = 0; | 740 | elapsed500MS = 0; |
741 | } | 741 | } |
742 | 742 | ||
743 | m_clients.ForEach( | 743 | m_scene.ClientManager.ForEach( |
744 | delegate(LLUDPClient client) | 744 | delegate(IClientAPI client) |
745 | { | 745 | { |
746 | if (client.DequeueOutgoing()) | 746 | if (client is LLClientView) |
747 | packetSent = true; | ||
748 | if (resendUnacked) | ||
749 | ResendUnacked(client); | ||
750 | if (sendAcks) | ||
751 | { | 747 | { |
752 | SendAcks(client); | 748 | LLUDPClient udpClient = ((LLClientView)client).UDPClient; |
753 | client.SendPacketStats(); | 749 | |
750 | if (udpClient.DequeueOutgoing()) | ||
751 | packetSent = true; | ||
752 | if (resendUnacked) | ||
753 | ResendUnacked(udpClient); | ||
754 | if (sendAcks) | ||
755 | { | ||
756 | SendAcks(udpClient); | ||
757 | udpClient.SendPacketStats(); | ||
758 | } | ||
759 | if (sendPings) | ||
760 | SendPing(udpClient); | ||
754 | } | 761 | } |
755 | if (sendPings) | ||
756 | SendPing(client); | ||
757 | } | 762 | } |
758 | ); | 763 | ); |
759 | 764 | ||
@@ -777,7 +782,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
777 | } | 782 | } |
778 | 783 | ||
779 | // Make sure this client is still alive | 784 | // Make sure this client is still alive |
780 | if (m_scene.ClientManager.TryGetClient(udpClient.CircuitCode, out client)) | 785 | if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client)) |
781 | { | 786 | { |
782 | try | 787 | try |
783 | { | 788 | { |