diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 134 |
1 files changed, 104 insertions, 30 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 102e581..ad3f715 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -210,7 +210,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
210 | /// <summary>Handlers for incoming packets</summary> | 210 | /// <summary>Handlers for incoming packets</summary> |
211 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | 211 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); |
212 | /// <summary>Incoming packets that are awaiting handling</summary> | 212 | /// <summary>Incoming packets that are awaiting handling</summary> |
213 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | 213 | //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); |
214 | |||
215 | private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>(); | ||
214 | 216 | ||
215 | /// <summary></summary> | 217 | /// <summary></summary> |
216 | //private UDPClientCollection m_clients = new UDPClientCollection(); | 218 | //private UDPClientCollection m_clients = new UDPClientCollection(); |
@@ -265,6 +267,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
265 | /// <summary>Flag to signal when clients should send pings</summary> | 267 | /// <summary>Flag to signal when clients should send pings</summary> |
266 | protected bool m_sendPing; | 268 | protected bool m_sendPing; |
267 | 269 | ||
270 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | ||
271 | |||
268 | /// <summary> | 272 | /// <summary> |
269 | /// Event used to signal when queued packets are available for sending. | 273 | /// Event used to signal when queued packets are available for sending. |
270 | /// </summary> | 274 | /// </summary> |
@@ -1011,6 +1015,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1011 | 1015 | ||
1012 | #region Queue or Send | 1016 | #region Queue or Send |
1013 | 1017 | ||
1018 | bool highPriority = false; | ||
1019 | |||
1020 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) | ||
1021 | { | ||
1022 | category = (ThrottleOutPacketType)((int)category & 127); | ||
1023 | highPriority = true; | ||
1024 | } | ||
1025 | |||
1014 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | 1026 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); |
1015 | // If we were not provided a method for handling unacked, use the UDPServer default method | 1027 | // If we were not provided a method for handling unacked, use the UDPServer default method |
1016 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | 1028 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); |
@@ -1019,7 +1031,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1019 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object | 1031 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object |
1020 | // packet so that it isn't sent before a queued update packet. | 1032 | // packet so that it isn't sent before a queued update packet. |
1021 | bool requestQueue = type == PacketType.KillObject; | 1033 | bool requestQueue = type == PacketType.KillObject; |
1022 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) | 1034 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) |
1023 | SendPacketFinal(outgoingPacket); | 1035 | SendPacketFinal(outgoingPacket); |
1024 | 1036 | ||
1025 | #endregion Queue or Send | 1037 | #endregion Queue or Send |
@@ -1310,34 +1322,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1310 | 1322 | ||
1311 | #region Packet to Client Mapping | 1323 | #region Packet to Client Mapping |
1312 | 1324 | ||
1313 | // UseCircuitCode handling | 1325 | // If there is already a client for this endpoint, don't process UseCircuitCode |
1314 | if (packet.Type == PacketType.UseCircuitCode) | 1326 | IClientAPI client = null; |
1327 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1315 | { | 1328 | { |
1316 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1329 | // UseCircuitCode handling |
1317 | // buffer. | 1330 | if (packet.Type == PacketType.UseCircuitCode) |
1318 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1331 | { |
1332 | // And if there is a UseCircuitCode pending, also drop it | ||
1333 | lock (m_pendingCache) | ||
1334 | { | ||
1335 | if (m_pendingCache.Contains(endPoint)) | ||
1336 | return; | ||
1319 | 1337 | ||
1320 | Util.FireAndForget(HandleUseCircuitCode, array); | 1338 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); |
1339 | } | ||
1321 | 1340 | ||
1322 | return; | 1341 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1342 | // buffer. | ||
1343 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1344 | |||
1345 | Util.FireAndForget(HandleUseCircuitCode, array); | ||
1346 | |||
1347 | return; | ||
1348 | } | ||
1323 | } | 1349 | } |
1324 | else if (packet.Type == PacketType.CompleteAgentMovement) | 1350 | |
1351 | // If this is a pending connection, enqueue, don't process yet | ||
1352 | lock (m_pendingCache) | ||
1325 | { | 1353 | { |
1326 | // Send ack straight away to let the viewer know that we got it. | 1354 | Queue<UDPPacketBuffer> queue; |
1327 | SendAckImmediate(endPoint, packet.Header.Sequence); | 1355 | if (m_pendingCache.TryGetValue(endPoint, out queue)) |
1356 | { | ||
1357 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); | ||
1358 | queue.Enqueue(buffer); | ||
1359 | return; | ||
1360 | } | ||
1361 | else if (packet.Type == PacketType.CompleteAgentMovement) | ||
1362 | { | ||
1363 | // Send ack straight away to let the viewer know that we got it. | ||
1364 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1328 | 1365 | ||
1329 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1366 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1330 | // buffer. | 1367 | // buffer. |
1331 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1368 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; |
1332 | 1369 | ||
1333 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | 1370 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); |
1334 | 1371 | ||
1335 | return; | 1372 | return; |
1373 | } | ||
1336 | } | 1374 | } |
1337 | 1375 | ||
1338 | // Determine which agent this packet came from | 1376 | // Determine which agent this packet came from |
1339 | IClientAPI client; | 1377 | if (client == null || !(client is LLClientView)) |
1340 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1341 | { | 1378 | { |
1342 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 1379 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
1343 | 1380 | ||
@@ -1354,7 +1391,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1354 | udpClient = ((LLClientView)client).UDPClient; | 1391 | udpClient = ((LLClientView)client).UDPClient; |
1355 | 1392 | ||
1356 | if (!udpClient.IsConnected) | 1393 | if (!udpClient.IsConnected) |
1394 | { | ||
1395 | m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName); | ||
1357 | return; | 1396 | return; |
1397 | } | ||
1358 | 1398 | ||
1359 | #endregion Packet to Client Mapping | 1399 | #endregion Packet to Client Mapping |
1360 | 1400 | ||
@@ -1503,7 +1543,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1503 | incomingPacket = new IncomingPacket((LLClientView)client, packet); | 1543 | incomingPacket = new IncomingPacket((LLClientView)client, packet); |
1504 | } | 1544 | } |
1505 | 1545 | ||
1506 | packetInbox.Enqueue(incomingPacket); | 1546 | if (incomingPacket.Packet.Type == PacketType.AgentUpdate || |
1547 | incomingPacket.Packet.Type == PacketType.ChatFromViewer) | ||
1548 | packetInbox.EnqueueHigh(incomingPacket); | ||
1549 | else | ||
1550 | packetInbox.EnqueueLow(incomingPacket); | ||
1507 | } | 1551 | } |
1508 | 1552 | ||
1509 | #region BinaryStats | 1553 | #region BinaryStats |
@@ -1655,6 +1699,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1655 | if (!tp) | 1699 | if (!tp) |
1656 | client.SceneAgent.SendInitialDataToMe(); | 1700 | client.SceneAgent.SendInitialDataToMe(); |
1657 | } | 1701 | } |
1702 | |||
1703 | // Now we know we can handle more data | ||
1704 | Thread.Sleep(200); | ||
1705 | |||
1706 | // Obtain the queue and remove it from the cache | ||
1707 | Queue<UDPPacketBuffer> queue = null; | ||
1708 | |||
1709 | lock (m_pendingCache) | ||
1710 | { | ||
1711 | if (!m_pendingCache.TryGetValue(endPoint, out queue)) | ||
1712 | { | ||
1713 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); | ||
1714 | return; | ||
1715 | } | ||
1716 | m_pendingCache.Remove(endPoint); | ||
1717 | } | ||
1718 | |||
1719 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); | ||
1720 | |||
1721 | // Reinject queued packets | ||
1722 | while(queue.Count > 0) | ||
1723 | { | ||
1724 | UDPPacketBuffer buf = queue.Dequeue(); | ||
1725 | PacketReceived(buf); | ||
1726 | } | ||
1727 | queue = null; | ||
1658 | } | 1728 | } |
1659 | else | 1729 | else |
1660 | { | 1730 | { |
@@ -1662,6 +1732,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1662 | m_log.WarnFormat( | 1732 | m_log.WarnFormat( |
1663 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1733 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1664 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | 1734 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1735 | lock (m_pendingCache) | ||
1736 | m_pendingCache.Remove(endPoint); | ||
1665 | } | 1737 | } |
1666 | 1738 | ||
1667 | // m_log.DebugFormat( | 1739 | // m_log.DebugFormat( |
@@ -1860,6 +1932,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1860 | 1932 | ||
1861 | while (IsRunningInbound) | 1933 | while (IsRunningInbound) |
1862 | { | 1934 | { |
1935 | m_scene.ThreadAlive(1); | ||
1863 | try | 1936 | try |
1864 | { | 1937 | { |
1865 | IncomingPacket incomingPacket = null; | 1938 | IncomingPacket incomingPacket = null; |
@@ -1909,6 +1982,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1909 | 1982 | ||
1910 | while (base.IsRunningOutbound) | 1983 | while (base.IsRunningOutbound) |
1911 | { | 1984 | { |
1985 | m_scene.ThreadAlive(2); | ||
1912 | try | 1986 | try |
1913 | { | 1987 | { |
1914 | m_packetSent = false; | 1988 | m_packetSent = false; |
@@ -2144,8 +2218,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2144 | Packet packet = incomingPacket.Packet; | 2218 | Packet packet = incomingPacket.Packet; |
2145 | LLClientView client = incomingPacket.Client; | 2219 | LLClientView client = incomingPacket.Client; |
2146 | 2220 | ||
2147 | if (client.IsActive) | 2221 | // if (client.IsActive) |
2148 | { | 2222 | // { |
2149 | m_currentIncomingClient = client; | 2223 | m_currentIncomingClient = client; |
2150 | 2224 | ||
2151 | try | 2225 | try |
@@ -2172,13 +2246,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2172 | { | 2246 | { |
2173 | m_currentIncomingClient = null; | 2247 | m_currentIncomingClient = null; |
2174 | } | 2248 | } |
2175 | } | 2249 | // } |
2176 | else | 2250 | // else |
2177 | { | 2251 | // { |
2178 | m_log.DebugFormat( | 2252 | // m_log.DebugFormat( |
2179 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 2253 | // "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
2180 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 2254 | // packet.Type, client.Name, m_scene.RegionInfo.RegionName); |
2181 | } | 2255 | // } |
2182 | 2256 | ||
2183 | IncomingPacketsProcessed++; | 2257 | IncomingPacketsProcessed++; |
2184 | } | 2258 | } |
@@ -2194,4 +2268,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2194 | } | 2268 | } |
2195 | } | 2269 | } |
2196 | } | 2270 | } |
2197 | } \ No newline at end of file | 2271 | } |