aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-06 10:12:59 -0700
committerJohn Hurliman2009-10-06 10:12:59 -0700
commitfb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98 (patch)
treebef6315759b63e337e17d7d1e717929e08778f8c /OpenSim/Region/ClientStack/LindenUDP
parentFixing a few compile errors in the previous commit (diff)
downloadopensim-SC_OLD-fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98.zip
opensim-SC_OLD-fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98.tar.gz
opensim-SC_OLD-fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98.tar.bz2
opensim-SC_OLD-fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98.tar.xz
* Try/catch around EndInvoke() when Util.FireAndForget() returns to catch exceptions thrown in the async method
* Added packet stats handling to the new LLUDP implementation * Attempting to avoid a race condition when creating a new LLUDPClient
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs3
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs40
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs147
3 files changed, 112 insertions, 78 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 767020f..84e705a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -186,8 +186,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
186 m_udpServer = udpServer; 186 m_udpServer = udpServer;
187 m_udpClient = udpClient; 187 m_udpClient = udpClient;
188 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 188 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
189 // FIXME: Implement this 189 m_udpClient.OnPacketStats += PopulateStats;
190 //m_udpClient.OnPacketStats += PopulateStats;
191 190
192 RegisterLocalPacketHandlers(); 191 RegisterLocalPacketHandlers();
193 } 192 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index ad01135..f2e76d3 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -33,6 +33,7 @@ using OpenMetaverse;
33 33
34namespace OpenSim.Region.ClientStack.LindenUDP 34namespace OpenSim.Region.ClientStack.LindenUDP
35{ 35{
36 public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes);
36 public delegate void QueueEmpty(ThrottleOutPacketType category); 37 public delegate void QueueEmpty(ThrottleOutPacketType category);
37 38
38 public class LLUDPClient 39 public class LLUDPClient
@@ -41,6 +42,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
41 /// or removed, this number must also change</summary> 42 /// or removed, this number must also change</summary>
42 const int THROTTLE_CATEGORY_COUNT = 7; 43 const int THROTTLE_CATEGORY_COUNT = 7;
43 44
45 public event PacketStats OnPacketStats;
44 public event QueueEmpty OnQueueEmpty; 46 public event QueueEmpty OnQueueEmpty;
45 47
46 /// <summary>AgentID for this client</summary> 48 /// <summary>AgentID for this client</summary>
@@ -84,6 +86,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
84 /// <summary>Number of bytes received since the last acknowledgement was sent out. This is used 86 /// <summary>Number of bytes received since the last acknowledgement was sent out. This is used
85 /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2)</summary> 87 /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2)</summary>
86 public int BytesSinceLastACK; 88 public int BytesSinceLastACK;
89 /// <summary>Number of packets received from this client</summary>
90 public int PacketsReceived;
91 /// <summary>Number of packets sent to this client</summary>
92 public int PacketsSent;
93 /// <summary>Total byte count of unacked packets sent to this client</summary>
94 public int UnackedBytes;
95
96 /// <summary>Total number of received packets that we have reported to the OnPacketStats event(s)</summary>
97 private int m_packetsReceivedReported;
98 /// <summary>Total number of sent packets that we have reported to the OnPacketStats event(s)</summary>
99 private int m_packetsSentReported;
87 100
88 /// <summary>Throttle bucket for this agent's connection</summary> 101 /// <summary>Throttle bucket for this agent's connection</summary>
89 private readonly TokenBucket throttle; 102 private readonly TokenBucket throttle;
@@ -162,17 +175,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
162 175
163 public string GetStats() 176 public string GetStats()
164 { 177 {
178 // TODO: ???
165 return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", 179 return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
166 0, 180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
167 0, 181 }
168 0, 182
169 0, 183 public void SendPacketStats()
170 0, 184 {
171 0, 185 PacketStats callback = OnPacketStats;
172 0, 186 if (callback != null)
173 0, 187 {
174 0, 188 int newPacketsReceived = PacketsReceived - m_packetsReceivedReported;
175 0); 189 int newPacketsSent = PacketsSent - m_packetsSentReported;
190
191 callback(newPacketsReceived, newPacketsSent, UnackedBytes);
192
193 m_packetsReceivedReported += newPacketsReceived;
194 m_packetsSentReported += newPacketsSent;
195 }
176 } 196 }
177 197
178 public void SetThrottles(byte[] throttleData) 198 public void SetThrottles(byte[] throttleData)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 348615e..38890da 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -359,6 +359,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
359 // is actually sent out again 359 // is actually sent out again
360 outgoingPacket.TickCount = 0; 360 outgoingPacket.TickCount = 0;
361 361
362 // Bump up the resend count on this packet
362 Interlocked.Increment(ref outgoingPacket.ResendCount); 363 Interlocked.Increment(ref outgoingPacket.ResendCount);
363 //Interlocked.Increment(ref Stats.ResentPackets); 364 //Interlocked.Increment(ref Stats.ResentPackets);
364 365
@@ -393,6 +394,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP
393 394
394 public void Flush() 395 public void Flush()
395 { 396 {
397 // FIXME: Implement?
398 }
399
400 internal void SendPacketFinal(OutgoingPacket outgoingPacket)
401 {
402 UDPPacketBuffer buffer = outgoingPacket.Buffer;
403 byte flags = buffer.Data[0];
404 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
405 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
406 LLUDPClient client = outgoingPacket.Client;
407
408 // Keep track of when this packet was sent out (right now)
409 outgoingPacket.TickCount = Environment.TickCount;
410
411 #region ACK Appending
412
413 int dataLength = buffer.DataLength;
414
415 // Keep appending ACKs until there is no room left in the packet or there are
416 // no more ACKs to append
417 uint ackCount = 0;
418 uint ack;
419 while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack))
420 {
421 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
422 dataLength += 4;
423 ++ackCount;
424 }
425
426 if (ackCount > 0)
427 {
428 // Set the last byte of the packet equal to the number of appended ACKs
429 buffer.Data[dataLength++] = (byte)ackCount;
430 // Set the appended ACKs flag on this packet
431 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
432 }
433
434 buffer.DataLength = dataLength;
435
436 #endregion ACK Appending
437
438 if (!isResend)
439 {
440 // Not a resend, assign a new sequence number
441 uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence);
442 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
443 outgoingPacket.SequenceNumber = sequenceNumber;
444
445 if (isReliable)
446 {
447 // Add this packet to the list of ACK responses we are waiting on from the server
448 client.NeedAcks.Add(outgoingPacket);
449 }
450 }
451
452 // Stats tracking
453 Interlocked.Increment(ref client.PacketsSent);
454 if (isReliable)
455 Interlocked.Add(ref client.UnackedBytes, outgoingPacket.Buffer.DataLength);
456
457 // Put the UDP payload on the wire
458 AsyncBeginSend(buffer);
396 } 459 }
397 460
398 protected override void PacketReceived(UDPPacketBuffer buffer) 461 protected override void PacketReceived(UDPPacketBuffer buffer)
@@ -456,8 +519,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
456 519
457 #endregion UseCircuitCode Handling 520 #endregion UseCircuitCode Handling
458 521
459 //if (packet.Header.Resent) 522 // Stats tracking
460 // Interlocked.Increment(ref Stats.ReceivedResends); 523 Interlocked.Increment(ref client.PacketsReceived);
461 524
462 #region ACK Receiving 525 #region ACK Receiving
463 526
@@ -581,7 +644,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
581 { 644 {
582 // Create the LLUDPClient 645 // Create the LLUDPClient
583 LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); 646 LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint);
584 clients.Add(agentID, client.RemoteEndPoint, client);
585 647
586 // Create the LLClientView 648 // Create the LLClientView
587 LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); 649 LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode);
@@ -589,12 +651,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
589 clientApi.OnLogout += LogoutHandler; 651 clientApi.OnLogout += LogoutHandler;
590 clientApi.OnConnectionClosed += RemoveClient; 652 clientApi.OnConnectionClosed += RemoveClient;
591 653
592 // Give LLUDPClient a reference to IClientAPI
593 client.ClientAPI = clientApi;
594
595 // Start the IClientAPI 654 // Start the IClientAPI
596 m_scene.ClientManager.Add(circuitCode, clientApi); 655 m_scene.ClientManager.Add(circuitCode, clientApi);
597 clientApi.Start(); 656 clientApi.Start();
657
658 // Give LLUDPClient a reference to IClientAPI
659 client.ClientAPI = clientApi;
660
661 // Add the new client to our list of tracked clients
662 clients.Add(agentID, client.RemoteEndPoint, client);
598 } 663 }
599 664
600 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) 665 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend)
@@ -602,6 +667,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
602 OutgoingPacket ackedPacket; 667 OutgoingPacket ackedPacket;
603 if (client.NeedAcks.RemoveUnsafe(ack, out ackedPacket) && !fromResend) 668 if (client.NeedAcks.RemoveUnsafe(ack, out ackedPacket) && !fromResend)
604 { 669 {
670 // Update stats
671 Interlocked.Add(ref client.UnackedBytes, -ackedPacket.Buffer.DataLength);
672
605 // Calculate the round-trip time for this packet and its ACK 673 // Calculate the round-trip time for this packet and its ACK
606 int rtt = currentTime - ackedPacket.TickCount; 674 int rtt = currentTime - ackedPacket.TickCount;
607 if (rtt > 0) 675 if (rtt > 0)
@@ -650,7 +718,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
650 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); 718 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
651 719
652 // Don't let a failure in an individual client thread crash the whole sim. 720 // Don't let a failure in an individual client thread crash the whole sim.
653 m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} {1} crashed. Logging them out", client.ClientAPI.Name, client.AgentID); 721 m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} crashed. Logging them out", client.AgentID);
654 m_log.Error(e.Message, e); 722 m_log.Error(e.Message, e);
655 723
656 try 724 try
@@ -674,7 +742,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
674 } 742 }
675 catch (Exception e2) 743 catch (Exception e2)
676 { 744 {
677 m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.ClientAPI.Name); 745 m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.AgentID);
678 m_log.Error(e2.Message, e2); 746 m_log.Error(e2.Message, e2);
679 } 747 }
680 } 748 }
@@ -715,8 +783,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
715 elapsed100MS = 0; 783 elapsed100MS = 0;
716 ++elapsed500MS; 784 ++elapsed500MS;
717 } 785 }
718 // Send pings to clients every 2000ms 786 // Send pings to clients every 5000ms
719 if (elapsed500MS >= 4) 787 if (elapsed500MS >= 10)
720 { 788 {
721 sendPings = true; 789 sendPings = true;
722 elapsed500MS = 0; 790 elapsed500MS = 0;
@@ -730,7 +798,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
730 if (resendUnacked) 798 if (resendUnacked)
731 ResendUnacked(client); 799 ResendUnacked(client);
732 if (sendAcks) 800 if (sendAcks)
801 {
733 SendAcks(client); 802 SendAcks(client);
803 client.SendPacketStats();
804 }
734 if (sendPings) 805 if (sendPings)
735 SendPing(client); 806 SendPing(client);
736 } 807 }
@@ -746,61 +817,5 @@ namespace OpenSim.Region.ClientStack.LindenUDP
746 client.SendLogoutPacket(); 817 client.SendLogoutPacket();
747 RemoveClient(client); 818 RemoveClient(client);
748 } 819 }
749
750 internal void SendPacketFinal(OutgoingPacket outgoingPacket)
751 {
752 UDPPacketBuffer buffer = outgoingPacket.Buffer;
753 byte flags = buffer.Data[0];
754 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
755 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
756 LLUDPClient client = outgoingPacket.Client;
757
758 // Keep track of when this packet was sent out (right now)
759 outgoingPacket.TickCount = Environment.TickCount;
760
761 #region ACK Appending
762
763 int dataLength = buffer.DataLength;
764
765 // Keep appending ACKs until there is no room left in the packet or there are
766 // no more ACKs to append
767 uint ackCount = 0;
768 uint ack;
769 while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack))
770 {
771 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
772 dataLength += 4;
773 ++ackCount;
774 }
775
776 if (ackCount > 0)
777 {
778 // Set the last byte of the packet equal to the number of appended ACKs
779 buffer.Data[dataLength++] = (byte)ackCount;
780 // Set the appended ACKs flag on this packet
781 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
782 }
783
784 buffer.DataLength = dataLength;
785
786 #endregion ACK Appending
787
788 if (!isResend)
789 {
790 // Not a resend, assign a new sequence number
791 uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence);
792 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
793 outgoingPacket.SequenceNumber = sequenceNumber;
794
795 if (isReliable)
796 {
797 // Add this packet to the list of ACK responses we are waiting on from the server
798 client.NeedAcks.Add(outgoingPacket);
799 }
800 }
801
802 // Put the UDP payload on the wire
803 AsyncBeginSend(buffer);
804 }
805 } 820 }
806} 821}