aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-13 14:50:03 -0700
committerJohn Hurliman2009-10-13 14:50:03 -0700
commit23a334b9f54a1ef5df3b503c165e7b76b746a2b1 (patch)
tree93003db47fcd77af4085c0c49cbc1f2f0293b5eb /OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
parent* Unregister event handlers in LLUDPServer when a client logs out and disconn... (diff)
downloadopensim-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.cs163
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 {