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 25e10be..544b54b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -168,7 +168,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
168 | /// <summary>Handlers for incoming packets</summary> | 168 | /// <summary>Handlers for incoming packets</summary> |
169 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | 169 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); |
170 | /// <summary>Incoming packets that are awaiting handling</summary> | 170 | /// <summary>Incoming packets that are awaiting handling</summary> |
171 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | 171 | //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); |
172 | |||
173 | private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>(); | ||
172 | 174 | ||
173 | /// <summary></summary> | 175 | /// <summary></summary> |
174 | //private UDPClientCollection m_clients = new UDPClientCollection(); | 176 | //private UDPClientCollection m_clients = new UDPClientCollection(); |
@@ -223,6 +225,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
223 | /// <summary>Flag to signal when clients should send pings</summary> | 225 | /// <summary>Flag to signal when clients should send pings</summary> |
224 | protected bool m_sendPing; | 226 | protected bool m_sendPing; |
225 | 227 | ||
228 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | ||
229 | |||
226 | /// <summary> | 230 | /// <summary> |
227 | /// Event used to signal when queued packets are available for sending. | 231 | /// Event used to signal when queued packets are available for sending. |
228 | /// </summary> | 232 | /// </summary> |
@@ -961,6 +965,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
961 | 965 | ||
962 | #region Queue or Send | 966 | #region Queue or Send |
963 | 967 | ||
968 | bool highPriority = false; | ||
969 | |||
970 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) | ||
971 | { | ||
972 | category = (ThrottleOutPacketType)((int)category & 127); | ||
973 | highPriority = true; | ||
974 | } | ||
975 | |||
964 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | 976 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); |
965 | // If we were not provided a method for handling unacked, use the UDPServer default method | 977 | // If we were not provided a method for handling unacked, use the UDPServer default method |
966 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | 978 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); |
@@ -969,7 +981,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
969 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object | 981 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object |
970 | // packet so that it isn't sent before a queued update packet. | 982 | // packet so that it isn't sent before a queued update packet. |
971 | bool requestQueue = type == PacketType.KillObject; | 983 | bool requestQueue = type == PacketType.KillObject; |
972 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) | 984 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) |
973 | SendPacketFinal(outgoingPacket); | 985 | SendPacketFinal(outgoingPacket); |
974 | 986 | ||
975 | #endregion Queue or Send | 987 | #endregion Queue or Send |
@@ -1254,34 +1266,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1254 | 1266 | ||
1255 | #region Packet to Client Mapping | 1267 | #region Packet to Client Mapping |
1256 | 1268 | ||
1257 | // UseCircuitCode handling | 1269 | // If there is already a client for this endpoint, don't process UseCircuitCode |
1258 | if (packet.Type == PacketType.UseCircuitCode) | 1270 | IClientAPI client = null; |
1271 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1259 | { | 1272 | { |
1260 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1273 | // UseCircuitCode handling |
1261 | // buffer. | 1274 | if (packet.Type == PacketType.UseCircuitCode) |
1262 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1275 | { |
1276 | // And if there is a UseCircuitCode pending, also drop it | ||
1277 | lock (m_pendingCache) | ||
1278 | { | ||
1279 | if (m_pendingCache.Contains(endPoint)) | ||
1280 | return; | ||
1263 | 1281 | ||
1264 | Util.FireAndForget(HandleUseCircuitCode, array); | 1282 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); |
1283 | } | ||
1265 | 1284 | ||
1266 | return; | 1285 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1286 | // buffer. | ||
1287 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1288 | |||
1289 | Util.FireAndForget(HandleUseCircuitCode, array); | ||
1290 | |||
1291 | return; | ||
1292 | } | ||
1267 | } | 1293 | } |
1268 | else if (packet.Type == PacketType.CompleteAgentMovement) | 1294 | |
1295 | // If this is a pending connection, enqueue, don't process yet | ||
1296 | lock (m_pendingCache) | ||
1269 | { | 1297 | { |
1270 | // Send ack straight away to let the viewer know that we got it. | 1298 | Queue<UDPPacketBuffer> queue; |
1271 | SendAckImmediate(endPoint, packet.Header.Sequence); | 1299 | if (m_pendingCache.TryGetValue(endPoint, out queue)) |
1300 | { | ||
1301 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); | ||
1302 | queue.Enqueue(buffer); | ||
1303 | return; | ||
1304 | } | ||
1305 | else if (packet.Type == PacketType.CompleteAgentMovement) | ||
1306 | { | ||
1307 | // Send ack straight away to let the viewer know that we got it. | ||
1308 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1272 | 1309 | ||
1273 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1310 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1274 | // buffer. | 1311 | // buffer. |
1275 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1312 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; |
1276 | 1313 | ||
1277 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | 1314 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); |
1278 | 1315 | ||
1279 | return; | 1316 | return; |
1317 | } | ||
1280 | } | 1318 | } |
1281 | 1319 | ||
1282 | // Determine which agent this packet came from | 1320 | // Determine which agent this packet came from |
1283 | IClientAPI client; | 1321 | if (client == null || !(client is LLClientView)) |
1284 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1285 | { | 1322 | { |
1286 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 1323 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
1287 | return; | 1324 | return; |
@@ -1290,7 +1327,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1290 | udpClient = ((LLClientView)client).UDPClient; | 1327 | udpClient = ((LLClientView)client).UDPClient; |
1291 | 1328 | ||
1292 | if (!udpClient.IsConnected) | 1329 | if (!udpClient.IsConnected) |
1330 | { | ||
1331 | m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName); | ||
1293 | return; | 1332 | return; |
1333 | } | ||
1294 | 1334 | ||
1295 | #endregion Packet to Client Mapping | 1335 | #endregion Packet to Client Mapping |
1296 | 1336 | ||
@@ -1439,7 +1479,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1439 | incomingPacket = new IncomingPacket((LLClientView)client, packet); | 1479 | incomingPacket = new IncomingPacket((LLClientView)client, packet); |
1440 | } | 1480 | } |
1441 | 1481 | ||
1442 | packetInbox.Enqueue(incomingPacket); | 1482 | if (incomingPacket.Packet.Type == PacketType.AgentUpdate || |
1483 | incomingPacket.Packet.Type == PacketType.ChatFromViewer) | ||
1484 | packetInbox.EnqueueHigh(incomingPacket); | ||
1485 | else | ||
1486 | packetInbox.EnqueueLow(incomingPacket); | ||
1443 | } | 1487 | } |
1444 | 1488 | ||
1445 | #region BinaryStats | 1489 | #region BinaryStats |
@@ -1591,6 +1635,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1591 | if (!tp) | 1635 | if (!tp) |
1592 | client.SceneAgent.SendInitialDataToMe(); | 1636 | client.SceneAgent.SendInitialDataToMe(); |
1593 | } | 1637 | } |
1638 | |||
1639 | // Now we know we can handle more data | ||
1640 | Thread.Sleep(200); | ||
1641 | |||
1642 | // Obtain the queue and remove it from the cache | ||
1643 | Queue<UDPPacketBuffer> queue = null; | ||
1644 | |||
1645 | lock (m_pendingCache) | ||
1646 | { | ||
1647 | if (!m_pendingCache.TryGetValue(endPoint, out queue)) | ||
1648 | { | ||
1649 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); | ||
1650 | return; | ||
1651 | } | ||
1652 | m_pendingCache.Remove(endPoint); | ||
1653 | } | ||
1654 | |||
1655 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); | ||
1656 | |||
1657 | // Reinject queued packets | ||
1658 | while(queue.Count > 0) | ||
1659 | { | ||
1660 | UDPPacketBuffer buf = queue.Dequeue(); | ||
1661 | PacketReceived(buf); | ||
1662 | } | ||
1663 | queue = null; | ||
1594 | } | 1664 | } |
1595 | else | 1665 | else |
1596 | { | 1666 | { |
@@ -1598,6 +1668,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1598 | m_log.WarnFormat( | 1668 | m_log.WarnFormat( |
1599 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1669 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1600 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | 1670 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1671 | lock (m_pendingCache) | ||
1672 | m_pendingCache.Remove(endPoint); | ||
1601 | } | 1673 | } |
1602 | 1674 | ||
1603 | // m_log.DebugFormat( | 1675 | // m_log.DebugFormat( |
@@ -1783,7 +1855,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1783 | if (!client.SceneAgent.IsChildAgent) | 1855 | if (!client.SceneAgent.IsChildAgent) |
1784 | client.Kick("Simulator logged you out due to connection timeout"); | 1856 | client.Kick("Simulator logged you out due to connection timeout"); |
1785 | 1857 | ||
1786 | client.CloseWithoutChecks(); | 1858 | client.CloseWithoutChecks(true); |
1787 | } | 1859 | } |
1788 | } | 1860 | } |
1789 | 1861 | ||
@@ -1795,6 +1867,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1795 | 1867 | ||
1796 | while (IsRunningInbound) | 1868 | while (IsRunningInbound) |
1797 | { | 1869 | { |
1870 | m_scene.ThreadAlive(1); | ||
1798 | try | 1871 | try |
1799 | { | 1872 | { |
1800 | IncomingPacket incomingPacket = null; | 1873 | IncomingPacket incomingPacket = null; |
@@ -1844,6 +1917,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1844 | 1917 | ||
1845 | while (base.IsRunningOutbound) | 1918 | while (base.IsRunningOutbound) |
1846 | { | 1919 | { |
1920 | m_scene.ThreadAlive(2); | ||
1847 | try | 1921 | try |
1848 | { | 1922 | { |
1849 | m_packetSent = false; | 1923 | m_packetSent = false; |
@@ -2078,8 +2152,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2078 | Packet packet = incomingPacket.Packet; | 2152 | Packet packet = incomingPacket.Packet; |
2079 | LLClientView client = incomingPacket.Client; | 2153 | LLClientView client = incomingPacket.Client; |
2080 | 2154 | ||
2081 | if (client.IsActive) | 2155 | // if (client.IsActive) |
2082 | { | 2156 | // { |
2083 | m_currentIncomingClient = client; | 2157 | m_currentIncomingClient = client; |
2084 | 2158 | ||
2085 | try | 2159 | try |
@@ -2106,13 +2180,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2106 | { | 2180 | { |
2107 | m_currentIncomingClient = null; | 2181 | m_currentIncomingClient = null; |
2108 | } | 2182 | } |
2109 | } | 2183 | // } |
2110 | else | 2184 | // else |
2111 | { | 2185 | // { |
2112 | m_log.DebugFormat( | 2186 | // m_log.DebugFormat( |
2113 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 2187 | // "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
2114 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 2188 | // packet.Type, client.Name, m_scene.RegionInfo.RegionName); |
2115 | } | 2189 | // } |
2116 | 2190 | ||
2117 | IncomingPacketsProcessed++; | 2191 | IncomingPacketsProcessed++; |
2118 | } | 2192 | } |
@@ -2124,8 +2198,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2124 | if (!client.IsLoggingOut) | 2198 | if (!client.IsLoggingOut) |
2125 | { | 2199 | { |
2126 | client.IsLoggingOut = true; | 2200 | client.IsLoggingOut = true; |
2127 | client.Close(); | 2201 | client.Close(false, false); |
2128 | } | 2202 | } |
2129 | } | 2203 | } |
2130 | } | 2204 | } |
2131 | } \ No newline at end of file | 2205 | } |