aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs5
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs24
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs197
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs175
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs9
7 files changed, 264 insertions, 152 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
index 90b3ede..1b8535c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -39,7 +39,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
39 public sealed class IncomingPacket 39 public sealed class IncomingPacket
40 { 40 {
41 /// <summary>Client this packet came from</summary> 41 /// <summary>Client this packet came from</summary>
42 public LLUDPClient Client; 42 public LLClientView Client;
43
43 /// <summary>Packet data that has been received</summary> 44 /// <summary>Packet data that has been received</summary>
44 public Packet Packet; 45 public Packet Packet;
45 46
@@ -48,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
48 /// </summary> 49 /// </summary>
49 /// <param name="client">Reference to the client this packet came from</param> 50 /// <param name="client">Reference to the client this packet came from</param>
50 /// <param name="packet">Packet data</param> 51 /// <param name="packet">Packet data</param>
51 public IncomingPacket(LLUDPClient client, Packet packet) 52 public IncomingPacket(LLClientView client, Packet packet)
52 { 53 {
53 Client = client; 54 Client = client;
54 Packet = packet; 55 Packet = packet;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 9c96b52..3461971 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -515,6 +515,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
515 /// </summary> 515 /// </summary>
516 public void Close(bool sendStop) 516 public void Close(bool sendStop)
517 { 517 {
518 IsActive = false;
519
518 m_log.DebugFormat( 520 m_log.DebugFormat(
519 "[CLIENT]: Close has been called for {0} attached to scene {1}", 521 "[CLIENT]: Close has been called for {0} attached to scene {1}",
520 Name, m_scene.RegionInfo.RegionName); 522 Name, m_scene.RegionInfo.RegionName);
@@ -3902,7 +3904,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3902 canUseImproved = false; 3904 canUseImproved = false;
3903 } 3905 }
3904 } 3906 }
3905 3907
3906 #endregion UpdateFlags to packet type conversion 3908 #endregion UpdateFlags to packet type conversion
3907 3909
3908 #region Block Construction 3910 #region Block Construction
@@ -11866,7 +11868,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11866 if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) 11868 if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect))
11867 logPacket = false; 11869 logPacket = false;
11868 11870
11869 if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) 11871 if (DebugPacketLevel <= 50
11872 & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
11870 logPacket = false; 11873 logPacket = false;
11871 11874
11872 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) 11875 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -12076,10 +12079,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12076 return string.Empty; 12079 return string.Empty;
12077 } 12080 }
12078 12081
12079 public void KillEndDone()
12080 {
12081 }
12082
12083 #region IClientCore 12082 #region IClientCore
12084 12083
12085 private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>(); 12084 private readonly Dictionary<Type, object> m_clientInterfaces = new Dictionary<Type, object>();
@@ -12167,21 +12166,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12167 protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) 12166 protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID)
12168 { 12167 {
12169 UUID requestID = UUID.Zero; 12168 UUID requestID = UUID.Zero;
12170 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) 12169 int sourceType = transferRequest.TransferInfo.SourceType;
12170
12171 if (sourceType == (int)SourceType.Asset)
12171 { 12172 {
12172 requestID = new UUID(transferRequest.TransferInfo.Params, 0); 12173 requestID = new UUID(transferRequest.TransferInfo.Params, 0);
12173 } 12174 }
12174 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) 12175 else if (sourceType == (int)SourceType.SimInventoryItem)
12175 { 12176 {
12176 requestID = new UUID(transferRequest.TransferInfo.Params, 80); 12177 requestID = new UUID(transferRequest.TransferInfo.Params, 80);
12177 } 12178 }
12178 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimEstate) 12179 else if (sourceType == (int)SourceType.SimEstate)
12179 { 12180 {
12180 requestID = taskID; 12181 requestID = taskID;
12181 } 12182 }
12182 12183
12183 12184// m_log.DebugFormat(
12184// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 12185// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12186// requestID, taskID, (SourceType)sourceType, Name);
12185 12187
12186 12188
12187 //Note, the bool returned from the below function is useless since it is always false. 12189 //Note, the bool returned from the below function is useless since it is always false.
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index bd8273d..754d9d2 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -147,21 +147,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
147 private int m_elapsed500MSOutgoingPacketHandler; 147 private int m_elapsed500MSOutgoingPacketHandler;
148 148
149 /// <summary>Flag to signal when clients should check for resends</summary> 149 /// <summary>Flag to signal when clients should check for resends</summary>
150 private bool m_resendUnacked; 150 protected bool m_resendUnacked;
151
151 /// <summary>Flag to signal when clients should send ACKs</summary> 152 /// <summary>Flag to signal when clients should send ACKs</summary>
152 private bool m_sendAcks; 153 protected bool m_sendAcks;
154
153 /// <summary>Flag to signal when clients should send pings</summary> 155 /// <summary>Flag to signal when clients should send pings</summary>
154 private bool m_sendPing; 156 protected bool m_sendPing;
155 157
156 private int m_defaultRTO = 0; 158 private int m_defaultRTO = 0;
157 private int m_maxRTO = 0; 159 private int m_maxRTO = 0;
158 160 private int m_ackTimeout = 0;
161 private int m_pausedAckTimeout = 0;
159 private bool m_disableFacelights = false; 162 private bool m_disableFacelights = false;
160 163
161 public Socket Server { get { return null; } } 164 public Socket Server { get { return null; } }
162 165
163 private int m_malformedCount = 0; // Guard against a spamming attack 166 private int m_malformedCount = 0; // Guard against a spamming attack
164 167
168 /// <summary>
169 /// Record current outgoing client for monitoring purposes.
170 /// </summary>
171 private IClientAPI m_currentOutgoingClient;
172
173 /// <summary>
174 /// Recording current incoming client for monitoring purposes.
175 /// </summary>
176 private IClientAPI m_currentIncomingClient;
177
165 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 178 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
166 : base(listenIP, (int)port) 179 : base(listenIP, (int)port)
167 { 180 {
@@ -198,11 +211,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
198 m_defaultRTO = config.GetInt("DefaultRTO", 0); 211 m_defaultRTO = config.GetInt("DefaultRTO", 0);
199 m_maxRTO = config.GetInt("MaxRTO", 0); 212 m_maxRTO = config.GetInt("MaxRTO", 0);
200 m_disableFacelights = config.GetBoolean("DisableFacelights", false); 213 m_disableFacelights = config.GetBoolean("DisableFacelights", false);
214 m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60);
215 m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300);
201 } 216 }
202 else 217 else
203 { 218 {
204 PrimUpdatesPerCallback = 100; 219 PrimUpdatesPerCallback = 100;
205 TextureSendLimit = 20; 220 TextureSendLimit = 20;
221 m_ackTimeout = 1000 * 60; // 1 minute
222 m_pausedAckTimeout = 1000 * 300; // 5 minutes
206 } 223 }
207 224
208 #region BinaryStats 225 #region BinaryStats
@@ -239,19 +256,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP
239 if (m_scene == null) 256 if (m_scene == null)
240 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); 257 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
241 258
242 m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode"); 259 m_log.InfoFormat(
260 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
261 m_asyncPacketHandling ? "asynchronous" : "synchronous");
243 262
244 base.Start(m_recvBufferSize, m_asyncPacketHandling); 263 base.Start(m_recvBufferSize, m_asyncPacketHandling);
245 264
246 // Start the packet processing threads 265 // Start the packet processing threads
247 Watchdog.StartThread( 266 Watchdog.StartThread(
248 IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true); 267 IncomingPacketHandler,
268 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
269 ThreadPriority.Normal,
270 false,
271 true,
272 GetWatchdogIncomingAlarmData,
273 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
274
249 Watchdog.StartThread( 275 Watchdog.StartThread(
250 OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true); 276 OutgoingPacketHandler,
277 string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName),
278 ThreadPriority.Normal,
279 false,
280 true,
281 GetWatchdogOutgoingAlarmData,
282 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
251 283
252 m_elapsedMSSinceLastStatReport = Environment.TickCount; 284 m_elapsedMSSinceLastStatReport = Environment.TickCount;
253 } 285 }
254 286
287 /// <summary>
288 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
289 /// </summary>
290 /// <returns></returns>
291 private string GetWatchdogIncomingAlarmData()
292 {
293 return string.Format(
294 "Client is {0}",
295 m_currentIncomingClient != null ? m_currentIncomingClient.Name : "none");
296 }
297
298 /// <summary>
299 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
300 /// </summary>
301 /// <returns></returns>
302 private string GetWatchdogOutgoingAlarmData()
303 {
304 return string.Format(
305 "Client is {0}",
306 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
307 }
308
255 public new void Stop() 309 public new void Stop()
256 { 310 {
257 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); 311 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
@@ -485,19 +539,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
485 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); 539 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null);
486 } 540 }
487 541
488 public void HandleUnacked(LLUDPClient udpClient) 542 public void HandleUnacked(LLClientView client)
489 { 543 {
544 LLUDPClient udpClient = client.UDPClient;
545
490 if (!udpClient.IsConnected) 546 if (!udpClient.IsConnected)
491 return; 547 return;
492 548
493 // Disconnect an agent if no packets are received for some time 549 // Disconnect an agent if no packets are received for some time
494 //FIXME: Make 60 an .ini setting 550 int timeoutTicks = m_ackTimeout;
495 if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60) 551
552 // Allow more slack if the client is "paused" eg file upload dialogue is open
553 // Some sort of limit is needed in case the client crashes, loses its network connection
554 // or some other disaster prevents it from sendung the AgentResume
555 if (udpClient.IsPaused)
556 timeoutTicks = m_pausedAckTimeout;
557
558 if (client.IsActive &&
559 (Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
496 { 560 {
497 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); 561 // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
498 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); 562 // though it's set later on by LLClientView.Close()
563 client.IsActive = false;
564
565 // Fire this out on a different thread so that we don't hold up outgoing packet processing for
566 // everybody else if this is being called due to an ack timeout.
567 // This is the same as processing as the async process of a logout request.
568 Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
499 569
500 RemoveClient(udpClient);
501 return; 570 return;
502 } 571 }
503 572
@@ -823,7 +892,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
823 #endregion Ping Check Handling 892 #endregion Ping Check Handling
824 893
825 // Inbox insertion 894 // Inbox insertion
826 packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); 895 packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
827 } 896 }
828 897
829 #region BinaryStats 898 #region BinaryStats
@@ -919,7 +988,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
919 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; 988 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
920 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 989 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
921 990
922 m_log.DebugFormat("[LLUDPSERVER]: Handling UseCircuitCode request from {0}", buffer.RemoteEndPoint); 991 m_log.DebugFormat(
992 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
993 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint);
923 994
924 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; 995 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
925 996
@@ -948,8 +1019,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
948 { 1019 {
949 // Don't create clients for unauthorized requesters. 1020 // Don't create clients for unauthorized requesters.
950 m_log.WarnFormat( 1021 m_log.WarnFormat(
951 "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", 1022 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
952 uccp.CircuitCode.ID, uccp.CircuitCode.Code, remoteEndPoint); 1023 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
953 } 1024 }
954 1025
955 // m_log.DebugFormat( 1026 // m_log.DebugFormat(
@@ -1047,15 +1118,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1047 return client; 1118 return client;
1048 } 1119 }
1049 1120
1050 private void RemoveClient(LLUDPClient udpClient) 1121 /// <summary>
1122 /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds).
1123 /// </summary>
1124 /// <remarks>
1125 /// If a connection is active then we will always receive packets even if nothing else is happening, due to
1126 /// regular client pings.
1127 /// </remarks>
1128 /// <param name='client'></param>
1129 private void DeactivateClientDueToTimeout(IClientAPI client)
1051 { 1130 {
1052 // Remove this client from the scene 1131 // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
1053 IClientAPI client; 1132 // though it's set later on by LLClientView.Close()
1054 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 1133 client.IsActive = false;
1055 { 1134
1056 client.IsLoggingOut = true; 1135 m_log.WarnFormat(
1057 client.Close(false); 1136 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
1058 } 1137 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
1138
1139 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1140
1141 if (!client.SceneAgent.IsChildAgent)
1142 client.Kick("Simulator logged you out due to connection timeout");
1143
1144 Util.FireAndForget(o => client.Close());
1059 } 1145 }
1060 1146
1061 private void IncomingPacketHandler() 1147 private void IncomingPacketHandler()
@@ -1164,6 +1250,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1164 // client. m_packetSent will be set to true if a packet is sent 1250 // client. m_packetSent will be set to true if a packet is sent
1165 m_scene.ForEachClient(clientPacketHandler); 1251 m_scene.ForEachClient(clientPacketHandler);
1166 1252
1253 m_currentOutgoingClient = null;
1254
1167 // If nothing was sent, sleep for the minimum amount of time before a 1255 // If nothing was sent, sleep for the minimum amount of time before a
1168 // token bucket could get more tokens 1256 // token bucket could get more tokens
1169 if (!m_packetSent) 1257 if (!m_packetSent)
@@ -1180,18 +1268,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1180 Watchdog.RemoveThread(); 1268 Watchdog.RemoveThread();
1181 } 1269 }
1182 1270
1183 private void ClientOutgoingPacketHandler(IClientAPI client) 1271 protected void ClientOutgoingPacketHandler(IClientAPI client)
1184 { 1272 {
1273 m_currentOutgoingClient = client;
1274
1185 try 1275 try
1186 { 1276 {
1187 if (client is LLClientView) 1277 if (client is LLClientView)
1188 { 1278 {
1189 LLUDPClient udpClient = ((LLClientView)client).UDPClient; 1279 LLClientView llClient = (LLClientView)client;
1280 LLUDPClient udpClient = llClient.UDPClient;
1190 1281
1191 if (udpClient.IsConnected) 1282 if (udpClient.IsConnected)
1192 { 1283 {
1193 if (m_resendUnacked) 1284 if (m_resendUnacked)
1194 HandleUnacked(udpClient); 1285 HandleUnacked(llClient);
1195 1286
1196 if (m_sendAcks) 1287 if (m_sendAcks)
1197 SendAcks(udpClient); 1288 SendAcks(udpClient);
@@ -1207,8 +1298,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1207 } 1298 }
1208 catch (Exception ex) 1299 catch (Exception ex)
1209 { 1300 {
1210 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + 1301 m_log.Error(
1211 " threw an exception: " + ex.Message, ex); 1302 string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex);
1212 } 1303 }
1213 } 1304 }
1214 1305
@@ -1234,11 +1325,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1234 { 1325 {
1235 nticks++; 1326 nticks++;
1236 watch1.Start(); 1327 watch1.Start();
1328 m_currentOutgoingClient = client;
1329
1237 try 1330 try
1238 { 1331 {
1239 if (client is LLClientView) 1332 if (client is LLClientView)
1240 { 1333 {
1241 LLUDPClient udpClient = ((LLClientView)client).UDPClient; 1334 LLClientView llClient = (LLClientView)client;
1335 LLUDPClient udpClient = llClient.UDPClient;
1242 1336
1243 if (udpClient.IsConnected) 1337 if (udpClient.IsConnected)
1244 { 1338 {
@@ -1247,7 +1341,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1247 nticksUnack++; 1341 nticksUnack++;
1248 watch2.Start(); 1342 watch2.Start();
1249 1343
1250 HandleUnacked(udpClient); 1344 HandleUnacked(llClient);
1251 1345
1252 watch2.Stop(); 1346 watch2.Stop();
1253 avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack); 1347 avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
@@ -1318,23 +1412,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1318 1412
1319 #endregion 1413 #endregion
1320 1414
1321 private void ProcessInPacket(object state) 1415 private void ProcessInPacket(IncomingPacket incomingPacket)
1322 { 1416 {
1323 IncomingPacket incomingPacket = (IncomingPacket)state;
1324 Packet packet = incomingPacket.Packet; 1417 Packet packet = incomingPacket.Packet;
1325 LLUDPClient udpClient = incomingPacket.Client; 1418 LLClientView client = incomingPacket.Client;
1326 IClientAPI client;
1327 1419
1328 // Sanity check 1420 if (client.IsActive)
1329 if (packet == null || udpClient == null)
1330 { 1421 {
1331 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"", 1422 m_currentIncomingClient = client;
1332 packet, udpClient);
1333 }
1334 1423
1335 // Make sure this client is still alive
1336 if (m_scene.TryGetClient(udpClient.AgentID, out client))
1337 {
1338 try 1424 try
1339 { 1425 {
1340 // Process this packet 1426 // Process this packet
@@ -1349,21 +1435,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1349 catch (Exception e) 1435 catch (Exception e)
1350 { 1436 {
1351 // Don't let a failure in an individual client thread crash the whole sim. 1437 // Don't let a failure in an individual client thread crash the whole sim.
1352 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type); 1438 m_log.Error(
1353 m_log.Error(e.Message, e); 1439 string.Format(
1440 "[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ",
1441 client.Name, packet.Type),
1442 e);
1443 }
1444 finally
1445 {
1446 m_currentIncomingClient = null;
1354 } 1447 }
1355 } 1448 }
1356 else 1449 else
1357 { 1450 {
1358 m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID); 1451 m_log.DebugFormat(
1452 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1453 packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1359 } 1454 }
1360 } 1455 }
1361 1456
1362 protected void LogoutHandler(IClientAPI client) 1457 protected void LogoutHandler(IClientAPI client)
1363 { 1458 {
1364 client.SendLogoutPacket(); 1459 client.SendLogoutPacket();
1365 if (client.IsActive) 1460
1366 RemoveClient(((LLClientView)client).UDPClient); 1461 if (!client.IsLoggingOut)
1462 {
1463 client.IsLoggingOut = true;
1464 client.Close();
1465 }
1367 } 1466 }
1368 } 1467 }
1369} 1468}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index a575e36..109a8e1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -45,6 +45,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
45 [TestFixture] 45 [TestFixture]
46 public class BasicCircuitTests 46 public class BasicCircuitTests
47 { 47 {
48 private Scene m_scene;
49 private TestLLUDPServer m_udpServer;
50
48 [TestFixtureSetUp] 51 [TestFixtureSetUp]
49 public void FixtureInit() 52 public void FixtureInit()
50 { 53 {
@@ -61,83 +64,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
61 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; 64 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
62 } 65 }
63 66
64// /// <summary> 67 [SetUp]
65// /// Add a client for testing 68 public void SetUp()
66// /// </summary> 69 {
67// /// <param name="scene"></param> 70 m_scene = new SceneHelpers().SetupScene();
68// /// <param name="testLLUDPServer"></param> 71 }
69// /// <param name="testPacketServer"></param>
70// /// <param name="acm">Agent circuit manager used in setting up the stack</param>
71// protected void SetupStack(
72// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer,
73// out AgentCircuitManager acm)
74// {
75// IConfigSource configSource = new IniConfigSource();
76// ClientStackUserSettings userSettings = new ClientStackUserSettings();
77// testLLUDPServer = new TestLLUDPServer();
78// acm = new AgentCircuitManager();
79//
80// uint port = 666;
81// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm);
82// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings);
83// testLLUDPServer.LocalScene = scene;
84// }
85
86// /// <summary>
87// /// Set up a client for tests which aren't concerned with this process itself and where only one client is being
88// /// tested
89// /// </summary>
90// /// <param name="circuitCode"></param>
91// /// <param name="epSender"></param>
92// /// <param name="testLLUDPServer"></param>
93// /// <param name="acm"></param>
94// protected void AddClient(
95// uint circuitCode, EndPoint epSender, TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
96// {
97// UUID myAgentUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
98// UUID mySessionUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
99//
100// AddClient(circuitCode, epSender, myAgentUuid, mySessionUuid, testLLUDPServer, acm);
101// }
102
103// /// <summary>
104// /// Set up a client for tests which aren't concerned with this process itself
105// /// </summary>
106// /// <param name="circuitCode"></param>
107// /// <param name="epSender"></param>
108// /// <param name="agentId"></param>
109// /// <param name="sessionId"></param>
110// /// <param name="testLLUDPServer"></param>
111// /// <param name="acm"></param>
112// protected void AddClient(
113// uint circuitCode, EndPoint epSender, UUID agentId, UUID sessionId,
114// TestLLUDPServer testLLUDPServer, AgentCircuitManager acm)
115// {
116// AgentCircuitData acd = new AgentCircuitData();
117// acd.AgentID = agentId;
118// acd.SessionID = sessionId;
119//
120// UseCircuitCodePacket uccp = new UseCircuitCodePacket();
121//
122// UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
123// = new UseCircuitCodePacket.CircuitCodeBlock();
124// uccpCcBlock.Code = circuitCode;
125// uccpCcBlock.ID = agentId;
126// uccpCcBlock.SessionID = sessionId;
127// uccp.CircuitCode = uccpCcBlock;
128//
129// acm.AddNewCircuit(circuitCode, acd);
130//
131// testLLUDPServer.LoadReceive(uccp, epSender);
132// testLLUDPServer.ReceiveData(null);
133// }
134 72
135 /// <summary> 73 /// <summary>
136 /// Build an object name packet for test purposes 74 /// Build an object name packet for test purposes
137 /// </summary> 75 /// </summary>
138 /// <param name="objectLocalId"></param> 76 /// <param name="objectLocalId"></param>
139 /// <param name="objectName"></param> 77 /// <param name="objectName"></param>
140 protected ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName) 78 private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName)
141 { 79 {
142 ObjectNamePacket onp = new ObjectNamePacket(); 80 ObjectNamePacket onp = new ObjectNamePacket();
143 ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock(); 81 ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock();
@@ -148,6 +86,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
148 86
149 return onp; 87 return onp;
150 } 88 }
89
90 private void AddUdpServer()
91 {
92 AddUdpServer(new IniConfigSource());
93 }
94
95 private void AddUdpServer(IniConfigSource configSource)
96 {
97 uint port = 0;
98 AgentCircuitManager acm = m_scene.AuthenticateHandler;
99
100 m_udpServer = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, configSource, acm);
101 m_udpServer.AddScene(m_scene);
102 }
103
104 /// <summary>
105 /// Used by tests that aren't testing this stage.
106 /// </summary>
107 private ScenePresence AddClient()
108 {
109 UUID myAgentUuid = TestHelpers.ParseTail(0x1);
110 UUID mySessionUuid = TestHelpers.ParseTail(0x2);
111 uint myCircuitCode = 123456;
112 IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
113
114 UseCircuitCodePacket uccp = new UseCircuitCodePacket();
115
116 UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
117 = new UseCircuitCodePacket.CircuitCodeBlock();
118 uccpCcBlock.Code = myCircuitCode;
119 uccpCcBlock.ID = myAgentUuid;
120 uccpCcBlock.SessionID = mySessionUuid;
121 uccp.CircuitCode = uccpCcBlock;
122
123 byte[] uccpBytes = uccp.ToBytes();
124 UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length);
125 upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
126 Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
127
128 AgentCircuitData acd = new AgentCircuitData();
129 acd.AgentID = myAgentUuid;
130 acd.SessionID = mySessionUuid;
131
132 m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
133
134 m_udpServer.PacketReceived(upb);
135
136 return m_scene.GetScenePresence(myAgentUuid);
137 }
151 138
152 /// <summary> 139 /// <summary>
153 /// Test adding a client to the stack 140 /// Test adding a client to the stack
@@ -158,19 +145,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
158 TestHelpers.InMethod(); 145 TestHelpers.InMethod();
159// XmlConfigurator.Configure(); 146// XmlConfigurator.Configure();
160 147
161 TestScene scene = SceneHelpers.SetupScene(); 148 AddUdpServer();
162 uint myCircuitCode = 123456; 149
163 UUID myAgentUuid = TestHelpers.ParseTail(0x1); 150 UUID myAgentUuid = TestHelpers.ParseTail(0x1);
164 UUID mySessionUuid = TestHelpers.ParseTail(0x2); 151 UUID mySessionUuid = TestHelpers.ParseTail(0x2);
152 uint myCircuitCode = 123456;
165 IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); 153 IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999);
166 154
167 uint port = 0;
168 AgentCircuitManager acm = scene.AuthenticateHandler;
169
170 TestLLUDPServer llUdpServer
171 = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, new IniConfigSource(), acm);
172 llUdpServer.AddScene(scene);
173
174 UseCircuitCodePacket uccp = new UseCircuitCodePacket(); 155 UseCircuitCodePacket uccp = new UseCircuitCodePacket();
175 156
176 UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock 157 UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock
@@ -185,26 +166,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
185 upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. 166 upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor.
186 Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); 167 Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length);
187 168
188 llUdpServer.PacketReceived(upb); 169 m_udpServer.PacketReceived(upb);
189 170
190 // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet 171 // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet
191 Assert.That(scene.GetScenePresence(myAgentUuid), Is.Null); 172 Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null);
192 173
193 AgentCircuitData acd = new AgentCircuitData(); 174 AgentCircuitData acd = new AgentCircuitData();
194 acd.AgentID = myAgentUuid; 175 acd.AgentID = myAgentUuid;
195 acd.SessionID = mySessionUuid; 176 acd.SessionID = mySessionUuid;
196 177
197 acm.AddNewCircuit(myCircuitCode, acd); 178 m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd);
198 179
199 llUdpServer.PacketReceived(upb); 180 m_udpServer.PacketReceived(upb);
200 181
201 // Should succeed now 182 // Should succeed now
202 ScenePresence sp = scene.GetScenePresence(myAgentUuid); 183 ScenePresence sp = m_scene.GetScenePresence(myAgentUuid);
203 Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); 184 Assert.That(sp.UUID, Is.EqualTo(myAgentUuid));
204 185
205 Assert.That(llUdpServer.PacketsSent.Count, Is.EqualTo(1)); 186 Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1));
206 187
207 Packet packet = llUdpServer.PacketsSent[0]; 188 Packet packet = m_udpServer.PacketsSent[0];
208 Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); 189 Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket)));
209 190
210 PacketAckPacket ackPacket = packet as PacketAckPacket; 191 PacketAckPacket ackPacket = packet as PacketAckPacket;
@@ -212,6 +193,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
212 Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0)); 193 Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0));
213 } 194 }
214 195
196 [Test]
197 public void TestLogoutClientDueToAck()
198 {
199 TestHelpers.InMethod();
200// TestHelpers.EnableLogging();
201
202 IniConfigSource ics = new IniConfigSource();
203 IConfig config = ics.AddConfig("ClientStack.LindenUDP");
204 config.Set("AckTimeout", -1);
205 AddUdpServer(ics);
206
207 ScenePresence sp = AddClient();
208 m_udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false);
209
210 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
211 Assert.That(spAfterAckTimeout, Is.Null);
212
213// TestHelpers.DisableLogging();
214 }
215
215// /// <summary> 216// /// <summary>
216// /// Test removing a client from the stack 217// /// Test removing a client from the stack
217// /// </summary> 218// /// </summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
index 1b68d68..5fcf376 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
@@ -79,7 +79,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
79 79
80 J2KDecoderModule j2kdm = new J2KDecoderModule(); 80 J2KDecoderModule j2kdm = new J2KDecoderModule();
81 81
82 scene = SceneHelpers.SetupScene(); 82 SceneHelpers sceneHelpers = new SceneHelpers();
83 scene = sceneHelpers.SetupScene();
83 SceneHelpers.SetupSceneModules(scene, j2kdm); 84 SceneHelpers.SetupSceneModules(scene, j2kdm);
84 85
85 tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); 86 tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
index d76927b..119a677 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
@@ -44,9 +44,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
44 } 44 }
45 protected int m_objectNameCallsReceived; 45 protected int m_objectNameCallsReceived;
46 46
47 public MockScene() 47 public MockScene() : base(new RegionInfo(1000, 1000, null, null))
48 { 48 {
49 m_regInfo = new RegionInfo(1000, 1000, null, null);
50 m_regStatus = RegionStatus.Up; 49 m_regStatus = RegionStatus.Up;
51 } 50 }
52 51
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs
index 0302385..27b9e5b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs
@@ -59,6 +59,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
59 PacketsSent.Add(packet); 59 PacketsSent.Add(packet);
60 } 60 }
61 61
62 public void ClientOutgoingPacketHandler(IClientAPI client, bool resendUnacked, bool sendAcks, bool sendPing)
63 {
64 m_resendUnacked = resendUnacked;
65 m_sendAcks = sendAcks;
66 m_sendPing = sendPing;
67
68 ClientOutgoingPacketHandler(client);
69 }
70
62//// /// <summary> 71//// /// <summary>
63//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive 72//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive
64//// /// </summary> 73//// /// </summary>