aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs219
1 files changed, 196 insertions, 23 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 14cc863..b8951d9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -113,7 +113,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
113 /// <summary>Handlers for incoming packets</summary> 113 /// <summary>Handlers for incoming packets</summary>
114 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 114 //PacketEventDictionary packetEvents = new PacketEventDictionary();
115 /// <summary>Incoming packets that are awaiting handling</summary> 115 /// <summary>Incoming packets that are awaiting handling</summary>
116 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 116 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
117
118 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
117 119
118 /// <summary></summary> 120 /// <summary></summary>
119 //private UDPClientCollection m_clients = new UDPClientCollection(); 121 //private UDPClientCollection m_clients = new UDPClientCollection();
@@ -168,6 +170,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
168 /// <summary>Flag to signal when clients should send pings</summary> 170 /// <summary>Flag to signal when clients should send pings</summary>
169 protected bool m_sendPing; 171 protected bool m_sendPing;
170 172
173 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
171 private Pool<IncomingPacket> m_incomingPacketPool; 174 private Pool<IncomingPacket> m_incomingPacketPool;
172 175
173 private Stat m_incomingPacketPoolStat; 176 private Stat m_incomingPacketPoolStat;
@@ -974,21 +977,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP
974 977
975 #region Packet to Client Mapping 978 #region Packet to Client Mapping
976 979
977 // UseCircuitCode handling 980 // If there is already a client for this endpoint, don't process UseCircuitCode
978 if (packet.Type == PacketType.UseCircuitCode) 981 IClientAPI client = null;
982 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
979 { 983 {
980 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 984 // UseCircuitCode handling
981 // buffer. 985 if (packet.Type == PacketType.UseCircuitCode)
982 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 986 {
987 // And if there is a UseCircuitCode pending, also drop it
988 lock (m_pendingCache)
989 {
990 if (m_pendingCache.Contains(endPoint))
991 return;
983 992
984 Util.FireAndForget(HandleUseCircuitCode, array); 993 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
994 }
985 995
986 return; 996 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
997 // buffer.
998 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
999
1000 Util.FireAndForget(HandleUseCircuitCode, array);
1001
1002 return;
1003 }
1004 }
1005
1006 // If this is a pending connection, enqueue, don't process yet
1007 lock (m_pendingCache)
1008 {
1009 Queue<UDPPacketBuffer> queue;
1010 if (m_pendingCache.TryGetValue(endPoint, out queue))
1011 {
1012 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1013 queue.Enqueue(buffer);
1014 return;
1015 }
987 } 1016 }
988 1017
989 // Determine which agent this packet came from 1018 // Determine which agent this packet came from
990 IClientAPI client; 1019 if (client == null || !(client is LLClientView))
991 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
992 { 1020 {
993 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1021 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
994 return; 1022 return;
@@ -997,7 +1025,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
997 udpClient = ((LLClientView)client).UDPClient; 1025 udpClient = ((LLClientView)client).UDPClient;
998 1026
999 if (!udpClient.IsConnected) 1027 if (!udpClient.IsConnected)
1028 {
1029// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
1000 return; 1030 return;
1031 }
1001 1032
1002 #endregion Packet to Client Mapping 1033 #endregion Packet to Client Mapping
1003 1034
@@ -1127,7 +1158,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1158 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1128 } 1159 }
1129 1160
1130 packetInbox.Enqueue(incomingPacket); 1161 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1162 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1163 packetInbox.EnqueueHigh(incomingPacket);
1164 else
1165 packetInbox.EnqueueLow(incomingPacket);
1131 } 1166 }
1132 1167
1133 #region BinaryStats 1168 #region BinaryStats
@@ -1247,6 +1282,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1247 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1282 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1248 if (client != null) 1283 if (client != null)
1249 client.SceneAgent.SendInitialDataToMe(); 1284 client.SceneAgent.SendInitialDataToMe();
1285
1286 // Now we know we can handle more data
1287 Thread.Sleep(200);
1288
1289 // Obtain the queue and remove it from the cache
1290 Queue<UDPPacketBuffer> queue = null;
1291
1292 lock (m_pendingCache)
1293 {
1294 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1295 {
1296 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1297 return;
1298 }
1299 m_pendingCache.Remove(endPoint);
1300 }
1301
1302 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1303
1304 // Reinject queued packets
1305 while(queue.Count > 0)
1306 {
1307 UDPPacketBuffer buf = queue.Dequeue();
1308 PacketReceived(buf);
1309 }
1310 queue = null;
1250 } 1311 }
1251 else 1312 else
1252 { 1313 {
@@ -1254,6 +1315,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1254 m_log.WarnFormat( 1315 m_log.WarnFormat(
1255 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1316 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1256 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1317 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1318 lock (m_pendingCache)
1319 m_pendingCache.Remove(endPoint);
1257 } 1320 }
1258 1321
1259 // m_log.DebugFormat( 1322 // m_log.DebugFormat(
@@ -1372,7 +1435,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1372 if (!client.SceneAgent.IsChildAgent) 1435 if (!client.SceneAgent.IsChildAgent)
1373 client.Kick("Simulator logged you out due to connection timeout"); 1436 client.Kick("Simulator logged you out due to connection timeout");
1374 1437
1375 client.CloseWithoutChecks(); 1438 client.CloseWithoutChecks(true);
1376 } 1439 }
1377 } 1440 }
1378 1441
@@ -1384,6 +1447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1384 1447
1385 while (IsRunningInbound) 1448 while (IsRunningInbound)
1386 { 1449 {
1450 m_scene.ThreadAlive(1);
1387 try 1451 try
1388 { 1452 {
1389 IncomingPacket incomingPacket = null; 1453 IncomingPacket incomingPacket = null;
@@ -1431,6 +1495,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1431 1495
1432 while (base.IsRunningOutbound) 1496 while (base.IsRunningOutbound)
1433 { 1497 {
1498 m_scene.ThreadAlive(2);
1434 try 1499 try
1435 { 1500 {
1436 m_packetSent = false; 1501 m_packetSent = false;
@@ -1652,8 +1717,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1652 Packet packet = incomingPacket.Packet; 1717 Packet packet = incomingPacket.Packet;
1653 LLClientView client = incomingPacket.Client; 1718 LLClientView client = incomingPacket.Client;
1654 1719
1655 if (client.IsActive) 1720// if (client.IsActive)
1656 { 1721// {
1657 m_currentIncomingClient = client; 1722 m_currentIncomingClient = client;
1658 1723
1659 try 1724 try
@@ -1680,13 +1745,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1680 { 1745 {
1681 m_currentIncomingClient = null; 1746 m_currentIncomingClient = null;
1682 } 1747 }
1683 } 1748// }
1684 else 1749// else
1685 { 1750// {
1686 m_log.DebugFormat( 1751// m_log.DebugFormat(
1687 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1752// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1688 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1753// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1689 } 1754// }
1690 } 1755 }
1691 1756
1692 protected void LogoutHandler(IClientAPI client) 1757 protected void LogoutHandler(IClientAPI client)
@@ -1696,8 +1761,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1696 if (!client.IsLoggingOut) 1761 if (!client.IsLoggingOut)
1697 { 1762 {
1698 client.IsLoggingOut = true; 1763 client.IsLoggingOut = true;
1699 client.Close(); 1764 client.Close(false, false);
1765 }
1766 }
1767 }
1768
1769 internal class DoubleQueue<T> where T:class
1770 {
1771 private Queue<T> m_lowQueue = new Queue<T>();
1772 private Queue<T> m_highQueue = new Queue<T>();
1773
1774 private object m_syncRoot = new object();
1775 private Semaphore m_s = new Semaphore(0, 1);
1776
1777 public DoubleQueue()
1778 {
1779 }
1780
1781 public virtual int Count
1782 {
1783 get { return m_highQueue.Count + m_lowQueue.Count; }
1784 }
1785
1786 public virtual void Enqueue(T data)
1787 {
1788 Enqueue(m_lowQueue, data);
1789 }
1790
1791 public virtual void EnqueueLow(T data)
1792 {
1793 Enqueue(m_lowQueue, data);
1794 }
1795
1796 public virtual void EnqueueHigh(T data)
1797 {
1798 Enqueue(m_highQueue, data);
1799 }
1800
1801 private void Enqueue(Queue<T> q, T data)
1802 {
1803 lock (m_syncRoot)
1804 {
1805 m_lowQueue.Enqueue(data);
1806 m_s.WaitOne(0);
1807 m_s.Release();
1808 }
1809 }
1810
1811 public virtual T Dequeue()
1812 {
1813 return Dequeue(Timeout.Infinite);
1814 }
1815
1816 public virtual T Dequeue(int tmo)
1817 {
1818 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1819 }
1820
1821 public virtual T Dequeue(TimeSpan wait)
1822 {
1823 T res = null;
1824
1825 if (!Dequeue(wait, ref res))
1826 return null;
1827
1828 return res;
1829 }
1830
1831 public bool Dequeue(int timeout, ref T res)
1832 {
1833 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1834 }
1835
1836 public bool Dequeue(TimeSpan wait, ref T res)
1837 {
1838 if (!m_s.WaitOne(wait))
1839 return false;
1840
1841 lock (m_syncRoot)
1842 {
1843 if (m_highQueue.Count > 0)
1844 res = m_highQueue.Dequeue();
1845 else
1846 res = m_lowQueue.Dequeue();
1847
1848 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1849 return true;
1850
1851 try
1852 {
1853 m_s.Release();
1854 }
1855 catch
1856 {
1857 }
1858
1859 return true;
1860 }
1861 }
1862
1863 public virtual void Clear()
1864 {
1865
1866 lock (m_syncRoot)
1867 {
1868 // Make sure sem count is 0
1869 m_s.WaitOne(0);
1870
1871 m_lowQueue.Clear();
1872 m_highQueue.Clear();
1700 } 1873 }
1701 } 1874 }
1702 } 1875 }
1703} \ No newline at end of file 1876}