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 419de66..df4bbb3 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 int m_defaultRTO = 0; 176 private int m_defaultRTO = 0;
@@ -891,21 +894,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP
891 894
892 #region Packet to Client Mapping 895 #region Packet to Client Mapping
893 896
894 // UseCircuitCode handling 897 // If there is already a client for this endpoint, don't process UseCircuitCode
895 if (packet.Type == PacketType.UseCircuitCode) 898 IClientAPI client = null;
899 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
896 { 900 {
897 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 901 // UseCircuitCode handling
898 // buffer. 902 if (packet.Type == PacketType.UseCircuitCode)
899 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 903 {
904 // And if there is a UseCircuitCode pending, also drop it
905 lock (m_pendingCache)
906 {
907 if (m_pendingCache.Contains(endPoint))
908 return;
900 909
901 Util.FireAndForget(HandleUseCircuitCode, array); 910 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
911 }
902 912
903 return; 913 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
914 // buffer.
915 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
916
917 Util.FireAndForget(HandleUseCircuitCode, array);
918
919 return;
920 }
921 }
922
923 // If this is a pending connection, enqueue, don't process yet
924 lock (m_pendingCache)
925 {
926 Queue<UDPPacketBuffer> queue;
927 if (m_pendingCache.TryGetValue(endPoint, out queue))
928 {
929 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
930 queue.Enqueue(buffer);
931 return;
932 }
904 } 933 }
905 934
906 // Determine which agent this packet came from 935 // Determine which agent this packet came from
907 IClientAPI client; 936 if (client == null || !(client is LLClientView))
908 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
909 { 937 {
910 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 938 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
911 return; 939 return;
@@ -914,7 +942,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
914 udpClient = ((LLClientView)client).UDPClient; 942 udpClient = ((LLClientView)client).UDPClient;
915 943
916 if (!udpClient.IsConnected) 944 if (!udpClient.IsConnected)
945 {
946// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
917 return; 947 return;
948 }
918 949
919 #endregion Packet to Client Mapping 950 #endregion Packet to Client Mapping
920 951
@@ -1044,7 +1075,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1044 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1075 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1045 } 1076 }
1046 1077
1047 packetInbox.Enqueue(incomingPacket); 1078 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1079 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1080 packetInbox.EnqueueHigh(incomingPacket);
1081 else
1082 packetInbox.EnqueueLow(incomingPacket);
1048 } 1083 }
1049 1084
1050 #region BinaryStats 1085 #region BinaryStats
@@ -1164,6 +1199,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1164 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1199 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1165 if (client != null) 1200 if (client != null)
1166 client.SceneAgent.SendInitialDataToMe(); 1201 client.SceneAgent.SendInitialDataToMe();
1202
1203 // Now we know we can handle more data
1204 Thread.Sleep(200);
1205
1206 // Obtain the queue and remove it from the cache
1207 Queue<UDPPacketBuffer> queue = null;
1208
1209 lock (m_pendingCache)
1210 {
1211 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1212 {
1213 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1214 return;
1215 }
1216 m_pendingCache.Remove(endPoint);
1217 }
1218
1219 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1220
1221 // Reinject queued packets
1222 while(queue.Count > 0)
1223 {
1224 UDPPacketBuffer buf = queue.Dequeue();
1225 PacketReceived(buf);
1226 }
1227 queue = null;
1167 } 1228 }
1168 else 1229 else
1169 { 1230 {
@@ -1171,6 +1232,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1171 m_log.WarnFormat( 1232 m_log.WarnFormat(
1172 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1233 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1173 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1234 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1235 lock (m_pendingCache)
1236 m_pendingCache.Remove(endPoint);
1174 } 1237 }
1175 1238
1176 // m_log.DebugFormat( 1239 // m_log.DebugFormat(
@@ -1289,7 +1352,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1289 if (!client.SceneAgent.IsChildAgent) 1352 if (!client.SceneAgent.IsChildAgent)
1290 client.Kick("Simulator logged you out due to connection timeout"); 1353 client.Kick("Simulator logged you out due to connection timeout");
1291 1354
1292 client.CloseWithoutChecks(); 1355 client.CloseWithoutChecks(true);
1293 } 1356 }
1294 } 1357 }
1295 1358
@@ -1301,6 +1364,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1301 1364
1302 while (IsRunningInbound) 1365 while (IsRunningInbound)
1303 { 1366 {
1367 m_scene.ThreadAlive(1);
1304 try 1368 try
1305 { 1369 {
1306 IncomingPacket incomingPacket = null; 1370 IncomingPacket incomingPacket = null;
@@ -1348,6 +1412,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1348 1412
1349 while (base.IsRunningOutbound) 1413 while (base.IsRunningOutbound)
1350 { 1414 {
1415 m_scene.ThreadAlive(2);
1351 try 1416 try
1352 { 1417 {
1353 m_packetSent = false; 1418 m_packetSent = false;
@@ -1569,8 +1634,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1569 Packet packet = incomingPacket.Packet; 1634 Packet packet = incomingPacket.Packet;
1570 LLClientView client = incomingPacket.Client; 1635 LLClientView client = incomingPacket.Client;
1571 1636
1572 if (client.IsActive) 1637// if (client.IsActive)
1573 { 1638// {
1574 m_currentIncomingClient = client; 1639 m_currentIncomingClient = client;
1575 1640
1576 try 1641 try
@@ -1597,13 +1662,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1597 { 1662 {
1598 m_currentIncomingClient = null; 1663 m_currentIncomingClient = null;
1599 } 1664 }
1600 } 1665// }
1601 else 1666// else
1602 { 1667// {
1603 m_log.DebugFormat( 1668// m_log.DebugFormat(
1604 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1669// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1605 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1670// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1606 } 1671// }
1607 } 1672 }
1608 1673
1609 protected void LogoutHandler(IClientAPI client) 1674 protected void LogoutHandler(IClientAPI client)
@@ -1613,8 +1678,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1613 if (!client.IsLoggingOut) 1678 if (!client.IsLoggingOut)
1614 { 1679 {
1615 client.IsLoggingOut = true; 1680 client.IsLoggingOut = true;
1616 client.Close(); 1681 client.Close(false, false);
1682 }
1683 }
1684 }
1685
1686 internal class DoubleQueue<T> where T:class
1687 {
1688 private Queue<T> m_lowQueue = new Queue<T>();
1689 private Queue<T> m_highQueue = new Queue<T>();
1690
1691 private object m_syncRoot = new object();
1692 private Semaphore m_s = new Semaphore(0, 1);
1693
1694 public DoubleQueue()
1695 {
1696 }
1697
1698 public virtual int Count
1699 {
1700 get { return m_highQueue.Count + m_lowQueue.Count; }
1701 }
1702
1703 public virtual void Enqueue(T data)
1704 {
1705 Enqueue(m_lowQueue, data);
1706 }
1707
1708 public virtual void EnqueueLow(T data)
1709 {
1710 Enqueue(m_lowQueue, data);
1711 }
1712
1713 public virtual void EnqueueHigh(T data)
1714 {
1715 Enqueue(m_highQueue, data);
1716 }
1717
1718 private void Enqueue(Queue<T> q, T data)
1719 {
1720 lock (m_syncRoot)
1721 {
1722 m_lowQueue.Enqueue(data);
1723 m_s.WaitOne(0);
1724 m_s.Release();
1725 }
1726 }
1727
1728 public virtual T Dequeue()
1729 {
1730 return Dequeue(Timeout.Infinite);
1731 }
1732
1733 public virtual T Dequeue(int tmo)
1734 {
1735 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1736 }
1737
1738 public virtual T Dequeue(TimeSpan wait)
1739 {
1740 T res = null;
1741
1742 if (!Dequeue(wait, ref res))
1743 return null;
1744
1745 return res;
1746 }
1747
1748 public bool Dequeue(int timeout, ref T res)
1749 {
1750 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1751 }
1752
1753 public bool Dequeue(TimeSpan wait, ref T res)
1754 {
1755 if (!m_s.WaitOne(wait))
1756 return false;
1757
1758 lock (m_syncRoot)
1759 {
1760 if (m_highQueue.Count > 0)
1761 res = m_highQueue.Dequeue();
1762 else
1763 res = m_lowQueue.Dequeue();
1764
1765 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1766 return true;
1767
1768 try
1769 {
1770 m_s.Release();
1771 }
1772 catch
1773 {
1774 }
1775
1776 return true;
1777 }
1778 }
1779
1780 public virtual void Clear()
1781 {
1782
1783 lock (m_syncRoot)
1784 {
1785 // Make sure sem count is 0
1786 m_s.WaitOne(0);
1787
1788 m_lowQueue.Clear();
1789 m_highQueue.Clear();
1617 } 1790 }
1618 } 1791 }
1619 } 1792 }
1620} \ No newline at end of file 1793}