diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 139 |
1 files changed, 106 insertions, 33 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index c0a4e56..50dae2a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -236,7 +236,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
236 | /// <summary>Handlers for incoming packets</summary> | 236 | /// <summary>Handlers for incoming packets</summary> |
237 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | 237 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); |
238 | /// <summary>Incoming packets that are awaiting handling</summary> | 238 | /// <summary>Incoming packets that are awaiting handling</summary> |
239 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | 239 | //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); |
240 | |||
241 | private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>(); | ||
240 | 242 | ||
241 | /// <summary></summary> | 243 | /// <summary></summary> |
242 | //private UDPClientCollection m_clients = new UDPClientCollection(); | 244 | //private UDPClientCollection m_clients = new UDPClientCollection(); |
@@ -291,6 +293,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
291 | /// <summary>Flag to signal when clients should send pings</summary> | 293 | /// <summary>Flag to signal when clients should send pings</summary> |
292 | protected bool m_sendPing; | 294 | protected bool m_sendPing; |
293 | 295 | ||
296 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | ||
297 | |||
294 | /// <summary> | 298 | /// <summary> |
295 | /// Event used to signal when queued packets are available for sending. | 299 | /// Event used to signal when queued packets are available for sending. |
296 | /// </summary> | 300 | /// </summary> |
@@ -1058,6 +1062,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1058 | 1062 | ||
1059 | #region Queue or Send | 1063 | #region Queue or Send |
1060 | 1064 | ||
1065 | bool highPriority = false; | ||
1066 | |||
1067 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) | ||
1068 | { | ||
1069 | category = (ThrottleOutPacketType)((int)category & 127); | ||
1070 | highPriority = true; | ||
1071 | } | ||
1072 | |||
1061 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | 1073 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); |
1062 | // If we were not provided a method for handling unacked, use the UDPServer default method | 1074 | // If we were not provided a method for handling unacked, use the UDPServer default method |
1063 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | 1075 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); |
@@ -1066,15 +1078,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1066 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object | 1078 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object |
1067 | // packet so that it isn't sent before a queued update packet. | 1079 | // packet so that it isn't sent before a queued update packet. |
1068 | bool requestQueue = type == PacketType.KillObject; | 1080 | bool requestQueue = type == PacketType.KillObject; |
1081 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) | ||
1069 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) | 1082 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) |
1070 | { | 1083 | { |
1071 | SendPacketFinal(outgoingPacket); | 1084 | SendPacketFinal(outgoingPacket); |
1072 | return true; | 1085 | return true; |
1073 | } | 1086 | } |
1074 | else | 1087 | |
1075 | { | 1088 | return false; |
1076 | return false; | ||
1077 | } | ||
1078 | 1089 | ||
1079 | #endregion Queue or Send | 1090 | #endregion Queue or Send |
1080 | } | 1091 | } |
@@ -1372,34 +1383,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1372 | 1383 | ||
1373 | #region Packet to Client Mapping | 1384 | #region Packet to Client Mapping |
1374 | 1385 | ||
1375 | // UseCircuitCode handling | 1386 | // If there is already a client for this endpoint, don't process UseCircuitCode |
1376 | if (packet.Type == PacketType.UseCircuitCode) | 1387 | IClientAPI client = null; |
1388 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1377 | { | 1389 | { |
1378 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1390 | // UseCircuitCode handling |
1379 | // buffer. | 1391 | if (packet.Type == PacketType.UseCircuitCode) |
1380 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1392 | { |
1393 | // And if there is a UseCircuitCode pending, also drop it | ||
1394 | lock (m_pendingCache) | ||
1395 | { | ||
1396 | if (m_pendingCache.Contains(endPoint)) | ||
1397 | return; | ||
1381 | 1398 | ||
1382 | Util.FireAndForget(HandleUseCircuitCode, array); | 1399 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); |
1400 | } | ||
1383 | 1401 | ||
1384 | return; | 1402 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1403 | // buffer. | ||
1404 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1405 | |||
1406 | Util.FireAndForget(HandleUseCircuitCode, array); | ||
1407 | |||
1408 | return; | ||
1409 | } | ||
1385 | } | 1410 | } |
1386 | else if (packet.Type == PacketType.CompleteAgentMovement) | 1411 | |
1412 | // If this is a pending connection, enqueue, don't process yet | ||
1413 | lock (m_pendingCache) | ||
1387 | { | 1414 | { |
1388 | // Send ack straight away to let the viewer know that we got it. | 1415 | Queue<UDPPacketBuffer> queue; |
1389 | SendAckImmediate(endPoint, packet.Header.Sequence); | 1416 | if (m_pendingCache.TryGetValue(endPoint, out queue)) |
1417 | { | ||
1418 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); | ||
1419 | queue.Enqueue(buffer); | ||
1420 | return; | ||
1421 | } | ||
1422 | else if (packet.Type == PacketType.CompleteAgentMovement) | ||
1423 | { | ||
1424 | // Send ack straight away to let the viewer know that we got it. | ||
1425 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1390 | 1426 | ||
1391 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1427 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1392 | // buffer. | 1428 | // buffer. |
1393 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1429 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; |
1394 | 1430 | ||
1395 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | 1431 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); |
1396 | 1432 | ||
1397 | return; | 1433 | return; |
1434 | } | ||
1398 | } | 1435 | } |
1399 | 1436 | ||
1400 | // Determine which agent this packet came from | 1437 | // Determine which agent this packet came from |
1401 | IClientAPI client; | 1438 | if (client == null || !(client is LLClientView)) |
1402 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1403 | { | 1439 | { |
1404 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 1440 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
1405 | 1441 | ||
@@ -1416,7 +1452,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1416 | udpClient = ((LLClientView)client).UDPClient; | 1452 | udpClient = ((LLClientView)client).UDPClient; |
1417 | 1453 | ||
1418 | if (!udpClient.IsConnected) | 1454 | if (!udpClient.IsConnected) |
1455 | { | ||
1456 | m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName); | ||
1419 | return; | 1457 | return; |
1458 | } | ||
1420 | 1459 | ||
1421 | #endregion Packet to Client Mapping | 1460 | #endregion Packet to Client Mapping |
1422 | 1461 | ||
@@ -1570,7 +1609,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1570 | incomingPacket = new IncomingPacket((LLClientView)client, packet); | 1609 | incomingPacket = new IncomingPacket((LLClientView)client, packet); |
1571 | } | 1610 | } |
1572 | 1611 | ||
1573 | packetInbox.Enqueue(incomingPacket); | 1612 | if (incomingPacket.Packet.Type == PacketType.AgentUpdate || |
1613 | incomingPacket.Packet.Type == PacketType.ChatFromViewer) | ||
1614 | packetInbox.EnqueueHigh(incomingPacket); | ||
1615 | else | ||
1616 | packetInbox.EnqueueLow(incomingPacket); | ||
1574 | } | 1617 | } |
1575 | 1618 | ||
1576 | #region BinaryStats | 1619 | #region BinaryStats |
@@ -1722,6 +1765,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1722 | if (!tp) | 1765 | if (!tp) |
1723 | client.SceneAgent.SendInitialDataToMe(); | 1766 | client.SceneAgent.SendInitialDataToMe(); |
1724 | } | 1767 | } |
1768 | |||
1769 | // Now we know we can handle more data | ||
1770 | Thread.Sleep(200); | ||
1771 | |||
1772 | // Obtain the queue and remove it from the cache | ||
1773 | Queue<UDPPacketBuffer> queue = null; | ||
1774 | |||
1775 | lock (m_pendingCache) | ||
1776 | { | ||
1777 | if (!m_pendingCache.TryGetValue(endPoint, out queue)) | ||
1778 | { | ||
1779 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); | ||
1780 | return; | ||
1781 | } | ||
1782 | m_pendingCache.Remove(endPoint); | ||
1783 | } | ||
1784 | |||
1785 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); | ||
1786 | |||
1787 | // Reinject queued packets | ||
1788 | while(queue.Count > 0) | ||
1789 | { | ||
1790 | UDPPacketBuffer buf = queue.Dequeue(); | ||
1791 | PacketReceived(buf); | ||
1792 | } | ||
1793 | queue = null; | ||
1725 | } | 1794 | } |
1726 | else | 1795 | else |
1727 | { | 1796 | { |
@@ -1729,6 +1798,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1729 | m_log.WarnFormat( | 1798 | m_log.WarnFormat( |
1730 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1799 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1731 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | 1800 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1801 | lock (m_pendingCache) | ||
1802 | m_pendingCache.Remove(endPoint); | ||
1732 | } | 1803 | } |
1733 | 1804 | ||
1734 | // m_log.DebugFormat( | 1805 | // m_log.DebugFormat( |
@@ -1971,6 +2042,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1971 | 2042 | ||
1972 | while (IsRunningInbound) | 2043 | while (IsRunningInbound) |
1973 | { | 2044 | { |
2045 | m_scene.ThreadAlive(1); | ||
1974 | try | 2046 | try |
1975 | { | 2047 | { |
1976 | IncomingPacket incomingPacket = null; | 2048 | IncomingPacket incomingPacket = null; |
@@ -2020,6 +2092,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2020 | 2092 | ||
2021 | while (base.IsRunningOutbound) | 2093 | while (base.IsRunningOutbound) |
2022 | { | 2094 | { |
2095 | m_scene.ThreadAlive(2); | ||
2023 | try | 2096 | try |
2024 | { | 2097 | { |
2025 | m_packetSent = false; | 2098 | m_packetSent = false; |
@@ -2255,8 +2328,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2255 | Packet packet = incomingPacket.Packet; | 2328 | Packet packet = incomingPacket.Packet; |
2256 | LLClientView client = incomingPacket.Client; | 2329 | LLClientView client = incomingPacket.Client; |
2257 | 2330 | ||
2258 | if (client.IsActive) | 2331 | // if (client.IsActive) |
2259 | { | 2332 | // { |
2260 | m_currentIncomingClient = client; | 2333 | m_currentIncomingClient = client; |
2261 | 2334 | ||
2262 | try | 2335 | try |
@@ -2283,13 +2356,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2283 | { | 2356 | { |
2284 | m_currentIncomingClient = null; | 2357 | m_currentIncomingClient = null; |
2285 | } | 2358 | } |
2286 | } | 2359 | // } |
2287 | else | 2360 | // else |
2288 | { | 2361 | // { |
2289 | m_log.DebugFormat( | 2362 | // m_log.DebugFormat( |
2290 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 2363 | // "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
2291 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 2364 | // packet.Type, client.Name, m_scene.RegionInfo.RegionName); |
2292 | } | 2365 | // } |
2293 | 2366 | ||
2294 | IncomingPacketsProcessed++; | 2367 | IncomingPacketsProcessed++; |
2295 | } | 2368 | } |
@@ -2305,4 +2378,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2305 | } | 2378 | } |
2306 | } | 2379 | } |
2307 | } | 2380 | } |
2308 | } \ No newline at end of file | 2381 | } |