aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs16
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs169
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs5
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs26
4 files changed, 175 insertions, 41 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index d4c3307..65a8fe3 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -122,6 +122,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
122 public int PacketsReceived; 122 public int PacketsReceived;
123 /// <summary>Number of packets sent to this client</summary> 123 /// <summary>Number of packets sent to this client</summary>
124 public int PacketsSent; 124 public int PacketsSent;
125 /// <summary>Number of packets resent to this client</summary>
126 public int PacketsResent;
125 /// <summary>Total byte count of unacked packets sent to this client</summary> 127 /// <summary>Total byte count of unacked packets sent to this client</summary>
126 public int UnackedBytes; 128 public int UnackedBytes;
127 129
@@ -256,9 +258,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
256 public string GetStats() 258 public string GetStats()
257 { 259 {
258 return string.Format( 260 return string.Format(
259 "{0,7} {1,7} {2,9} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7} {10,7}", 261 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}",
262 PacketsReceived,
260 PacketsSent, 263 PacketsSent,
261 PacketsReceived, 264 PacketsResent,
262 UnackedBytes, 265 UnackedBytes,
263 m_packetOutboxes[(int)ThrottleOutPacketType.Resend].Count, 266 m_packetOutboxes[(int)ThrottleOutPacketType.Resend].Count,
264 m_packetOutboxes[(int)ThrottleOutPacketType.Land].Count, 267 m_packetOutboxes[(int)ThrottleOutPacketType.Land].Count,
@@ -441,13 +444,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
441 /// an outgoing packet from each, obeying the throttling bucket limits 444 /// an outgoing packet from each, obeying the throttling bucket limits
442 /// </summary> 445 /// </summary>
443 /// 446 ///
447 /// <remarks>
444 /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower 448 /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower
445 /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have 449 /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have
446 /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the 450 /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the
447 /// wind queue). 451 /// wind queue).
448 /// 452 ///
449 /// <remarks>This function is only called from a synchronous loop in the 453 /// This function is only called from a synchronous loop in the
450 /// UDPServer so we don't need to bother making this thread safe</remarks> 454 /// UDPServer so we don't need to bother making this thread safe
455 /// </remarks>
456 ///
451 /// <returns>True if any packets were sent, otherwise false</returns> 457 /// <returns>True if any packets were sent, otherwise false</returns>
452 public bool DequeueOutgoing() 458 public bool DequeueOutgoing()
453 { 459 {
@@ -476,7 +482,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
476 m_udpServer.SendPacketFinal(nextPacket); 482 m_udpServer.SendPacketFinal(nextPacket);
477 m_nextPackets[i] = null; 483 m_nextPackets[i] = null;
478 packetSent = true; 484 packetSent = true;
479 this.PacketsSent++;
480 } 485 }
481 } 486 }
482 else 487 else
@@ -493,7 +498,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
493 // Send the packet 498 // Send the packet
494 m_udpServer.SendPacketFinal(packet); 499 m_udpServer.SendPacketFinal(packet);
495 packetSent = true; 500 packetSent = true;
496 this.PacketsSent++;
497 } 501 }
498 else 502 else
499 { 503 {
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index df8ddbb..584c577 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.IO; 31using System.IO;
31using System.Net; 32using System.Net;
32using System.Net.Sockets; 33using System.Net.Sockets;
@@ -506,7 +507,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
506 507
507 // Bump up the resend count on this packet 508 // Bump up the resend count on this packet
508 Interlocked.Increment(ref outgoingPacket.ResendCount); 509 Interlocked.Increment(ref outgoingPacket.ResendCount);
509 //Interlocked.Increment(ref Stats.ResentPackets);
510 510
511 // Requeue or resend the packet 511 // Requeue or resend the packet
512 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) 512 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
@@ -582,6 +582,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
582 udpClient.NeedAcks.Add(outgoingPacket); 582 udpClient.NeedAcks.Add(outgoingPacket);
583 } 583 }
584 } 584 }
585 else
586 {
587 Interlocked.Increment(ref udpClient.PacketsResent);
588 }
585 589
586 #endregion Sequence Number Assignment 590 #endregion Sequence Number Assignment
587 591
@@ -636,10 +640,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
636 { 640 {
637 object[] array = new object[] { buffer, packet }; 641 object[] array = new object[] { buffer, packet };
638 642
639 if (m_asyncPacketHandling) 643 Util.FireAndForget(HandleUseCircuitCode, array);
640 Util.FireAndForget(HandleUseCircuitCode, array);
641 else
642 HandleUseCircuitCode(array);
643 644
644 return; 645 return;
645 } 646 }
@@ -856,10 +857,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
856 // Begin the process of adding the client to the simulator 857 // Begin the process of adding the client to the simulator
857 AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint); 858 AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint);
858 859
859 // Acknowledge the UseCircuitCode packet 860 // Send ack
860 SendAckImmediate(remoteEndPoint, packet.Header.Sequence); 861 SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
861 862
862// m_log.DebugFormat( 863 // m_log.DebugFormat(
863// "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", 864// "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
864// buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); 865// buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
865 } 866 }
@@ -923,25 +924,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
923 924
924 protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 925 protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
925 { 926 {
926 // Create the LLUDPClient 927 // In priciple there shouldn't be more than one thread here, ever.
927 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 928 // But in case that happens, we need to synchronize this piece of code
928 IClientAPI existingClient; 929 // because it's too important
929 930 lock (this)
930 if (!m_scene.TryGetClient(agentID, out existingClient))
931 { 931 {
932 // Create the LLClientView 932 IClientAPI existingClient;
933 LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
934 client.OnLogout += LogoutHandler;
935 933
936 client.DisableFacelights = m_disableFacelights; 934 if (!m_scene.TryGetClient(agentID, out existingClient))
935 {
936 // Create the LLUDPClient
937 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
938 // Create the LLClientView
939 LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
940 client.OnLogout += LogoutHandler;
937 941
938 // Start the IClientAPI 942 client.DisableFacelights = m_disableFacelights;
939 client.Start(); 943
940 } 944 // Start the IClientAPI
941 else 945 client.Start();
942 { 946
943 m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", 947 }
944 udpClient.AgentID, remoteEndPoint, circuitCode); 948 else
949 {
950 m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}",
951 existingClient.AgentId, remoteEndPoint, circuitCode);
952 }
945 } 953 }
946 } 954 }
947 955
@@ -1050,6 +1058,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1050 1058
1051 #endregion Update Timers 1059 #endregion Update Timers
1052 1060
1061 // Use this for emergency monitoring -- bug hunting
1062 //if (m_scene.EmergencyMonitoring)
1063 // clientPacketHandler = MonitoredClientOutgoingPacketHandler;
1064 //else
1065 // clientPacketHandler = ClientOutgoingPacketHandler;
1066
1053 // Handle outgoing packets, resends, acknowledgements, and pings for each 1067 // Handle outgoing packets, resends, acknowledgements, and pings for each
1054 // client. m_packetSent will be set to true if a packet is sent 1068 // client. m_packetSent will be set to true if a packet is sent
1055 m_scene.ForEachClient(clientPacketHandler); 1069 m_scene.ForEachClient(clientPacketHandler);
@@ -1065,6 +1079,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1065 { 1079 {
1066 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); 1080 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
1067 } 1081 }
1082
1068 } 1083 }
1069 1084
1070 Watchdog.RemoveThread(); 1085 Watchdog.RemoveThread();
@@ -1102,6 +1117,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1102 } 1117 }
1103 } 1118 }
1104 1119
1120 #region Emergency Monitoring
1121 // Alternative packet handler fuull of instrumentation
1122 // Handy for hunting bugs
1123 private Stopwatch watch1 = new Stopwatch();
1124 private Stopwatch watch2 = new Stopwatch();
1125
1126 private float avgProcessingTicks = 0;
1127 private float avgResendUnackedTicks = 0;
1128 private float avgSendAcksTicks = 0;
1129 private float avgSendPingTicks = 0;
1130 private float avgDequeueTicks = 0;
1131 private long nticks = 0;
1132 private long nticksUnack = 0;
1133 private long nticksAck = 0;
1134 private long nticksPing = 0;
1135 private int npacksSent = 0;
1136 private int npackNotSent = 0;
1137
1138 private void MonitoredClientOutgoingPacketHandler(IClientAPI client)
1139 {
1140 nticks++;
1141 watch1.Start();
1142 try
1143 {
1144 if (client is LLClientView)
1145 {
1146 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
1147
1148 if (udpClient.IsConnected)
1149 {
1150 if (m_resendUnacked)
1151 {
1152 nticksUnack++;
1153 watch2.Start();
1154
1155 ResendUnacked(udpClient);
1156
1157 watch2.Stop();
1158 avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
1159 watch2.Reset();
1160 }
1161
1162 if (m_sendAcks)
1163 {
1164 nticksAck++;
1165 watch2.Start();
1166
1167 SendAcks(udpClient);
1168
1169 watch2.Stop();
1170 avgSendAcksTicks = (nticksAck - 1) / (float)nticksAck * avgSendAcksTicks + (watch2.ElapsedTicks / (float)nticksAck);
1171 watch2.Reset();
1172 }
1173
1174 if (m_sendPing)
1175 {
1176 nticksPing++;
1177 watch2.Start();
1178
1179 SendPing(udpClient);
1180
1181 watch2.Stop();
1182 avgSendPingTicks = (nticksPing - 1) / (float)nticksPing * avgSendPingTicks + (watch2.ElapsedTicks / (float)nticksPing);
1183 watch2.Reset();
1184 }
1185
1186 watch2.Start();
1187 // Dequeue any outgoing packets that are within the throttle limits
1188 if (udpClient.DequeueOutgoing())
1189 {
1190 m_packetSent = true;
1191 npacksSent++;
1192 }
1193 else
1194 npackNotSent++;
1195
1196 watch2.Stop();
1197 avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks);
1198 watch2.Reset();
1199
1200 }
1201 else
1202 m_log.WarnFormat("[LLUDPSERVER]: Client is not connected");
1203 }
1204 }
1205 catch (Exception ex)
1206 {
1207 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
1208 " threw an exception: " + ex.Message, ex);
1209 }
1210 watch1.Stop();
1211 avgProcessingTicks = (nticks - 1) / (float)nticks * avgProcessingTicks + (watch1.ElapsedTicks / (float)nticks);
1212 watch1.Reset();
1213
1214 // reuse this -- it's every ~100ms
1215 if (m_scene.EmergencyMonitoring && nticks % 100 == 0)
1216 {
1217 m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})",
1218 avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent);
1219 npackNotSent = npacksSent = 0;
1220 }
1221
1222 }
1223
1224 #endregion
1225
1105 private void ProcessInPacket(object state) 1226 private void ProcessInPacket(object state)
1106 { 1227 {
1107 IncomingPacket incomingPacket = (IncomingPacket)state; 1228 IncomingPacket incomingPacket = (IncomingPacket)state;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index bdbd284..0a8331f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -210,6 +210,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
210 content = Math.Min(content + dripAmount, maxBurst); 210 content = Math.Min(content + dripAmount, maxBurst);
211 lastDrip = now; 211 lastDrip = now;
212 212
213 if (dripAmount < 0 || content < 0)
214 // sim has been idle for too long, integer has overflown
215 // previous calculation is meaningless, let's put it at correct max
216 content = maxBurst;
217
213 return true; 218 return true;
214 } 219 }
215 } 220 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index 9d40688..d195110 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -143,7 +143,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
143 // Process all the pending adds 143 // Process all the pending adds
144 OutgoingPacket pendingAdd; 144 OutgoingPacket pendingAdd;
145 while (m_pendingAdds.TryDequeue(out pendingAdd)) 145 while (m_pendingAdds.TryDequeue(out pendingAdd))
146 m_packets[pendingAdd.SequenceNumber] = pendingAdd; 146 if (pendingAdd != null)
147 m_packets[pendingAdd.SequenceNumber] = pendingAdd;
147 148
148 // Process all the pending removes, including updating statistics and round-trip times 149 // Process all the pending removes, including updating statistics and round-trip times
149 PendingAck pendingRemove; 150 PendingAck pendingRemove;
@@ -152,17 +153,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
152 { 153 {
153 if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) 154 if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket))
154 { 155 {
155 m_packets.Remove(pendingRemove.SequenceNumber); 156 if (ackedPacket != null)
156
157 // Update stats
158 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
159
160 if (!pendingRemove.FromResend)
161 { 157 {
162 // Calculate the round-trip time for this packet and its ACK 158 m_packets.Remove(pendingRemove.SequenceNumber);
163 int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; 159
164 if (rtt > 0) 160 // Update stats
165 ackedPacket.Client.UpdateRoundTrip(rtt); 161 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
162
163 if (!pendingRemove.FromResend)
164 {
165 // Calculate the round-trip time for this packet and its ACK
166 int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
167 if (rtt > 0)
168 ackedPacket.Client.UpdateRoundTrip(rtt);
169 }
166 } 170 }
167 } 171 }
168 } 172 }