aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/PacketPool.cs (renamed from OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs)97
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs169
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs338
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs116
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs7
6 files changed, 157 insertions, 577 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Framework/PacketPool.cs
index 9f22fb4..41d17c5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
+++ b/OpenSim/Framework/PacketPool.cs
@@ -31,10 +31,10 @@ using System.Reflection;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenMetaverse.Packets; 32using OpenMetaverse.Packets;
33using log4net; 33using log4net;
34using OpenSim.Framework.Monitoring;
35 34
36namespace OpenSim.Region.ClientStack.LindenUDP 35namespace OpenSim.Framework
37{ 36{
37
38 public sealed class PacketPool 38 public sealed class PacketPool
39 { 39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -44,32 +44,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
44 private bool packetPoolEnabled = true; 44 private bool packetPoolEnabled = true;
45 private bool dataBlockPoolEnabled = true; 45 private bool dataBlockPoolEnabled = true;
46 46
47 private PercentageStat m_packetsReusedStat = new PercentageStat(
48 "PacketsReused",
49 "Packets reused",
50 "Number of packets reused out of all requests to the packet pool",
51 "clientstack",
52 "packetpool",
53 StatType.Push,
54 null,
55 StatVerbosity.Debug);
56
57 private PercentageStat m_blocksReusedStat = new PercentageStat(
58 "PacketDataBlocksReused",
59 "Packet data blocks reused",
60 "Number of data blocks reused out of all requests to the packet pool",
61 "clientstack",
62 "packetpool",
63 StatType.Push,
64 null,
65 StatVerbosity.Debug);
66
67 /// <summary>
68 /// Pool of packets available for reuse.
69 /// </summary>
70 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); 47 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>();
71 48
72 private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>(); 49 private static Dictionary<Type, Stack<Object>> DataBlocks =
50 new Dictionary<Type, Stack<Object>>();
51
52 static PacketPool()
53 {
54 }
73 55
74 public static PacketPool Instance 56 public static PacketPool Instance
75 { 57 {
@@ -88,45 +70,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
88 get { return dataBlockPoolEnabled; } 70 get { return dataBlockPoolEnabled; }
89 } 71 }
90 72
91 private PacketPool()
92 {
93 StatsManager.RegisterStat(m_packetsReusedStat);
94 StatsManager.RegisterStat(m_blocksReusedStat);
95
96 StatsManager.RegisterStat(
97 new Stat(
98 "PacketsPoolCount",
99 "Objects within the packet pool",
100 "The number of objects currently stored within the packet pool",
101 "",
102 "clientstack",
103 "packetpool",
104 StatType.Pull,
105 stat => { lock (pool) { stat.Value = pool.Count; } },
106 StatVerbosity.Debug));
107
108 StatsManager.RegisterStat(
109 new Stat(
110 "PacketDataBlocksPoolCount",
111 "Objects within the packet data block pool",
112 "The number of objects currently stored within the packet data block pool",
113 "",
114 "clientstack",
115 "packetpool",
116 StatType.Pull,
117 stat => { lock (DataBlocks) { stat.Value = DataBlocks.Count; } },
118 StatVerbosity.Debug));
119 }
120
121 /// <summary>
122 /// Gets a packet of the given type.
123 /// </summary>
124 /// <param name='type'></param>
125 /// <returns>Guaranteed to always return a packet, whether from the pool or newly constructed.</returns>
126 public Packet GetPacket(PacketType type) 73 public Packet GetPacket(PacketType type)
127 { 74 {
128 m_packetsReusedStat.Consequent++;
129
130 Packet packet; 75 Packet packet;
131 76
132 if (!packetPoolEnabled) 77 if (!packetPoolEnabled)
@@ -136,19 +81,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
136 { 81 {
137 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) 82 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
138 { 83 {
139// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type);
140
141 // Creating a new packet if we cannot reuse an old package 84 // Creating a new packet if we cannot reuse an old package
142 packet = Packet.BuildPacket(type); 85 packet = Packet.BuildPacket(type);
143 } 86 }
144 else 87 else
145 { 88 {
146// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type);
147
148 // Recycle old packages 89 // Recycle old packages
149 m_packetsReusedStat.Antecedent++; 90 packet = (pool[type]).Pop();
150
151 packet = pool[type].Pop();
152 } 91 }
153 } 92 }
154 93
@@ -197,7 +136,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
197 { 136 {
198 PacketType type = GetType(bytes); 137 PacketType type = GetType(bytes);
199 138
200// Array.Clear(zeroBuffer, 0, zeroBuffer.Length); 139 Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
201 140
202 int i = 0; 141 int i = 0;
203 Packet packet = GetPacket(type); 142 Packet packet = GetPacket(type);
@@ -244,7 +183,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
244 switch (packet.Type) 183 switch (packet.Type)
245 { 184 {
246 // List pooling packets here 185 // List pooling packets here
247 case PacketType.AgentUpdate:
248 case PacketType.PacketAck: 186 case PacketType.PacketAck:
249 case PacketType.ObjectUpdate: 187 case PacketType.ObjectUpdate:
250 case PacketType.ImprovedTerseObjectUpdate: 188 case PacketType.ImprovedTerseObjectUpdate:
@@ -259,9 +197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
259 197
260 if ((pool[type]).Count < 50) 198 if ((pool[type]).Count < 50)
261 { 199 {
262// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); 200 (pool[type]).Push(packet);
263
264 pool[type].Push(packet);
265 } 201 }
266 } 202 }
267 break; 203 break;
@@ -273,21 +209,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
273 } 209 }
274 } 210 }
275 211
276 public T GetDataBlock<T>() where T: new() 212 public static T GetDataBlock<T>() where T: new()
277 { 213 {
278 lock (DataBlocks) 214 lock (DataBlocks)
279 { 215 {
280 m_blocksReusedStat.Consequent++;
281
282 Stack<Object> s; 216 Stack<Object> s;
283 217
284 if (DataBlocks.TryGetValue(typeof(T), out s)) 218 if (DataBlocks.TryGetValue(typeof(T), out s))
285 { 219 {
286 if (s.Count > 0) 220 if (s.Count > 0)
287 {
288 m_blocksReusedStat.Antecedent++;
289 return (T)s.Pop(); 221 return (T)s.Pop();
290 }
291 } 222 }
292 else 223 else
293 { 224 {
@@ -298,7 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
298 } 229 }
299 } 230 }
300 231
301 public void ReturnDataBlock<T>(T block) where T: new() 232 public static void ReturnDataBlock<T>(T block) where T: new()
302 { 233 {
303 if (block == null) 234 if (block == null)
304 return; 235 return;
@@ -313,4 +244,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
313 } 244 }
314 } 245 }
315 } 246 }
316} \ No newline at end of file 247}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
index e22670b..1b8535c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -45,12 +45,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45 public Packet Packet; 45 public Packet Packet;
46 46
47 /// <summary> 47 /// <summary>
48 /// No arg constructor. 48 /// Default constructor
49 /// </summary>
50 public IncomingPacket() {}
51
52 /// <summary>
53 /// Constructor
54 /// </summary> 49 /// </summary>
55 /// <param name="client">Reference to the client this packet came from</param> 50 /// <param name="client">Reference to the client this packet came from</param>
56 /// <param name="packet">Packet data</param> 51 /// <param name="packet">Packet data</param>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index c9aa4ca..ae9ed7f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -47,7 +47,6 @@ using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer; 48using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using RegionFlags = OpenMetaverse.RegionFlags;
51using Nini.Config; 50using Nini.Config;
52 51
53using System.IO; 52using System.IO;
@@ -356,17 +355,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
356 private bool m_deliverPackets = true; 355 private bool m_deliverPackets = true;
357 private int m_animationSequenceNumber = 1; 356 private int m_animationSequenceNumber = 1;
358 private bool m_SendLogoutPacketWhenClosing = true; 357 private bool m_SendLogoutPacketWhenClosing = true;
359 358 private AgentUpdateArgs lastarg;
360 /// <summary>
361 /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for
362 /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it
363 /// is doing absolutely nothing.
364 /// </summary>
365 /// <remarks>
366 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
367 /// cannot retain a reference to it outside of that method.
368 /// </remarks>
369 private AgentUpdateArgs m_lastAgentUpdateArgs;
370 359
371 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 360 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
372 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 361 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -521,18 +510,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
521 /// </summary> 510 /// </summary>
522 public void Close() 511 public void Close()
523 { 512 {
524 Close(true, false); 513 Close(true);
525 } 514 }
526 515
527 public void Close(bool sendStop, bool force) 516 /// <summary>
517 /// Shut down the client view
518 /// </summary>
519 public void Close(bool sendStop)
528 { 520 {
529 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 521 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
530 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 522 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
531 lock (CloseSyncLock) 523 lock (CloseSyncLock)
532 { 524 {
533 // We still perform a force close inside the sync lock since this is intended to attempt close where 525 if (!IsActive)
534 // there is some unidentified connection problem, not where we have issues due to deadlock
535 if (!IsActive && !force)
536 return; 526 return;
537 527
538 IsActive = false; 528 IsActive = false;
@@ -847,9 +837,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
847 OutPacket(mov, ThrottleOutPacketType.Unknown); 837 OutPacket(mov, ThrottleOutPacketType.Unknown);
848 } 838 }
849 839
850 public void SendChatMessage( 840 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName,
851 string message, byte type, Vector3 fromPos, string fromName, 841 UUID fromAgentID, byte source, byte audible)
852 UUID fromAgentID, UUID ownerID, byte source, byte audible)
853 { 842 {
854 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 843 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
855 reply.ChatData.Audible = audible; 844 reply.ChatData.Audible = audible;
@@ -858,7 +847,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
858 reply.ChatData.SourceType = source; 847 reply.ChatData.SourceType = source;
859 reply.ChatData.Position = fromPos; 848 reply.ChatData.Position = fromPos;
860 reply.ChatData.FromName = Util.StringToBytes256(fromName); 849 reply.ChatData.FromName = Util.StringToBytes256(fromName);
861 reply.ChatData.OwnerID = ownerID; 850 reply.ChatData.OwnerID = fromAgentID;
862 reply.ChatData.SourceID = fromAgentID; 851 reply.ChatData.SourceID = fromAgentID;
863 852
864 OutPacket(reply, ThrottleOutPacketType.Unknown); 853 OutPacket(reply, ThrottleOutPacketType.Unknown);
@@ -3996,8 +3985,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3996 { 3985 {
3997 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3986 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3998 3987
3999 ImprovedTerseObjectUpdatePacket packet 3988 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
4000 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
4001 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3989 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4002 packet.RegionData.TimeDilation = timeDilation; 3990 packet.RegionData.TimeDilation = timeDilation;
4003 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3991 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4042,9 +4030,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4042 { 4030 {
4043 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 4031 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4044 4032
4045 ImprovedTerseObjectUpdatePacket packet 4033 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
4046 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4047 PacketType.ImprovedTerseObjectUpdate);
4048 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4034 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4049 packet.RegionData.TimeDilation = timeDilation; 4035 packet.RegionData.TimeDilation = timeDilation;
4050 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4036 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4052,7 +4038,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4052 for (int i = 0; i < blocks.Count; i++) 4038 for (int i = 0; i < blocks.Count; i++)
4053 packet.ObjectData[i] = blocks[i]; 4039 packet.ObjectData[i] = blocks[i];
4054 4040
4055 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 4041 OutPacket(packet, ThrottleOutPacketType.Task, true);
4056 } 4042 }
4057 4043
4058 #endregion Packet Sending 4044 #endregion Packet Sending
@@ -4549,7 +4535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4549 { 4535 {
4550 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); 4536 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4551 } 4537 }
4552 j = 0; 4538 j = 0;
4553 4539
4554 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4540 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4555 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4541 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@@ -5053,9 +5039,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5053 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; 5039 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
5054 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; 5040 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
5055 5041
5056 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block 5042 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
5057 = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
5058
5059 block.Data = data; 5043 block.Data = data;
5060 5044
5061 if (textureEntry != null && textureEntry.Length > 0) 5045 if (textureEntry != null && textureEntry.Length > 0)
@@ -5305,18 +5289,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5305 protected virtual void RegisterLocalPacketHandlers() 5289 protected virtual void RegisterLocalPacketHandlers()
5306 { 5290 {
5307 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); 5291 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
5308
5309 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5310 // for each AgentUpdate packet.
5311 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5292 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5312
5313 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5293 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5314 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5294 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5315 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5295 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5316 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5296 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
5317 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); 5297 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5318 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); 5298 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false);
5319 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); 5299 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false);
5320 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); 5300 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
5321 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); 5301 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
5322 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5302 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
@@ -5538,84 +5518,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5538 5518
5539 #region Scene/Avatar 5519 #region Scene/Avatar
5540 5520
5541 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 5521 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
5542 { 5522 {
5543 if (OnAgentUpdate != null) 5523 if (OnAgentUpdate != null)
5544 { 5524 {
5545 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; 5525 bool update = false;
5526 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5546 5527
5547 #region Packet Session and User Check 5528 #region Packet Session and User Check
5548 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) 5529 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId)
5549 {
5550 PacketPool.Instance.ReturnPacket(packet);
5551 return false; 5530 return false;
5552 }
5553 #endregion 5531 #endregion
5554 5532
5555 bool update = false; 5533 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
5556 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 5534
5535 // We can only check when we have something to check
5536 // against.
5557 5537
5558 if (m_lastAgentUpdateArgs != null) 5538 if (lastarg != null)
5559 { 5539 {
5560 // These should be ordered from most-likely to
5561 // least likely to change. I've made an initial
5562 // guess at that.
5563 update = 5540 update =
5564 ( 5541 (
5565 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || 5542 (x.BodyRotation != lastarg.BodyRotation) ||
5566 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || 5543 (x.CameraAtAxis != lastarg.CameraAtAxis) ||
5567 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || 5544 (x.CameraCenter != lastarg.CameraCenter) ||
5568 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || 5545 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5569 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || 5546 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5570 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || 5547 (x.ControlFlags != lastarg.ControlFlags) ||
5571 (x.ControlFlags != 0) || 5548 (x.ControlFlags != 0) ||
5572 (x.Far != m_lastAgentUpdateArgs.Far) || 5549 (x.Far != lastarg.Far) ||
5573 (x.Flags != m_lastAgentUpdateArgs.Flags) || 5550 (x.Flags != lastarg.Flags) ||
5574 (x.State != m_lastAgentUpdateArgs.State) || 5551 (x.State != lastarg.State) ||
5575 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || 5552 (x.HeadRotation != lastarg.HeadRotation) ||
5576 (x.SessionID != m_lastAgentUpdateArgs.SessionID) || 5553 (x.SessionID != lastarg.SessionID) ||
5577 (x.AgentID != m_lastAgentUpdateArgs.AgentID) 5554 (x.AgentID != lastarg.AgentID)
5578 ); 5555 );
5579 } 5556 }
5580 else 5557 else
5581 { 5558 {
5582 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5583 update = true; 5559 update = true;
5584 } 5560 }
5585 5561
5562 // These should be ordered from most-likely to
5563 // least likely to change. I've made an initial
5564 // guess at that.
5565
5586 if (update) 5566 if (update)
5587 { 5567 {
5588// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5568// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
5589 5569
5590 m_lastAgentUpdateArgs.AgentID = x.AgentID; 5570 AgentUpdateArgs arg = new AgentUpdateArgs();
5591 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; 5571 arg.AgentID = x.AgentID;
5592 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; 5572 arg.BodyRotation = x.BodyRotation;
5593 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; 5573 arg.CameraAtAxis = x.CameraAtAxis;
5594 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; 5574 arg.CameraCenter = x.CameraCenter;
5595 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; 5575 arg.CameraLeftAxis = x.CameraLeftAxis;
5596 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; 5576 arg.CameraUpAxis = x.CameraUpAxis;
5597 m_lastAgentUpdateArgs.Far = x.Far; 5577 arg.ControlFlags = x.ControlFlags;
5598 m_lastAgentUpdateArgs.Flags = x.Flags; 5578 arg.Far = x.Far;
5599 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; 5579 arg.Flags = x.Flags;
5600 m_lastAgentUpdateArgs.SessionID = x.SessionID; 5580 arg.HeadRotation = x.HeadRotation;
5601 m_lastAgentUpdateArgs.State = x.State; 5581 arg.SessionID = x.SessionID;
5602 5582 arg.State = x.State;
5603 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5583 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5604 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5584 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5605 5585 lastarg = arg; // save this set of arguments for nexttime
5606 if (handlerPreAgentUpdate != null) 5586 if (handlerPreAgentUpdate != null)
5607 OnPreAgentUpdate(this, m_lastAgentUpdateArgs); 5587 OnPreAgentUpdate(this, arg);
5608
5609 if (handlerAgentUpdate != null) 5588 if (handlerAgentUpdate != null)
5610 OnAgentUpdate(this, m_lastAgentUpdateArgs); 5589 OnAgentUpdate(this, arg);
5611 5590
5612 handlerAgentUpdate = null; 5591 handlerAgentUpdate = null;
5613 handlerPreAgentUpdate = null; 5592 handlerPreAgentUpdate = null;
5614 } 5593 }
5615 } 5594 }
5616 5595
5617 PacketPool.Instance.ReturnPacket(packet);
5618
5619 return true; 5596 return true;
5620 } 5597 }
5621 5598
@@ -5987,8 +5964,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5987 msgpack.MessageBlock.ID, 5964 msgpack.MessageBlock.ID,
5988 msgpack.MessageBlock.Offline != 0 ? true : false, 5965 msgpack.MessageBlock.Offline != 0 ? true : false,
5989 msgpack.MessageBlock.Position, 5966 msgpack.MessageBlock.Position,
5990 msgpack.MessageBlock.BinaryBucket, 5967 msgpack.MessageBlock.BinaryBucket);
5991 true);
5992 5968
5993 handlerInstantMessage(this, im); 5969 handlerInstantMessage(this, im);
5994 } 5970 }
@@ -9275,9 +9251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9275 } 9251 }
9276 #endregion 9252 #endregion
9277 9253
9278 string method = Utils.BytesToString(messagePacket.MethodData.Method); 9254 switch (Utils.BytesToString(messagePacket.MethodData.Method))
9279
9280 switch (method)
9281 { 9255 {
9282 case "getinfo": 9256 case "getinfo":
9283 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 9257 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
@@ -9593,17 +9567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9593 return true; 9567 return true;
9594 9568
9595 default: 9569 default:
9596 m_log.WarnFormat( 9570 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket);
9597 "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}",
9598 method, Name, Scene.Name);
9599
9600 for (int i = 0; i < messagePacket.ParamList.Length; i++)
9601 {
9602 EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i];
9603 string data = (string)Utils.BytesToString(block.Parameter);
9604 m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data);
9605 }
9606
9607 return true; 9571 return true;
9608 } 9572 }
9609 9573
@@ -11996,7 +11960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11996 logPacket = false; 11960 logPacket = false;
11997 11961
11998 if (DebugPacketLevel <= 50 11962 if (DebugPacketLevel <= 50
11999 && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) 11963 & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
12000 logPacket = false; 11964 logPacket = false;
12001 11965
12002 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) 11966 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -12070,6 +12034,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12070 12034
12071 if (!ProcessPacketMethod(packet)) 12035 if (!ProcessPacketMethod(packet))
12072 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 12036 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
12037
12038 PacketPool.Instance.ReturnPacket(packet);
12073 } 12039 }
12074 12040
12075 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 12041 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -12238,7 +12204,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12238 { 12204 {
12239 Kick(reason); 12205 Kick(reason);
12240 Thread.Sleep(1000); 12206 Thread.Sleep(1000);
12241 Disconnect(); 12207 Close();
12242 } 12208 }
12243 12209
12244 public void Disconnect() 12210 public void Disconnect()
@@ -12526,10 +12492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12526 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 12492 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12527 12493
12528 12494
12529 ImprovedTerseObjectUpdatePacket packet 12495 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
12530 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12531 PacketType.ImprovedTerseObjectUpdate);
12532
12533 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 12496 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
12534 packet.RegionData.TimeDilation = timeDilation; 12497 packet.RegionData.TimeDilation = timeDilation;
12535 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 12498 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index b8951d9..d6513c5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,7 +37,6 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Console;
41using OpenSim.Framework.Monitoring; 40using OpenSim.Framework.Monitoring;
42using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
43using OpenMetaverse; 42using OpenMetaverse;
@@ -101,11 +100,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
101 100
102 /// <summary>The measured resolution of Environment.TickCount</summary> 101 /// <summary>The measured resolution of Environment.TickCount</summary>
103 public readonly float TickCountResolution; 102 public readonly float TickCountResolution;
104
105 /// <summary>Number of prim updates to put on the queue each time the 103 /// <summary>Number of prim updates to put on the queue each time the
106 /// OnQueueEmpty event is triggered for updates</summary> 104 /// OnQueueEmpty event is triggered for updates</summary>
107 public readonly int PrimUpdatesPerCallback; 105 public readonly int PrimUpdatesPerCallback;
108
109 /// <summary>Number of texture packets to put on the queue each time the 106 /// <summary>Number of texture packets to put on the queue each time the
110 /// OnQueueEmpty event is triggered for textures</summary> 107 /// OnQueueEmpty event is triggered for textures</summary>
111 public readonly int TextureSendLimit; 108 public readonly int TextureSendLimit;
@@ -127,37 +124,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
127 124
128 /// <summary>Manages authentication for agent circuits</summary> 125 /// <summary>Manages authentication for agent circuits</summary>
129 private AgentCircuitManager m_circuitManager; 126 private AgentCircuitManager m_circuitManager;
130
131 /// <summary>Reference to the scene this UDP server is attached to</summary> 127 /// <summary>Reference to the scene this UDP server is attached to</summary>
132 protected Scene m_scene; 128 protected Scene m_scene;
133
134 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 129 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
135 private Location m_location; 130 private Location m_location;
136
137 /// <summary>The size of the receive buffer for the UDP socket. This value 131 /// <summary>The size of the receive buffer for the UDP socket. This value
138 /// is passed up to the operating system and used in the system networking 132 /// is passed up to the operating system and used in the system networking
139 /// stack. Use zero to leave this value as the default</summary> 133 /// stack. Use zero to leave this value as the default</summary>
140 private int m_recvBufferSize; 134 private int m_recvBufferSize;
141
142 /// <summary>Flag to process packets asynchronously or synchronously</summary> 135 /// <summary>Flag to process packets asynchronously or synchronously</summary>
143 private bool m_asyncPacketHandling; 136 private bool m_asyncPacketHandling;
144
145 /// <summary>Tracks whether or not a packet was sent each round so we know 137 /// <summary>Tracks whether or not a packet was sent each round so we know
146 /// whether or not to sleep</summary> 138 /// whether or not to sleep</summary>
147 private bool m_packetSent; 139 private bool m_packetSent;
148 140
149 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> 141 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
150 private int m_elapsedMSSinceLastStatReport = 0; 142 private int m_elapsedMSSinceLastStatReport = 0;
151
152 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> 143 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
153 private int m_tickLastOutgoingPacketHandler; 144 private int m_tickLastOutgoingPacketHandler;
154
155 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> 145 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
156 private int m_elapsedMSOutgoingPacketHandler; 146 private int m_elapsedMSOutgoingPacketHandler;
157
158 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> 147 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
159 private int m_elapsed100MSOutgoingPacketHandler; 148 private int m_elapsed100MSOutgoingPacketHandler;
160
161 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> 149 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
162 private int m_elapsed500MSOutgoingPacketHandler; 150 private int m_elapsed500MSOutgoingPacketHandler;
163 151
@@ -171,9 +159,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
171 protected bool m_sendPing; 159 protected bool m_sendPing;
172 160
173 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
174 private Pool<IncomingPacket> m_incomingPacketPool;
175
176 private Stat m_incomingPacketPoolStat;
177 162
178 private int m_defaultRTO = 0; 163 private int m_defaultRTO = 0;
179 private int m_maxRTO = 0; 164 private int m_maxRTO = 0;
@@ -195,9 +180,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
195 /// </summary> 180 /// </summary>
196 private IClientAPI m_currentIncomingClient; 181 private IClientAPI m_currentIncomingClient;
197 182
198 public LLUDPServer( 183 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
199 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
200 IConfigSource configSource, AgentCircuitManager circuitManager)
201 : base(listenIP, (int)port) 184 : base(listenIP, (int)port)
202 { 185 {
203 #region Environment.TickCount Measurement 186 #region Environment.TickCount Measurement
@@ -219,7 +202,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
219 202
220 m_circuitManager = circuitManager; 203 m_circuitManager = circuitManager;
221 int sceneThrottleBps = 0; 204 int sceneThrottleBps = 0;
222 bool usePools = false;
223 205
224 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 206 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
225 if (config != null) 207 if (config != null)
@@ -245,16 +227,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
245 m_pausedAckTimeout = 1000 * 300; // 5 minutes 227 m_pausedAckTimeout = 1000 * 300; // 5 minutes
246 } 228 }
247 229
248 // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers.
249 // However, there is no harm in temporarily doing it multiple times.
250 IConfig packetConfig = configSource.Configs["PacketPool"];
251 if (packetConfig != null)
252 {
253 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
254 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
255 usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools);
256 }
257
258 #region BinaryStats 230 #region BinaryStats
259 config = configSource.Configs["Statistics.Binary"]; 231 config = configSource.Configs["Statistics.Binary"];
260 m_shouldCollectStats = false; 232 m_shouldCollectStats = false;
@@ -282,28 +254,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
282 254
283 m_throttle = new TokenBucket(null, sceneThrottleBps); 255 m_throttle = new TokenBucket(null, sceneThrottleBps);
284 ThrottleRates = new ThrottleRates(configSource); 256 ThrottleRates = new ThrottleRates(configSource);
285
286 if (usePools)
287 EnablePools();
288 } 257 }
289 258
290 public void Start() 259 public void Start()
291 { 260 {
292 StartInbound(); 261 if (m_scene == null)
293 StartOutbound(); 262 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
294 263
295 m_elapsedMSSinceLastStatReport = Environment.TickCount;
296 }
297
298 private void StartInbound()
299 {
300 m_log.InfoFormat( 264 m_log.InfoFormat(
301 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", 265 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
302 m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); 266 m_asyncPacketHandling ? "asynchronous" : "synchronous");
303 267
304 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); 268 base.Start(m_recvBufferSize, m_asyncPacketHandling);
305 269
306 // This thread will process the packets received that are placed on the packetInbox 270 // Start the packet processing threads
307 Watchdog.StartThread( 271 Watchdog.StartThread(
308 IncomingPacketHandler, 272 IncomingPacketHandler,
309 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), 273 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -312,13 +276,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
312 true, 276 true,
313 GetWatchdogIncomingAlarmData, 277 GetWatchdogIncomingAlarmData,
314 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 278 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
315 }
316
317 private new void StartOutbound()
318 {
319 m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server");
320
321 base.StartOutbound();
322 279
323 Watchdog.StartThread( 280 Watchdog.StartThread(
324 OutgoingPacketHandler, 281 OutgoingPacketHandler,
@@ -328,57 +285,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
328 true, 285 true,
329 GetWatchdogOutgoingAlarmData, 286 GetWatchdogOutgoingAlarmData,
330 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 287 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
331 }
332
333 public void Stop()
334 {
335 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
336 base.StopOutbound();
337 base.StopInbound();
338 }
339 288
340 protected override bool EnablePools() 289 m_elapsedMSSinceLastStatReport = Environment.TickCount;
341 {
342 if (!UsePools)
343 {
344 base.EnablePools();
345
346 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
347
348 m_incomingPacketPoolStat
349 = new Stat(
350 "IncomingPacketPoolCount",
351 "Objects within incoming packet pool",
352 "The number of objects currently stored within the incoming packet pool",
353 "",
354 "clientstack",
355 "packetpool",
356 StatType.Pull,
357 stat => stat.Value = m_incomingPacketPool.Count,
358 StatVerbosity.Debug);
359
360 StatsManager.RegisterStat(m_incomingPacketPoolStat);
361
362 return true;
363 }
364
365 return false;
366 }
367
368 protected override bool DisablePools()
369 {
370 if (UsePools)
371 {
372 base.DisablePools();
373
374 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
375
376 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
377
378 return true;
379 }
380
381 return false;
382 } 290 }
383 291
384 /// <summary> 292 /// <summary>
@@ -403,6 +311,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
403 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); 311 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
404 } 312 }
405 313
314 public new void Stop()
315 {
316 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
317 base.Stop();
318 }
319
406 public void AddScene(IScene scene) 320 public void AddScene(IScene scene)
407 { 321 {
408 if (m_scene != null) 322 if (m_scene != null)
@@ -419,117 +333,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
419 333
420 m_scene = (Scene)scene; 334 m_scene = (Scene)scene;
421 m_location = new Location(m_scene.RegionInfo.RegionHandle); 335 m_location = new Location(m_scene.RegionInfo.RegionHandle);
422
423 MainConsole.Instance.Commands.AddCommand(
424 "Debug",
425 false,
426 "debug lludp start",
427 "debug lludp start <in|out|all>",
428 "Control LLUDP packet processing.",
429 "No effect if packet processing has already started.\n"
430 + "in - start inbound processing.\n"
431 + "out - start outbound processing.\n"
432 + "all - start in and outbound processing.\n",
433 HandleStartCommand);
434
435 MainConsole.Instance.Commands.AddCommand(
436 "Debug",
437 false,
438 "debug lludp stop",
439 "debug lludp stop <in|out|all>",
440 "Stop LLUDP packet processing.",
441 "No effect if packet processing has already stopped.\n"
442 + "in - stop inbound processing.\n"
443 + "out - stop outbound processing.\n"
444 + "all - stop in and outbound processing.\n",
445 HandleStopCommand);
446
447 MainConsole.Instance.Commands.AddCommand(
448 "Debug",
449 false,
450 "debug lludp pool",
451 "debug lludp pool <on|off>",
452 "Turn object pooling within the lludp component on or off.",
453 HandlePoolCommand);
454
455 MainConsole.Instance.Commands.AddCommand(
456 "Debug",
457 false,
458 "debug lludp status",
459 "debug lludp status",
460 "Return status of LLUDP packet processing.",
461 HandleStatusCommand);
462 }
463
464 private void HandleStartCommand(string module, string[] args)
465 {
466 if (args.Length != 4)
467 {
468 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
469 return;
470 }
471
472 string subCommand = args[3];
473
474 if (subCommand == "in" || subCommand == "all")
475 StartInbound();
476
477 if (subCommand == "out" || subCommand == "all")
478 StartOutbound();
479 }
480
481 private void HandleStopCommand(string module, string[] args)
482 {
483 if (args.Length != 4)
484 {
485 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
486 return;
487 }
488
489 string subCommand = args[3];
490
491 if (subCommand == "in" || subCommand == "all")
492 StopInbound();
493
494 if (subCommand == "out" || subCommand == "all")
495 StopOutbound();
496 }
497
498 private void HandlePoolCommand(string module, string[] args)
499 {
500 if (args.Length != 4)
501 {
502 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
503 return;
504 }
505
506 string enabled = args[3];
507
508 if (enabled == "on")
509 {
510 if (EnablePools())
511 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name);
512 }
513 else if (enabled == "off")
514 {
515 if (DisablePools())
516 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name);
517 }
518 else
519 {
520 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
521 }
522 }
523
524 private void HandleStatusCommand(string module, string[] args)
525 {
526 MainConsole.Instance.OutputFormat(
527 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
528
529 MainConsole.Instance.OutputFormat(
530 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
531
532 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
533 } 336 }
534 337
535 public bool HandlesRegion(Location x) 338 public bool HandlesRegion(Location x)
@@ -613,8 +416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
613 byte[] data = packet.ToBytes(); 416 byte[] data = packet.ToBytes();
614 SendPacketData(udpClient, data, packet.Type, category, method); 417 SendPacketData(udpClient, data, packet.Type, category, method);
615 } 418 }
616
617 PacketPool.Instance.ReturnPacket(packet);
618 } 419 }
619 420
620 /// <summary> 421 /// <summary>
@@ -899,7 +700,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
899 LLUDPClient udpClient = null; 700 LLUDPClient udpClient = null;
900 Packet packet = null; 701 Packet packet = null;
901 int packetEnd = buffer.DataLength - 1; 702 int packetEnd = buffer.DataLength - 1;
902 IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; 703 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;
903 704
904 #region Decoding 705 #region Decoding
905 706
@@ -909,7 +710,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
909// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 710// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
910// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 711// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
911 712
912 return; // Drop undersized packet 713 return; // Drop undersizd packet
913 } 714 }
914 715
915 int headerLen = 7; 716 int headerLen = 7;
@@ -932,13 +733,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
932 733
933 try 734 try
934 { 735 {
935// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 736 packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
936// // Only allocate a buffer for zerodecoding if the packet is zerocoded
937// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
938 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
939 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
940 // bytes are copied out).
941 packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
942 // Only allocate a buffer for zerodecoding if the packet is zerocoded 737 // Only allocate a buffer for zerodecoding if the packet is zerocoded
943 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 738 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
944 } 739 }
@@ -953,13 +748,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
953 748
954 return; // Drop short packet 749 return; // Drop short packet
955 } 750 }
956 catch (Exception e) 751 catch(Exception e)
957 { 752 {
958 if (m_malformedCount < 100) 753 if (m_malformedCount < 100)
959 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 754 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
960
961 m_malformedCount++; 755 m_malformedCount++;
962
963 if ((m_malformedCount % 100000) == 0) 756 if ((m_malformedCount % 100000) == 0)
964 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); 757 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
965 } 758 }
@@ -979,7 +772,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 772
980 // If there is already a client for this endpoint, don't process UseCircuitCode 773 // If there is already a client for this endpoint, don't process UseCircuitCode
981 IClientAPI client = null; 774 IClientAPI client = null;
982 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) 775 if (!m_scene.TryGetClient(address, out client))
983 { 776 {
984 // UseCircuitCode handling 777 // UseCircuitCode handling
985 if (packet.Type == PacketType.UseCircuitCode) 778 if (packet.Type == PacketType.UseCircuitCode)
@@ -987,15 +780,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
987 // And if there is a UseCircuitCode pending, also drop it 780 // And if there is a UseCircuitCode pending, also drop it
988 lock (m_pendingCache) 781 lock (m_pendingCache)
989 { 782 {
990 if (m_pendingCache.Contains(endPoint)) 783 if (m_pendingCache.Contains(address))
991 return; 784 return;
992 785
993 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); 786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60);
994 } 787 }
995 788
996 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 789 object[] array = new object[] { buffer, packet };
997 // buffer.
998 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
999 790
1000 Util.FireAndForget(HandleUseCircuitCode, array); 791 Util.FireAndForget(HandleUseCircuitCode, array);
1001 792
@@ -1007,7 +798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1007 lock (m_pendingCache) 798 lock (m_pendingCache)
1008 { 799 {
1009 Queue<UDPPacketBuffer> queue; 800 Queue<UDPPacketBuffer> queue;
1010 if (m_pendingCache.TryGetValue(endPoint, out queue)) 801 if (m_pendingCache.TryGetValue(address, out queue))
1011 { 802 {
1012 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); 803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1013 queue.Enqueue(buffer); 804 queue.Enqueue(buffer);
@@ -1043,10 +834,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1043 // Handle appended ACKs 834 // Handle appended ACKs
1044 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 835 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
1045 { 836 {
1046// m_log.DebugFormat(
1047// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1048// packet.Header.AckList.Length, client.Name, m_scene.Name);
1049
1050 for (int i = 0; i < packet.Header.AckList.Length; i++) 837 for (int i = 0; i < packet.Header.AckList.Length; i++)
1051 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 838 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
1052 } 839 }
@@ -1056,10 +843,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1056 { 843 {
1057 PacketAckPacket ackPacket = (PacketAckPacket)packet; 844 PacketAckPacket ackPacket = (PacketAckPacket)packet;
1058 845
1059// m_log.DebugFormat(
1060// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1061// ackPacket.Packets.Length, client.Name, m_scene.Name);
1062
1063 for (int i = 0; i < ackPacket.Packets.Length; i++) 846 for (int i = 0; i < ackPacket.Packets.Length; i++)
1064 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 847 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
1065 848
@@ -1073,10 +856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1073 856
1074 if (packet.Header.Reliable) 857 if (packet.Header.Reliable)
1075 { 858 {
1076// m_log.DebugFormat(
1077// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}",
1078// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name);
1079
1080 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 859 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
1081 860
1082 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 861 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
@@ -1123,8 +902,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1123 902
1124 if (packet.Type == PacketType.StartPingCheck) 903 if (packet.Type == PacketType.StartPingCheck)
1125 { 904 {
1126// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);
1127
1128 // We don't need to do anything else with ping checks 905 // We don't need to do anything else with ping checks
1129 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 906 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
1130 CompletePing(udpClient, startPing.PingID.PingID); 907 CompletePing(udpClient, startPing.PingID.PingID);
@@ -1144,25 +921,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1144 921
1145 #endregion Ping Check Handling 922 #endregion Ping Check Handling
1146 923
1147 IncomingPacket incomingPacket;
1148
1149 // Inbox insertion 924 // Inbox insertion
1150 if (UsePools) 925 if (packet.Type == PacketType.AgentUpdate ||
1151 { 926 packet.Type == PacketType.ChatFromViewer)
1152 incomingPacket = m_incomingPacketPool.GetObject(); 927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
1153 incomingPacket.Client = (LLClientView)client;
1154 incomingPacket.Packet = packet;
1155 }
1156 else
1157 {
1158 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1159 }
1160
1161 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1162 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1163 packetInbox.EnqueueHigh(incomingPacket);
1164 else 928 else
1165 packetInbox.EnqueueLow(incomingPacket); 929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
1166 } 931 }
1167 932
1168 #region BinaryStats 933 #region BinaryStats
@@ -1248,19 +1013,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1248 1013
1249 private void HandleUseCircuitCode(object o) 1014 private void HandleUseCircuitCode(object o)
1250 { 1015 {
1251 IPEndPoint endPoint = null; 1016 IPEndPoint remoteEndPoint = null;
1252 IClientAPI client = null; 1017 IClientAPI client = null;
1253 1018
1254 try 1019 try
1255 { 1020 {
1256 // DateTime startTime = DateTime.Now; 1021 // DateTime startTime = DateTime.Now;
1257 object[] array = (object[])o; 1022 object[] array = (object[])o;
1258 endPoint = (IPEndPoint)array[0]; 1023 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
1259 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1024 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
1260 1025
1261 m_log.DebugFormat( 1026 m_log.DebugFormat(
1262 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1027 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1263 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); 1028 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint);
1029
1030 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
1264 1031
1265 AuthenticateResponse sessionInfo; 1032 AuthenticateResponse sessionInfo;
1266 if (IsClientAuthorized(uccp, out sessionInfo)) 1033 if (IsClientAuthorized(uccp, out sessionInfo))
@@ -1271,13 +1038,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1271 uccp.CircuitCode.Code, 1038 uccp.CircuitCode.Code,
1272 uccp.CircuitCode.ID, 1039 uccp.CircuitCode.ID,
1273 uccp.CircuitCode.SessionID, 1040 uccp.CircuitCode.SessionID,
1274 endPoint, 1041 remoteEndPoint,
1275 sessionInfo); 1042 sessionInfo);
1276 1043
1277 // Send ack straight away to let the viewer know that the connection is active. 1044 // Send ack straight away to let the viewer know that the connection is active.
1278 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1045 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1279 // circuit code to the existing child agent. This is not particularly obvious. 1046 // circuit code to the existing child agent. This is not particularly obvious.
1280 SendAckImmediate(endPoint, uccp.Header.Sequence); 1047 SendAckImmediate(remoteEndPoint, uccp.Header.Sequence);
1281 1048
1282 // 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.
1283 if (client != null) 1050 if (client != null)
@@ -1291,12 +1058,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1291 1058
1292 lock (m_pendingCache) 1059 lock (m_pendingCache)
1293 { 1060 {
1294 if (!m_pendingCache.TryGetValue(endPoint, out queue)) 1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue))
1295 { 1062 {
1296 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1297 return; 1064 return;
1298 } 1065 }
1299 m_pendingCache.Remove(endPoint); 1066 m_pendingCache.Remove(remoteEndPoint);
1300 } 1067 }
1301 1068
1302 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); 1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
@@ -1314,9 +1081,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1314 // Don't create clients for unauthorized requesters. 1081 // Don't create clients for unauthorized requesters.
1315 m_log.WarnFormat( 1082 m_log.WarnFormat(
1316 "[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}",
1317 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
1318 lock (m_pendingCache) 1085 lock (m_pendingCache)
1319 m_pendingCache.Remove(endPoint); 1086 m_pendingCache.Remove(remoteEndPoint);
1320 } 1087 }
1321 1088
1322 // m_log.DebugFormat( 1089 // m_log.DebugFormat(
@@ -1328,7 +1095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1328 { 1095 {
1329 m_log.ErrorFormat( 1096 m_log.ErrorFormat(
1330 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", 1097 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1331 endPoint != null ? endPoint.ToString() : "n/a", 1098 remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a",
1332 client != null ? client.Name : "unknown", 1099 client != null ? client.Name : "unknown",
1333 client != null ? client.AgentId.ToString() : "unknown", 1100 client != null ? client.AgentId.ToString() : "unknown",
1334 e.Message, 1101 e.Message,
@@ -1393,20 +1160,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1393 { 1160 {
1394 IClientAPI client = null; 1161 IClientAPI client = null;
1395 1162
1396 // We currently synchronize this code across the whole scene to avoid issues such as 1163 // In priciple there shouldn't be more than one thread here, ever.
1397 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done 1164 // But in case that happens, we need to synchronize this piece of code
1398 // consistently, this lock could probably be removed. 1165 // because it's too important
1399 lock (this) 1166 lock (this)
1400 { 1167 {
1401 if (!m_scene.TryGetClient(agentID, out client)) 1168 if (!m_scene.TryGetClient(agentID, out client))
1402 { 1169 {
1403 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1170 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1404 1171
1405 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1172 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1406 client.OnLogout += LogoutHandler; 1173 client.OnLogout += LogoutHandler;
1407 1174
1408 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1175 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1409 1176
1410 client.Start(); 1177 client.Start();
1411 } 1178 }
1412 } 1179 }
@@ -1445,7 +1212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1445 // on to en-US to avoid number parsing issues 1212 // on to en-US to avoid number parsing issues
1446 Culture.SetCurrentCulture(); 1213 Culture.SetCurrentCulture();
1447 1214
1448 while (IsRunningInbound) 1215 while (base.IsRunning)
1449 { 1216 {
1450 m_scene.ThreadAlive(1); 1217 m_scene.ThreadAlive(1);
1451 try 1218 try
@@ -1461,12 +1228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1461 } 1228 }
1462 1229
1463 if (packetInbox.Dequeue(100, ref incomingPacket)) 1230 if (packetInbox.Dequeue(100, ref incomingPacket))
1464 {
1465 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); 1231 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
1466
1467 if (UsePools)
1468 m_incomingPacketPool.ReturnObject(incomingPacket);
1469 }
1470 } 1232 }
1471 catch (Exception ex) 1233 catch (Exception ex)
1472 { 1234 {
@@ -1493,7 +1255,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1493 // Action generic every round 1255 // Action generic every round
1494 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1256 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1495 1257
1496 while (base.IsRunningOutbound) 1258 while (base.IsRunning)
1497 { 1259 {
1498 m_scene.ThreadAlive(2); 1260 m_scene.ThreadAlive(2);
1499 try 1261 try
@@ -1761,7 +1523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1761 if (!client.IsLoggingOut) 1523 if (!client.IsLoggingOut)
1762 { 1524 {
1763 client.IsLoggingOut = true; 1525 client.IsLoggingOut = true;
1764 client.Close(false, false); 1526 client.Close(false);
1765 } 1527 }
1766 } 1528 }
1767 } 1529 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 8bd3461..cfe7c9d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -30,8 +30,6 @@ using System.Net;
30using System.Net.Sockets; 30using System.Net.Sockets;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
35 33
36namespace OpenMetaverse 34namespace OpenMetaverse
37{ 35{
@@ -60,31 +58,17 @@ namespace OpenMetaverse
60 /// <summary>Flag to process packets asynchronously or synchronously</summary> 58 /// <summary>Flag to process packets asynchronously or synchronously</summary>
61 private bool m_asyncPacketHandling; 59 private bool m_asyncPacketHandling;
62 60
63 /// <summary> 61 /// <summary>The all important shutdown flag</summary>
64 /// Pool to use for handling data. May be null if UsePools = false; 62 private volatile bool m_shutdownFlag = true;
65 /// </summary>
66 protected OpenSim.Framework.Pool<UDPPacketBuffer> m_pool;
67
68 /// <summary>
69 /// Are we to use object pool(s) to reduce memory churn when receiving data?
70 /// </summary>
71 public bool UsePools { get; protected set; }
72
73 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
74 public bool IsRunningInbound { get; private set; }
75 63
76 /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary> 64 /// <summary>Returns true if the server is currently listening, otherwise false</summary>
77 /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks> 65 public bool IsRunning { get { return !m_shutdownFlag; } }
78 public bool IsRunningOutbound { get; private set; }
79
80 private Stat m_poolCountStat;
81 66
82 /// <summary> 67 /// <summary>
83 /// Default constructor 68 /// Default constructor
84 /// </summary> 69 /// </summary>
85 /// <param name="bindAddress">Local IP address to bind the server to</param> 70 /// <param name="bindAddress">Local IP address to bind the server to</param>
86 /// <param name="port">Port to listening for incoming UDP packets on</param> 71 /// <param name="port">Port to listening for incoming UDP packets on</param>
87 /// /// <param name="usePool">Are we to use an object pool to get objects for handing inbound data?</param>
88 public OpenSimUDPBase(IPAddress bindAddress, int port) 72 public OpenSimUDPBase(IPAddress bindAddress, int port)
89 { 73 {
90 m_localBindAddress = bindAddress; 74 m_localBindAddress = bindAddress;
@@ -92,7 +76,7 @@ namespace OpenMetaverse
92 } 76 }
93 77
94 /// <summary> 78 /// <summary>
95 /// Start inbound UDP packet handling. 79 /// Start the UDP server
96 /// </summary> 80 /// </summary>
97 /// <param name="recvBufferSize">The size of the receive buffer for 81 /// <param name="recvBufferSize">The size of the receive buffer for
98 /// the UDP socket. This value is passed up to the operating system 82 /// the UDP socket. This value is passed up to the operating system
@@ -107,11 +91,11 @@ namespace OpenMetaverse
107 /// manner (not throwing an exception when the remote side resets the 91 /// manner (not throwing an exception when the remote side resets the
108 /// connection). This call is ignored on Mono where the flag is not 92 /// connection). This call is ignored on Mono where the flag is not
109 /// necessary</remarks> 93 /// necessary</remarks>
110 public void StartInbound(int recvBufferSize, bool asyncPacketHandling) 94 public void Start(int recvBufferSize, bool asyncPacketHandling)
111 { 95 {
112 m_asyncPacketHandling = asyncPacketHandling; 96 m_asyncPacketHandling = asyncPacketHandling;
113 97
114 if (!IsRunningInbound) 98 if (m_shutdownFlag)
115 { 99 {
116 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
117 101
@@ -139,7 +123,8 @@ namespace OpenMetaverse
139 123
140 m_udpSocket.Bind(ipep); 124 m_udpSocket.Bind(ipep);
141 125
142 IsRunningInbound = true; 126 // we're not shutting down, we're starting up
127 m_shutdownFlag = false;
143 128
144 // kick off an async receive. The Start() method will return, the 129 // kick off an async receive. The Start() method will return, the
145 // actual receives will occur asynchronously and will be caught in 130 // actual receives will occur asynchronously and will be caught in
@@ -149,84 +134,28 @@ namespace OpenMetaverse
149 } 134 }
150 135
151 /// <summary> 136 /// <summary>
152 /// Start outbound UDP packet handling. 137 /// Stops the UDP server
153 /// </summary> 138 /// </summary>
154 public void StartOutbound() 139 public void Stop()
155 {
156 IsRunningOutbound = true;
157 }
158
159 public void StopInbound()
160 { 140 {
161 if (IsRunningInbound) 141 if (!m_shutdownFlag)
162 { 142 {
163 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 143 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
164 // will deny any more reader locks, in effect blocking all other send/receive 144 // will deny any more reader locks, in effect blocking all other send/receive
165 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other 145 // threads. Once we have the lock, we set shutdownFlag to inform the other
166 // threads that the socket is closed. 146 // threads that the socket is closed.
167 IsRunningInbound = false; 147 m_shutdownFlag = true;
168 m_udpSocket.Close(); 148 m_udpSocket.Close();
169 } 149 }
170 } 150 }
171 151
172 public void StopOutbound()
173 {
174 IsRunningOutbound = false;
175 }
176
177 protected virtual bool EnablePools()
178 {
179 if (!UsePools)
180 {
181 m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
182
183 m_poolCountStat
184 = new Stat(
185 "UDPPacketBufferPoolCount",
186 "Objects within the UDPPacketBuffer pool",
187 "The number of objects currently stored within the UDPPacketBuffer pool",
188 "",
189 "clientstack",
190 "packetpool",
191 StatType.Pull,
192 stat => stat.Value = m_pool.Count,
193 StatVerbosity.Debug);
194
195 StatsManager.RegisterStat(m_poolCountStat);
196
197 UsePools = true;
198
199 return true;
200 }
201
202 return false;
203 }
204
205 protected virtual bool DisablePools()
206 {
207 if (UsePools)
208 {
209 UsePools = false;
210 StatsManager.DeregisterStat(m_poolCountStat);
211
212 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
213
214 return true;
215 }
216
217 return false;
218 }
219
220 private void AsyncBeginReceive() 152 private void AsyncBeginReceive()
221 { 153 {
222 UDPPacketBuffer buf; 154 // allocate a packet buffer
223 155 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
224 if (UsePools) 156 UDPPacketBuffer buf = new UDPPacketBuffer();
225 buf = m_pool.GetObject();
226 else
227 buf = new UDPPacketBuffer();
228 157
229 if (IsRunningInbound) 158 if (!m_shutdownFlag)
230 { 159 {
231 try 160 try
232 { 161 {
@@ -279,7 +208,7 @@ namespace OpenMetaverse
279 { 208 {
280 // Asynchronous receive operations will complete here through the call 209 // Asynchronous receive operations will complete here through the call
281 // to AsyncBeginReceive 210 // to AsyncBeginReceive
282 if (IsRunningInbound) 211 if (!m_shutdownFlag)
283 { 212 {
284 // Asynchronous mode will start another receive before the 213 // Asynchronous mode will start another receive before the
285 // callback for this packet is even fired. Very parallel :-) 214 // callback for this packet is even fired. Very parallel :-)
@@ -288,6 +217,8 @@ namespace OpenMetaverse
288 217
289 // get the buffer that was created in AsyncBeginReceive 218 // get the buffer that was created in AsyncBeginReceive
290 // this is the received data 219 // this is the received data
220 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
221 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
291 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 222 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
292 223
293 try 224 try
@@ -304,8 +235,7 @@ namespace OpenMetaverse
304 catch (ObjectDisposedException) { } 235 catch (ObjectDisposedException) { }
305 finally 236 finally
306 { 237 {
307 if (UsePools) 238 //wrappedBuffer.Dispose();
308 m_pool.ReturnObject(buffer);
309 239
310 // Synchronous mode waits until the packet callback completes 240 // Synchronous mode waits until the packet callback completes
311 // before starting the receive to fetch another packet 241 // before starting the receive to fetch another packet
@@ -318,7 +248,7 @@ namespace OpenMetaverse
318 248
319 public void AsyncBeginSend(UDPPacketBuffer buf) 249 public void AsyncBeginSend(UDPPacketBuffer buf)
320 { 250 {
321 if (IsRunningOutbound) 251 if (!m_shutdownFlag)
322 { 252 {
323 try 253 try
324 { 254 {
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 556df30..109a8e1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
43 /// This will contain basic tests for the LindenUDP client stack 43 /// This will contain basic tests for the LindenUDP client stack
44 /// </summary> 44 /// </summary>
45 [TestFixture] 45 [TestFixture]
46 public class BasicCircuitTests : OpenSimTestCase 46 public class BasicCircuitTests
47 { 47 {
48 private Scene m_scene; 48 private Scene m_scene;
49 private TestLLUDPServer m_udpServer; 49 private TestLLUDPServer m_udpServer;
@@ -65,9 +65,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
65 } 65 }
66 66
67 [SetUp] 67 [SetUp]
68 public override void SetUp() 68 public void SetUp()
69 { 69 {
70 base.SetUp();
71 m_scene = new SceneHelpers().SetupScene(); 70 m_scene = new SceneHelpers().SetupScene();
72 } 71 }
73 72
@@ -144,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
144 public void TestAddClient() 143 public void TestAddClient()
145 { 144 {
146 TestHelpers.InMethod(); 145 TestHelpers.InMethod();
147// TestHelpers.EnableLogging(); 146// XmlConfigurator.Configure();
148 147
149 AddUdpServer(); 148 AddUdpServer();
150 149