aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs134
1 files changed, 77 insertions, 57 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 07764cb..0b5b51d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -183,10 +183,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
183 183
184 public void RemoveClient(LLUDPClient udpClient) 184 public void RemoveClient(LLUDPClient udpClient)
185 { 185 {
186 m_log.Debug("[LLUDPSERVER]: Removing LLUDPClient for " + udpClient.ClientAPI.Name); 186 m_log.Debug("[LLUDPSERVER]: Removing LLUDPClient for " + udpClient.AgentID);
187 187
188 m_scene.ClientManager.Remove(udpClient.CircuitCode); 188 // Shut down the IClientAPI and remove it from the scene
189 udpClient.ClientAPI.Close(false); 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
190 udpClient.Shutdown(); 197 udpClient.Shutdown();
191 m_clients.Remove(udpClient.RemoteEndPoint); 198 m_clients.Remove(udpClient.RemoteEndPoint);
192 } 199 }
@@ -222,7 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
222 } 229 }
223 } 230 }
224 231
225 public void SendPacket(LLUDPClient client, Packet packet, ThrottleOutPacketType category, bool allowSplitting) 232 public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
226 { 233 {
227 // CoarseLocationUpdate packets cannot be split in an automated way 234 // CoarseLocationUpdate packets cannot be split in an automated way
228 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) 235 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
@@ -239,17 +246,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
239 for (int i = 0; i < packetCount; i++) 246 for (int i = 0; i < packetCount; i++)
240 { 247 {
241 byte[] data = datas[i]; 248 byte[] data = datas[i];
242 SendPacketData(client, data, packet.Type, category); 249 SendPacketData(udpClient, data, packet.Type, category);
243 } 250 }
244 } 251 }
245 else 252 else
246 { 253 {
247 byte[] data = packet.ToBytes(); 254 byte[] data = packet.ToBytes();
248 SendPacketData(client, data, packet.Type, category); 255 SendPacketData(udpClient, data, packet.Type, category);
249 } 256 }
250 } 257 }
251 258
252 public void SendPacketData(LLUDPClient client, byte[] data, PacketType type, ThrottleOutPacketType category) 259 public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category)
253 { 260 {
254 int dataLength = data.Length; 261 int dataLength = data.Length;
255 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; 262 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
@@ -260,7 +267,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
260 // to accomodate for both common scenarios and provide ample room for ACK appending in both 267 // to accomodate for both common scenarios and provide ample room for ACK appending in both
261 int bufferSize = (dataLength > 180) ? Packet.MTU : 200; 268 int bufferSize = (dataLength > 180) ? Packet.MTU : 200;
262 269
263 UDPPacketBuffer buffer = new UDPPacketBuffer(client.RemoteEndPoint, bufferSize); 270 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
264 271
265 // Zerocode if needed 272 // Zerocode if needed
266 if (doZerocode) 273 if (doZerocode)
@@ -285,7 +292,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 #region Queue or Send 292 #region Queue or Send
286 293
287 // Look up the UDPClient this is going to 294 // Look up the UDPClient this is going to
288 OutgoingPacket outgoingPacket = new OutgoingPacket(client, buffer, category); 295 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
289 296
290 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 297 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
291 SendPacketFinal(outgoingPacket); 298 SendPacketFinal(outgoingPacket);
@@ -293,18 +300,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 #endregion Queue or Send 300 #endregion Queue or Send
294 } 301 }
295 302
296 public void SendAcks(LLUDPClient client) 303 public void SendAcks(LLUDPClient udpClient)
297 { 304 {
298 uint ack; 305 uint ack;
299 306
300 if (client.PendingAcks.Dequeue(out ack)) 307 if (udpClient.PendingAcks.Dequeue(out ack))
301 { 308 {
302 List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); 309 List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>();
303 PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); 310 PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock();
304 block.ID = ack; 311 block.ID = ack;
305 blocks.Add(block); 312 blocks.Add(block);
306 313
307 while (client.PendingAcks.Dequeue(out ack)) 314 while (udpClient.PendingAcks.Dequeue(out ack))
308 { 315 {
309 block = new PacketAckPacket.PacketsBlock(); 316 block = new PacketAckPacket.PacketsBlock();
310 block.ID = ack; 317 block.ID = ack;
@@ -315,22 +322,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
315 packet.Header.Reliable = false; 322 packet.Header.Reliable = false;
316 packet.Packets = blocks.ToArray(); 323 packet.Packets = blocks.ToArray();
317 324
318 SendPacket(client, packet, ThrottleOutPacketType.Unknown, true); 325 SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true);
319 } 326 }
320 } 327 }
321 328
322 public void SendPing(LLUDPClient client) 329 public void SendPing(LLUDPClient udpClient)
323 { 330 {
324 IClientAPI api = client.ClientAPI; 331 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
325 if (api != null) 332 pc.Header.Reliable = false;
326 api.SendStartPingCheck(client.CurrentPingSequence++); 333
334 OutgoingPacket oldestPacket = udpClient.NeedAcks.GetOldest();
335
336 pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++;
337 pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0;
338
339 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false);
327 } 340 }
328 341
329 public void ResendUnacked(LLUDPClient client) 342 public void ResendUnacked(LLUDPClient udpClient)
330 { 343 {
331 if (client.NeedAcks.Count > 0) 344 if (udpClient.NeedAcks.Count > 0)
332 { 345 {
333 List<OutgoingPacket> expiredPackets = client.NeedAcks.GetExpiredPackets(client.RTO); 346 List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO);
334 347
335 if (expiredPackets != null) 348 if (expiredPackets != null)
336 { 349 {
@@ -366,18 +379,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
366 m_log.DebugFormat("[LLUDPSERVER]: Dropping packet #{0} for agent {1} after {2} failed attempts", 379 m_log.DebugFormat("[LLUDPSERVER]: Dropping packet #{0} for agent {1} after {2} failed attempts",
367 outgoingPacket.SequenceNumber, outgoingPacket.Client.RemoteEndPoint, outgoingPacket.ResendCount); 380 outgoingPacket.SequenceNumber, outgoingPacket.Client.RemoteEndPoint, outgoingPacket.ResendCount);
368 381
369 lock (client.NeedAcks.SyncRoot) 382 lock (udpClient.NeedAcks.SyncRoot)
370 client.NeedAcks.RemoveUnsafe(outgoingPacket.SequenceNumber); 383 udpClient.NeedAcks.RemoveUnsafe(outgoingPacket.SequenceNumber);
371 384
372 //Interlocked.Increment(ref Stats.DroppedPackets); 385 //Interlocked.Increment(ref Stats.DroppedPackets);
373 386
374 // Disconnect an agent if no packets are received for some time 387 // Disconnect an agent if no packets are received for some time
375 //FIXME: Make 60 an .ini setting 388 //FIXME: Make 60 an .ini setting
376 if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60) 389 if (Environment.TickCount - udpClient.TickLastPacketReceived > 1000 * 60)
377 { 390 {
378 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.ClientAPI.Name); 391 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
379 392
380 RemoveClient(client); 393 RemoveClient(udpClient);
381 return; 394 return;
382 } 395 }
383 } 396 }
@@ -397,7 +410,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
397 byte flags = buffer.Data[0]; 410 byte flags = buffer.Data[0];
398 bool isResend = (flags & Helpers.MSG_RESENT) != 0; 411 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
399 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; 412 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
400 LLUDPClient client = outgoingPacket.Client; 413 LLUDPClient udpClient = outgoingPacket.Client;
401 414
402 // Keep track of when this packet was sent out (right now) 415 // Keep track of when this packet was sent out (right now)
403 outgoingPacket.TickCount = Environment.TickCount; 416 outgoingPacket.TickCount = Environment.TickCount;
@@ -410,7 +423,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
410 // no more ACKs to append 423 // no more ACKs to append
411 uint ackCount = 0; 424 uint ackCount = 0;
412 uint ack; 425 uint ack;
413 while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) 426 while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack))
414 { 427 {
415 Utils.UIntToBytesBig(ack, buffer.Data, dataLength); 428 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
416 dataLength += 4; 429 dataLength += 4;
@@ -429,24 +442,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
429 442
430 #endregion ACK Appending 443 #endregion ACK Appending
431 444
445 #region Sequence Number Assignment
446
432 if (!isResend) 447 if (!isResend)
433 { 448 {
434 // Not a resend, assign a new sequence number 449 // Not a resend, assign a new sequence number
435 uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); 450 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
436 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 451 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
437 outgoingPacket.SequenceNumber = sequenceNumber; 452 outgoingPacket.SequenceNumber = sequenceNumber;
438 453
439 if (isReliable) 454 if (isReliable)
440 { 455 {
441 // Add this packet to the list of ACK responses we are waiting on from the server 456 // Add this packet to the list of ACK responses we are waiting on from the server
442 client.NeedAcks.Add(outgoingPacket); 457 udpClient.NeedAcks.Add(outgoingPacket);
443 } 458 }
444 } 459 }
445 460
461 #endregion Sequence Number Assignment
462
446 // Stats tracking 463 // Stats tracking
447 Interlocked.Increment(ref client.PacketsSent); 464 Interlocked.Increment(ref udpClient.PacketsSent);
448 if (isReliable) 465 if (isReliable)
449 Interlocked.Add(ref client.UnackedBytes, outgoingPacket.Buffer.DataLength); 466 Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength);
450 467
451 // Put the UDP payload on the wire 468 // Put the UDP payload on the wire
452 AsyncBeginSend(buffer); 469 AsyncBeginSend(buffer);
@@ -455,7 +472,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
455 protected override void PacketReceived(UDPPacketBuffer buffer) 472 protected override void PacketReceived(UDPPacketBuffer buffer)
456 { 473 {
457 // Debugging/Profiling 474 // Debugging/Profiling
458 //try { Thread.CurrentThread.Name = "PacketReceived (" + scene.RegionName + ")"; } 475 //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
459 //catch (Exception) { } 476 //catch (Exception) { }
460 477
461 LLUDPClient client = null; 478 LLUDPClient client = null;
@@ -484,9 +501,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
484 return; 501 return;
485 } 502 }
486 503
487 //Stats.RecvBytes += (ulong)buffer.DataLength;
488 //++Stats.RecvPackets;
489
490 #endregion Decoding 504 #endregion Decoding
491 505
492 #region UseCircuitCode Handling 506 #region UseCircuitCode Handling
@@ -508,7 +522,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
508 if (!m_clients.TryGetValue(address, out client)) 522 if (!m_clients.TryGetValue(address, out client))
509 { 523 {
510 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + 524 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address +
511 ", currently tracking " + m_clients.Count + " clients"); 525 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_clients.Count + " clients");
512 return; 526 return;
513 } 527 }
514 528
@@ -549,7 +563,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
549 #region ACK Sending 563 #region ACK Sending
550 564
551 if (packet.Header.Reliable) 565 if (packet.Header.Reliable)
552 client.PendingAcks.Enqueue((uint)packet.Header.Sequence); 566 client.PendingAcks.Enqueue(packet.Header.Sequence);
553 567
554 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 568 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
555 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove 569 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
@@ -648,9 +662,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
648 m_scene.ClientManager.Add(circuitCode, clientApi); 662 m_scene.ClientManager.Add(circuitCode, clientApi);
649 clientApi.Start(); 663 clientApi.Start();
650 664
651 // Give LLUDPClient a reference to IClientAPI
652 udpClient.ClientAPI = clientApi;
653
654 // Add the new client to our list of tracked clients 665 // Add the new client to our list of tracked clients
655 m_clients.Add(udpClient.RemoteEndPoint, udpClient); 666 m_clients.Add(udpClient.RemoteEndPoint, udpClient);
656 } 667 }
@@ -756,31 +767,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
756 { 767 {
757 IncomingPacket incomingPacket = (IncomingPacket)state; 768 IncomingPacket incomingPacket = (IncomingPacket)state;
758 Packet packet = incomingPacket.Packet; 769 Packet packet = incomingPacket.Packet;
759 LLUDPClient client = incomingPacket.Client; 770 LLUDPClient udpClient = incomingPacket.Client;
771 IClientAPI client;
760 772
761 // Sanity check 773 // Sanity check
762 if (packet == null || client == null || client.ClientAPI == null) 774 if (packet == null || udpClient == null)
763 { 775 {
764 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", Client=\"{1}\", Client.ClientAPI=\"{2}\"", 776 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
765 packet, client, (client != null) ? client.ClientAPI : null); 777 packet, udpClient);
766 } 778 }
767 779
768 try 780 // Make sure this client is still alive
781 if (m_scene.ClientManager.TryGetClient(udpClient.CircuitCode, out client))
769 { 782 {
770 // Process this packet 783 try
771 client.ClientAPI.ProcessInPacket(packet); 784 {
772 } 785 // Process this packet
773 catch (ThreadAbortException) 786 client.ProcessInPacket(packet);
774 { 787 }
775 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down 788 catch (ThreadAbortException)
776 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server"); 789 {
777 Stop(); 790 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down
791 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server");
792 Stop();
793 }
794 catch (Exception e)
795 {
796 // Don't let a failure in an individual client thread crash the whole sim.
797 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type);
798 m_log.Error(e.Message, e);
799 }
778 } 800 }
779 catch (Exception e) 801 else
780 { 802 {
781 // Don't let a failure in an individual client thread crash the whole sim. 803 m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID);
782 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", client.AgentID, packet.Type);
783 m_log.Error(e.Message, e);
784 } 804 }
785 } 805 }
786 806