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 e3f4679..97b79ce 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -112,7 +112,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
112 /// <summary>Handlers for incoming packets</summary> 112 /// <summary>Handlers for incoming packets</summary>
113 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 113 //PacketEventDictionary packetEvents = new PacketEventDictionary();
114 /// <summary>Incoming packets that are awaiting handling</summary> 114 /// <summary>Incoming packets that are awaiting handling</summary>
115 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 115 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
116
117 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
116 118
117 /// <summary></summary> 119 /// <summary></summary>
118 //private UDPClientCollection m_clients = new UDPClientCollection(); 120 //private UDPClientCollection m_clients = new UDPClientCollection();
@@ -167,6 +169,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
167 /// <summary>Flag to signal when clients should send pings</summary> 169 /// <summary>Flag to signal when clients should send pings</summary>
168 protected bool m_sendPing; 170 protected bool m_sendPing;
169 171
172 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
173
170 private int m_defaultRTO = 0; 174 private int m_defaultRTO = 0;
171 private int m_maxRTO = 0; 175 private int m_maxRTO = 0;
172 private int m_ackTimeout = 0; 176 private int m_ackTimeout = 0;
@@ -793,19 +797,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
793 797
794 #region Packet to Client Mapping 798 #region Packet to Client Mapping
795 799
796 // UseCircuitCode handling 800 // If there is already a client for this endpoint, don't process UseCircuitCode
797 if (packet.Type == PacketType.UseCircuitCode) 801 IClientAPI client = null;
802 if (!m_scene.TryGetClient(address, out client))
798 { 803 {
799 object[] array = new object[] { buffer, packet }; 804 // UseCircuitCode handling
805 if (packet.Type == PacketType.UseCircuitCode)
806 {
807 // And if there is a UseCircuitCode pending, also drop it
808 lock (m_pendingCache)
809 {
810 if (m_pendingCache.Contains(address))
811 return;
812
813 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60);
814 }
800 815
801 Util.FireAndForget(HandleUseCircuitCode, array); 816 object[] array = new object[] { buffer, packet };
802 817
803 return; 818 Util.FireAndForget(HandleUseCircuitCode, array);
819
820 return;
821 }
822 }
823
824 // If this is a pending connection, enqueue, don't process yet
825 lock (m_pendingCache)
826 {
827 Queue<UDPPacketBuffer> queue;
828 if (m_pendingCache.TryGetValue(address, out queue))
829 {
830 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
831 queue.Enqueue(buffer);
832 return;
833 }
804 } 834 }
805 835
806 // Determine which agent this packet came from 836 // Determine which agent this packet came from
807 IClientAPI client; 837 if (client == null || !(client is LLClientView))
808 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
809 { 838 {
810 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 839 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
811 return; 840 return;
@@ -814,7 +843,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
814 udpClient = ((LLClientView)client).UDPClient; 843 udpClient = ((LLClientView)client).UDPClient;
815 844
816 if (!udpClient.IsConnected) 845 if (!udpClient.IsConnected)
846 {
847// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
817 return; 848 return;
849 }
818 850
819 #endregion Packet to Client Mapping 851 #endregion Packet to Client Mapping
820 852
@@ -917,7 +949,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
917 #endregion Ping Check Handling 949 #endregion Ping Check Handling
918 950
919 // Inbox insertion 951 // Inbox insertion
920 packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); 952 if (packet.Type == PacketType.AgentUpdate ||
953 packet.Type == PacketType.ChatFromViewer)
954 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
955 else
956 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
957// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
921 } 958 }
922 959
923 #region BinaryStats 960 #region BinaryStats
@@ -1039,6 +1076,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1039 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1076 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1040 if (client != null) 1077 if (client != null)
1041 client.SceneAgent.SendInitialDataToMe(); 1078 client.SceneAgent.SendInitialDataToMe();
1079
1080 // Now we know we can handle more data
1081 Thread.Sleep(200);
1082
1083 // Obtain the queue and remove it from the cache
1084 Queue<UDPPacketBuffer> queue = null;
1085
1086 lock (m_pendingCache)
1087 {
1088 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue))
1089 {
1090 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1091 return;
1092 }
1093 m_pendingCache.Remove(remoteEndPoint);
1094 }
1095
1096 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1097
1098 // Reinject queued packets
1099 while(queue.Count > 0)
1100 {
1101 UDPPacketBuffer buf = queue.Dequeue();
1102 PacketReceived(buf);
1103 }
1104 queue = null;
1042 } 1105 }
1043 else 1106 else
1044 { 1107 {
@@ -1046,6 +1109,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1046 m_log.WarnFormat( 1109 m_log.WarnFormat(
1047 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1110 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1048 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1111 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
1112 lock (m_pendingCache)
1113 m_pendingCache.Remove(remoteEndPoint);
1049 } 1114 }
1050 1115
1051 // m_log.DebugFormat( 1116 // m_log.DebugFormat(
@@ -1164,7 +1229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1164 if (!client.SceneAgent.IsChildAgent) 1229 if (!client.SceneAgent.IsChildAgent)
1165 client.Kick("Simulator logged you out due to connection timeout"); 1230 client.Kick("Simulator logged you out due to connection timeout");
1166 1231
1167 client.CloseWithoutChecks(); 1232 client.CloseWithoutChecks(true);
1168 } 1233 }
1169 } 1234 }
1170 1235
@@ -1176,6 +1241,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1176 1241
1177 while (base.IsRunning) 1242 while (base.IsRunning)
1178 { 1243 {
1244 m_scene.ThreadAlive(1);
1179 try 1245 try
1180 { 1246 {
1181 IncomingPacket incomingPacket = null; 1247 IncomingPacket incomingPacket = null;
@@ -1218,6 +1284,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1218 1284
1219 while (base.IsRunning) 1285 while (base.IsRunning)
1220 { 1286 {
1287 m_scene.ThreadAlive(2);
1221 try 1288 try
1222 { 1289 {
1223 m_packetSent = false; 1290 m_packetSent = false;
@@ -1439,8 +1506,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1439 Packet packet = incomingPacket.Packet; 1506 Packet packet = incomingPacket.Packet;
1440 LLClientView client = incomingPacket.Client; 1507 LLClientView client = incomingPacket.Client;
1441 1508
1442 if (client.IsActive) 1509// if (client.IsActive)
1443 { 1510// {
1444 m_currentIncomingClient = client; 1511 m_currentIncomingClient = client;
1445 1512
1446 try 1513 try
@@ -1467,13 +1534,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1467 { 1534 {
1468 m_currentIncomingClient = null; 1535 m_currentIncomingClient = null;
1469 } 1536 }
1470 } 1537// }
1471 else 1538// else
1472 { 1539// {
1473 m_log.DebugFormat( 1540// m_log.DebugFormat(
1474 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1541// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1475 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1542// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1476 } 1543// }
1477 } 1544 }
1478 1545
1479 protected void LogoutHandler(IClientAPI client) 1546 protected void LogoutHandler(IClientAPI client)
@@ -1483,8 +1550,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1483 if (!client.IsLoggingOut) 1550 if (!client.IsLoggingOut)
1484 { 1551 {
1485 client.IsLoggingOut = true; 1552 client.IsLoggingOut = true;
1486 client.Close(); 1553 client.Close(false, false);
1554 }
1555 }
1556 }
1557
1558 internal class DoubleQueue<T> where T:class
1559 {
1560 private Queue<T> m_lowQueue = new Queue<T>();
1561 private Queue<T> m_highQueue = new Queue<T>();
1562
1563 private object m_syncRoot = new object();
1564 private Semaphore m_s = new Semaphore(0, 1);
1565
1566 public DoubleQueue()
1567 {
1568 }
1569
1570 public virtual int Count
1571 {
1572 get { return m_highQueue.Count + m_lowQueue.Count; }
1573 }
1574
1575 public virtual void Enqueue(T data)
1576 {
1577 Enqueue(m_lowQueue, data);
1578 }
1579
1580 public virtual void EnqueueLow(T data)
1581 {
1582 Enqueue(m_lowQueue, data);
1583 }
1584
1585 public virtual void EnqueueHigh(T data)
1586 {
1587 Enqueue(m_highQueue, data);
1588 }
1589
1590 private void Enqueue(Queue<T> q, T data)
1591 {
1592 lock (m_syncRoot)
1593 {
1594 m_lowQueue.Enqueue(data);
1595 m_s.WaitOne(0);
1596 m_s.Release();
1597 }
1598 }
1599
1600 public virtual T Dequeue()
1601 {
1602 return Dequeue(Timeout.Infinite);
1603 }
1604
1605 public virtual T Dequeue(int tmo)
1606 {
1607 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1608 }
1609
1610 public virtual T Dequeue(TimeSpan wait)
1611 {
1612 T res = null;
1613
1614 if (!Dequeue(wait, ref res))
1615 return null;
1616
1617 return res;
1618 }
1619
1620 public bool Dequeue(int timeout, ref T res)
1621 {
1622 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1623 }
1624
1625 public bool Dequeue(TimeSpan wait, ref T res)
1626 {
1627 if (!m_s.WaitOne(wait))
1628 return false;
1629
1630 lock (m_syncRoot)
1631 {
1632 if (m_highQueue.Count > 0)
1633 res = m_highQueue.Dequeue();
1634 else
1635 res = m_lowQueue.Dequeue();
1636
1637 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1638 return true;
1639
1640 try
1641 {
1642 m_s.Release();
1643 }
1644 catch
1645 {
1646 }
1647
1648 return true;
1649 }
1650 }
1651
1652 public virtual void Clear()
1653 {
1654
1655 lock (m_syncRoot)
1656 {
1657 // Make sure sem count is 0
1658 m_s.WaitOne(0);
1659
1660 m_lowQueue.Clear();
1661 m_highQueue.Clear();
1487 } 1662 }
1488 } 1663 }
1489 } 1664 }
1490} \ No newline at end of file 1665}