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.cs218
1 files changed, 197 insertions, 21 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index d11fcbf..b3db064 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -110,7 +110,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
110 /// <summary>Handlers for incoming packets</summary> 110 /// <summary>Handlers for incoming packets</summary>
111 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 111 //PacketEventDictionary packetEvents = new PacketEventDictionary();
112 /// <summary>Incoming packets that are awaiting handling</summary> 112 /// <summary>Incoming packets that are awaiting handling</summary>
113 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 113 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
114
115 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
116
114 /// <summary></summary> 117 /// <summary></summary>
115 //private UDPClientCollection m_clients = new UDPClientCollection(); 118 //private UDPClientCollection m_clients = new UDPClientCollection();
116 /// <summary>Bandwidth throttle for this UDP server</summary> 119 /// <summary>Bandwidth throttle for this UDP server</summary>
@@ -155,6 +158,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
155 /// <summary>Flag to signal when clients should send pings</summary> 158 /// <summary>Flag to signal when clients should send pings</summary>
156 protected bool m_sendPing; 159 protected bool m_sendPing;
157 160
161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
162
158 private int m_defaultRTO = 0; 163 private int m_defaultRTO = 0;
159 private int m_maxRTO = 0; 164 private int m_maxRTO = 0;
160 private int m_ackTimeout = 0; 165 private int m_ackTimeout = 0;
@@ -774,19 +779,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
774 779
775 #region Packet to Client Mapping 780 #region Packet to Client Mapping
776 781
777 // UseCircuitCode handling 782 // If there is already a client for this endpoint, don't process UseCircuitCode
778 if (packet.Type == PacketType.UseCircuitCode) 783 IClientAPI client = null;
784 if (!m_scene.TryGetClient(address, out client))
779 { 785 {
780 object[] array = new object[] { buffer, packet }; 786 // UseCircuitCode handling
787 if (packet.Type == PacketType.UseCircuitCode)
788 {
789 // And if there is a UseCircuitCode pending, also drop it
790 lock (m_pendingCache)
791 {
792 if (m_pendingCache.Contains(address))
793 return;
781 794
782 Util.FireAndForget(HandleUseCircuitCode, array); 795 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60);
796 }
783 797
784 return; 798 object[] array = new object[] { buffer, packet };
799
800 Util.FireAndForget(HandleUseCircuitCode, array);
801
802 return;
803 }
804 }
805
806 // If this is a pending connection, enqueue, don't process yet
807 lock (m_pendingCache)
808 {
809 Queue<UDPPacketBuffer> queue;
810 if (m_pendingCache.TryGetValue(address, out queue))
811 {
812 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
813 queue.Enqueue(buffer);
814 return;
815 }
785 } 816 }
786 817
787 // Determine which agent this packet came from 818 // Determine which agent this packet came from
788 IClientAPI client; 819 if (client == null || !(client is LLClientView))
789 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
790 { 820 {
791 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 821 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
792 return; 822 return;
@@ -795,7 +825,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
795 udpClient = ((LLClientView)client).UDPClient; 825 udpClient = ((LLClientView)client).UDPClient;
796 826
797 if (!udpClient.IsConnected) 827 if (!udpClient.IsConnected)
828 {
829// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
798 return; 830 return;
831 }
799 832
800 #endregion Packet to Client Mapping 833 #endregion Packet to Client Mapping
801 834
@@ -898,7 +931,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
898 #endregion Ping Check Handling 931 #endregion Ping Check Handling
899 932
900 // Inbox insertion 933 // Inbox insertion
901 packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); 934 if (packet.Type == PacketType.AgentUpdate ||
935 packet.Type == PacketType.ChatFromViewer)
936 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
937 else
938 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
939// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
902 } 940 }
903 941
904 #region BinaryStats 942 #region BinaryStats
@@ -1020,6 +1058,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1020 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1058 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1021 if (client != null) 1059 if (client != null)
1022 client.SceneAgent.SendInitialDataToMe(); 1060 client.SceneAgent.SendInitialDataToMe();
1061
1062 // Now we know we can handle more data
1063 Thread.Sleep(200);
1064
1065 // Obtain the queue and remove it from the cache
1066 Queue<UDPPacketBuffer> queue = null;
1067
1068 lock (m_pendingCache)
1069 {
1070 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue))
1071 {
1072 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1073 return;
1074 }
1075 m_pendingCache.Remove(remoteEndPoint);
1076 }
1077
1078 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1079
1080 // Reinject queued packets
1081 while(queue.Count > 0)
1082 {
1083 UDPPacketBuffer buf = queue.Dequeue();
1084 PacketReceived(buf);
1085 }
1086 queue = null;
1023 } 1087 }
1024 else 1088 else
1025 { 1089 {
@@ -1027,6 +1091,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1027 m_log.WarnFormat( 1091 m_log.WarnFormat(
1028 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1092 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1029 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1093 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
1094 lock (m_pendingCache)
1095 m_pendingCache.Remove(remoteEndPoint);
1030 } 1096 }
1031 1097
1032 // m_log.DebugFormat( 1098 // m_log.DebugFormat(
@@ -1145,7 +1211,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1145 if (!client.SceneAgent.IsChildAgent) 1211 if (!client.SceneAgent.IsChildAgent)
1146 client.Kick("Simulator logged you out due to connection timeout"); 1212 client.Kick("Simulator logged you out due to connection timeout");
1147 1213
1148 client.CloseWithoutChecks(); 1214 client.CloseWithoutChecks(true);
1149 } 1215 }
1150 } 1216 }
1151 1217
@@ -1157,6 +1223,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1157 1223
1158 while (base.IsRunning) 1224 while (base.IsRunning)
1159 { 1225 {
1226 m_scene.ThreadAlive(1);
1160 try 1227 try
1161 { 1228 {
1162 IncomingPacket incomingPacket = null; 1229 IncomingPacket incomingPacket = null;
@@ -1199,6 +1266,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1199 1266
1200 while (base.IsRunning) 1267 while (base.IsRunning)
1201 { 1268 {
1269 m_scene.ThreadAlive(2);
1202 try 1270 try
1203 { 1271 {
1204 m_packetSent = false; 1272 m_packetSent = false;
@@ -1420,8 +1488,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1420 Packet packet = incomingPacket.Packet; 1488 Packet packet = incomingPacket.Packet;
1421 LLClientView client = incomingPacket.Client; 1489 LLClientView client = incomingPacket.Client;
1422 1490
1423 if (client.IsActive) 1491// if (client.IsActive)
1424 { 1492// {
1425 m_currentIncomingClient = client; 1493 m_currentIncomingClient = client;
1426 1494
1427 try 1495 try
@@ -1448,13 +1516,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1448 { 1516 {
1449 m_currentIncomingClient = null; 1517 m_currentIncomingClient = null;
1450 } 1518 }
1451 } 1519// }
1452 else 1520// else
1453 { 1521// {
1454 m_log.DebugFormat( 1522// m_log.DebugFormat(
1455 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1523// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1456 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1524// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1457 } 1525// }
1458 } 1526 }
1459 1527
1460 protected void LogoutHandler(IClientAPI client) 1528 protected void LogoutHandler(IClientAPI client)
@@ -1464,8 +1532,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1464 if (!client.IsLoggingOut) 1532 if (!client.IsLoggingOut)
1465 { 1533 {
1466 client.IsLoggingOut = true; 1534 client.IsLoggingOut = true;
1467 client.Close(); 1535 client.Close(false, false);
1536 }
1537 }
1538 }
1539
1540 internal class DoubleQueue<T> where T:class
1541 {
1542 private Queue<T> m_lowQueue = new Queue<T>();
1543 private Queue<T> m_highQueue = new Queue<T>();
1544
1545 private object m_syncRoot = new object();
1546 private Semaphore m_s = new Semaphore(0, 1);
1547
1548 public DoubleQueue()
1549 {
1550 }
1551
1552 public virtual int Count
1553 {
1554 get { return m_highQueue.Count + m_lowQueue.Count; }
1555 }
1556
1557 public virtual void Enqueue(T data)
1558 {
1559 Enqueue(m_lowQueue, data);
1560 }
1561
1562 public virtual void EnqueueLow(T data)
1563 {
1564 Enqueue(m_lowQueue, data);
1565 }
1566
1567 public virtual void EnqueueHigh(T data)
1568 {
1569 Enqueue(m_highQueue, data);
1570 }
1571
1572 private void Enqueue(Queue<T> q, T data)
1573 {
1574 lock (m_syncRoot)
1575 {
1576 m_lowQueue.Enqueue(data);
1577 m_s.WaitOne(0);
1578 m_s.Release();
1579 }
1580 }
1581
1582 public virtual T Dequeue()
1583 {
1584 return Dequeue(Timeout.Infinite);
1585 }
1586
1587 public virtual T Dequeue(int tmo)
1588 {
1589 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1590 }
1591
1592 public virtual T Dequeue(TimeSpan wait)
1593 {
1594 T res = null;
1595
1596 if (!Dequeue(wait, ref res))
1597 return null;
1598
1599 return res;
1600 }
1601
1602 public bool Dequeue(int timeout, ref T res)
1603 {
1604 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1605 }
1606
1607 public bool Dequeue(TimeSpan wait, ref T res)
1608 {
1609 if (!m_s.WaitOne(wait))
1610 return false;
1611
1612 lock (m_syncRoot)
1613 {
1614 if (m_highQueue.Count > 0)
1615 res = m_highQueue.Dequeue();
1616 else
1617 res = m_lowQueue.Dequeue();
1618
1619 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1620 return true;
1621
1622 try
1623 {
1624 m_s.Release();
1625 }
1626 catch
1627 {
1628 }
1629
1630 return true;
1631 }
1632 }
1633
1634 public virtual void Clear()
1635 {
1636
1637 lock (m_syncRoot)
1638 {
1639 // Make sure sem count is 0
1640 m_s.WaitOne(0);
1641
1642 m_lowQueue.Clear();
1643 m_highQueue.Clear();
1468 } 1644 }
1469 } 1645 }
1470 } 1646 }
1471} \ No newline at end of file 1647}