diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 138 |
1 files changed, 106 insertions, 32 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 85fe1a4..2a2c819 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -184,7 +184,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
184 | /// <summary>Handlers for incoming packets</summary> | 184 | /// <summary>Handlers for incoming packets</summary> |
185 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | 185 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); |
186 | /// <summary>Incoming packets that are awaiting handling</summary> | 186 | /// <summary>Incoming packets that are awaiting handling</summary> |
187 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | 187 | //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); |
188 | |||
189 | private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>(); | ||
188 | 190 | ||
189 | /// <summary></summary> | 191 | /// <summary></summary> |
190 | //private UDPClientCollection m_clients = new UDPClientCollection(); | 192 | //private UDPClientCollection m_clients = new UDPClientCollection(); |
@@ -239,6 +241,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
239 | /// <summary>Flag to signal when clients should send pings</summary> | 241 | /// <summary>Flag to signal when clients should send pings</summary> |
240 | protected bool m_sendPing; | 242 | protected bool m_sendPing; |
241 | 243 | ||
244 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | ||
245 | |||
242 | /// <summary> | 246 | /// <summary> |
243 | /// Event used to signal when queued packets are available for sending. | 247 | /// Event used to signal when queued packets are available for sending. |
244 | /// </summary> | 248 | /// </summary> |
@@ -977,6 +981,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
977 | 981 | ||
978 | #region Queue or Send | 982 | #region Queue or Send |
979 | 983 | ||
984 | bool highPriority = false; | ||
985 | |||
986 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) | ||
987 | { | ||
988 | category = (ThrottleOutPacketType)((int)category & 127); | ||
989 | highPriority = true; | ||
990 | } | ||
991 | |||
980 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | 992 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); |
981 | // If we were not provided a method for handling unacked, use the UDPServer default method | 993 | // If we were not provided a method for handling unacked, use the UDPServer default method |
982 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | 994 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); |
@@ -985,7 +997,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
985 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object | 997 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object |
986 | // packet so that it isn't sent before a queued update packet. | 998 | // packet so that it isn't sent before a queued update packet. |
987 | bool requestQueue = type == PacketType.KillObject; | 999 | bool requestQueue = type == PacketType.KillObject; |
988 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) | 1000 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) |
989 | SendPacketFinal(outgoingPacket); | 1001 | SendPacketFinal(outgoingPacket); |
990 | 1002 | ||
991 | #endregion Queue or Send | 1003 | #endregion Queue or Send |
@@ -1270,34 +1282,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1270 | 1282 | ||
1271 | #region Packet to Client Mapping | 1283 | #region Packet to Client Mapping |
1272 | 1284 | ||
1273 | // UseCircuitCode handling | 1285 | // If there is already a client for this endpoint, don't process UseCircuitCode |
1274 | if (packet.Type == PacketType.UseCircuitCode) | 1286 | IClientAPI client = null; |
1287 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1275 | { | 1288 | { |
1276 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1289 | // UseCircuitCode handling |
1277 | // buffer. | 1290 | if (packet.Type == PacketType.UseCircuitCode) |
1278 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1291 | { |
1292 | // And if there is a UseCircuitCode pending, also drop it | ||
1293 | lock (m_pendingCache) | ||
1294 | { | ||
1295 | if (m_pendingCache.Contains(endPoint)) | ||
1296 | return; | ||
1279 | 1297 | ||
1280 | Util.FireAndForget(HandleUseCircuitCode, array); | 1298 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); |
1299 | } | ||
1281 | 1300 | ||
1282 | return; | 1301 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1302 | // buffer. | ||
1303 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1304 | |||
1305 | Util.FireAndForget(HandleUseCircuitCode, array); | ||
1306 | |||
1307 | return; | ||
1308 | } | ||
1283 | } | 1309 | } |
1284 | else if (packet.Type == PacketType.CompleteAgentMovement) | 1310 | |
1311 | // If this is a pending connection, enqueue, don't process yet | ||
1312 | lock (m_pendingCache) | ||
1285 | { | 1313 | { |
1286 | // Send ack straight away to let the viewer know that we got it. | 1314 | Queue<UDPPacketBuffer> queue; |
1287 | SendAckImmediate(endPoint, packet.Header.Sequence); | 1315 | if (m_pendingCache.TryGetValue(endPoint, out queue)) |
1316 | { | ||
1317 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); | ||
1318 | queue.Enqueue(buffer); | ||
1319 | return; | ||
1320 | } | ||
1321 | else if (packet.Type == PacketType.CompleteAgentMovement) | ||
1322 | { | ||
1323 | // Send ack straight away to let the viewer know that we got it. | ||
1324 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1288 | 1325 | ||
1289 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1326 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1290 | // buffer. | 1327 | // buffer. |
1291 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1328 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; |
1292 | 1329 | ||
1293 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | 1330 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); |
1294 | 1331 | ||
1295 | return; | 1332 | return; |
1333 | } | ||
1296 | } | 1334 | } |
1297 | 1335 | ||
1298 | // Determine which agent this packet came from | 1336 | // Determine which agent this packet came from |
1299 | IClientAPI client; | 1337 | if (client == null || !(client is LLClientView)) |
1300 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1301 | { | 1338 | { |
1302 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 1339 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
1303 | return; | 1340 | return; |
@@ -1306,7 +1343,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1306 | udpClient = ((LLClientView)client).UDPClient; | 1343 | udpClient = ((LLClientView)client).UDPClient; |
1307 | 1344 | ||
1308 | if (!udpClient.IsConnected) | 1345 | if (!udpClient.IsConnected) |
1346 | { | ||
1347 | m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName); | ||
1309 | return; | 1348 | return; |
1349 | } | ||
1310 | 1350 | ||
1311 | #endregion Packet to Client Mapping | 1351 | #endregion Packet to Client Mapping |
1312 | 1352 | ||
@@ -1455,7 +1495,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1455 | incomingPacket = new IncomingPacket((LLClientView)client, packet); | 1495 | incomingPacket = new IncomingPacket((LLClientView)client, packet); |
1456 | } | 1496 | } |
1457 | 1497 | ||
1458 | packetInbox.Enqueue(incomingPacket); | 1498 | if (incomingPacket.Packet.Type == PacketType.AgentUpdate || |
1499 | incomingPacket.Packet.Type == PacketType.ChatFromViewer) | ||
1500 | packetInbox.EnqueueHigh(incomingPacket); | ||
1501 | else | ||
1502 | packetInbox.EnqueueLow(incomingPacket); | ||
1459 | } | 1503 | } |
1460 | 1504 | ||
1461 | #region BinaryStats | 1505 | #region BinaryStats |
@@ -1607,6 +1651,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1607 | if (!tp) | 1651 | if (!tp) |
1608 | client.SceneAgent.SendInitialDataToMe(); | 1652 | client.SceneAgent.SendInitialDataToMe(); |
1609 | } | 1653 | } |
1654 | |||
1655 | // Now we know we can handle more data | ||
1656 | Thread.Sleep(200); | ||
1657 | |||
1658 | // Obtain the queue and remove it from the cache | ||
1659 | Queue<UDPPacketBuffer> queue = null; | ||
1660 | |||
1661 | lock (m_pendingCache) | ||
1662 | { | ||
1663 | if (!m_pendingCache.TryGetValue(endPoint, out queue)) | ||
1664 | { | ||
1665 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); | ||
1666 | return; | ||
1667 | } | ||
1668 | m_pendingCache.Remove(endPoint); | ||
1669 | } | ||
1670 | |||
1671 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); | ||
1672 | |||
1673 | // Reinject queued packets | ||
1674 | while(queue.Count > 0) | ||
1675 | { | ||
1676 | UDPPacketBuffer buf = queue.Dequeue(); | ||
1677 | PacketReceived(buf); | ||
1678 | } | ||
1679 | queue = null; | ||
1610 | } | 1680 | } |
1611 | else | 1681 | else |
1612 | { | 1682 | { |
@@ -1614,6 +1684,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1614 | m_log.WarnFormat( | 1684 | m_log.WarnFormat( |
1615 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1685 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1616 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | 1686 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1687 | lock (m_pendingCache) | ||
1688 | m_pendingCache.Remove(endPoint); | ||
1617 | } | 1689 | } |
1618 | 1690 | ||
1619 | // m_log.DebugFormat( | 1691 | // m_log.DebugFormat( |
@@ -1800,7 +1872,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1800 | if (!client.SceneAgent.IsChildAgent) | 1872 | if (!client.SceneAgent.IsChildAgent) |
1801 | client.Kick("Simulator logged you out due to connection timeout."); | 1873 | client.Kick("Simulator logged you out due to connection timeout."); |
1802 | 1874 | ||
1803 | client.CloseWithoutChecks(); | 1875 | client.CloseWithoutChecks(true); |
1804 | } | 1876 | } |
1805 | } | 1877 | } |
1806 | 1878 | ||
@@ -1812,6 +1884,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1812 | 1884 | ||
1813 | while (IsRunningInbound) | 1885 | while (IsRunningInbound) |
1814 | { | 1886 | { |
1887 | m_scene.ThreadAlive(1); | ||
1815 | try | 1888 | try |
1816 | { | 1889 | { |
1817 | IncomingPacket incomingPacket = null; | 1890 | IncomingPacket incomingPacket = null; |
@@ -1861,6 +1934,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1861 | 1934 | ||
1862 | while (base.IsRunningOutbound) | 1935 | while (base.IsRunningOutbound) |
1863 | { | 1936 | { |
1937 | m_scene.ThreadAlive(2); | ||
1864 | try | 1938 | try |
1865 | { | 1939 | { |
1866 | m_packetSent = false; | 1940 | m_packetSent = false; |
@@ -2095,8 +2169,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2095 | Packet packet = incomingPacket.Packet; | 2169 | Packet packet = incomingPacket.Packet; |
2096 | LLClientView client = incomingPacket.Client; | 2170 | LLClientView client = incomingPacket.Client; |
2097 | 2171 | ||
2098 | if (client.IsActive) | 2172 | // if (client.IsActive) |
2099 | { | 2173 | // { |
2100 | m_currentIncomingClient = client; | 2174 | m_currentIncomingClient = client; |
2101 | 2175 | ||
2102 | try | 2176 | try |
@@ -2123,13 +2197,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2123 | { | 2197 | { |
2124 | m_currentIncomingClient = null; | 2198 | m_currentIncomingClient = null; |
2125 | } | 2199 | } |
2126 | } | 2200 | // } |
2127 | else | 2201 | // else |
2128 | { | 2202 | // { |
2129 | m_log.DebugFormat( | 2203 | // m_log.DebugFormat( |
2130 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 2204 | // "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
2131 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 2205 | // packet.Type, client.Name, m_scene.RegionInfo.RegionName); |
2132 | } | 2206 | // } |
2133 | 2207 | ||
2134 | IncomingPacketsProcessed++; | 2208 | IncomingPacketsProcessed++; |
2135 | } | 2209 | } |
@@ -2141,8 +2215,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2141 | if (!client.IsLoggingOut) | 2215 | if (!client.IsLoggingOut) |
2142 | { | 2216 | { |
2143 | client.IsLoggingOut = true; | 2217 | client.IsLoggingOut = true; |
2144 | client.Close(); | 2218 | client.Close(false, false); |
2145 | } | 2219 | } |
2146 | } | 2220 | } |
2147 | } | 2221 | } |
2148 | } \ No newline at end of file | 2222 | } |