aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs8
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs23
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs212
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs37
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs197
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs2
6 files changed, 156 insertions, 323 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 943be07..3cb9388 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -12555,14 +12555,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12555 /// provide your own method.</param> 12555 /// provide your own method.</param>
12556 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) 12556 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
12557 { 12557 {
12558
12559/* this is causing packet loss for some reason
12560 if(!m_udpClient.IsConnected)
12561 {
12562 PacketPool.Instance.ReturnPacket(packet);
12563 return;
12564 }
12565*/
12566 if (m_outPacketsToDrop != null) 12558 if (m_outPacketsToDrop != null)
12567 { 12559 {
12568 if (m_outPacketsToDrop.Contains(packet.Type.ToString())) 12560 if (m_outPacketsToDrop.Contains(packet.Type.ToString()))
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 439621a..bc75d82 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -120,7 +120,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
120 /// <summary>Circuit code that this client is connected on</summary> 120 /// <summary>Circuit code that this client is connected on</summary>
121 public readonly uint CircuitCode; 121 public readonly uint CircuitCode;
122 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> 122 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
123 public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); 123 public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(256);
124 124
125 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 125 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
126 public UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 126 public UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
@@ -803,8 +803,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
803 } 803 }
804 } 804 }
805 805
806
807
808 /// <summary> 806 /// <summary>
809 /// Fires the OnQueueEmpty callback and sets the minimum time that it 807 /// Fires the OnQueueEmpty callback and sets the minimum time that it
810 /// can be called again 808 /// can be called again
@@ -843,6 +841,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
843 return 0; 841 return 0;
844 } 842 }
845 843
844 public void FreeUDPBuffer(UDPPacketBuffer buf)
845 {
846 m_udpServer.FreeUDPBuffer(buf);
847 }
848
846 /// <summary> 849 /// <summary>
847 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a 850 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
848 /// flag value 851 /// flag value
@@ -853,20 +856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
853 { 856 {
854 ThrottleOutPacketType category = (ThrottleOutPacketType)i; 857 ThrottleOutPacketType category = (ThrottleOutPacketType)i;
855 858
856 /*
857 * Land = 1,
858 /// <summary>Wind data</summary>
859 Wind = 2,
860 /// <summary>Cloud data</summary>
861 Cloud = 3,
862 /// <summary>Any packets that do not fit into the other throttles</summary>
863 Task = 4,
864 /// <summary>Texture assets</summary>
865 Texture = 5,
866 /// <summary>Non-texture assets</summary>
867 Asset = 6,
868 */
869
870 switch (category) 859 switch (category)
871 { 860 {
872 case ThrottleOutPacketType.Land: 861 case ThrottleOutPacketType.Land:
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 35d29a5..4739ae8 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -344,18 +344,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
344 344
345 protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 345 protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
346 346
347 protected Pool<IncomingPacket> m_incomingPacketPool;
348
349 /// <summary>
350 /// Stat for number of packets in the main pool awaiting use.
351 /// </summary>
352 protected Stat m_poolCountStat;
353
354 /// <summary>
355 /// Stat for number of packets in the inbound packet pool awaiting use.
356 /// </summary>
357 protected Stat m_incomingPacketPoolStat;
358
359 protected int m_defaultRTO = 0; 347 protected int m_defaultRTO = 0;
360 protected int m_maxRTO = 0; 348 protected int m_maxRTO = 0;
361 protected int m_ackTimeout = 0; 349 protected int m_ackTimeout = 0;
@@ -498,7 +486,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
498 486
499// if (usePools) 487// if (usePools)
500// EnablePools(); 488// EnablePools();
501 base.DisablePools();
502 } 489 }
503 490
504 public void Start() 491 public void Start()
@@ -554,83 +541,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
554 OqrEngine.Stop(); 541 OqrEngine.Stop();
555 } 542 }
556 543
557 public override bool EnablePools()
558 {
559 if (!UsePools)
560 {
561 base.EnablePools();
562
563 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
564
565 return true;
566 }
567
568 return false;
569 }
570
571 public override bool DisablePools()
572 {
573 if (UsePools)
574 {
575 base.DisablePools();
576
577 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
578
579 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
580
581 return true;
582 }
583
584 return false;
585 }
586
587 /// <summary>
588 /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene
589 /// stats.
590 /// </summary>
591 protected internal void EnablePoolStats()
592 {
593 m_poolCountStat
594 = new Stat(
595 "UDPPacketBufferPoolCount",
596 "Objects within the UDPPacketBuffer pool",
597 "The number of objects currently stored within the UDPPacketBuffer pool",
598 "",
599 "clientstack",
600 Scene.Name,
601 StatType.Pull,
602 stat => stat.Value = Pool.Count,
603 StatVerbosity.Debug);
604
605 StatsManager.RegisterStat(m_poolCountStat);
606
607 m_incomingPacketPoolStat
608 = new Stat(
609 "IncomingPacketPoolCount",
610 "Objects within incoming packet pool",
611 "The number of objects currently stored within the incoming packet pool",
612 "",
613 "clientstack",
614 Scene.Name,
615 StatType.Pull,
616 stat => stat.Value = m_incomingPacketPool.Count,
617 StatVerbosity.Debug);
618
619 StatsManager.RegisterStat(m_incomingPacketPoolStat);
620 }
621
622 /// <summary>
623 /// Disables pool stats.
624 /// </summary>
625 protected internal void DisablePoolStats()
626 {
627 StatsManager.DeregisterStat(m_poolCountStat);
628 m_poolCountStat = null;
629
630 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
631 m_incomingPacketPoolStat = null;
632 }
633
634 /// <summary> 544 /// <summary>
635 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. 545 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
636 /// </summary> 546 /// </summary>
@@ -658,8 +568,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
658 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), 568 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name),
659 "INCOMING PACKET ASYNC HANDLING ENGINE"); 569 "INCOMING PACKET ASYNC HANDLING ENGINE");
660*/ 570*/
661 OqrEngine 571 OqrEngine = new JobEngine(
662 = new JobEngine(
663 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), 572 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name),
664 "OUTGOING QUEUE REFILL ENGINE"); 573 "OUTGOING QUEUE REFILL ENGINE");
665 574
@@ -769,15 +678,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
769 stat => stat.Value = OqrEngine.JobsWaiting, 678 stat => stat.Value = OqrEngine.JobsWaiting,
770 StatVerbosity.Debug)); 679 StatVerbosity.Debug));
771 680
772 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by 681 StatsManager.RegisterStat(
773 // scene name 682 new Stat(
774 if (UsePools) 683 "UDPBuffersPoolCount",
775 EnablePoolStats(); 684 "Buffers in the UDP buffers pool",
776 685 "The number of buffers currently stored within the UDP buffers pool",
686 "",
687 "clientstack",
688 Scene.Name,
689 StatType.Pull,
690 stat => stat.Value = m_udpBuffersPoolPtr,
691 StatVerbosity.Debug));
777 692
778 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); 693 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
779 commands.Register(); 694 commands.Register();
780
781 } 695 }
782 696
783 public bool HandlesRegion(Location x) 697 public bool HandlesRegion(Location x)
@@ -939,9 +853,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
939 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting 853 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
940 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here 854 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
941 // to accomodate for both common scenarios and provide ample room for ACK appending in both 855 // to accomodate for both common scenarios and provide ample room for ACK appending in both
942 int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; 856 //int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
943 857
944 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 858 //UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
859 UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
945 860
946 // Zerocode if needed 861 // Zerocode if needed
947 if (doZerocode) 862 if (doZerocode)
@@ -971,7 +886,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
971 // If the packet data wasn't already copied during zerocoding, copy it now 886 // If the packet data wasn't already copied during zerocoding, copy it now
972 if (doCopy) 887 if (doCopy)
973 { 888 {
974 if (dataLength <= buffer.Data.Length) 889 //if (dataLength <= buffer.Data.Length)
890 if (dataLength <= LLUDPServer.MTU)
975 { 891 {
976 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 892 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
977 } 893 }
@@ -979,7 +895,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 { 895 {
980 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + 896 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
981 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length); 897 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
982 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength); 898 // buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength);
899 buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
983 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 900 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
984 } 901 }
985 } 902 }
@@ -1168,22 +1085,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1168 // Set the appended ACKs flag on this packet 1085 // Set the appended ACKs flag on this packet
1169 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); 1086 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
1170 } 1087 }
1088 buffer.DataLength = dataLength;
1171 } 1089 }
1172 1090
1173 buffer.DataLength = dataLength;
1174
1175 if (!isResend) 1091 if (!isResend)
1176 { 1092 {
1177 // Not a resend, assign a new sequence number 1093 // Not a resend, assign a new sequence number
1178 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence); 1094 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
1179 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 1095 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
1180 outgoingPacket.SequenceNumber = sequenceNumber; 1096 outgoingPacket.SequenceNumber = sequenceNumber;
1181
1182 if (isReliable)
1183 {
1184 // Add this packet to the list of ACK responses we are waiting on from the server
1185 udpClient.NeedAcks.Add(outgoingPacket);
1186 }
1187 } 1097 }
1188 else 1098 else
1189 { 1099 {
@@ -1196,9 +1106,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1196 PacketsSentCount++; 1106 PacketsSentCount++;
1197 1107
1198 SyncSend(buffer); 1108 SyncSend(buffer);
1109
1199 // Keep track of when this packet was sent out (right now) 1110 // Keep track of when this packet was sent out (right now)
1200 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1111 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
1201 1112
1113 if (outgoingPacket.UnackedMethod == null)
1114 FreeUDPBuffer(buffer);
1115 else if(!isResend)
1116 {
1117 // Add this packet to the list of ACK responses we are waiting on from the server
1118 udpClient.NeedAcks.Add(outgoingPacket);
1119 }
1120
1202 if (udpClient.DebugDataOutLevel > 0) 1121 if (udpClient.DebugDataOutLevel > 0)
1203 m_log.DebugFormat( 1122 m_log.DebugFormat(
1204 "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}", 1123 "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}",
@@ -1240,7 +1159,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1240// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1159// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1241 1160
1242 RecordMalformedInboundPacket(endPoint); 1161 RecordMalformedInboundPacket(endPoint);
1243 1162 FreeUDPBuffer(buffer);
1244 return; // Drop undersized packet 1163 return; // Drop undersized packet
1245 } 1164 }
1246 1165
@@ -1260,21 +1179,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1260// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1179// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1261 1180
1262 RecordMalformedInboundPacket(endPoint); 1181 RecordMalformedInboundPacket(endPoint);
1263 1182 FreeUDPBuffer(buffer);
1264 return; // Malformed header 1183 return; // Malformed header
1265 } 1184 }
1266 1185
1267 try 1186 try
1268 { 1187 {
1269// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 1188 packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
1270// // Only allocate a buffer for zerodecoding if the packet is zerocoded 1189 // Only allocate a buffer for zerodecoding if the packet is zerocoded
1271// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1190 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
1272 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we 1191 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
1273 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all 1192 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
1274 // bytes are copied out). 1193 // bytes are copied out).
1275 packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, 1194// packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
1276 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1195 // Only allocate a buffer for zerodecoding if the packet is zerocoded
1277 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1196// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
1278 } 1197 }
1279 catch (Exception e) 1198 catch (Exception e)
1280 { 1199 {
@@ -1292,7 +1211,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1292 } 1211 }
1293 1212
1294 RecordMalformedInboundPacket(endPoint); 1213 RecordMalformedInboundPacket(endPoint);
1295 1214 FreeUDPBuffer(buffer);
1296 return; 1215 return;
1297 } 1216 }
1298 1217
@@ -1311,17 +1230,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1311 lock (m_pendingCache) 1230 lock (m_pendingCache)
1312 { 1231 {
1313 if (m_pendingCache.Contains(endPoint)) 1232 if (m_pendingCache.Contains(endPoint))
1233 {
1234 FreeUDPBuffer(buffer);
1314 return; 1235 return;
1236 }
1315 1237
1316 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); 1238 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1317 } 1239 }
1318 1240
1319 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1241 Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet });
1320 // buffer. 1242 FreeUDPBuffer(buffer);
1321 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1322
1323 Util.FireAndForget(HandleUseCircuitCode, array);
1324
1325 return; 1243 return;
1326 } 1244 }
1327 } 1245 }
@@ -1336,24 +1254,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1336 queue.Enqueue(buffer); 1254 queue.Enqueue(buffer);
1337 return; 1255 return;
1338 } 1256 }
1339
1340/*
1341 else if (packet.Type == PacketType.CompleteAgentMovement)
1342 {
1343 // Send ack straight away to let the viewer know that we got it.
1344 SendAckImmediate(endPoint, packet.Header.Sequence);
1345
1346 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1347 // buffer.
1348 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1349
1350 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1351
1352 return;
1353 }
1354 */
1355 } 1257 }
1356 1258
1259 FreeUDPBuffer(buffer);
1260
1357 // Determine which agent this packet came from 1261 // Determine which agent this packet came from
1358 if (client == null || !(client is LLClientView)) 1262 if (client == null || !(client is LLClientView))
1359 { 1263 {
@@ -1471,10 +1375,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1471 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1375 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1472 #endregion BinaryStats 1376 #endregion BinaryStats
1473 1377
1474
1475//AgentUpdate removed from here
1476
1477
1478 #region Ping Check Handling 1378 #region Ping Check Handling
1479 1379
1480 if (packet.Type == PacketType.StartPingCheck) 1380 if (packet.Type == PacketType.StartPingCheck)
@@ -1506,17 +1406,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1506 1406
1507 IncomingPacket incomingPacket; 1407 IncomingPacket incomingPacket;
1508 1408
1509 // Inbox insertion 1409 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1510 if (UsePools)
1511 {
1512 incomingPacket = m_incomingPacketPool.GetObject();
1513 incomingPacket.Client = (LLClientView)client;
1514 incomingPacket.Packet = packet;
1515 }
1516 else
1517 {
1518 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1519 }
1520 1410
1521// if (incomingPacket.Packet.Type == PacketType.AgentUpdate || 1411// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1522// incomingPacket.Packet.Type == PacketType.ChatFromViewer) 1412// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
@@ -1525,7 +1415,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1525// else 1415// else
1526// packetInbox.Enqueue(incomingPacket); 1416// packetInbox.Enqueue(incomingPacket);
1527 packetInbox.Add(incomingPacket); 1417 packetInbox.Add(incomingPacket);
1528
1529 } 1418 }
1530 1419
1531 #region BinaryStats 1420 #region BinaryStats
@@ -1881,13 +1770,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1881 byte[] packetData = ack.ToBytes(); 1770 byte[] packetData = ack.ToBytes();
1882 int length = packetData.Length; 1771 int length = packetData.Length;
1883 1772
1884 UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length); 1773 UDPPacketBuffer buffer = GetNewUDPBuffer(remoteEndpoint);
1885 buffer.DataLength = length; 1774 buffer.DataLength = length;
1886 1775
1887 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); 1776 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
1888 1777
1889// AsyncBeginSend(buffer); 1778// AsyncBeginSend(buffer);
1890 SyncSend(buffer); 1779 SyncSend(buffer);
1780 FreeUDPBuffer(buffer);
1891 } 1781 }
1892 1782
1893 protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) 1783 protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
@@ -1982,17 +1872,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1982 Scene.ThreadAlive(1); 1872 Scene.ThreadAlive(1);
1983 try 1873 try
1984 { 1874 {
1985 packetInbox.TryTake(out incomingPacket, 250); 1875 packetInbox.TryTake(out incomingPacket, 4500);
1986 1876
1987 if (incomingPacket != null && IsRunningInbound) 1877 if (incomingPacket != null && IsRunningInbound)
1988 { 1878 {
1989 ProcessInPacket(incomingPacket); 1879 ProcessInPacket(incomingPacket);
1990
1991 if (UsePools)
1992 {
1993 incomingPacket.Client = null;
1994 m_incomingPacketPool.ReturnObject(incomingPacket);
1995 }
1996 incomingPacket = null; 1880 incomingPacket = null;
1997 } 1881 }
1998 } 1882 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
index 012a57d..a4d7eb9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
@@ -777,41 +777,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
777 m_udpServer.StopOutbound(); 777 m_udpServer.StopOutbound();
778 } 778 }
779 779
780 private void HandlePoolCommand(string module, string[] args)
781 {
782 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
783 return;
784
785 if (args.Length != 4)
786 {
787 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
788 return;
789 }
790
791 string enabled = args[3];
792
793 if (enabled == "on")
794 {
795 if (m_udpServer.EnablePools())
796 {
797 m_udpServer.EnablePoolStats();
798 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_udpServer.Scene.Name);
799 }
800 }
801 else if (enabled == "off")
802 {
803 if (m_udpServer.DisablePools())
804 {
805 m_udpServer.DisablePoolStats();
806 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_udpServer.Scene.Name);
807 }
808 }
809 else
810 {
811 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
812 }
813 }
814
815 private void HandleAgentUpdateCommand(string module, string[] args) 780 private void HandleAgentUpdateCommand(string module, string[] args)
816 { 781 {
817 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) 782 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
@@ -834,8 +799,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
834 MainConsole.Instance.OutputFormat( 799 MainConsole.Instance.OutputFormat(
835 "OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled"); 800 "OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled");
836 801
837 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_udpServer.Scene.Name, m_udpServer.UsePools ? "on" : "off");
838
839 MainConsole.Instance.OutputFormat( 802 MainConsole.Instance.OutputFormat(
840 "Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel); 803 "Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel);
841 } 804 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index f362b06..0bfd86c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Concurrent;
29using System.Net; 30using System.Net;
30using System.Net.Sockets; 31using System.Net.Sockets;
31using System.Threading; 32using System.Threading;
@@ -57,15 +58,9 @@ namespace OpenMetaverse
57 /// <summary>UDP socket, used in either client or server mode</summary> 58 /// <summary>UDP socket, used in either client or server mode</summary>
58 private Socket m_udpSocket; 59 private Socket m_udpSocket;
59 60
60 /// <summary> 61 public static Object m_udpBuffersPoolLock = new Object();
61 /// Are we to use object pool(s) to reduce memory churn when receiving data? 62 public static UDPPacketBuffer[] m_udpBuffersPool = new UDPPacketBuffer[1000];
62 /// </summary> 63 public static int m_udpBuffersPoolPtr = -1;
63 public bool UsePools { get; protected set; }
64
65 /// <summary>
66 /// Pool to use for handling data. May be null if UsePools = false;
67 /// </summary>
68 protected OpenSim.Framework.Pool<UDPPacketBuffer> Pool { get; private set; }
69 64
70 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary> 65 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
71 public bool IsRunningInbound { get; private set; } 66 public bool IsRunningInbound { get; private set; }
@@ -186,6 +181,52 @@ namespace OpenMetaverse
186 if(m_udpSocket !=null) 181 if(m_udpSocket !=null)
187 try { m_udpSocket.Close(); } catch { } 182 try { m_udpSocket.Close(); } catch { }
188 } 183 }
184
185 public UDPPacketBuffer GetNewUDPBuffer()
186 {
187 lock (m_udpBuffersPoolLock)
188 {
189 if (m_udpBuffersPoolPtr >= 0)
190 {
191 UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr];
192 m_udpBuffersPool[m_udpBuffersPoolPtr] = null;
193 m_udpBuffersPoolPtr--;
194 buf.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
195 return buf;
196 }
197 }
198 return new UDPPacketBuffer(new IPEndPoint(IPAddress.Any, 0));
199 }
200
201 public UDPPacketBuffer GetNewUDPBuffer(IPEndPoint remoteEndpoint)
202 {
203 lock (m_udpBuffersPoolLock)
204 {
205 if (m_udpBuffersPoolPtr >= 0)
206 {
207 UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr];
208 m_udpBuffersPool[m_udpBuffersPoolPtr] = null;
209 m_udpBuffersPoolPtr--;
210 buf.RemoteEndPoint = remoteEndpoint;
211 return buf;
212 }
213 }
214 return new UDPPacketBuffer(remoteEndpoint);
215 }
216
217 public void FreeUDPBuffer(UDPPacketBuffer buf)
218 {
219 lock (m_udpBuffersPoolLock)
220 {
221 if (m_udpBuffersPoolPtr < 999)
222 {
223 buf.RemoteEndPoint = null;
224 m_udpBuffersPoolPtr++;
225 m_udpBuffersPool[m_udpBuffersPoolPtr] = buf;
226 }
227 }
228 }
229
189 /// <summary> 230 /// <summary>
190 /// Start inbound UDP packet handling. 231 /// Start inbound UDP packet handling.
191 /// </summary> 232 /// </summary>
@@ -202,6 +243,7 @@ namespace OpenMetaverse
202 /// manner (not throwing an exception when the remote side resets the 243 /// manner (not throwing an exception when the remote side resets the
203 /// connection). This call is ignored on Mono where the flag is not 244 /// connection). This call is ignored on Mono where the flag is not
204 /// necessary</remarks> 245 /// necessary</remarks>
246
205 public virtual void StartInbound(int recvBufferSize) 247 public virtual void StartInbound(int recvBufferSize)
206 { 248 {
207 if (!IsRunningInbound) 249 if (!IsRunningInbound)
@@ -306,101 +348,64 @@ namespace OpenMetaverse
306 IsRunningOutbound = false; 348 IsRunningOutbound = false;
307 } 349 }
308 350
309 public virtual bool EnablePools() 351 private void AsyncBeginReceive()
310 { 352 {
311 if (!UsePools) 353 if (!IsRunningInbound)
312 { 354 return;
313 Pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
314
315 UsePools = true;
316
317 return true;
318 }
319
320 return false;
321 }
322 355
323 public virtual bool DisablePools() 356 UDPPacketBuffer buf = GetNewUDPBuffer();
324 { 357 try
325 if (UsePools)
326 { 358 {
327 UsePools = false; 359 // kick off an async read
328 360 m_udpSocket.BeginReceiveFrom(
329 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. 361 //wrappedBuffer.Instance.Data,
330 362 buf.Data,
331 return true; 363 0,
364 UDPPacketBuffer.BUFFER_SIZE,
365 SocketFlags.None,
366 ref buf.RemoteEndPoint,
367 AsyncEndReceive,
368 //wrappedBuffer);
369 buf);
332 } 370 }
333 371 catch (SocketException e)
334 return false;
335 }
336
337 private void AsyncBeginReceive()
338 {
339 UDPPacketBuffer buf;
340
341 // FIXME: Disabled for now as this causes issues with reused packet objects interfering with each other
342 // on Windows with m_asyncPacketHandling = true, though this has not been seen on Linux.
343 // Possibly some unexpected issue with fetching UDP data concurrently with multiple threads. Requires more investigation.
344// if (UsePools)
345// buf = Pool.GetObject();
346// else
347 buf = new UDPPacketBuffer();
348
349 if (IsRunningInbound)
350 { 372 {
351 try 373 if (e.SocketErrorCode == SocketError.ConnectionReset)
352 { 374 {
353 // kick off an async read 375 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
354 m_udpSocket.BeginReceiveFrom( 376 bool salvaged = false;
355 //wrappedBuffer.Instance.Data, 377 while (!salvaged)
356 buf.Data,
357 0,
358 UDPPacketBuffer.BUFFER_SIZE,
359 SocketFlags.None,
360 ref buf.RemoteEndPoint,
361 AsyncEndReceive,
362 //wrappedBuffer);
363 buf);
364 }
365 catch (SocketException e)
366 {
367 if (e.SocketErrorCode == SocketError.ConnectionReset)
368 { 378 {
369 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort); 379 try
370 bool salvaged = false;
371 while (!salvaged)
372 { 380 {
373 try 381 m_udpSocket.BeginReceiveFrom(
374 { 382 //wrappedBuffer.Instance.Data,
375 m_udpSocket.BeginReceiveFrom( 383 buf.Data,
376 //wrappedBuffer.Instance.Data, 384 0,
377 buf.Data, 385 UDPPacketBuffer.BUFFER_SIZE,
378 0, 386 SocketFlags.None,
379 UDPPacketBuffer.BUFFER_SIZE, 387 ref buf.RemoteEndPoint,
380 SocketFlags.None, 388 AsyncEndReceive,
381 ref buf.RemoteEndPoint, 389 //wrappedBuffer);
382 AsyncEndReceive, 390 buf);
383 //wrappedBuffer); 391 salvaged = true;
384 buf);
385 salvaged = true;
386 }
387 catch (SocketException) { }
388 catch (ObjectDisposedException) { return; }
389 } 392 }
390 393 catch (SocketException) { }
391 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); 394 catch (ObjectDisposedException) { return; }
392 } 395 }
396
397 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
393 } 398 }
394 catch (ObjectDisposedException e) 399 }
395 { 400 catch (ObjectDisposedException e)
396 m_log.Error( 401 {
397 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); 402 m_log.Error(
398 } 403 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
399 catch (Exception e) 404 }
400 { 405 catch (Exception e)
401 m_log.Error( 406 {
402 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); 407 m_log.Error(
403 } 408 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
404 } 409 }
405 } 410 }
406 411
@@ -465,14 +470,12 @@ namespace OpenMetaverse
465 } 470 }
466 finally 471 finally
467 { 472 {
468// if (UsePools)
469// Pool.ReturnObject(buffer);
470
471 AsyncBeginReceive(); 473 AsyncBeginReceive();
472 } 474 }
473 } 475 }
474 } 476 }
475 477
478/* not in use
476 public void AsyncBeginSend(UDPPacketBuffer buf) 479 public void AsyncBeginSend(UDPPacketBuffer buf)
477 { 480 {
478// if (IsRunningOutbound) 481// if (IsRunningOutbound)
@@ -511,7 +514,7 @@ namespace OpenMetaverse
511 catch (SocketException) { } 514 catch (SocketException) { }
512 catch (ObjectDisposedException) { } 515 catch (ObjectDisposedException) { }
513 } 516 }
514 517*/
515 public void SyncSend(UDPPacketBuffer buf) 518 public void SyncSend(UDPPacketBuffer buf)
516 { 519 {
517 try 520 try
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
index 76f4c6f..e0eee53 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
@@ -203,6 +203,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
203 if (ackedPacket != null) 203 if (ackedPacket != null)
204 { 204 {
205 m_packets.Remove(pendingAcknowledgement.SequenceNumber); 205 m_packets.Remove(pendingAcknowledgement.SequenceNumber);
206 ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer);
206 207
207 // As with other network applications, assume that an acknowledged packet is an 208 // As with other network applications, assume that an acknowledged packet is an
208 // indication that the network can handle a little more load, speed up the transmission 209 // indication that the network can handle a little more load, speed up the transmission
@@ -241,6 +242,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
241 if (removedPacket != null) 242 if (removedPacket != null)
242 { 243 {
243 m_packets.Remove(pendingRemove); 244 m_packets.Remove(pendingRemove);
245 removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer);
244 246
245 // Update stats 247 // Update stats
246 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); 248 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);