aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs305
1 files changed, 206 insertions, 99 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 4528714..b5bdd46 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -284,7 +284,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
284 /// <summary>Handlers for incoming packets</summary> 284 /// <summary>Handlers for incoming packets</summary>
285 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 285 //PacketEventDictionary packetEvents = new PacketEventDictionary();
286 /// <summary>Incoming packets that are awaiting handling</summary> 286 /// <summary>Incoming packets that are awaiting handling</summary>
287 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 287 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
288
289 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
288 290
289 /// <summary>Bandwidth throttle for this UDP server</summary> 291 /// <summary>Bandwidth throttle for this UDP server</summary>
290 public TokenBucket Throttle { get; private set; } 292 public TokenBucket Throttle { get; private set; }
@@ -342,14 +344,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
342 /// <summary>Flag to signal when clients should send pings</summary> 344 /// <summary>Flag to signal when clients should send pings</summary>
343 protected bool m_sendPing; 345 protected bool m_sendPing;
344 346
347 private int m_animationSequenceNumber;
348
349 public int NextAnimationSequenceNumber
350 {
351 get
352 {
353 m_animationSequenceNumber++;
354 if (m_animationSequenceNumber > 2147482624)
355 m_animationSequenceNumber = 1;
356 return m_animationSequenceNumber;
357 }
358 }
359
360
361
362 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
363
345 /// <summary> 364 /// <summary>
346 /// Event used to signal when queued packets are available for sending. 365 /// Event used to signal when queued packets are available for sending.
347 /// </summary> 366 /// </summary>
348 /// <remarks> 367 /// <remarks>
349 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling. 368 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling.
350 /// Some data is sent immediately and not queued. That data would not trigger this event. 369 /// Some data is sent immediately and not queued. That data would not trigger this event.
370 /// WRONG use. May be usefull in future revision
351 /// </remarks> 371 /// </remarks>
352 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false); 372// private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
353 373
354 private Pool<IncomingPacket> m_incomingPacketPool; 374 private Pool<IncomingPacket> m_incomingPacketPool;
355 375
@@ -431,16 +451,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
431 451
432 // Measure the resolution of Environment.TickCount 452 // Measure the resolution of Environment.TickCount
433 TickCountResolution = 0f; 453 TickCountResolution = 0f;
434 for (int i = 0; i < 5; i++) 454 for (int i = 0; i < 10; i++)
435 { 455 {
436 int start = Environment.TickCount; 456 int start = Environment.TickCount;
437 int now = start; 457 int now = start;
438 while (now == start) 458 while (now == start)
439 now = Environment.TickCount; 459 now = Environment.TickCount;
440 TickCountResolution += (float)(now - start) * 0.2f; 460 TickCountResolution += (float)(now - start) * 0.1f;
441 } 461 }
442 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
443 TickCountResolution = (float)Math.Ceiling(TickCountResolution); 462 TickCountResolution = (float)Math.Ceiling(TickCountResolution);
463 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
444 464
445 #endregion Environment.TickCount Measurement 465 #endregion Environment.TickCount Measurement
446 466
@@ -448,6 +468,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
448 int sceneThrottleBps = 0; 468 int sceneThrottleBps = 0;
449 bool usePools = false; 469 bool usePools = false;
450 470
471
472
451 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 473 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
452 if (config != null) 474 if (config != null)
453 { 475 {
@@ -494,15 +516,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
494 } 516 }
495 #endregion BinaryStats 517 #endregion BinaryStats
496 518
497 // FIXME: Can't add info here because don't know scene yet. 519 Throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f);
498// m_throttle
499// = new TokenBucket(
500// string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps);
501
502 Throttle = new TokenBucket("server throttle bucket", null, 0, sceneThrottleBps);
503
504 ThrottleRates = new ThrottleRates(configSource); 520 ThrottleRates = new ThrottleRates(configSource);
505 521
522 Random rnd = new Random(Util.EnvironmentTickCount());
523 m_animationSequenceNumber = rnd.Next(11474826);
524
506 if (usePools) 525 if (usePools)
507 EnablePools(); 526 EnablePools();
508 } 527 }
@@ -798,8 +817,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
798 if (UsePools) 817 if (UsePools)
799 EnablePoolStats(); 818 EnablePoolStats();
800 819
820
801 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); 821 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
802 commands.Register(); 822 commands.Register();
823
803 } 824 }
804 825
805 public bool HandlesRegion(Location x) 826 public bool HandlesRegion(Location x)
@@ -907,8 +928,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
907 928
908 PacketPool.Instance.ReturnPacket(packet); 929 PacketPool.Instance.ReturnPacket(packet);
909 930
910 if (packetQueued) 931 /// WRONG use. May be usefull in future revision
911 m_dataPresentEvent.Set(); 932// if (packetQueued)
933// m_dataPresentEvent.Set();
912 } 934 }
913 935
914 /// <summary> 936 /// <summary>
@@ -979,6 +1001,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 1001
980 #region Queue or Send 1002 #region Queue or Send
981 1003
1004 bool highPriority = false;
1005
1006 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
1007 {
1008 category = (ThrottleOutPacketType)((int)category & 127);
1009 highPriority = true;
1010 }
1011
982 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); 1012 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
983 1013
984 // If we were not provided a method for handling unacked, use the UDPServer default method 1014 // If we were not provided a method for handling unacked, use the UDPServer default method
@@ -988,26 +1018,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
988 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 1018 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
989 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object 1019 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
990 // packet so that it isn't sent before a queued update packet. 1020 // packet so that it isn't sent before a queued update packet.
991 bool forceQueue = (type == PacketType.KillObject);
992 1021
993// if (type == PacketType.ImprovedTerseObjectUpdate) 1022 bool requestQueue = type == PacketType.KillObject;
994// { 1023 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
995// m_log.DebugFormat("Direct send ITOU to {0} in {1}", udpClient.AgentID, Scene.Name);
996// SendPacketFinal(outgoingPacket);
997// return false;
998// }
999// else
1000// {
1001 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forceQueue))
1002 { 1024 {
1003 SendPacketFinal(outgoingPacket); 1025 SendPacketFinal(outgoingPacket);
1004 return true; 1026 return true;
1005 } 1027 }
1006 else 1028
1007 { 1029 return false;
1008 return false;
1009 }
1010// }
1011 1030
1012 #endregion Queue or Send 1031 #endregion Queue or Send
1013 } 1032 }
@@ -1048,6 +1067,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1048 pc.PingID.OldestUnacked = 0; 1067 pc.PingID.OldestUnacked = 0;
1049 1068
1050 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); 1069 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
1070 udpClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1051 } 1071 }
1052 1072
1053 public void CompletePing(LLUDPClient udpClient, byte pingID) 1073 public void CompletePing(LLUDPClient udpClient, byte pingID)
@@ -1145,7 +1165,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1145 int dataLength = buffer.DataLength; 1165 int dataLength = buffer.DataLength;
1146 1166
1147 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here 1167 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here
1148 if (!isZerocoded) 1168 if (!isZerocoded && !isResend && outgoingPacket.UnackedMethod == null)
1149 { 1169 {
1150 // Keep appending ACKs until there is no room left in the buffer or there are 1170 // Keep appending ACKs until there is no room left in the buffer or there are
1151 // no more ACKs to append 1171 // no more ACKs to append
@@ -1311,35 +1331,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1311 1331
1312 #region Packet to Client Mapping 1332 #region Packet to Client Mapping
1313 1333
1314 // UseCircuitCode handling 1334 // If there is already a client for this endpoint, don't process UseCircuitCode
1315 if (packet.Type == PacketType.UseCircuitCode) 1335 IClientAPI client = null;
1336 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1316 { 1337 {
1317 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1338 // UseCircuitCode handling
1318 // buffer. 1339 if (packet.Type == PacketType.UseCircuitCode)
1319 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1340 {
1341 // And if there is a UseCircuitCode pending, also drop it
1342 lock (m_pendingCache)
1343 {
1344 if (m_pendingCache.Contains(endPoint))
1345 return;
1346
1347 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1348 }
1320 1349
1321 Util.FireAndForget(HandleUseCircuitCode, array, "LLUDPServer.HandleUseCircuitCode"); 1350 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1351 // buffer.
1352 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1322 1353
1323 return; 1354 Util.FireAndForget(HandleUseCircuitCode, array);
1355
1356 return;
1357 }
1324 } 1358 }
1325 else if (packet.Type == PacketType.CompleteAgentMovement) 1359
1360 // If this is a pending connection, enqueue, don't process yet
1361 lock (m_pendingCache)
1326 { 1362 {
1327 // Send ack straight away to let the viewer know that we got it. 1363 Queue<UDPPacketBuffer> queue;
1328 SendAckImmediate(endPoint, packet.Header.Sequence); 1364 if (m_pendingCache.TryGetValue(endPoint, out queue))
1365 {
1366 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1367 queue.Enqueue(buffer);
1368 return;
1369 }
1329 1370
1330 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1371/*
1331 // buffer. 1372 else if (packet.Type == PacketType.CompleteAgentMovement)
1332 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1373 {
1374 // Send ack straight away to let the viewer know that we got it.
1375 SendAckImmediate(endPoint, packet.Header.Sequence);
1333 1376
1334 Util.FireAndForget( 1377 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1335 HandleCompleteMovementIntoRegion, array, "LLUDPServer.HandleCompleteMovementIntoRegion"); 1378 // buffer.
1379 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1336 1380
1337 return; 1381 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1382
1383 return;
1384 }
1385 */
1338 } 1386 }
1339 1387
1340 // Determine which agent this packet came from 1388 // Determine which agent this packet came from
1341 IClientAPI client; 1389 if (client == null || !(client is LLClientView))
1342 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1343 { 1390 {
1344 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1391 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1345 1392
@@ -1356,7 +1403,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1356 udpClient = ((LLClientView)client).UDPClient; 1403 udpClient = ((LLClientView)client).UDPClient;
1357 1404
1358 if (!udpClient.IsConnected) 1405 if (!udpClient.IsConnected)
1406 {
1407 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + Scene.RegionInfo.RegionName);
1359 return; 1408 return;
1409 }
1360 1410
1361 #endregion Packet to Client Mapping 1411 #endregion Packet to Client Mapping
1362 1412
@@ -1459,24 +1509,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1459 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1509 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1460 #endregion BinaryStats 1510 #endregion BinaryStats
1461 1511
1462 if (packet.Type == PacketType.AgentUpdate)
1463 {
1464 if (DiscardInboundAgentUpdates)
1465 return;
1466
1467 ((LLClientView)client).TotalAgentUpdates++;
1468 1512
1469 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; 1513//Ubit AgentUpdate mess removed from here
1470 1514
1471 LLClientView llClient = client as LLClientView;
1472 if (agentUpdate.AgentData.SessionID != client.SessionId
1473 || agentUpdate.AgentData.AgentID != client.AgentId
1474 || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) )
1475 {
1476 PacketPool.Instance.ReturnPacket(packet);
1477 return;
1478 }
1479 }
1480 1515
1481 #region Ping Check Handling 1516 #region Ping Check Handling
1482 1517
@@ -1487,7 +1522,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1487 // We don't need to do anything else with ping checks 1522 // We don't need to do anything else with ping checks
1488 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1523 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
1489 CompletePing(udpClient, startPing.PingID.PingID); 1524 CompletePing(udpClient, startPing.PingID.PingID);
1490 1525
1491 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000) 1526 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000)
1492 { 1527 {
1493 udpClient.SendPacketStats(); 1528 udpClient.SendPacketStats();
@@ -1497,7 +1532,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1497 } 1532 }
1498 else if (packet.Type == PacketType.CompletePingCheck) 1533 else if (packet.Type == PacketType.CompletePingCheck)
1499 { 1534 {
1500 // We don't currently track client ping times 1535 int t = Util.EnvironmentTickCountSubtract(udpClient.m_lastStartpingTimeMS);
1536 int c = udpClient.m_pingMS;
1537 c = 800 * c + 200 * t;
1538 c /= 1000;
1539 udpClient.m_pingMS = c;
1501 return; 1540 return;
1502 } 1541 }
1503 1542
@@ -1517,7 +1556,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1517 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1556 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1518 } 1557 }
1519 1558
1520 packetInbox.Enqueue(incomingPacket); 1559// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1560// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1561 if (incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1562 packetInbox.EnqueueHigh(incomingPacket);
1563 else
1564 packetInbox.EnqueueLow(incomingPacket);
1565
1521 } 1566 }
1522 1567
1523 #region BinaryStats 1568 #region BinaryStats
@@ -1634,7 +1679,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1634 1679
1635 try 1680 try
1636 { 1681 {
1637 // DateTime startTime = DateTime.Now; 1682// DateTime startTime = DateTime.Now;
1638 object[] array = (object[])o; 1683 object[] array = (object[])o;
1639 endPoint = (IPEndPoint)array[0]; 1684 endPoint = (IPEndPoint)array[0];
1640 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1685 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
@@ -1646,6 +1691,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1646 AuthenticateResponse sessionInfo; 1691 AuthenticateResponse sessionInfo;
1647 if (IsClientAuthorized(uccp, out sessionInfo)) 1692 if (IsClientAuthorized(uccp, out sessionInfo))
1648 { 1693 {
1694 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1695
1649 // Begin the process of adding the client to the simulator 1696 // Begin the process of adding the client to the simulator
1650 client 1697 client
1651 = AddClient( 1698 = AddClient(
@@ -1654,20 +1701,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1654 uccp.CircuitCode.SessionID, 1701 uccp.CircuitCode.SessionID,
1655 endPoint, 1702 endPoint,
1656 sessionInfo); 1703 sessionInfo);
1657 1704
1705 // This will be true if the client is new, e.g. not
1706 // an existing child agent, and there is no circuit data
1707 if (client != null && aCircuit == null)
1708 {
1709 Scene.CloseAgent(client.AgentId, true);
1710 return;
1711 }
1712
1713 // Now we know we can handle more data
1714 Thread.Sleep(200);
1715
1716 // Obtain the pending queue and remove it from the cache
1717 Queue<UDPPacketBuffer> queue = null;
1718
1719 lock (m_pendingCache)
1720 {
1721 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1722 {
1723 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1724 return;
1725
1726 }
1727 m_pendingCache.Remove(endPoint);
1728 }
1729
1730 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1731
1732 // Reinject queued packets
1733 while (queue.Count > 0)
1734 {
1735 UDPPacketBuffer buf = queue.Dequeue();
1736 PacketReceived(buf);
1737 }
1738
1739 queue = null;
1740
1658 // Send ack straight away to let the viewer know that the connection is active. 1741 // Send ack straight away to let the viewer know that the connection is active.
1659 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1742 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1660 // circuit code to the existing child agent. This is not particularly obvious. 1743 // circuit code to the existing child agent. This is not particularly obvious.
1661 SendAckImmediate(endPoint, uccp.Header.Sequence); 1744 SendAckImmediate(endPoint, uccp.Header.Sequence);
1662 1745
1663 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1746 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1664 if (client != null) 1747 if (client != null)
1665 { 1748 {
1666 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1667 bool tp = (aCircuit.teleportFlags > 0); 1749 bool tp = (aCircuit.teleportFlags > 0);
1668 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from 1750 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1669 if (!tp && !client.SceneAgent.SentInitialDataToClient) 1751 if (!tp)
1670 client.SceneAgent.SendInitialDataToClient(); 1752 client.SceneAgent.SendInitialDataToMe();
1671 } 1753 }
1672 } 1754 }
1673 else 1755 else
@@ -1675,9 +1757,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1675 // Don't create clients for unauthorized requesters. 1757 // Don't create clients for unauthorized requesters.
1676 m_log.WarnFormat( 1758 m_log.WarnFormat(
1677 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1759 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1760
1678 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1761 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1679 } 1762
1680 1763 lock (m_pendingCache)
1764 m_pendingCache.Remove(endPoint);
1765 }
1766
1681 // m_log.DebugFormat( 1767 // m_log.DebugFormat(
1682 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", 1768 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
1683 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); 1769 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
@@ -1694,8 +1780,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1694 e.StackTrace); 1780 e.StackTrace);
1695 } 1781 }
1696 } 1782 }
1697 1783/*
1698 private void HandleCompleteMovementIntoRegion(object o) 1784 private void HandleCompleteMovementIntoRegion(object o)
1699 { 1785 {
1700 IPEndPoint endPoint = null; 1786 IPEndPoint endPoint = null;
1701 IClientAPI client = null; 1787 IClientAPI client = null;
@@ -1804,6 +1890,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1804 e.StackTrace); 1890 e.StackTrace);
1805 } 1891 }
1806 } 1892 }
1893*/
1807 1894
1808 /// <summary> 1895 /// <summary>
1809 /// Send an ack immediately to the given endpoint. 1896 /// Send an ack immediately to the given endpoint.
@@ -1861,6 +1948,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1861 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 1948 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
1862 { 1949 {
1863 IClientAPI client = null; 1950 IClientAPI client = null;
1951 bool createNew = false;
1864 1952
1865 // We currently synchronize this code across the whole scene to avoid issues such as 1953 // We currently synchronize this code across the whole scene to avoid issues such as
1866 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done 1954 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
@@ -1869,7 +1957,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1869 { 1957 {
1870 if (!Scene.TryGetClient(agentID, out client)) 1958 if (!Scene.TryGetClient(agentID, out client))
1871 { 1959 {
1960 createNew = true;
1961 }
1962 else
1963 {
1964 if (client.SceneAgent == null)
1965 {
1966 Scene.CloseAgent(agentID, true);
1967 createNew = true;
1968 }
1969 }
1970
1971 if (createNew)
1972 {
1872 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1973 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1974
1873 1975
1874 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1976 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1875 client.OnLogout += LogoutHandler; 1977 client.OnLogout += LogoutHandler;
@@ -1899,15 +2001,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1899 { 2001 {
1900 ClientLogoutsDueToNoReceives++; 2002 ClientLogoutsDueToNoReceives++;
1901 2003
1902 m_log.WarnFormat( 2004 if (client.SceneAgent != null)
1903 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", 2005 {
1904 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name); 2006 m_log.WarnFormat(
2007 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
2008 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name);
1905 2009
1906 if (!client.SceneAgent.IsChildAgent) 2010 if (!client.SceneAgent.IsChildAgent)
1907 client.Kick("Simulator logged you out due to connection timeout."); 2011 client.Kick("Simulator logged you out due to connection timeout.");
2012 }
1908 } 2013 }
1909 2014
1910 Scene.CloseAgent(client.AgentId, true); 2015 if (!Scene.CloseAgent(client.AgentId, true))
2016 client.Close(true,true);
1911 } 2017 }
1912 2018
1913 private void IncomingPacketHandler() 2019 private void IncomingPacketHandler()
@@ -1920,6 +2026,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1920 2026
1921 while (IsRunningInbound) 2027 while (IsRunningInbound)
1922 { 2028 {
2029 Scene.ThreadAlive(1);
1923 try 2030 try
1924 { 2031 {
1925 IncomingPacket incomingPacket = null; 2032 IncomingPacket incomingPacket = null;
@@ -1942,7 +2049,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1942 m_incomingPacketPool.ReturnObject(incomingPacket); 2049 m_incomingPacketPool.ReturnObject(incomingPacket);
1943 } 2050 }
1944 } 2051 }
1945 catch (Exception ex) 2052 catch(Exception ex)
1946 { 2053 {
1947 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 2054 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
1948 } 2055 }
@@ -1971,6 +2078,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1971 2078
1972 while (base.IsRunningOutbound) 2079 while (base.IsRunningOutbound)
1973 { 2080 {
2081 Scene.ThreadAlive(2);
1974 try 2082 try
1975 { 2083 {
1976 m_packetSent = false; 2084 m_packetSent = false;
@@ -2029,13 +2137,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2029 2137
2030 // If nothing was sent, sleep for the minimum amount of time before a 2138 // If nothing was sent, sleep for the minimum amount of time before a
2031 // token bucket could get more tokens 2139 // token bucket could get more tokens
2032 //if (!m_packetSent) 2140
2033 // Thread.Sleep((int)TickCountResolution);
2034 //
2035 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
2036 // modern mono it reduces CPU base load since there is no more continuous polling.
2037 if (!m_packetSent) 2141 if (!m_packetSent)
2038 m_dataPresentEvent.WaitOne(100); 2142 Thread.Sleep((int)TickCountResolution);
2143
2144 // .... wrong core code removed
2145
2039 2146
2040 Watchdog.UpdateThread(); 2147 Watchdog.UpdateThread();
2041 } 2148 }
@@ -2206,8 +2313,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2206 Packet packet = incomingPacket.Packet; 2313 Packet packet = incomingPacket.Packet;
2207 LLClientView client = incomingPacket.Client; 2314 LLClientView client = incomingPacket.Client;
2208 2315
2209 if (client.IsActive) 2316// if (client.IsActive)
2210 { 2317// {
2211 m_currentIncomingClient = client; 2318 m_currentIncomingClient = client;
2212 2319
2213 try 2320 try
@@ -2234,13 +2341,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2234 { 2341 {
2235 m_currentIncomingClient = null; 2342 m_currentIncomingClient = null;
2236 } 2343 }
2237 } 2344// }
2238 else 2345// else
2239 { 2346// {
2240 m_log.DebugFormat( 2347// m_log.DebugFormat(
2241 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 2348// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
2242 packet.Type, client.Name, Scene.RegionInfo.RegionName); 2349// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
2243 } 2350// }
2244 2351
2245 IncomingPacketsProcessed++; 2352 IncomingPacketsProcessed++;
2246 } 2353 }