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.cs217
1 files changed, 196 insertions, 21 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index fc6dd4d..1d304db 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,8 @@ 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>>();
174
171 private int m_defaultRTO = 0; 175 private int m_defaultRTO = 0;
172 private int m_maxRTO = 0; 176 private int m_maxRTO = 0;
173 private int m_ackTimeout = 0; 177 private int m_ackTimeout = 0;
@@ -881,19 +885,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
881 885
882 #region Packet to Client Mapping 886 #region Packet to Client Mapping
883 887
884 // UseCircuitCode handling 888 // If there is already a client for this endpoint, don't process UseCircuitCode
885 if (packet.Type == PacketType.UseCircuitCode) 889 IClientAPI client = null;
890 if (!m_scene.TryGetClient(address, out client))
886 { 891 {
887 object[] array = new object[] { buffer, packet }; 892 // UseCircuitCode handling
893 if (packet.Type == PacketType.UseCircuitCode)
894 {
895 // And if there is a UseCircuitCode pending, also drop it
896 lock (m_pendingCache)
897 {
898 if (m_pendingCache.Contains(address))
899 return;
900
901 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60);
902 }
888 903
889 Util.FireAndForget(HandleUseCircuitCode, array); 904 object[] array = new object[] { buffer, packet };
890 905
891 return; 906 Util.FireAndForget(HandleUseCircuitCode, array);
907
908 return;
909 }
910 }
911
912 // If this is a pending connection, enqueue, don't process yet
913 lock (m_pendingCache)
914 {
915 Queue<UDPPacketBuffer> queue;
916 if (m_pendingCache.TryGetValue(address, out queue))
917 {
918 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
919 queue.Enqueue(buffer);
920 return;
921 }
892 } 922 }
893 923
894 // Determine which agent this packet came from 924 // Determine which agent this packet came from
895 IClientAPI client; 925 if (client == null || !(client is LLClientView))
896 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
897 { 926 {
898 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 927 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
899 return; 928 return;
@@ -902,7 +931,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
902 udpClient = ((LLClientView)client).UDPClient; 931 udpClient = ((LLClientView)client).UDPClient;
903 932
904 if (!udpClient.IsConnected) 933 if (!udpClient.IsConnected)
934 {
935// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
905 return; 936 return;
937 }
906 938
907 #endregion Packet to Client Mapping 939 #endregion Packet to Client Mapping
908 940
@@ -1005,7 +1037,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1005 #endregion Ping Check Handling 1037 #endregion Ping Check Handling
1006 1038
1007 // Inbox insertion 1039 // Inbox insertion
1008 packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); 1040 if (packet.Type == PacketType.AgentUpdate ||
1041 packet.Type == PacketType.ChatFromViewer)
1042 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
1043 else
1044 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
1045// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
1009 } 1046 }
1010 1047
1011 #region BinaryStats 1048 #region BinaryStats
@@ -1127,6 +1164,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1164 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1128 if (client != null) 1165 if (client != null)
1129 client.SceneAgent.SendInitialDataToMe(); 1166 client.SceneAgent.SendInitialDataToMe();
1167
1168 // Now we know we can handle more data
1169 Thread.Sleep(200);
1170
1171 // Obtain the queue and remove it from the cache
1172 Queue<UDPPacketBuffer> queue = null;
1173
1174 lock (m_pendingCache)
1175 {
1176 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue))
1177 {
1178 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1179 return;
1180 }
1181 m_pendingCache.Remove(remoteEndPoint);
1182 }
1183
1184 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1185
1186 // Reinject queued packets
1187 while(queue.Count > 0)
1188 {
1189 UDPPacketBuffer buf = queue.Dequeue();
1190 PacketReceived(buf);
1191 }
1192 queue = null;
1130 } 1193 }
1131 else 1194 else
1132 { 1195 {
@@ -1134,6 +1197,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1134 m_log.WarnFormat( 1197 m_log.WarnFormat(
1135 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1198 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1136 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1199 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
1200 lock (m_pendingCache)
1201 m_pendingCache.Remove(remoteEndPoint);
1137 } 1202 }
1138 1203
1139 // m_log.DebugFormat( 1204 // m_log.DebugFormat(
@@ -1252,7 +1317,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1252 if (!client.SceneAgent.IsChildAgent) 1317 if (!client.SceneAgent.IsChildAgent)
1253 client.Kick("Simulator logged you out due to connection timeout"); 1318 client.Kick("Simulator logged you out due to connection timeout");
1254 1319
1255 client.CloseWithoutChecks(); 1320 client.CloseWithoutChecks(true);
1256 } 1321 }
1257 } 1322 }
1258 1323
@@ -1264,6 +1329,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1264 1329
1265 while (base.IsRunningInbound) 1330 while (base.IsRunningInbound)
1266 { 1331 {
1332 m_scene.ThreadAlive(1);
1267 try 1333 try
1268 { 1334 {
1269 IncomingPacket incomingPacket = null; 1335 IncomingPacket incomingPacket = null;
@@ -1306,6 +1372,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1306 1372
1307 while (base.IsRunningOutbound) 1373 while (base.IsRunningOutbound)
1308 { 1374 {
1375 m_scene.ThreadAlive(2);
1309 try 1376 try
1310 { 1377 {
1311 m_packetSent = false; 1378 m_packetSent = false;
@@ -1527,8 +1594,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1527 Packet packet = incomingPacket.Packet; 1594 Packet packet = incomingPacket.Packet;
1528 LLClientView client = incomingPacket.Client; 1595 LLClientView client = incomingPacket.Client;
1529 1596
1530 if (client.IsActive) 1597// if (client.IsActive)
1531 { 1598// {
1532 m_currentIncomingClient = client; 1599 m_currentIncomingClient = client;
1533 1600
1534 try 1601 try
@@ -1555,13 +1622,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1555 { 1622 {
1556 m_currentIncomingClient = null; 1623 m_currentIncomingClient = null;
1557 } 1624 }
1558 } 1625// }
1559 else 1626// else
1560 { 1627// {
1561 m_log.DebugFormat( 1628// m_log.DebugFormat(
1562 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1629// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1563 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1630// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1564 } 1631// }
1565 } 1632 }
1566 1633
1567 protected void LogoutHandler(IClientAPI client) 1634 protected void LogoutHandler(IClientAPI client)
@@ -1571,8 +1638,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1571 if (!client.IsLoggingOut) 1638 if (!client.IsLoggingOut)
1572 { 1639 {
1573 client.IsLoggingOut = true; 1640 client.IsLoggingOut = true;
1574 client.Close(); 1641 client.Close(false, false);
1642 }
1643 }
1644 }
1645
1646 internal class DoubleQueue<T> where T:class
1647 {
1648 private Queue<T> m_lowQueue = new Queue<T>();
1649 private Queue<T> m_highQueue = new Queue<T>();
1650
1651 private object m_syncRoot = new object();
1652 private Semaphore m_s = new Semaphore(0, 1);
1653
1654 public DoubleQueue()
1655 {
1656 }
1657
1658 public virtual int Count
1659 {
1660 get { return m_highQueue.Count + m_lowQueue.Count; }
1661 }
1662
1663 public virtual void Enqueue(T data)
1664 {
1665 Enqueue(m_lowQueue, data);
1666 }
1667
1668 public virtual void EnqueueLow(T data)
1669 {
1670 Enqueue(m_lowQueue, data);
1671 }
1672
1673 public virtual void EnqueueHigh(T data)
1674 {
1675 Enqueue(m_highQueue, data);
1676 }
1677
1678 private void Enqueue(Queue<T> q, T data)
1679 {
1680 lock (m_syncRoot)
1681 {
1682 m_lowQueue.Enqueue(data);
1683 m_s.WaitOne(0);
1684 m_s.Release();
1685 }
1686 }
1687
1688 public virtual T Dequeue()
1689 {
1690 return Dequeue(Timeout.Infinite);
1691 }
1692
1693 public virtual T Dequeue(int tmo)
1694 {
1695 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1696 }
1697
1698 public virtual T Dequeue(TimeSpan wait)
1699 {
1700 T res = null;
1701
1702 if (!Dequeue(wait, ref res))
1703 return null;
1704
1705 return res;
1706 }
1707
1708 public bool Dequeue(int timeout, ref T res)
1709 {
1710 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1711 }
1712
1713 public bool Dequeue(TimeSpan wait, ref T res)
1714 {
1715 if (!m_s.WaitOne(wait))
1716 return false;
1717
1718 lock (m_syncRoot)
1719 {
1720 if (m_highQueue.Count > 0)
1721 res = m_highQueue.Dequeue();
1722 else
1723 res = m_lowQueue.Dequeue();
1724
1725 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1726 return true;
1727
1728 try
1729 {
1730 m_s.Release();
1731 }
1732 catch
1733 {
1734 }
1735
1736 return true;
1737 }
1738 }
1739
1740 public virtual void Clear()
1741 {
1742
1743 lock (m_syncRoot)
1744 {
1745 // Make sure sem count is 0
1746 m_s.WaitOne(0);
1747
1748 m_lowQueue.Clear();
1749 m_highQueue.Clear();
1575 } 1750 }
1576 } 1751 }
1577 } 1752 }
1578} \ No newline at end of file 1753}