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 3bd1ef1..4854893 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -223,7 +223,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
223 | /// <summary>Handlers for incoming packets</summary> | 223 | /// <summary>Handlers for incoming packets</summary> |
224 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | 224 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); |
225 | /// <summary>Incoming packets that are awaiting handling</summary> | 225 | /// <summary>Incoming packets that are awaiting handling</summary> |
226 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | 226 | //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); |
227 | |||
228 | private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>(); | ||
227 | 229 | ||
228 | /// <summary></summary> | 230 | /// <summary></summary> |
229 | //private UDPClientCollection m_clients = new UDPClientCollection(); | 231 | //private UDPClientCollection m_clients = new UDPClientCollection(); |
@@ -278,6 +280,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
278 | /// <summary>Flag to signal when clients should send pings</summary> | 280 | /// <summary>Flag to signal when clients should send pings</summary> |
279 | protected bool m_sendPing; | 281 | protected bool m_sendPing; |
280 | 282 | ||
283 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | ||
284 | |||
281 | /// <summary> | 285 | /// <summary> |
282 | /// Event used to signal when queued packets are available for sending. | 286 | /// Event used to signal when queued packets are available for sending. |
283 | /// </summary> | 287 | /// </summary> |
@@ -1040,6 +1044,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1040 | 1044 | ||
1041 | #region Queue or Send | 1045 | #region Queue or Send |
1042 | 1046 | ||
1047 | bool highPriority = false; | ||
1048 | |||
1049 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) | ||
1050 | { | ||
1051 | category = (ThrottleOutPacketType)((int)category & 127); | ||
1052 | highPriority = true; | ||
1053 | } | ||
1054 | |||
1043 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | 1055 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); |
1044 | // If we were not provided a method for handling unacked, use the UDPServer default method | 1056 | // If we were not provided a method for handling unacked, use the UDPServer default method |
1045 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | 1057 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); |
@@ -1048,15 +1060,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1048 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object | 1060 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object |
1049 | // packet so that it isn't sent before a queued update packet. | 1061 | // packet so that it isn't sent before a queued update packet. |
1050 | bool requestQueue = type == PacketType.KillObject; | 1062 | bool requestQueue = type == PacketType.KillObject; |
1063 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) | ||
1051 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) | 1064 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) |
1052 | { | 1065 | { |
1053 | SendPacketFinal(outgoingPacket); | 1066 | SendPacketFinal(outgoingPacket); |
1054 | return true; | 1067 | return true; |
1055 | } | 1068 | } |
1056 | else | 1069 | |
1057 | { | 1070 | return false; |
1058 | return false; | ||
1059 | } | ||
1060 | 1071 | ||
1061 | #endregion Queue or Send | 1072 | #endregion Queue or Send |
1062 | } | 1073 | } |
@@ -1354,34 +1365,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1354 | 1365 | ||
1355 | #region Packet to Client Mapping | 1366 | #region Packet to Client Mapping |
1356 | 1367 | ||
1357 | // UseCircuitCode handling | 1368 | // If there is already a client for this endpoint, don't process UseCircuitCode |
1358 | if (packet.Type == PacketType.UseCircuitCode) | 1369 | IClientAPI client = null; |
1370 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1359 | { | 1371 | { |
1360 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1372 | // UseCircuitCode handling |
1361 | // buffer. | 1373 | if (packet.Type == PacketType.UseCircuitCode) |
1362 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1374 | { |
1375 | // And if there is a UseCircuitCode pending, also drop it | ||
1376 | lock (m_pendingCache) | ||
1377 | { | ||
1378 | if (m_pendingCache.Contains(endPoint)) | ||
1379 | return; | ||
1363 | 1380 | ||
1364 | Util.FireAndForget(HandleUseCircuitCode, array); | 1381 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); |
1382 | } | ||
1365 | 1383 | ||
1366 | return; | 1384 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1385 | // buffer. | ||
1386 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1387 | |||
1388 | Util.FireAndForget(HandleUseCircuitCode, array); | ||
1389 | |||
1390 | return; | ||
1391 | } | ||
1367 | } | 1392 | } |
1368 | else if (packet.Type == PacketType.CompleteAgentMovement) | 1393 | |
1394 | // If this is a pending connection, enqueue, don't process yet | ||
1395 | lock (m_pendingCache) | ||
1369 | { | 1396 | { |
1370 | // Send ack straight away to let the viewer know that we got it. | 1397 | Queue<UDPPacketBuffer> queue; |
1371 | SendAckImmediate(endPoint, packet.Header.Sequence); | 1398 | if (m_pendingCache.TryGetValue(endPoint, out queue)) |
1399 | { | ||
1400 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); | ||
1401 | queue.Enqueue(buffer); | ||
1402 | return; | ||
1403 | } | ||
1404 | else if (packet.Type == PacketType.CompleteAgentMovement) | ||
1405 | { | ||
1406 | // Send ack straight away to let the viewer know that we got it. | ||
1407 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1372 | 1408 | ||
1373 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1409 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1374 | // buffer. | 1410 | // buffer. |
1375 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1411 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; |
1376 | 1412 | ||
1377 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | 1413 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); |
1378 | 1414 | ||
1379 | return; | 1415 | return; |
1416 | } | ||
1380 | } | 1417 | } |
1381 | 1418 | ||
1382 | // Determine which agent this packet came from | 1419 | // Determine which agent this packet came from |
1383 | IClientAPI client; | 1420 | if (client == null || !(client is LLClientView)) |
1384 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1385 | { | 1421 | { |
1386 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 1422 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
1387 | 1423 | ||
@@ -1398,7 +1434,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1398 | udpClient = ((LLClientView)client).UDPClient; | 1434 | udpClient = ((LLClientView)client).UDPClient; |
1399 | 1435 | ||
1400 | if (!udpClient.IsConnected) | 1436 | if (!udpClient.IsConnected) |
1437 | { | ||
1438 | m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName); | ||
1401 | return; | 1439 | return; |
1440 | } | ||
1402 | 1441 | ||
1403 | #endregion Packet to Client Mapping | 1442 | #endregion Packet to Client Mapping |
1404 | 1443 | ||
@@ -1547,7 +1586,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1547 | incomingPacket = new IncomingPacket((LLClientView)client, packet); | 1586 | incomingPacket = new IncomingPacket((LLClientView)client, packet); |
1548 | } | 1587 | } |
1549 | 1588 | ||
1550 | packetInbox.Enqueue(incomingPacket); | 1589 | if (incomingPacket.Packet.Type == PacketType.AgentUpdate || |
1590 | incomingPacket.Packet.Type == PacketType.ChatFromViewer) | ||
1591 | packetInbox.EnqueueHigh(incomingPacket); | ||
1592 | else | ||
1593 | packetInbox.EnqueueLow(incomingPacket); | ||
1551 | } | 1594 | } |
1552 | 1595 | ||
1553 | #region BinaryStats | 1596 | #region BinaryStats |
@@ -1699,6 +1742,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1699 | if (!tp) | 1742 | if (!tp) |
1700 | client.SceneAgent.SendInitialDataToMe(); | 1743 | client.SceneAgent.SendInitialDataToMe(); |
1701 | } | 1744 | } |
1745 | |||
1746 | // Now we know we can handle more data | ||
1747 | Thread.Sleep(200); | ||
1748 | |||
1749 | // Obtain the queue and remove it from the cache | ||
1750 | Queue<UDPPacketBuffer> queue = null; | ||
1751 | |||
1752 | lock (m_pendingCache) | ||
1753 | { | ||
1754 | if (!m_pendingCache.TryGetValue(endPoint, out queue)) | ||
1755 | { | ||
1756 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); | ||
1757 | return; | ||
1758 | } | ||
1759 | m_pendingCache.Remove(endPoint); | ||
1760 | } | ||
1761 | |||
1762 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); | ||
1763 | |||
1764 | // Reinject queued packets | ||
1765 | while(queue.Count > 0) | ||
1766 | { | ||
1767 | UDPPacketBuffer buf = queue.Dequeue(); | ||
1768 | PacketReceived(buf); | ||
1769 | } | ||
1770 | queue = null; | ||
1702 | } | 1771 | } |
1703 | else | 1772 | else |
1704 | { | 1773 | { |
@@ -1706,6 +1775,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1706 | m_log.WarnFormat( | 1775 | m_log.WarnFormat( |
1707 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1776 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1708 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | 1777 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1778 | lock (m_pendingCache) | ||
1779 | m_pendingCache.Remove(endPoint); | ||
1709 | } | 1780 | } |
1710 | 1781 | ||
1711 | // m_log.DebugFormat( | 1782 | // m_log.DebugFormat( |
@@ -1948,6 +2019,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1948 | 2019 | ||
1949 | while (IsRunningInbound) | 2020 | while (IsRunningInbound) |
1950 | { | 2021 | { |
2022 | m_scene.ThreadAlive(1); | ||
1951 | try | 2023 | try |
1952 | { | 2024 | { |
1953 | IncomingPacket incomingPacket = null; | 2025 | IncomingPacket incomingPacket = null; |
@@ -1997,6 +2069,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1997 | 2069 | ||
1998 | while (base.IsRunningOutbound) | 2070 | while (base.IsRunningOutbound) |
1999 | { | 2071 | { |
2072 | m_scene.ThreadAlive(2); | ||
2000 | try | 2073 | try |
2001 | { | 2074 | { |
2002 | m_packetSent = false; | 2075 | m_packetSent = false; |
@@ -2232,8 +2305,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2232 | Packet packet = incomingPacket.Packet; | 2305 | Packet packet = incomingPacket.Packet; |
2233 | LLClientView client = incomingPacket.Client; | 2306 | LLClientView client = incomingPacket.Client; |
2234 | 2307 | ||
2235 | if (client.IsActive) | 2308 | // if (client.IsActive) |
2236 | { | 2309 | // { |
2237 | m_currentIncomingClient = client; | 2310 | m_currentIncomingClient = client; |
2238 | 2311 | ||
2239 | try | 2312 | try |
@@ -2260,13 +2333,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2260 | { | 2333 | { |
2261 | m_currentIncomingClient = null; | 2334 | m_currentIncomingClient = null; |
2262 | } | 2335 | } |
2263 | } | 2336 | // } |
2264 | else | 2337 | // else |
2265 | { | 2338 | // { |
2266 | m_log.DebugFormat( | 2339 | // m_log.DebugFormat( |
2267 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 2340 | // "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
2268 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 2341 | // packet.Type, client.Name, m_scene.RegionInfo.RegionName); |
2269 | } | 2342 | // } |
2270 | 2343 | ||
2271 | IncomingPacketsProcessed++; | 2344 | IncomingPacketsProcessed++; |
2272 | } | 2345 | } |
@@ -2282,4 +2355,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2282 | } | 2355 | } |
2283 | } | 2356 | } |
2284 | } | 2357 | } |
2285 | } \ No newline at end of file | 2358 | } |