aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs21
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs2
-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/PacketPool.cs316
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs7
-rw-r--r--OpenSim/Region/ClientStack/RegionApplicationBase.cs2
11 files changed, 824 insertions, 165 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 650cd50..f6146a9 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -241,8 +241,8 @@ namespace OpenSim.Region.ClientStack.Linden
241 m_HostCapsObj.RegisterHandler( 241 m_HostCapsObj.RegisterHandler(
242 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); 242 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
243 243
244 m_log.DebugFormat( 244// m_log.DebugFormat(
245 "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); 245// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
246 246
247 //m_capsHandlers["MapLayer"] = 247 //m_capsHandlers["MapLayer"] =
248 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 248 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
@@ -337,11 +337,12 @@ namespace OpenSim.Region.ClientStack.Linden
337 public string SeedCapRequest(string request, string path, string param, 337 public string SeedCapRequest(string request, string path, string param,
338 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 338 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
339 { 339 {
340// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); 340 m_log.DebugFormat(
341 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
341 342
342 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 343 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
343 { 344 {
344 m_log.DebugFormat( 345 m_log.WarnFormat(
345 "[CAPS]: Unauthorized CAPS client {0} from {1}", 346 "[CAPS]: Unauthorized CAPS client {0} from {1}",
346 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); 347 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
347 348
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index e113c60..5bbdce8 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden
94 94
95 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); 95 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
96 96
97 scene.EventManager.OnNewClient += OnNewClient; 97// scene.EventManager.OnNewClient += OnNewClient;
98 98
99 // TODO: Leaving these open, or closing them when we 99 // TODO: Leaving these open, or closing them when we
100 // become a child is incorrect. It messes up TP in a big 100 // become a child is incorrect. It messes up TP in a big
@@ -102,6 +102,7 @@ namespace OpenSim.Region.ClientStack.Linden
102 // circuit is there. 102 // circuit is there.
103 103
104 scene.EventManager.OnClientClosed += ClientClosed; 104 scene.EventManager.OnClientClosed += ClientClosed;
105
105 scene.EventManager.OnMakeChildAgent += MakeChildAgent; 106 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
106 scene.EventManager.OnRegisterCaps += OnRegisterCaps; 107 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
107 108
@@ -110,10 +111,10 @@ namespace OpenSim.Region.ClientStack.Linden
110 false, 111 false,
111 "debug eq", 112 "debug eq",
112 "debug eq [0|1|2]", 113 "debug eq [0|1|2]",
113 "Turn on event queue debugging" 114 "Turn on event queue debugging\n"
114 + "<= 0 - turns off all event queue logging" 115 + " <= 0 - turns off all event queue logging\n"
115 + ">= 1 - turns on outgoing event logging" 116 + " >= 1 - turns on outgoing event logging\n"
116 + ">= 2 - turns on poll notification", 117 + " >= 2 - turns on poll notification",
117 HandleDebugEq); 118 HandleDebugEq);
118 } 119 }
119 else 120 else
@@ -226,16 +227,6 @@ namespace OpenSim.Region.ClientStack.Linden
226 227
227 #endregion 228 #endregion
228 229
229 private void OnNewClient(IClientAPI client)
230 {
231 //client.OnLogout += ClientClosed;
232 }
233
234// private void ClientClosed(IClientAPI client)
235// {
236// ClientClosed(client.AgentId);
237// }
238
239 private void ClientClosed(UUID agentID, Scene scene) 230 private void ClientClosed(UUID agentID, Scene scene)
240 { 231 {
241// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 232// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index cd70410..d604cf6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
94 UUID spId = TestHelpers.ParseTail(0x1); 94 UUID spId = TestHelpers.ParseTail(0x1);
95 95
96 SceneHelpers.AddScenePresence(m_scene, spId); 96 SceneHelpers.AddScenePresence(m_scene, spId);
97 m_scene.IncomingCloseAgent(spId); 97 m_scene.IncomingCloseAgent(spId, false);
98 98
99 // TODO: Add more assertions for the other aspects of event queues 99 // TODO: Add more assertions for the other aspects of event queues
100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index 0a5ad0f..fcac182 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -109,7 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden
109 109
110 UUID capID = UUID.Random(); 110 UUID capID = UUID.Random();
111 111
112 m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 112// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
113 caps.RegisterHandler( 113 caps.RegisterHandler(
114 "SimConsoleAsync", 114 "SimConsoleAsync",
115 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); 115 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene));
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
index 1b8535c..e22670b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -45,7 +45,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45 public Packet Packet; 45 public Packet Packet;
46 46
47 /// <summary> 47 /// <summary>
48 /// Default constructor 48 /// No arg constructor.
49 /// </summary>
50 public IncomingPacket() {}
51
52 /// <summary>
53 /// Constructor
49 /// </summary> 54 /// </summary>
50 /// <param name="client">Reference to the client this packet came from</param> 55 /// <param name="client">Reference to the client this packet came from</param>
51 /// <param name="packet">Packet data</param> 56 /// <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 ae9ed7f..c9aa4ca 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -47,6 +47,7 @@ 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;
50using Nini.Config; 51using Nini.Config;
51 52
52using System.IO; 53using System.IO;
@@ -355,7 +356,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
355 private bool m_deliverPackets = true; 356 private bool m_deliverPackets = true;
356 private int m_animationSequenceNumber = 1; 357 private int m_animationSequenceNumber = 1;
357 private bool m_SendLogoutPacketWhenClosing = true; 358 private bool m_SendLogoutPacketWhenClosing = true;
358 private AgentUpdateArgs lastarg; 359
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;
359 370
360 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 371 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
361 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 372 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -510,19 +521,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
510 /// </summary> 521 /// </summary>
511 public void Close() 522 public void Close()
512 { 523 {
513 Close(true); 524 Close(true, false);
514 } 525 }
515 526
516 /// <summary> 527 public void Close(bool sendStop, bool force)
517 /// Shut down the client view
518 /// </summary>
519 public void Close(bool sendStop)
520 { 528 {
521 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 529 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
522 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 530 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
523 lock (CloseSyncLock) 531 lock (CloseSyncLock)
524 { 532 {
525 if (!IsActive) 533 // We still perform a force close inside the sync lock since this is intended to attempt close where
534 // there is some unidentified connection problem, not where we have issues due to deadlock
535 if (!IsActive && !force)
526 return; 536 return;
527 537
528 IsActive = false; 538 IsActive = false;
@@ -837,8 +847,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
837 OutPacket(mov, ThrottleOutPacketType.Unknown); 847 OutPacket(mov, ThrottleOutPacketType.Unknown);
838 } 848 }
839 849
840 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, 850 public void SendChatMessage(
841 UUID fromAgentID, byte source, byte audible) 851 string message, byte type, Vector3 fromPos, string fromName,
852 UUID fromAgentID, UUID ownerID, byte source, byte audible)
842 { 853 {
843 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 854 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
844 reply.ChatData.Audible = audible; 855 reply.ChatData.Audible = audible;
@@ -847,7 +858,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
847 reply.ChatData.SourceType = source; 858 reply.ChatData.SourceType = source;
848 reply.ChatData.Position = fromPos; 859 reply.ChatData.Position = fromPos;
849 reply.ChatData.FromName = Util.StringToBytes256(fromName); 860 reply.ChatData.FromName = Util.StringToBytes256(fromName);
850 reply.ChatData.OwnerID = fromAgentID; 861 reply.ChatData.OwnerID = ownerID;
851 reply.ChatData.SourceID = fromAgentID; 862 reply.ChatData.SourceID = fromAgentID;
852 863
853 OutPacket(reply, ThrottleOutPacketType.Unknown); 864 OutPacket(reply, ThrottleOutPacketType.Unknown);
@@ -3985,7 +3996,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3985 { 3996 {
3986 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3997 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3987 3998
3988 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3999 ImprovedTerseObjectUpdatePacket packet
4000 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3989 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4001 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3990 packet.RegionData.TimeDilation = timeDilation; 4002 packet.RegionData.TimeDilation = timeDilation;
3991 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4003 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4030,7 +4042,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4030 { 4042 {
4031 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 4043 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4032 4044
4033 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 4045 ImprovedTerseObjectUpdatePacket packet
4046 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4047 PacketType.ImprovedTerseObjectUpdate);
4034 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4048 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4035 packet.RegionData.TimeDilation = timeDilation; 4049 packet.RegionData.TimeDilation = timeDilation;
4036 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4050 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4038,7 +4052,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4038 for (int i = 0; i < blocks.Count; i++) 4052 for (int i = 0; i < blocks.Count; i++)
4039 packet.ObjectData[i] = blocks[i]; 4053 packet.ObjectData[i] = blocks[i];
4040 4054
4041 OutPacket(packet, ThrottleOutPacketType.Task, true); 4055 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4042 } 4056 }
4043 4057
4044 #endregion Packet Sending 4058 #endregion Packet Sending
@@ -4535,7 +4549,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4535 { 4549 {
4536 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); 4550 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4537 } 4551 }
4538 j = 0; 4552 j = 0;
4539 4553
4540 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4554 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4541 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4555 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@@ -5039,7 +5053,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5039 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; 5053 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
5040 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; 5054 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
5041 5055
5042 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); 5056 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block
5057 = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
5058
5043 block.Data = data; 5059 block.Data = data;
5044 5060
5045 if (textureEntry != null && textureEntry.Length > 0) 5061 if (textureEntry != null && textureEntry.Length > 0)
@@ -5289,14 +5305,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5289 protected virtual void RegisterLocalPacketHandlers() 5305 protected virtual void RegisterLocalPacketHandlers()
5290 { 5306 {
5291 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); 5307 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.
5292 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5311 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5312
5293 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5313 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5294 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5314 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5295 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5315 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5296 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5316 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
5297 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); 5317 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5298 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); 5318 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
5299 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); 5319 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
5300 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); 5320 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
5301 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); 5321 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
5302 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5322 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
@@ -5518,81 +5538,84 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5518 5538
5519 #region Scene/Avatar 5539 #region Scene/Avatar
5520 5540
5521 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) 5541 private bool HandleAgentUpdate(IClientAPI sener, Packet packet)
5522 { 5542 {
5523 if (OnAgentUpdate != null) 5543 if (OnAgentUpdate != null)
5524 { 5544 {
5525 bool update = false; 5545 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5526 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5527 5546
5528 #region Packet Session and User Check 5547 #region Packet Session and User Check
5529 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) 5548 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId)
5549 {
5550 PacketPool.Instance.ReturnPacket(packet);
5530 return false; 5551 return false;
5552 }
5531 #endregion 5553 #endregion
5532 5554
5533 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; 5555 bool update = false;
5534 5556 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5535 // We can only check when we have something to check
5536 // against.
5537 5557
5538 if (lastarg != null) 5558 if (m_lastAgentUpdateArgs != null)
5539 { 5559 {
5560 // These should be ordered from most-likely to
5561 // least likely to change. I've made an initial
5562 // guess at that.
5540 update = 5563 update =
5541 ( 5564 (
5542 (x.BodyRotation != lastarg.BodyRotation) || 5565 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) ||
5543 (x.CameraAtAxis != lastarg.CameraAtAxis) || 5566 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) ||
5544 (x.CameraCenter != lastarg.CameraCenter) || 5567 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
5545 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5568 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5546 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5569 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5547 (x.ControlFlags != lastarg.ControlFlags) || 5570 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5548 (x.ControlFlags != 0) || 5571 (x.ControlFlags != 0) ||
5549 (x.Far != lastarg.Far) || 5572 (x.Far != m_lastAgentUpdateArgs.Far) ||
5550 (x.Flags != lastarg.Flags) || 5573 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5551 (x.State != lastarg.State) || 5574 (x.State != m_lastAgentUpdateArgs.State) ||
5552 (x.HeadRotation != lastarg.HeadRotation) || 5575 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
5553 (x.SessionID != lastarg.SessionID) || 5576 (x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
5554 (x.AgentID != lastarg.AgentID) 5577 (x.AgentID != m_lastAgentUpdateArgs.AgentID)
5555 ); 5578 );
5556 } 5579 }
5557 else 5580 else
5558 { 5581 {
5582 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5559 update = true; 5583 update = true;
5560 } 5584 }
5561 5585
5562 // These should be ordered from most-likely to
5563 // least likely to change. I've made an initial
5564 // guess at that.
5565
5566 if (update) 5586 if (update)
5567 { 5587 {
5568// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5588// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
5569 5589
5570 AgentUpdateArgs arg = new AgentUpdateArgs(); 5590 m_lastAgentUpdateArgs.AgentID = x.AgentID;
5571 arg.AgentID = x.AgentID; 5591 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation;
5572 arg.BodyRotation = x.BodyRotation; 5592 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5573 arg.CameraAtAxis = x.CameraAtAxis; 5593 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter;
5574 arg.CameraCenter = x.CameraCenter; 5594 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5575 arg.CameraLeftAxis = x.CameraLeftAxis; 5595 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5576 arg.CameraUpAxis = x.CameraUpAxis; 5596 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags;
5577 arg.ControlFlags = x.ControlFlags; 5597 m_lastAgentUpdateArgs.Far = x.Far;
5578 arg.Far = x.Far; 5598 m_lastAgentUpdateArgs.Flags = x.Flags;
5579 arg.Flags = x.Flags; 5599 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
5580 arg.HeadRotation = x.HeadRotation; 5600 m_lastAgentUpdateArgs.SessionID = x.SessionID;
5581 arg.SessionID = x.SessionID; 5601 m_lastAgentUpdateArgs.State = x.State;
5582 arg.State = x.State; 5602
5583 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5603 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5584 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5604 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5585 lastarg = arg; // save this set of arguments for nexttime 5605
5586 if (handlerPreAgentUpdate != null) 5606 if (handlerPreAgentUpdate != null)
5587 OnPreAgentUpdate(this, arg); 5607 OnPreAgentUpdate(this, m_lastAgentUpdateArgs);
5608
5588 if (handlerAgentUpdate != null) 5609 if (handlerAgentUpdate != null)
5589 OnAgentUpdate(this, arg); 5610 OnAgentUpdate(this, m_lastAgentUpdateArgs);
5590 5611
5591 handlerAgentUpdate = null; 5612 handlerAgentUpdate = null;
5592 handlerPreAgentUpdate = null; 5613 handlerPreAgentUpdate = null;
5593 } 5614 }
5594 } 5615 }
5595 5616
5617 PacketPool.Instance.ReturnPacket(packet);
5618
5596 return true; 5619 return true;
5597 } 5620 }
5598 5621
@@ -5964,7 +5987,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5964 msgpack.MessageBlock.ID, 5987 msgpack.MessageBlock.ID,
5965 msgpack.MessageBlock.Offline != 0 ? true : false, 5988 msgpack.MessageBlock.Offline != 0 ? true : false,
5966 msgpack.MessageBlock.Position, 5989 msgpack.MessageBlock.Position,
5967 msgpack.MessageBlock.BinaryBucket); 5990 msgpack.MessageBlock.BinaryBucket,
5991 true);
5968 5992
5969 handlerInstantMessage(this, im); 5993 handlerInstantMessage(this, im);
5970 } 5994 }
@@ -9251,7 +9275,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9251 } 9275 }
9252 #endregion 9276 #endregion
9253 9277
9254 switch (Utils.BytesToString(messagePacket.MethodData.Method)) 9278 string method = Utils.BytesToString(messagePacket.MethodData.Method);
9279
9280 switch (method)
9255 { 9281 {
9256 case "getinfo": 9282 case "getinfo":
9257 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 9283 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
@@ -9567,7 +9593,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9567 return true; 9593 return true;
9568 9594
9569 default: 9595 default:
9570 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); 9596 m_log.WarnFormat(
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
9571 return true; 9607 return true;
9572 } 9608 }
9573 9609
@@ -11960,7 +11996,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11960 logPacket = false; 11996 logPacket = false;
11961 11997
11962 if (DebugPacketLevel <= 50 11998 if (DebugPacketLevel <= 50
11963 & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) 11999 && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
11964 logPacket = false; 12000 logPacket = false;
11965 12001
11966 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) 12002 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -12034,8 +12070,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12034 12070
12035 if (!ProcessPacketMethod(packet)) 12071 if (!ProcessPacketMethod(packet))
12036 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 12072 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
12037
12038 PacketPool.Instance.ReturnPacket(packet);
12039 } 12073 }
12040 12074
12041 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 12075 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -12204,7 +12238,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12204 { 12238 {
12205 Kick(reason); 12239 Kick(reason);
12206 Thread.Sleep(1000); 12240 Thread.Sleep(1000);
12207 Close(); 12241 Disconnect();
12208 } 12242 }
12209 12243
12210 public void Disconnect() 12244 public void Disconnect()
@@ -12492,7 +12526,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12492 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 12526 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12493 12527
12494 12528
12495 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 12529 ImprovedTerseObjectUpdatePacket packet
12530 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12531 PacketType.ImprovedTerseObjectUpdate);
12532
12496 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 12533 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
12497 packet.RegionData.TimeDilation = timeDilation; 12534 packet.RegionData.TimeDilation = timeDilation;
12498 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 12535 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 d6513c5..b8951d9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,6 +37,7 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 41using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42using OpenMetaverse; 43using OpenMetaverse;
@@ -100,9 +101,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
100 101
101 /// <summary>The measured resolution of Environment.TickCount</summary> 102 /// <summary>The measured resolution of Environment.TickCount</summary>
102 public readonly float TickCountResolution; 103 public readonly float TickCountResolution;
104
103 /// <summary>Number of prim updates to put on the queue each time the 105 /// <summary>Number of prim updates to put on the queue each time the
104 /// OnQueueEmpty event is triggered for updates</summary> 106 /// OnQueueEmpty event is triggered for updates</summary>
105 public readonly int PrimUpdatesPerCallback; 107 public readonly int PrimUpdatesPerCallback;
108
106 /// <summary>Number of texture packets to put on the queue each time the 109 /// <summary>Number of texture packets to put on the queue each time the
107 /// OnQueueEmpty event is triggered for textures</summary> 110 /// OnQueueEmpty event is triggered for textures</summary>
108 public readonly int TextureSendLimit; 111 public readonly int TextureSendLimit;
@@ -124,28 +127,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
124 127
125 /// <summary>Manages authentication for agent circuits</summary> 128 /// <summary>Manages authentication for agent circuits</summary>
126 private AgentCircuitManager m_circuitManager; 129 private AgentCircuitManager m_circuitManager;
130
127 /// <summary>Reference to the scene this UDP server is attached to</summary> 131 /// <summary>Reference to the scene this UDP server is attached to</summary>
128 protected Scene m_scene; 132 protected Scene m_scene;
133
129 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 134 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
130 private Location m_location; 135 private Location m_location;
136
131 /// <summary>The size of the receive buffer for the UDP socket. This value 137 /// <summary>The size of the receive buffer for the UDP socket. This value
132 /// is passed up to the operating system and used in the system networking 138 /// is passed up to the operating system and used in the system networking
133 /// stack. Use zero to leave this value as the default</summary> 139 /// stack. Use zero to leave this value as the default</summary>
134 private int m_recvBufferSize; 140 private int m_recvBufferSize;
141
135 /// <summary>Flag to process packets asynchronously or synchronously</summary> 142 /// <summary>Flag to process packets asynchronously or synchronously</summary>
136 private bool m_asyncPacketHandling; 143 private bool m_asyncPacketHandling;
144
137 /// <summary>Tracks whether or not a packet was sent each round so we know 145 /// <summary>Tracks whether or not a packet was sent each round so we know
138 /// whether or not to sleep</summary> 146 /// whether or not to sleep</summary>
139 private bool m_packetSent; 147 private bool m_packetSent;
140 148
141 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> 149 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
142 private int m_elapsedMSSinceLastStatReport = 0; 150 private int m_elapsedMSSinceLastStatReport = 0;
151
143 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> 152 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
144 private int m_tickLastOutgoingPacketHandler; 153 private int m_tickLastOutgoingPacketHandler;
154
145 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> 155 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
146 private int m_elapsedMSOutgoingPacketHandler; 156 private int m_elapsedMSOutgoingPacketHandler;
157
147 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> 158 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
148 private int m_elapsed100MSOutgoingPacketHandler; 159 private int m_elapsed100MSOutgoingPacketHandler;
160
149 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> 161 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
150 private int m_elapsed500MSOutgoingPacketHandler; 162 private int m_elapsed500MSOutgoingPacketHandler;
151 163
@@ -159,6 +171,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
159 protected bool m_sendPing; 171 protected bool m_sendPing;
160 172
161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 173 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
174 private Pool<IncomingPacket> m_incomingPacketPool;
175
176 private Stat m_incomingPacketPoolStat;
162 177
163 private int m_defaultRTO = 0; 178 private int m_defaultRTO = 0;
164 private int m_maxRTO = 0; 179 private int m_maxRTO = 0;
@@ -180,7 +195,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
180 /// </summary> 195 /// </summary>
181 private IClientAPI m_currentIncomingClient; 196 private IClientAPI m_currentIncomingClient;
182 197
183 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 198 public LLUDPServer(
199 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
200 IConfigSource configSource, AgentCircuitManager circuitManager)
184 : base(listenIP, (int)port) 201 : base(listenIP, (int)port)
185 { 202 {
186 #region Environment.TickCount Measurement 203 #region Environment.TickCount Measurement
@@ -202,6 +219,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 219
203 m_circuitManager = circuitManager; 220 m_circuitManager = circuitManager;
204 int sceneThrottleBps = 0; 221 int sceneThrottleBps = 0;
222 bool usePools = false;
205 223
206 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 224 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
207 if (config != null) 225 if (config != null)
@@ -227,6 +245,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
227 m_pausedAckTimeout = 1000 * 300; // 5 minutes 245 m_pausedAckTimeout = 1000 * 300; // 5 minutes
228 } 246 }
229 247
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
230 #region BinaryStats 258 #region BinaryStats
231 config = configSource.Configs["Statistics.Binary"]; 259 config = configSource.Configs["Statistics.Binary"];
232 m_shouldCollectStats = false; 260 m_shouldCollectStats = false;
@@ -254,20 +282,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
254 282
255 m_throttle = new TokenBucket(null, sceneThrottleBps); 283 m_throttle = new TokenBucket(null, sceneThrottleBps);
256 ThrottleRates = new ThrottleRates(configSource); 284 ThrottleRates = new ThrottleRates(configSource);
285
286 if (usePools)
287 EnablePools();
257 } 288 }
258 289
259 public void Start() 290 public void Start()
260 { 291 {
261 if (m_scene == null) 292 StartInbound();
262 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); 293 StartOutbound();
263 294
295 m_elapsedMSSinceLastStatReport = Environment.TickCount;
296 }
297
298 private void StartInbound()
299 {
264 m_log.InfoFormat( 300 m_log.InfoFormat(
265 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", 301 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}",
266 m_asyncPacketHandling ? "asynchronous" : "synchronous"); 302 m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools);
267 303
268 base.Start(m_recvBufferSize, m_asyncPacketHandling); 304 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling);
269 305
270 // Start the packet processing threads 306 // This thread will process the packets received that are placed on the packetInbox
271 Watchdog.StartThread( 307 Watchdog.StartThread(
272 IncomingPacketHandler, 308 IncomingPacketHandler,
273 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), 309 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -276,6 +312,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
276 true, 312 true,
277 GetWatchdogIncomingAlarmData, 313 GetWatchdogIncomingAlarmData,
278 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 314 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();
279 322
280 Watchdog.StartThread( 323 Watchdog.StartThread(
281 OutgoingPacketHandler, 324 OutgoingPacketHandler,
@@ -285,8 +328,57 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 true, 328 true,
286 GetWatchdogOutgoingAlarmData, 329 GetWatchdogOutgoingAlarmData,
287 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 330 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
331 }
288 332
289 m_elapsedMSSinceLastStatReport = Environment.TickCount; 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
340 protected override bool EnablePools()
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;
290 } 382 }
291 383
292 /// <summary> 384 /// <summary>
@@ -311,12 +403,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
311 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); 403 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
312 } 404 }
313 405
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
320 public void AddScene(IScene scene) 406 public void AddScene(IScene scene)
321 { 407 {
322 if (m_scene != null) 408 if (m_scene != null)
@@ -333,6 +419,117 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 419
334 m_scene = (Scene)scene; 420 m_scene = (Scene)scene;
335 m_location = new Location(m_scene.RegionInfo.RegionHandle); 421 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");
336 } 533 }
337 534
338 public bool HandlesRegion(Location x) 535 public bool HandlesRegion(Location x)
@@ -416,6 +613,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 byte[] data = packet.ToBytes(); 613 byte[] data = packet.ToBytes();
417 SendPacketData(udpClient, data, packet.Type, category, method); 614 SendPacketData(udpClient, data, packet.Type, category, method);
418 } 615 }
616
617 PacketPool.Instance.ReturnPacket(packet);
419 } 618 }
420 619
421 /// <summary> 620 /// <summary>
@@ -700,7 +899,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
700 LLUDPClient udpClient = null; 899 LLUDPClient udpClient = null;
701 Packet packet = null; 900 Packet packet = null;
702 int packetEnd = buffer.DataLength - 1; 901 int packetEnd = buffer.DataLength - 1;
703 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; 902 IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint;
704 903
705 #region Decoding 904 #region Decoding
706 905
@@ -710,7 +909,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
710// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 909// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
711// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 910// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
712 911
713 return; // Drop undersizd packet 912 return; // Drop undersized packet
714 } 913 }
715 914
716 int headerLen = 7; 915 int headerLen = 7;
@@ -733,7 +932,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
733 932
734 try 933 try
735 { 934 {
736 packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 935// 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,
737 // Only allocate a buffer for zerodecoding if the packet is zerocoded 942 // Only allocate a buffer for zerodecoding if the packet is zerocoded
738 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 943 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
739 } 944 }
@@ -748,11 +953,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
748 953
749 return; // Drop short packet 954 return; // Drop short packet
750 } 955 }
751 catch(Exception e) 956 catch (Exception e)
752 { 957 {
753 if (m_malformedCount < 100) 958 if (m_malformedCount < 100)
754 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 959 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
960
755 m_malformedCount++; 961 m_malformedCount++;
962
756 if ((m_malformedCount % 100000) == 0) 963 if ((m_malformedCount % 100000) == 0)
757 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); 964 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
758 } 965 }
@@ -772,7 +979,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
772 979
773 // If there is already a client for this endpoint, don't process UseCircuitCode 980 // If there is already a client for this endpoint, don't process UseCircuitCode
774 IClientAPI client = null; 981 IClientAPI client = null;
775 if (!m_scene.TryGetClient(address, out client)) 982 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
776 { 983 {
777 // UseCircuitCode handling 984 // UseCircuitCode handling
778 if (packet.Type == PacketType.UseCircuitCode) 985 if (packet.Type == PacketType.UseCircuitCode)
@@ -780,13 +987,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
780 // And if there is a UseCircuitCode pending, also drop it 987 // And if there is a UseCircuitCode pending, also drop it
781 lock (m_pendingCache) 988 lock (m_pendingCache)
782 { 989 {
783 if (m_pendingCache.Contains(address)) 990 if (m_pendingCache.Contains(endPoint))
784 return; 991 return;
785 992
786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60); 993 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
787 } 994 }
788 995
789 object[] array = new object[] { buffer, packet }; 996 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
997 // buffer.
998 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
790 999
791 Util.FireAndForget(HandleUseCircuitCode, array); 1000 Util.FireAndForget(HandleUseCircuitCode, array);
792 1001
@@ -798,7 +1007,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
798 lock (m_pendingCache) 1007 lock (m_pendingCache)
799 { 1008 {
800 Queue<UDPPacketBuffer> queue; 1009 Queue<UDPPacketBuffer> queue;
801 if (m_pendingCache.TryGetValue(address, out queue)) 1010 if (m_pendingCache.TryGetValue(endPoint, out queue))
802 { 1011 {
803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); 1012 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
804 queue.Enqueue(buffer); 1013 queue.Enqueue(buffer);
@@ -834,6 +1043,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
834 // Handle appended ACKs 1043 // Handle appended ACKs
835 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 1044 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
836 { 1045 {
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
837 for (int i = 0; i < packet.Header.AckList.Length; i++) 1050 for (int i = 0; i < packet.Header.AckList.Length; i++)
838 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1051 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
839 } 1052 }
@@ -843,6 +1056,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
843 { 1056 {
844 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1057 PacketAckPacket ackPacket = (PacketAckPacket)packet;
845 1058
1059// m_log.DebugFormat(
1060// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1061// ackPacket.Packets.Length, client.Name, m_scene.Name);
1062
846 for (int i = 0; i < ackPacket.Packets.Length; i++) 1063 for (int i = 0; i < ackPacket.Packets.Length; i++)
847 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1064 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
848 1065
@@ -856,6 +1073,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
856 1073
857 if (packet.Header.Reliable) 1074 if (packet.Header.Reliable)
858 { 1075 {
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
859 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 1080 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
860 1081
861 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 1082 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
@@ -902,6 +1123,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
902 1123
903 if (packet.Type == PacketType.StartPingCheck) 1124 if (packet.Type == PacketType.StartPingCheck)
904 { 1125 {
1126// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);
1127
905 // We don't need to do anything else with ping checks 1128 // We don't need to do anything else with ping checks
906 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1129 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
907 CompletePing(udpClient, startPing.PingID.PingID); 1130 CompletePing(udpClient, startPing.PingID.PingID);
@@ -921,13 +1144,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
921 1144
922 #endregion Ping Check Handling 1145 #endregion Ping Check Handling
923 1146
1147 IncomingPacket incomingPacket;
1148
924 // Inbox insertion 1149 // Inbox insertion
925 if (packet.Type == PacketType.AgentUpdate || 1150 if (UsePools)
926 packet.Type == PacketType.ChatFromViewer) 1151 {
927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); 1152 incomingPacket = m_incomingPacketPool.GetObject();
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);
928 else 1164 else
929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); 1165 packetInbox.EnqueueLow(incomingPacket);
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
931 } 1166 }
932 1167
933 #region BinaryStats 1168 #region BinaryStats
@@ -1013,21 +1248,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1013 1248
1014 private void HandleUseCircuitCode(object o) 1249 private void HandleUseCircuitCode(object o)
1015 { 1250 {
1016 IPEndPoint remoteEndPoint = null; 1251 IPEndPoint endPoint = null;
1017 IClientAPI client = null; 1252 IClientAPI client = null;
1018 1253
1019 try 1254 try
1020 { 1255 {
1021 // DateTime startTime = DateTime.Now; 1256 // DateTime startTime = DateTime.Now;
1022 object[] array = (object[])o; 1257 object[] array = (object[])o;
1023 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; 1258 endPoint = (IPEndPoint)array[0];
1024 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1259 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
1025 1260
1026 m_log.DebugFormat( 1261 m_log.DebugFormat(
1027 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1262 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1028 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); 1263 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint);
1029
1030 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
1031 1264
1032 AuthenticateResponse sessionInfo; 1265 AuthenticateResponse sessionInfo;
1033 if (IsClientAuthorized(uccp, out sessionInfo)) 1266 if (IsClientAuthorized(uccp, out sessionInfo))
@@ -1038,13 +1271,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1038 uccp.CircuitCode.Code, 1271 uccp.CircuitCode.Code,
1039 uccp.CircuitCode.ID, 1272 uccp.CircuitCode.ID,
1040 uccp.CircuitCode.SessionID, 1273 uccp.CircuitCode.SessionID,
1041 remoteEndPoint, 1274 endPoint,
1042 sessionInfo); 1275 sessionInfo);
1043 1276
1044 // Send ack straight away to let the viewer know that the connection is active. 1277 // Send ack straight away to let the viewer know that the connection is active.
1045 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1278 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1046 // circuit code to the existing child agent. This is not particularly obvious. 1279 // circuit code to the existing child agent. This is not particularly obvious.
1047 SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); 1280 SendAckImmediate(endPoint, uccp.Header.Sequence);
1048 1281
1049 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1282 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1050 if (client != null) 1283 if (client != null)
@@ -1058,12 +1291,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1058 1291
1059 lock (m_pendingCache) 1292 lock (m_pendingCache)
1060 { 1293 {
1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) 1294 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1062 { 1295 {
1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1296 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1064 return; 1297 return;
1065 } 1298 }
1066 m_pendingCache.Remove(remoteEndPoint); 1299 m_pendingCache.Remove(endPoint);
1067 } 1300 }
1068 1301
1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); 1302 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
@@ -1081,9 +1314,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1081 // Don't create clients for unauthorized requesters. 1314 // Don't create clients for unauthorized requesters.
1082 m_log.WarnFormat( 1315 m_log.WarnFormat(
1083 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1316 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1317 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1085 lock (m_pendingCache) 1318 lock (m_pendingCache)
1086 m_pendingCache.Remove(remoteEndPoint); 1319 m_pendingCache.Remove(endPoint);
1087 } 1320 }
1088 1321
1089 // m_log.DebugFormat( 1322 // m_log.DebugFormat(
@@ -1095,7 +1328,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1095 { 1328 {
1096 m_log.ErrorFormat( 1329 m_log.ErrorFormat(
1097 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", 1330 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1098 remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", 1331 endPoint != null ? endPoint.ToString() : "n/a",
1099 client != null ? client.Name : "unknown", 1332 client != null ? client.Name : "unknown",
1100 client != null ? client.AgentId.ToString() : "unknown", 1333 client != null ? client.AgentId.ToString() : "unknown",
1101 e.Message, 1334 e.Message,
@@ -1160,20 +1393,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1160 { 1393 {
1161 IClientAPI client = null; 1394 IClientAPI client = null;
1162 1395
1163 // In priciple there shouldn't be more than one thread here, ever. 1396 // We currently synchronize this code across the whole scene to avoid issues such as
1164 // But in case that happens, we need to synchronize this piece of code 1397 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
1165 // because it's too important 1398 // consistently, this lock could probably be removed.
1166 lock (this) 1399 lock (this)
1167 { 1400 {
1168 if (!m_scene.TryGetClient(agentID, out client)) 1401 if (!m_scene.TryGetClient(agentID, out client))
1169 { 1402 {
1170 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1403 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1171 1404
1172 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1405 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1173 client.OnLogout += LogoutHandler; 1406 client.OnLogout += LogoutHandler;
1174 1407
1175 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1408 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1176 1409
1177 client.Start(); 1410 client.Start();
1178 } 1411 }
1179 } 1412 }
@@ -1212,7 +1445,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1212 // on to en-US to avoid number parsing issues 1445 // on to en-US to avoid number parsing issues
1213 Culture.SetCurrentCulture(); 1446 Culture.SetCurrentCulture();
1214 1447
1215 while (base.IsRunning) 1448 while (IsRunningInbound)
1216 { 1449 {
1217 m_scene.ThreadAlive(1); 1450 m_scene.ThreadAlive(1);
1218 try 1451 try
@@ -1228,7 +1461,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1228 } 1461 }
1229 1462
1230 if (packetInbox.Dequeue(100, ref incomingPacket)) 1463 if (packetInbox.Dequeue(100, ref incomingPacket))
1464 {
1231 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); 1465 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
1466
1467 if (UsePools)
1468 m_incomingPacketPool.ReturnObject(incomingPacket);
1469 }
1232 } 1470 }
1233 catch (Exception ex) 1471 catch (Exception ex)
1234 { 1472 {
@@ -1255,7 +1493,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1255 // Action generic every round 1493 // Action generic every round
1256 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1494 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1257 1495
1258 while (base.IsRunning) 1496 while (base.IsRunningOutbound)
1259 { 1497 {
1260 m_scene.ThreadAlive(2); 1498 m_scene.ThreadAlive(2);
1261 try 1499 try
@@ -1523,7 +1761,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1523 if (!client.IsLoggingOut) 1761 if (!client.IsLoggingOut)
1524 { 1762 {
1525 client.IsLoggingOut = true; 1763 client.IsLoggingOut = true;
1526 client.Close(false); 1764 client.Close(false, false);
1527 } 1765 }
1528 } 1766 }
1529 } 1767 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index cfe7c9d..8bd3461 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -30,6 +30,8 @@ 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;
33 35
34namespace OpenMetaverse 36namespace OpenMetaverse
35{ 37{
@@ -58,17 +60,31 @@ namespace OpenMetaverse
58 /// <summary>Flag to process packets asynchronously or synchronously</summary> 60 /// <summary>Flag to process packets asynchronously or synchronously</summary>
59 private bool m_asyncPacketHandling; 61 private bool m_asyncPacketHandling;
60 62
61 /// <summary>The all important shutdown flag</summary> 63 /// <summary>
62 private volatile bool m_shutdownFlag = true; 64 /// Pool to use for handling data. May be null if UsePools = false;
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; }
63 75
64 /// <summary>Returns true if the server is currently listening, otherwise false</summary> 76 /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary>
65 public bool IsRunning { get { return !m_shutdownFlag; } } 77 /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks>
78 public bool IsRunningOutbound { get; private set; }
79
80 private Stat m_poolCountStat;
66 81
67 /// <summary> 82 /// <summary>
68 /// Default constructor 83 /// Default constructor
69 /// </summary> 84 /// </summary>
70 /// <param name="bindAddress">Local IP address to bind the server to</param> 85 /// <param name="bindAddress">Local IP address to bind the server to</param>
71 /// <param name="port">Port to listening for incoming UDP packets on</param> 86 /// <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>
72 public OpenSimUDPBase(IPAddress bindAddress, int port) 88 public OpenSimUDPBase(IPAddress bindAddress, int port)
73 { 89 {
74 m_localBindAddress = bindAddress; 90 m_localBindAddress = bindAddress;
@@ -76,7 +92,7 @@ namespace OpenMetaverse
76 } 92 }
77 93
78 /// <summary> 94 /// <summary>
79 /// Start the UDP server 95 /// Start inbound UDP packet handling.
80 /// </summary> 96 /// </summary>
81 /// <param name="recvBufferSize">The size of the receive buffer for 97 /// <param name="recvBufferSize">The size of the receive buffer for
82 /// the UDP socket. This value is passed up to the operating system 98 /// the UDP socket. This value is passed up to the operating system
@@ -91,11 +107,11 @@ namespace OpenMetaverse
91 /// manner (not throwing an exception when the remote side resets the 107 /// manner (not throwing an exception when the remote side resets the
92 /// connection). This call is ignored on Mono where the flag is not 108 /// connection). This call is ignored on Mono where the flag is not
93 /// necessary</remarks> 109 /// necessary</remarks>
94 public void Start(int recvBufferSize, bool asyncPacketHandling) 110 public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
95 { 111 {
96 m_asyncPacketHandling = asyncPacketHandling; 112 m_asyncPacketHandling = asyncPacketHandling;
97 113
98 if (m_shutdownFlag) 114 if (!IsRunningInbound)
99 { 115 {
100 const int SIO_UDP_CONNRESET = -1744830452; 116 const int SIO_UDP_CONNRESET = -1744830452;
101 117
@@ -123,8 +139,7 @@ namespace OpenMetaverse
123 139
124 m_udpSocket.Bind(ipep); 140 m_udpSocket.Bind(ipep);
125 141
126 // we're not shutting down, we're starting up 142 IsRunningInbound = true;
127 m_shutdownFlag = false;
128 143
129 // kick off an async receive. The Start() method will return, the 144 // kick off an async receive. The Start() method will return, the
130 // actual receives will occur asynchronously and will be caught in 145 // actual receives will occur asynchronously and will be caught in
@@ -134,28 +149,84 @@ namespace OpenMetaverse
134 } 149 }
135 150
136 /// <summary> 151 /// <summary>
137 /// Stops the UDP server 152 /// Start outbound UDP packet handling.
138 /// </summary> 153 /// </summary>
139 public void Stop() 154 public void StartOutbound()
155 {
156 IsRunningOutbound = true;
157 }
158
159 public void StopInbound()
140 { 160 {
141 if (!m_shutdownFlag) 161 if (IsRunningInbound)
142 { 162 {
143 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 163 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
144 // will deny any more reader locks, in effect blocking all other send/receive 164 // will deny any more reader locks, in effect blocking all other send/receive
145 // threads. Once we have the lock, we set shutdownFlag to inform the other 165 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other
146 // threads that the socket is closed. 166 // threads that the socket is closed.
147 m_shutdownFlag = true; 167 IsRunningInbound = false;
148 m_udpSocket.Close(); 168 m_udpSocket.Close();
149 } 169 }
150 } 170 }
151 171
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
152 private void AsyncBeginReceive() 220 private void AsyncBeginReceive()
153 { 221 {
154 // allocate a packet buffer 222 UDPPacketBuffer buf;
155 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); 223
156 UDPPacketBuffer buf = new UDPPacketBuffer(); 224 if (UsePools)
225 buf = m_pool.GetObject();
226 else
227 buf = new UDPPacketBuffer();
157 228
158 if (!m_shutdownFlag) 229 if (IsRunningInbound)
159 { 230 {
160 try 231 try
161 { 232 {
@@ -208,7 +279,7 @@ namespace OpenMetaverse
208 { 279 {
209 // Asynchronous receive operations will complete here through the call 280 // Asynchronous receive operations will complete here through the call
210 // to AsyncBeginReceive 281 // to AsyncBeginReceive
211 if (!m_shutdownFlag) 282 if (IsRunningInbound)
212 { 283 {
213 // Asynchronous mode will start another receive before the 284 // Asynchronous mode will start another receive before the
214 // callback for this packet is even fired. Very parallel :-) 285 // callback for this packet is even fired. Very parallel :-)
@@ -217,8 +288,6 @@ namespace OpenMetaverse
217 288
218 // get the buffer that was created in AsyncBeginReceive 289 // get the buffer that was created in AsyncBeginReceive
219 // this is the received data 290 // this is the received data
220 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
221 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
222 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 291 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
223 292
224 try 293 try
@@ -235,7 +304,8 @@ namespace OpenMetaverse
235 catch (ObjectDisposedException) { } 304 catch (ObjectDisposedException) { }
236 finally 305 finally
237 { 306 {
238 //wrappedBuffer.Dispose(); 307 if (UsePools)
308 m_pool.ReturnObject(buffer);
239 309
240 // Synchronous mode waits until the packet callback completes 310 // Synchronous mode waits until the packet callback completes
241 // before starting the receive to fetch another packet 311 // before starting the receive to fetch another packet
@@ -248,7 +318,7 @@ namespace OpenMetaverse
248 318
249 public void AsyncBeginSend(UDPPacketBuffer buf) 319 public void AsyncBeginSend(UDPPacketBuffer buf)
250 { 320 {
251 if (!m_shutdownFlag) 321 if (IsRunningOutbound)
252 { 322 {
253 try 323 try
254 { 324 {
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
new file mode 100644
index 0000000..9f22fb4
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
@@ -0,0 +1,316 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using OpenMetaverse.Packets;
33using log4net;
34using OpenSim.Framework.Monitoring;
35
36namespace OpenSim.Region.ClientStack.LindenUDP
37{
38 public sealed class PacketPool
39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 private static readonly PacketPool instance = new PacketPool();
43
44 private bool packetPoolEnabled = true;
45 private bool dataBlockPoolEnabled = true;
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>>();
71
72 private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>();
73
74 public static PacketPool Instance
75 {
76 get { return instance; }
77 }
78
79 public bool RecyclePackets
80 {
81 set { packetPoolEnabled = value; }
82 get { return packetPoolEnabled; }
83 }
84
85 public bool RecycleDataBlocks
86 {
87 set { dataBlockPoolEnabled = value; }
88 get { return dataBlockPoolEnabled; }
89 }
90
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)
127 {
128 m_packetsReusedStat.Consequent++;
129
130 Packet packet;
131
132 if (!packetPoolEnabled)
133 return Packet.BuildPacket(type);
134
135 lock (pool)
136 {
137 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
138 {
139// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type);
140
141 // Creating a new packet if we cannot reuse an old package
142 packet = Packet.BuildPacket(type);
143 }
144 else
145 {
146// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type);
147
148 // Recycle old packages
149 m_packetsReusedStat.Antecedent++;
150
151 packet = pool[type].Pop();
152 }
153 }
154
155 return packet;
156 }
157
158 // private byte[] decoded_header = new byte[10];
159 private static PacketType GetType(byte[] bytes)
160 {
161 byte[] decoded_header = new byte[10 + 8];
162 ushort id;
163 PacketFrequency freq;
164
165 if ((bytes[0] & Helpers.MSG_ZEROCODED) != 0)
166 {
167 Helpers.ZeroDecode(bytes, 16, decoded_header);
168 }
169 else
170 {
171 Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10);
172 }
173
174 if (decoded_header[6] == 0xFF)
175 {
176 if (decoded_header[7] == 0xFF)
177 {
178 id = (ushort) ((decoded_header[8] << 8) + decoded_header[9]);
179 freq = PacketFrequency.Low;
180 }
181 else
182 {
183 id = decoded_header[7];
184 freq = PacketFrequency.Medium;
185 }
186 }
187 else
188 {
189 id = decoded_header[6];
190 freq = PacketFrequency.High;
191 }
192
193 return Packet.GetType(id, freq);
194 }
195
196 public Packet GetPacket(byte[] bytes, ref int packetEnd, byte[] zeroBuffer)
197 {
198 PacketType type = GetType(bytes);
199
200// Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
201
202 int i = 0;
203 Packet packet = GetPacket(type);
204 if (packet == null)
205 m_log.WarnFormat("[PACKETPOOL]: Failed to get packet of type {0}", type);
206 else
207 packet.FromBytes(bytes, ref i, ref packetEnd, zeroBuffer);
208
209 return packet;
210 }
211
212 /// <summary>
213 /// Return a packet to the packet pool
214 /// </summary>
215 /// <param name="packet"></param>
216 public void ReturnPacket(Packet packet)
217 {
218 if (dataBlockPoolEnabled)
219 {
220 switch (packet.Type)
221 {
222 case PacketType.ObjectUpdate:
223 ObjectUpdatePacket oup = (ObjectUpdatePacket)packet;
224
225 foreach (ObjectUpdatePacket.ObjectDataBlock oupod in oup.ObjectData)
226 ReturnDataBlock<ObjectUpdatePacket.ObjectDataBlock>(oupod);
227
228 oup.ObjectData = null;
229 break;
230
231 case PacketType.ImprovedTerseObjectUpdate:
232 ImprovedTerseObjectUpdatePacket itoup = (ImprovedTerseObjectUpdatePacket)packet;
233
234 foreach (ImprovedTerseObjectUpdatePacket.ObjectDataBlock itoupod in itoup.ObjectData)
235 ReturnDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(itoupod);
236
237 itoup.ObjectData = null;
238 break;
239 }
240 }
241
242 if (packetPoolEnabled)
243 {
244 switch (packet.Type)
245 {
246 // List pooling packets here
247 case PacketType.AgentUpdate:
248 case PacketType.PacketAck:
249 case PacketType.ObjectUpdate:
250 case PacketType.ImprovedTerseObjectUpdate:
251 lock (pool)
252 {
253 PacketType type = packet.Type;
254
255 if (!pool.ContainsKey(type))
256 {
257 pool[type] = new Stack<Packet>();
258 }
259
260 if ((pool[type]).Count < 50)
261 {
262// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type);
263
264 pool[type].Push(packet);
265 }
266 }
267 break;
268
269 // Other packets wont pool
270 default:
271 return;
272 }
273 }
274 }
275
276 public T GetDataBlock<T>() where T: new()
277 {
278 lock (DataBlocks)
279 {
280 m_blocksReusedStat.Consequent++;
281
282 Stack<Object> s;
283
284 if (DataBlocks.TryGetValue(typeof(T), out s))
285 {
286 if (s.Count > 0)
287 {
288 m_blocksReusedStat.Antecedent++;
289 return (T)s.Pop();
290 }
291 }
292 else
293 {
294 DataBlocks[typeof(T)] = new Stack<Object>();
295 }
296
297 return new T();
298 }
299 }
300
301 public void ReturnDataBlock<T>(T block) where T: new()
302 {
303 if (block == null)
304 return;
305
306 lock (DataBlocks)
307 {
308 if (!DataBlocks.ContainsKey(typeof(T)))
309 DataBlocks[typeof(T)] = new Stack<Object>();
310
311 if (DataBlocks[typeof(T)].Count < 50)
312 DataBlocks[typeof(T)].Push(block);
313 }
314 }
315 }
316} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 109a8e1..556df30 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 46 public class BasicCircuitTests : OpenSimTestCase
47 { 47 {
48 private Scene m_scene; 48 private Scene m_scene;
49 private TestLLUDPServer m_udpServer; 49 private TestLLUDPServer m_udpServer;
@@ -65,8 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
65 } 65 }
66 66
67 [SetUp] 67 [SetUp]
68 public void SetUp() 68 public override void SetUp()
69 { 69 {
70 base.SetUp();
70 m_scene = new SceneHelpers().SetupScene(); 71 m_scene = new SceneHelpers().SetupScene();
71 } 72 }
72 73
@@ -143,7 +144,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
143 public void TestAddClient() 144 public void TestAddClient()
144 { 145 {
145 TestHelpers.InMethod(); 146 TestHelpers.InMethod();
146// XmlConfigurator.Configure(); 147// TestHelpers.EnableLogging();
147 148
148 AddUdpServer(); 149 AddUdpServer();
149 150
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index 4672f8a..853b72d 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack
76 76
77 protected override void StartupSpecific() 77 protected override void StartupSpecific()
78 { 78 {
79 SceneManager = new SceneManager(); 79 SceneManager = SceneManager.Instance;
80 m_clientStackManager = CreateClientStackManager(); 80 m_clientStackManager = CreateClientStackManager();
81 81
82 Initialize(); 82 Initialize();