diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 305 |
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 | } |