diff options
Merge branch 'master' of /home/opensim/src/OpenSim/Core
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 169 |
1 files changed, 145 insertions, 24 deletions
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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | ||
30 | using System.IO; | 31 | using System.IO; |
31 | using System.Net; | 32 | using System.Net; |
32 | using System.Net.Sockets; | 33 | using 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; |