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 55780d6..60ab70e 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;
@@ -765,19 +770,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
765 770
766 #region Packet to Client Mapping 771 #region Packet to Client Mapping
767 772
768 // UseCircuitCode handling 773 // If there is already a client for this endpoint, don't process UseCircuitCode
769 if (packet.Type == PacketType.UseCircuitCode) 774 IClientAPI client = null;
775 if (!m_scene.TryGetClient(address, out client))
770 { 776 {
771 object[] array = new object[] { buffer, packet }; 777 // UseCircuitCode handling
778 if (packet.Type == PacketType.UseCircuitCode)
779 {
780 // And if there is a UseCircuitCode pending, also drop it
781 lock (m_pendingCache)
782 {
783 if (m_pendingCache.Contains(address))
784 return;
772 785
773 Util.FireAndForget(HandleUseCircuitCode, array); 786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60);
787 }
774 788
775 return; 789 object[] array = new object[] { buffer, packet };
790
791 Util.FireAndForget(HandleUseCircuitCode, array);
792
793 return;
794 }
795 }
796
797 // If this is a pending connection, enqueue, don't process yet
798 lock (m_pendingCache)
799 {
800 Queue<UDPPacketBuffer> queue;
801 if (m_pendingCache.TryGetValue(address, out queue))
802 {
803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
804 queue.Enqueue(buffer);
805 return;
806 }
776 } 807 }
777 808
778 // Determine which agent this packet came from 809 // Determine which agent this packet came from
779 IClientAPI client; 810 if (client == null || !(client is LLClientView))
780 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
781 { 811 {
782 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 812 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
783 return; 813 return;
@@ -786,7 +816,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
786 udpClient = ((LLClientView)client).UDPClient; 816 udpClient = ((LLClientView)client).UDPClient;
787 817
788 if (!udpClient.IsConnected) 818 if (!udpClient.IsConnected)
819 {
820// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
789 return; 821 return;
822 }
790 823
791 #endregion Packet to Client Mapping 824 #endregion Packet to Client Mapping
792 825
@@ -889,7 +922,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
889 #endregion Ping Check Handling 922 #endregion Ping Check Handling
890 923
891 // Inbox insertion 924 // Inbox insertion
892 packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); 925 if (packet.Type == PacketType.AgentUpdate ||
926 packet.Type == PacketType.ChatFromViewer)
927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
928 else
929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
893 } 931 }
894 932
895 #region BinaryStats 933 #region BinaryStats
@@ -1011,6 +1049,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1011 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1049 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1012 if (client != null) 1050 if (client != null)
1013 client.SceneAgent.SendInitialDataToMe(); 1051 client.SceneAgent.SendInitialDataToMe();
1052
1053 // Now we know we can handle more data
1054 Thread.Sleep(200);
1055
1056 // Obtain the queue and remove it from the cache
1057 Queue<UDPPacketBuffer> queue = null;
1058
1059 lock (m_pendingCache)
1060 {
1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue))
1062 {
1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1064 return;
1065 }
1066 m_pendingCache.Remove(remoteEndPoint);
1067 }
1068
1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1070
1071 // Reinject queued packets
1072 while(queue.Count > 0)
1073 {
1074 UDPPacketBuffer buf = queue.Dequeue();
1075 PacketReceived(buf);
1076 }
1077 queue = null;
1014 } 1078 }
1015 else 1079 else
1016 { 1080 {
@@ -1018,6 +1082,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1018 m_log.WarnFormat( 1082 m_log.WarnFormat(
1019 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1083 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1020 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
1085 lock (m_pendingCache)
1086 m_pendingCache.Remove(remoteEndPoint);
1021 } 1087 }
1022 1088
1023 // m_log.DebugFormat( 1089 // m_log.DebugFormat(
@@ -1136,7 +1202,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1136 if (!client.SceneAgent.IsChildAgent) 1202 if (!client.SceneAgent.IsChildAgent)
1137 client.Kick("Simulator logged you out due to connection timeout"); 1203 client.Kick("Simulator logged you out due to connection timeout");
1138 1204
1139 client.CloseWithoutChecks(); 1205 client.CloseWithoutChecks(true);
1140 } 1206 }
1141 } 1207 }
1142 1208
@@ -1148,6 +1214,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1148 1214
1149 while (base.IsRunning) 1215 while (base.IsRunning)
1150 { 1216 {
1217 m_scene.ThreadAlive(1);
1151 try 1218 try
1152 { 1219 {
1153 IncomingPacket incomingPacket = null; 1220 IncomingPacket incomingPacket = null;
@@ -1190,6 +1257,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1190 1257
1191 while (base.IsRunning) 1258 while (base.IsRunning)
1192 { 1259 {
1260 m_scene.ThreadAlive(2);
1193 try 1261 try
1194 { 1262 {
1195 m_packetSent = false; 1263 m_packetSent = false;
@@ -1411,8 +1479,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1411 Packet packet = incomingPacket.Packet; 1479 Packet packet = incomingPacket.Packet;
1412 LLClientView client = incomingPacket.Client; 1480 LLClientView client = incomingPacket.Client;
1413 1481
1414 if (client.IsActive) 1482// if (client.IsActive)
1415 { 1483// {
1416 m_currentIncomingClient = client; 1484 m_currentIncomingClient = client;
1417 1485
1418 try 1486 try
@@ -1439,13 +1507,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1439 { 1507 {
1440 m_currentIncomingClient = null; 1508 m_currentIncomingClient = null;
1441 } 1509 }
1442 } 1510// }
1443 else 1511// else
1444 { 1512// {
1445 m_log.DebugFormat( 1513// m_log.DebugFormat(
1446 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1514// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1447 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1515// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1448 } 1516// }
1449 } 1517 }
1450 1518
1451 protected void LogoutHandler(IClientAPI client) 1519 protected void LogoutHandler(IClientAPI client)
@@ -1455,8 +1523,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1455 if (!client.IsLoggingOut) 1523 if (!client.IsLoggingOut)
1456 { 1524 {
1457 client.IsLoggingOut = true; 1525 client.IsLoggingOut = true;
1458 client.Close(); 1526 client.Close(false, false);
1527 }
1528 }
1529 }
1530
1531 internal class DoubleQueue<T> where T:class
1532 {
1533 private Queue<T> m_lowQueue = new Queue<T>();
1534 private Queue<T> m_highQueue = new Queue<T>();
1535
1536 private object m_syncRoot = new object();
1537 private Semaphore m_s = new Semaphore(0, 1);
1538
1539 public DoubleQueue()
1540 {
1541 }
1542
1543 public virtual int Count
1544 {
1545 get { return m_highQueue.Count + m_lowQueue.Count; }
1546 }
1547
1548 public virtual void Enqueue(T data)
1549 {
1550 Enqueue(m_lowQueue, data);
1551 }
1552
1553 public virtual void EnqueueLow(T data)
1554 {
1555 Enqueue(m_lowQueue, data);
1556 }
1557
1558 public virtual void EnqueueHigh(T data)
1559 {
1560 Enqueue(m_highQueue, data);
1561 }
1562
1563 private void Enqueue(Queue<T> q, T data)
1564 {
1565 lock (m_syncRoot)
1566 {
1567 m_lowQueue.Enqueue(data);
1568 m_s.WaitOne(0);
1569 m_s.Release();
1570 }
1571 }
1572
1573 public virtual T Dequeue()
1574 {
1575 return Dequeue(Timeout.Infinite);
1576 }
1577
1578 public virtual T Dequeue(int tmo)
1579 {
1580 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1581 }
1582
1583 public virtual T Dequeue(TimeSpan wait)
1584 {
1585 T res = null;
1586
1587 if (!Dequeue(wait, ref res))
1588 return null;
1589
1590 return res;
1591 }
1592
1593 public bool Dequeue(int timeout, ref T res)
1594 {
1595 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1596 }
1597
1598 public bool Dequeue(TimeSpan wait, ref T res)
1599 {
1600 if (!m_s.WaitOne(wait))
1601 return false;
1602
1603 lock (m_syncRoot)
1604 {
1605 if (m_highQueue.Count > 0)
1606 res = m_highQueue.Dequeue();
1607 else
1608 res = m_lowQueue.Dequeue();
1609
1610 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1611 return true;
1612
1613 try
1614 {
1615 m_s.Release();
1616 }
1617 catch
1618 {
1619 }
1620
1621 return true;
1622 }
1623 }
1624
1625 public virtual void Clear()
1626 {
1627
1628 lock (m_syncRoot)
1629 {
1630 // Make sure sem count is 0
1631 m_s.WaitOne(0);
1632
1633 m_lowQueue.Clear();
1634 m_highQueue.Clear();
1459 } 1635 }
1460 } 1636 }
1461 } 1637 }
1462} \ No newline at end of file 1638}