diff options
author | BlueWall | 2012-10-20 05:25:58 -0400 |
---|---|---|
committer | BlueWall | 2012-10-20 05:25:58 -0400 |
commit | 07f1d44174f5e2b4e3d5ffdec3619bb84f357af2 (patch) | |
tree | 83cc0442b2c1b89a5b3dd94cff23d5098415777e /OpenSim/Region/ClientStack/Linden/UDP | |
parent | Merge branch 'master' into connector_plugin (diff) | |
parent | Fix: invinite loading for Viewer3 : parcelinfo request of traffic-value (impl... (diff) | |
download | opensim-SC-07f1d44174f5e2b4e3d5ffdec3619bb84f357af2.zip opensim-SC-07f1d44174f5e2b4e3d5ffdec3619bb84f357af2.tar.gz opensim-SC-07f1d44174f5e2b4e3d5ffdec3619bb84f357af2.tar.bz2 opensim-SC-07f1d44174f5e2b4e3d5ffdec3619bb84f357af2.tar.xz |
Merge branch 'master' into connector_plugin
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
6 files changed, 388 insertions, 128 deletions
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 62f51d9..7427c59 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -347,7 +347,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
347 | private int m_moneyBalance; | 347 | private int m_moneyBalance; |
348 | private int m_animationSequenceNumber = 1; | 348 | private int m_animationSequenceNumber = 1; |
349 | private bool m_SendLogoutPacketWhenClosing = true; | 349 | private bool m_SendLogoutPacketWhenClosing = true; |
350 | private AgentUpdateArgs lastarg; | 350 | |
351 | /// <summary> | ||
352 | /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for | ||
353 | /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it | ||
354 | /// is doing absolutely nothing. | ||
355 | /// </summary> | ||
356 | /// <remarks> | ||
357 | /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods | ||
358 | /// cannot retain a reference to it outside of that method. | ||
359 | /// </remarks> | ||
360 | private AgentUpdateArgs m_lastAgentUpdateArgs; | ||
351 | 361 | ||
352 | protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); | 362 | protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); |
353 | protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers | 363 | protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers |
@@ -3922,7 +3932,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3922 | { | 3932 | { |
3923 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; | 3933 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; |
3924 | 3934 | ||
3925 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | 3935 | ImprovedTerseObjectUpdatePacket packet |
3936 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
3937 | |||
3926 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 3938 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
3927 | packet.RegionData.TimeDilation = timeDilation; | 3939 | packet.RegionData.TimeDilation = timeDilation; |
3928 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | 3940 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; |
@@ -3967,7 +3979,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3967 | { | 3979 | { |
3968 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; | 3980 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; |
3969 | 3981 | ||
3970 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | 3982 | ImprovedTerseObjectUpdatePacket packet |
3983 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( | ||
3984 | PacketType.ImprovedTerseObjectUpdate); | ||
3985 | |||
3971 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 3986 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
3972 | packet.RegionData.TimeDilation = timeDilation; | 3987 | packet.RegionData.TimeDilation = timeDilation; |
3973 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | 3988 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; |
@@ -4959,7 +4974,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4959 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; | 4974 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; |
4960 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; | 4975 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; |
4961 | 4976 | ||
4962 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); | 4977 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block |
4978 | = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); | ||
4979 | |||
4963 | block.Data = data; | 4980 | block.Data = data; |
4964 | 4981 | ||
4965 | if (textureEntry != null && textureEntry.Length > 0) | 4982 | if (textureEntry != null && textureEntry.Length > 0) |
@@ -5191,7 +5208,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5191 | protected virtual void RegisterLocalPacketHandlers() | 5208 | protected virtual void RegisterLocalPacketHandlers() |
5192 | { | 5209 | { |
5193 | AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); | 5210 | AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); |
5211 | |||
5212 | // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs | ||
5213 | // for each AgentUpdate packet. | ||
5194 | AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); | 5214 | AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); |
5215 | |||
5195 | AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); | 5216 | AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); |
5196 | AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); | 5217 | AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); |
5197 | AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); | 5218 | AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); |
@@ -5418,80 +5439,83 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5418 | 5439 | ||
5419 | #region Scene/Avatar | 5440 | #region Scene/Avatar |
5420 | 5441 | ||
5421 | private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) | 5442 | private bool HandleAgentUpdate(IClientAPI sener, Packet packet) |
5422 | { | 5443 | { |
5423 | if (OnAgentUpdate != null) | 5444 | if (OnAgentUpdate != null) |
5424 | { | 5445 | { |
5425 | bool update = false; | 5446 | AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; |
5426 | AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; | ||
5427 | 5447 | ||
5428 | #region Packet Session and User Check | 5448 | #region Packet Session and User Check |
5429 | if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) | 5449 | if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) |
5450 | { | ||
5451 | PacketPool.Instance.ReturnPacket(packet); | ||
5430 | return false; | 5452 | return false; |
5453 | } | ||
5431 | #endregion | 5454 | #endregion |
5432 | 5455 | ||
5433 | AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; | 5456 | bool update = false; |
5434 | 5457 | AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; | |
5435 | // We can only check when we have something to check | ||
5436 | // against. | ||
5437 | 5458 | ||
5438 | if (lastarg != null) | 5459 | if (m_lastAgentUpdateArgs != null) |
5439 | { | 5460 | { |
5461 | // These should be ordered from most-likely to | ||
5462 | // least likely to change. I've made an initial | ||
5463 | // guess at that. | ||
5440 | update = | 5464 | update = |
5441 | ( | 5465 | ( |
5442 | (x.BodyRotation != lastarg.BodyRotation) || | 5466 | (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || |
5443 | (x.CameraAtAxis != lastarg.CameraAtAxis) || | 5467 | (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || |
5444 | (x.CameraCenter != lastarg.CameraCenter) || | 5468 | (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || |
5445 | (x.CameraLeftAxis != lastarg.CameraLeftAxis) || | 5469 | (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || |
5446 | (x.CameraUpAxis != lastarg.CameraUpAxis) || | 5470 | (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || |
5447 | (x.ControlFlags != lastarg.ControlFlags) || | 5471 | (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || |
5448 | (x.Far != lastarg.Far) || | 5472 | (x.Far != m_lastAgentUpdateArgs.Far) || |
5449 | (x.Flags != lastarg.Flags) || | 5473 | (x.Flags != m_lastAgentUpdateArgs.Flags) || |
5450 | (x.State != lastarg.State) || | 5474 | (x.State != m_lastAgentUpdateArgs.State) || |
5451 | (x.HeadRotation != lastarg.HeadRotation) || | 5475 | (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || |
5452 | (x.SessionID != lastarg.SessionID) || | 5476 | (x.SessionID != m_lastAgentUpdateArgs.SessionID) || |
5453 | (x.AgentID != lastarg.AgentID) | 5477 | (x.AgentID != m_lastAgentUpdateArgs.AgentID) |
5454 | ); | 5478 | ); |
5455 | } | 5479 | } |
5456 | else | 5480 | else |
5457 | { | 5481 | { |
5482 | m_lastAgentUpdateArgs = new AgentUpdateArgs(); | ||
5458 | update = true; | 5483 | update = true; |
5459 | } | 5484 | } |
5460 | 5485 | ||
5461 | // These should be ordered from most-likely to | ||
5462 | // least likely to change. I've made an initial | ||
5463 | // guess at that. | ||
5464 | |||
5465 | if (update) | 5486 | if (update) |
5466 | { | 5487 | { |
5467 | // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); | 5488 | // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); |
5468 | 5489 | ||
5469 | AgentUpdateArgs arg = new AgentUpdateArgs(); | 5490 | m_lastAgentUpdateArgs.AgentID = x.AgentID; |
5470 | arg.AgentID = x.AgentID; | 5491 | m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; |
5471 | arg.BodyRotation = x.BodyRotation; | 5492 | m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; |
5472 | arg.CameraAtAxis = x.CameraAtAxis; | 5493 | m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; |
5473 | arg.CameraCenter = x.CameraCenter; | 5494 | m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; |
5474 | arg.CameraLeftAxis = x.CameraLeftAxis; | 5495 | m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; |
5475 | arg.CameraUpAxis = x.CameraUpAxis; | 5496 | m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; |
5476 | arg.ControlFlags = x.ControlFlags; | 5497 | m_lastAgentUpdateArgs.Far = x.Far; |
5477 | arg.Far = x.Far; | 5498 | m_lastAgentUpdateArgs.Flags = x.Flags; |
5478 | arg.Flags = x.Flags; | 5499 | m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; |
5479 | arg.HeadRotation = x.HeadRotation; | 5500 | m_lastAgentUpdateArgs.SessionID = x.SessionID; |
5480 | arg.SessionID = x.SessionID; | 5501 | m_lastAgentUpdateArgs.State = x.State; |
5481 | arg.State = x.State; | 5502 | |
5482 | UpdateAgent handlerAgentUpdate = OnAgentUpdate; | 5503 | UpdateAgent handlerAgentUpdate = OnAgentUpdate; |
5483 | UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; | 5504 | UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; |
5484 | lastarg = arg; // save this set of arguments for nexttime | 5505 | |
5485 | if (handlerPreAgentUpdate != null) | 5506 | if (handlerPreAgentUpdate != null) |
5486 | OnPreAgentUpdate(this, arg); | 5507 | OnPreAgentUpdate(this, m_lastAgentUpdateArgs); |
5508 | |||
5487 | if (handlerAgentUpdate != null) | 5509 | if (handlerAgentUpdate != null) |
5488 | OnAgentUpdate(this, arg); | 5510 | OnAgentUpdate(this, m_lastAgentUpdateArgs); |
5489 | 5511 | ||
5490 | handlerAgentUpdate = null; | 5512 | handlerAgentUpdate = null; |
5491 | handlerPreAgentUpdate = null; | 5513 | handlerPreAgentUpdate = null; |
5492 | } | 5514 | } |
5493 | } | 5515 | } |
5494 | 5516 | ||
5517 | PacketPool.Instance.ReturnPacket(packet); | ||
5518 | |||
5495 | return true; | 5519 | return true; |
5496 | } | 5520 | } |
5497 | 5521 | ||
@@ -9056,7 +9080,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9056 | } | 9080 | } |
9057 | #endregion | 9081 | #endregion |
9058 | 9082 | ||
9059 | switch (Utils.BytesToString(messagePacket.MethodData.Method)) | 9083 | string method = Utils.BytesToString(messagePacket.MethodData.Method); |
9084 | |||
9085 | switch (method) | ||
9060 | { | 9086 | { |
9061 | case "getinfo": | 9087 | case "getinfo": |
9062 | if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) | 9088 | if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) |
@@ -9372,7 +9398,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9372 | return true; | 9398 | return true; |
9373 | 9399 | ||
9374 | default: | 9400 | default: |
9375 | m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); | 9401 | m_log.WarnFormat( |
9402 | "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", | ||
9403 | method, Name, Scene.Name); | ||
9404 | |||
9405 | for (int i = 0; i < messagePacket.ParamList.Length; i++) | ||
9406 | { | ||
9407 | EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i]; | ||
9408 | string data = (string)Utils.BytesToString(block.Parameter); | ||
9409 | m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data); | ||
9410 | } | ||
9411 | |||
9376 | return true; | 9412 | return true; |
9377 | } | 9413 | } |
9378 | 9414 | ||
@@ -11758,7 +11794,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11758 | logPacket = false; | 11794 | logPacket = false; |
11759 | 11795 | ||
11760 | if (DebugPacketLevel <= 50 | 11796 | if (DebugPacketLevel <= 50 |
11761 | & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) | 11797 | && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) |
11762 | logPacket = false; | 11798 | logPacket = false; |
11763 | 11799 | ||
11764 | if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) | 11800 | if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) |
@@ -11832,8 +11868,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11832 | 11868 | ||
11833 | if (!ProcessPacketMethod(packet)) | 11869 | if (!ProcessPacketMethod(packet)) |
11834 | m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); | 11870 | m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); |
11835 | |||
11836 | PacketPool.Instance.ReturnPacket(packet); | ||
11837 | } | 11871 | } |
11838 | 11872 | ||
11839 | private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) | 11873 | private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) |
@@ -12286,7 +12320,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12286 | ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); | 12320 | ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); |
12287 | 12321 | ||
12288 | 12322 | ||
12289 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); | 12323 | ImprovedTerseObjectUpdatePacket packet |
12324 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( | ||
12325 | PacketType.ImprovedTerseObjectUpdate); | ||
12326 | |||
12290 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 12327 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
12291 | packet.RegionData.TimeDilation = timeDilation; | 12328 | packet.RegionData.TimeDilation = timeDilation; |
12292 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | 12329 | 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 d11fcbf..419de66 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -37,6 +37,7 @@ using log4net; | |||
37 | using Nini.Config; | 37 | using Nini.Config; |
38 | using OpenMetaverse.Packets; | 38 | using OpenMetaverse.Packets; |
39 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
40 | using OpenSim.Framework.Console; | ||
40 | using OpenSim.Framework.Monitoring; | 41 | using OpenSim.Framework.Monitoring; |
41 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
42 | using OpenMetaverse; | 43 | using 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; |
@@ -111,6 +114,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
111 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | 114 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); |
112 | /// <summary>Incoming packets that are awaiting handling</summary> | 115 | /// <summary>Incoming packets that are awaiting handling</summary> |
113 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | 116 | private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); |
117 | |||
114 | /// <summary></summary> | 118 | /// <summary></summary> |
115 | //private UDPClientCollection m_clients = new UDPClientCollection(); | 119 | //private UDPClientCollection m_clients = new UDPClientCollection(); |
116 | /// <summary>Bandwidth throttle for this UDP server</summary> | 120 | /// <summary>Bandwidth throttle for this UDP server</summary> |
@@ -121,28 +125,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
121 | 125 | ||
122 | /// <summary>Manages authentication for agent circuits</summary> | 126 | /// <summary>Manages authentication for agent circuits</summary> |
123 | private AgentCircuitManager m_circuitManager; | 127 | private AgentCircuitManager m_circuitManager; |
128 | |||
124 | /// <summary>Reference to the scene this UDP server is attached to</summary> | 129 | /// <summary>Reference to the scene this UDP server is attached to</summary> |
125 | protected Scene m_scene; | 130 | protected Scene m_scene; |
131 | |||
126 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> | 132 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> |
127 | private Location m_location; | 133 | private Location m_location; |
134 | |||
128 | /// <summary>The size of the receive buffer for the UDP socket. This value | 135 | /// <summary>The size of the receive buffer for the UDP socket. This value |
129 | /// is passed up to the operating system and used in the system networking | 136 | /// is passed up to the operating system and used in the system networking |
130 | /// stack. Use zero to leave this value as the default</summary> | 137 | /// stack. Use zero to leave this value as the default</summary> |
131 | private int m_recvBufferSize; | 138 | private int m_recvBufferSize; |
139 | |||
132 | /// <summary>Flag to process packets asynchronously or synchronously</summary> | 140 | /// <summary>Flag to process packets asynchronously or synchronously</summary> |
133 | private bool m_asyncPacketHandling; | 141 | private bool m_asyncPacketHandling; |
142 | |||
134 | /// <summary>Tracks whether or not a packet was sent each round so we know | 143 | /// <summary>Tracks whether or not a packet was sent each round so we know |
135 | /// whether or not to sleep</summary> | 144 | /// whether or not to sleep</summary> |
136 | private bool m_packetSent; | 145 | private bool m_packetSent; |
137 | 146 | ||
138 | /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> | 147 | /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> |
139 | private int m_elapsedMSSinceLastStatReport = 0; | 148 | private int m_elapsedMSSinceLastStatReport = 0; |
149 | |||
140 | /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> | 150 | /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> |
141 | private int m_tickLastOutgoingPacketHandler; | 151 | private int m_tickLastOutgoingPacketHandler; |
152 | |||
142 | /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> | 153 | /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> |
143 | private int m_elapsedMSOutgoingPacketHandler; | 154 | private int m_elapsedMSOutgoingPacketHandler; |
155 | |||
144 | /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> | 156 | /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> |
145 | private int m_elapsed100MSOutgoingPacketHandler; | 157 | private int m_elapsed100MSOutgoingPacketHandler; |
158 | |||
146 | /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> | 159 | /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> |
147 | private int m_elapsed500MSOutgoingPacketHandler; | 160 | private int m_elapsed500MSOutgoingPacketHandler; |
148 | 161 | ||
@@ -155,6 +168,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
155 | /// <summary>Flag to signal when clients should send pings</summary> | 168 | /// <summary>Flag to signal when clients should send pings</summary> |
156 | protected bool m_sendPing; | 169 | protected bool m_sendPing; |
157 | 170 | ||
171 | private Pool<IncomingPacket> m_incomingPacketPool; | ||
172 | |||
158 | private int m_defaultRTO = 0; | 173 | private int m_defaultRTO = 0; |
159 | private int m_maxRTO = 0; | 174 | private int m_maxRTO = 0; |
160 | private int m_ackTimeout = 0; | 175 | private int m_ackTimeout = 0; |
@@ -175,7 +190,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
175 | /// </summary> | 190 | /// </summary> |
176 | private IClientAPI m_currentIncomingClient; | 191 | private IClientAPI m_currentIncomingClient; |
177 | 192 | ||
178 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) | 193 | public LLUDPServer( |
194 | IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, | ||
195 | IConfigSource configSource, AgentCircuitManager circuitManager) | ||
179 | : base(listenIP, (int)port) | 196 | : base(listenIP, (int)port) |
180 | { | 197 | { |
181 | #region Environment.TickCount Measurement | 198 | #region Environment.TickCount Measurement |
@@ -229,6 +246,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
229 | { | 246 | { |
230 | PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); | 247 | PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); |
231 | PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); | 248 | PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); |
249 | UsePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", false); | ||
232 | } | 250 | } |
233 | 251 | ||
234 | #region BinaryStats | 252 | #region BinaryStats |
@@ -258,20 +276,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
258 | 276 | ||
259 | m_throttle = new TokenBucket(null, sceneThrottleBps); | 277 | m_throttle = new TokenBucket(null, sceneThrottleBps); |
260 | ThrottleRates = new ThrottleRates(configSource); | 278 | ThrottleRates = new ThrottleRates(configSource); |
279 | |||
280 | if (UsePools) | ||
281 | m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500); | ||
261 | } | 282 | } |
262 | 283 | ||
263 | public void Start() | 284 | public void Start() |
264 | { | 285 | { |
265 | if (m_scene == null) | 286 | StartInbound(); |
266 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); | 287 | StartOutbound(); |
288 | |||
289 | m_elapsedMSSinceLastStatReport = Environment.TickCount; | ||
290 | } | ||
267 | 291 | ||
292 | private void StartInbound() | ||
293 | { | ||
268 | m_log.InfoFormat( | 294 | m_log.InfoFormat( |
269 | "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", | 295 | "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", |
270 | m_asyncPacketHandling ? "asynchronous" : "synchronous"); | 296 | m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); |
271 | 297 | ||
272 | base.Start(m_recvBufferSize, m_asyncPacketHandling); | 298 | base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); |
273 | 299 | ||
274 | // Start the packet processing threads | 300 | // This thread will process the packets received that are placed on the packetInbox |
275 | Watchdog.StartThread( | 301 | Watchdog.StartThread( |
276 | IncomingPacketHandler, | 302 | IncomingPacketHandler, |
277 | string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), | 303 | string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), |
@@ -280,6 +306,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
280 | true, | 306 | true, |
281 | GetWatchdogIncomingAlarmData, | 307 | GetWatchdogIncomingAlarmData, |
282 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | 308 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); |
309 | } | ||
310 | |||
311 | private new void StartOutbound() | ||
312 | { | ||
313 | m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); | ||
314 | |||
315 | base.StartOutbound(); | ||
283 | 316 | ||
284 | Watchdog.StartThread( | 317 | Watchdog.StartThread( |
285 | OutgoingPacketHandler, | 318 | OutgoingPacketHandler, |
@@ -289,8 +322,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
289 | true, | 322 | true, |
290 | GetWatchdogOutgoingAlarmData, | 323 | GetWatchdogOutgoingAlarmData, |
291 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | 324 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); |
325 | } | ||
292 | 326 | ||
293 | m_elapsedMSSinceLastStatReport = Environment.TickCount; | 327 | public void Stop() |
328 | { | ||
329 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | ||
330 | base.StopOutbound(); | ||
331 | base.StopInbound(); | ||
294 | } | 332 | } |
295 | 333 | ||
296 | /// <summary> | 334 | /// <summary> |
@@ -315,12 +353,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
315 | m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); | 353 | m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); |
316 | } | 354 | } |
317 | 355 | ||
318 | public new void Stop() | ||
319 | { | ||
320 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | ||
321 | base.Stop(); | ||
322 | } | ||
323 | |||
324 | public void AddScene(IScene scene) | 356 | public void AddScene(IScene scene) |
325 | { | 357 | { |
326 | if (m_scene != null) | 358 | if (m_scene != null) |
@@ -337,6 +369,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
337 | 369 | ||
338 | m_scene = (Scene)scene; | 370 | m_scene = (Scene)scene; |
339 | m_location = new Location(m_scene.RegionInfo.RegionHandle); | 371 | m_location = new Location(m_scene.RegionInfo.RegionHandle); |
372 | |||
373 | MainConsole.Instance.Commands.AddCommand( | ||
374 | "Debug", | ||
375 | false, | ||
376 | "debug lludp start", | ||
377 | "debug lludp start <in|out|all>", | ||
378 | "Control LLUDP packet processing.", | ||
379 | "No effect if packet processing has already started.\n" | ||
380 | + "in - start inbound processing.\n" | ||
381 | + "out - start outbound processing.\n" | ||
382 | + "all - start in and outbound processing.\n", | ||
383 | HandleStartCommand); | ||
384 | |||
385 | MainConsole.Instance.Commands.AddCommand( | ||
386 | "Debug", | ||
387 | false, | ||
388 | "debug lludp stop", | ||
389 | "debug lludp stop <in|out|all>", | ||
390 | "Stop LLUDP packet processing.", | ||
391 | "No effect if packet processing has already stopped.\n" | ||
392 | + "in - stop inbound processing.\n" | ||
393 | + "out - stop outbound processing.\n" | ||
394 | + "all - stop in and outbound processing.\n", | ||
395 | HandleStopCommand); | ||
396 | |||
397 | MainConsole.Instance.Commands.AddCommand( | ||
398 | "Debug", | ||
399 | false, | ||
400 | "debug lludp status", | ||
401 | "debug lludp status", | ||
402 | "Return status of LLUDP packet processing.", | ||
403 | HandleStatusCommand); | ||
404 | } | ||
405 | |||
406 | private void HandleStartCommand(string module, string[] args) | ||
407 | { | ||
408 | if (args.Length != 4) | ||
409 | { | ||
410 | MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>"); | ||
411 | return; | ||
412 | } | ||
413 | |||
414 | string subCommand = args[3]; | ||
415 | |||
416 | if (subCommand == "in" || subCommand == "all") | ||
417 | StartInbound(); | ||
418 | |||
419 | if (subCommand == "out" || subCommand == "all") | ||
420 | StartOutbound(); | ||
421 | } | ||
422 | |||
423 | private void HandleStopCommand(string module, string[] args) | ||
424 | { | ||
425 | if (args.Length != 4) | ||
426 | { | ||
427 | MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); | ||
428 | return; | ||
429 | } | ||
430 | |||
431 | string subCommand = args[3]; | ||
432 | |||
433 | if (subCommand == "in" || subCommand == "all") | ||
434 | StopInbound(); | ||
435 | |||
436 | if (subCommand == "out" || subCommand == "all") | ||
437 | StopOutbound(); | ||
438 | } | ||
439 | |||
440 | private void HandleStatusCommand(string module, string[] args) | ||
441 | { | ||
442 | MainConsole.Instance.OutputFormat( | ||
443 | "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); | ||
444 | |||
445 | MainConsole.Instance.OutputFormat( | ||
446 | "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); | ||
340 | } | 447 | } |
341 | 448 | ||
342 | public bool HandlesRegion(Location x) | 449 | public bool HandlesRegion(Location x) |
@@ -420,6 +527,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
420 | byte[] data = packet.ToBytes(); | 527 | byte[] data = packet.ToBytes(); |
421 | SendPacketData(udpClient, data, packet.Type, category, method); | 528 | SendPacketData(udpClient, data, packet.Type, category, method); |
422 | } | 529 | } |
530 | |||
531 | PacketPool.Instance.ReturnPacket(packet); | ||
423 | } | 532 | } |
424 | 533 | ||
425 | /// <summary> | 534 | /// <summary> |
@@ -704,7 +813,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
704 | LLUDPClient udpClient = null; | 813 | LLUDPClient udpClient = null; |
705 | Packet packet = null; | 814 | Packet packet = null; |
706 | int packetEnd = buffer.DataLength - 1; | 815 | int packetEnd = buffer.DataLength - 1; |
707 | IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; | 816 | IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; |
708 | 817 | ||
709 | #region Decoding | 818 | #region Decoding |
710 | 819 | ||
@@ -714,7 +823,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
714 | // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", | 823 | // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", |
715 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); | 824 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); |
716 | 825 | ||
717 | return; // Drop undersizd packet | 826 | return; // Drop undersized packet |
718 | } | 827 | } |
719 | 828 | ||
720 | int headerLen = 7; | 829 | int headerLen = 7; |
@@ -737,7 +846,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
737 | 846 | ||
738 | try | 847 | try |
739 | { | 848 | { |
740 | packet = Packet.BuildPacket(buffer.Data, ref packetEnd, | 849 | // packet = Packet.BuildPacket(buffer.Data, ref packetEnd, |
850 | // // Only allocate a buffer for zerodecoding if the packet is zerocoded | ||
851 | // ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | ||
852 | // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we | ||
853 | // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all | ||
854 | // bytes are copied out). | ||
855 | packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, | ||
741 | // Only allocate a buffer for zerodecoding if the packet is zerocoded | 856 | // Only allocate a buffer for zerodecoding if the packet is zerocoded |
742 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | 857 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); |
743 | } | 858 | } |
@@ -752,11 +867,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
752 | 867 | ||
753 | return; // Drop short packet | 868 | return; // Drop short packet |
754 | } | 869 | } |
755 | catch(Exception e) | 870 | catch (Exception e) |
756 | { | 871 | { |
757 | if (m_malformedCount < 100) | 872 | if (m_malformedCount < 100) |
758 | m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); | 873 | m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); |
874 | |||
759 | m_malformedCount++; | 875 | m_malformedCount++; |
876 | |||
760 | if ((m_malformedCount % 100000) == 0) | 877 | if ((m_malformedCount % 100000) == 0) |
761 | m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); | 878 | m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); |
762 | } | 879 | } |
@@ -777,7 +894,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
777 | // UseCircuitCode handling | 894 | // UseCircuitCode handling |
778 | if (packet.Type == PacketType.UseCircuitCode) | 895 | if (packet.Type == PacketType.UseCircuitCode) |
779 | { | 896 | { |
780 | object[] array = new object[] { buffer, packet }; | 897 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
898 | // buffer. | ||
899 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
781 | 900 | ||
782 | Util.FireAndForget(HandleUseCircuitCode, array); | 901 | Util.FireAndForget(HandleUseCircuitCode, array); |
783 | 902 | ||
@@ -786,7 +905,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
786 | 905 | ||
787 | // Determine which agent this packet came from | 906 | // Determine which agent this packet came from |
788 | IClientAPI client; | 907 | IClientAPI client; |
789 | if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView)) | 908 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) |
790 | { | 909 | { |
791 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 910 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
792 | return; | 911 | return; |
@@ -810,6 +929,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
810 | // Handle appended ACKs | 929 | // Handle appended ACKs |
811 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) | 930 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) |
812 | { | 931 | { |
932 | // m_log.DebugFormat( | ||
933 | // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", | ||
934 | // packet.Header.AckList.Length, client.Name, m_scene.Name); | ||
935 | |||
813 | for (int i = 0; i < packet.Header.AckList.Length; i++) | 936 | for (int i = 0; i < packet.Header.AckList.Length; i++) |
814 | udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); | 937 | udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); |
815 | } | 938 | } |
@@ -819,6 +942,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
819 | { | 942 | { |
820 | PacketAckPacket ackPacket = (PacketAckPacket)packet; | 943 | PacketAckPacket ackPacket = (PacketAckPacket)packet; |
821 | 944 | ||
945 | // m_log.DebugFormat( | ||
946 | // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", | ||
947 | // ackPacket.Packets.Length, client.Name, m_scene.Name); | ||
948 | |||
822 | for (int i = 0; i < ackPacket.Packets.Length; i++) | 949 | for (int i = 0; i < ackPacket.Packets.Length; i++) |
823 | udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); | 950 | udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); |
824 | 951 | ||
@@ -832,6 +959,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
832 | 959 | ||
833 | if (packet.Header.Reliable) | 960 | if (packet.Header.Reliable) |
834 | { | 961 | { |
962 | // m_log.DebugFormat( | ||
963 | // "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}", | ||
964 | // packet.Type, packet.Header.Sequence, client.Name, m_scene.Name); | ||
965 | |||
835 | udpClient.PendingAcks.Enqueue(packet.Header.Sequence); | 966 | udpClient.PendingAcks.Enqueue(packet.Header.Sequence); |
836 | 967 | ||
837 | // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, | 968 | // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, |
@@ -878,6 +1009,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
878 | 1009 | ||
879 | if (packet.Type == PacketType.StartPingCheck) | 1010 | if (packet.Type == PacketType.StartPingCheck) |
880 | { | 1011 | { |
1012 | // m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name); | ||
1013 | |||
881 | // We don't need to do anything else with ping checks | 1014 | // We don't need to do anything else with ping checks |
882 | StartPingCheckPacket startPing = (StartPingCheckPacket)packet; | 1015 | StartPingCheckPacket startPing = (StartPingCheckPacket)packet; |
883 | CompletePing(udpClient, startPing.PingID.PingID); | 1016 | CompletePing(udpClient, startPing.PingID.PingID); |
@@ -897,8 +1030,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
897 | 1030 | ||
898 | #endregion Ping Check Handling | 1031 | #endregion Ping Check Handling |
899 | 1032 | ||
1033 | IncomingPacket incomingPacket; | ||
1034 | |||
900 | // Inbox insertion | 1035 | // Inbox insertion |
901 | packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); | 1036 | if (UsePools) |
1037 | { | ||
1038 | incomingPacket = m_incomingPacketPool.GetObject(); | ||
1039 | incomingPacket.Client = (LLClientView)client; | ||
1040 | incomingPacket.Packet = packet; | ||
1041 | } | ||
1042 | else | ||
1043 | { | ||
1044 | incomingPacket = new IncomingPacket((LLClientView)client, packet); | ||
1045 | } | ||
1046 | |||
1047 | packetInbox.Enqueue(incomingPacket); | ||
902 | } | 1048 | } |
903 | 1049 | ||
904 | #region BinaryStats | 1050 | #region BinaryStats |
@@ -984,21 +1130,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
984 | 1130 | ||
985 | private void HandleUseCircuitCode(object o) | 1131 | private void HandleUseCircuitCode(object o) |
986 | { | 1132 | { |
987 | IPEndPoint remoteEndPoint = null; | 1133 | IPEndPoint endPoint = null; |
988 | IClientAPI client = null; | 1134 | IClientAPI client = null; |
989 | 1135 | ||
990 | try | 1136 | try |
991 | { | 1137 | { |
992 | // DateTime startTime = DateTime.Now; | 1138 | // DateTime startTime = DateTime.Now; |
993 | object[] array = (object[])o; | 1139 | object[] array = (object[])o; |
994 | UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; | 1140 | endPoint = (IPEndPoint)array[0]; |
995 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; | 1141 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; |
996 | 1142 | ||
997 | m_log.DebugFormat( | 1143 | m_log.DebugFormat( |
998 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", | 1144 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", |
999 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); | 1145 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); |
1000 | |||
1001 | remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; | ||
1002 | 1146 | ||
1003 | AuthenticateResponse sessionInfo; | 1147 | AuthenticateResponse sessionInfo; |
1004 | if (IsClientAuthorized(uccp, out sessionInfo)) | 1148 | if (IsClientAuthorized(uccp, out sessionInfo)) |
@@ -1009,13 +1153,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1009 | uccp.CircuitCode.Code, | 1153 | uccp.CircuitCode.Code, |
1010 | uccp.CircuitCode.ID, | 1154 | uccp.CircuitCode.ID, |
1011 | uccp.CircuitCode.SessionID, | 1155 | uccp.CircuitCode.SessionID, |
1012 | remoteEndPoint, | 1156 | endPoint, |
1013 | sessionInfo); | 1157 | sessionInfo); |
1014 | 1158 | ||
1015 | // Send ack straight away to let the viewer know that the connection is active. | 1159 | // Send ack straight away to let the viewer know that the connection is active. |
1016 | // The client will be null if it already exists (e.g. if on a region crossing the client sends a use | 1160 | // The client will be null if it already exists (e.g. if on a region crossing the client sends a use |
1017 | // circuit code to the existing child agent. This is not particularly obvious. | 1161 | // circuit code to the existing child agent. This is not particularly obvious. |
1018 | SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); | 1162 | SendAckImmediate(endPoint, uccp.Header.Sequence); |
1019 | 1163 | ||
1020 | // We only want to send initial data to new clients, not ones which are being converted from child to root. | 1164 | // We only want to send initial data to new clients, not ones which are being converted from child to root. |
1021 | if (client != null) | 1165 | if (client != null) |
@@ -1026,7 +1170,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1026 | // Don't create clients for unauthorized requesters. | 1170 | // Don't create clients for unauthorized requesters. |
1027 | m_log.WarnFormat( | 1171 | m_log.WarnFormat( |
1028 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1172 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1029 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); | 1173 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1030 | } | 1174 | } |
1031 | 1175 | ||
1032 | // m_log.DebugFormat( | 1176 | // m_log.DebugFormat( |
@@ -1038,7 +1182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1038 | { | 1182 | { |
1039 | m_log.ErrorFormat( | 1183 | m_log.ErrorFormat( |
1040 | "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", | 1184 | "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", |
1041 | remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", | 1185 | endPoint != null ? endPoint.ToString() : "n/a", |
1042 | client != null ? client.Name : "unknown", | 1186 | client != null ? client.Name : "unknown", |
1043 | client != null ? client.AgentId.ToString() : "unknown", | 1187 | client != null ? client.AgentId.ToString() : "unknown", |
1044 | e.Message, | 1188 | e.Message, |
@@ -1103,20 +1247,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1103 | { | 1247 | { |
1104 | IClientAPI client = null; | 1248 | IClientAPI client = null; |
1105 | 1249 | ||
1106 | // In priciple there shouldn't be more than one thread here, ever. | 1250 | // We currently synchronize this code across the whole scene to avoid issues such as |
1107 | // But in case that happens, we need to synchronize this piece of code | 1251 | // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done |
1108 | // because it's too important | 1252 | // consistently, this lock could probably be removed. |
1109 | lock (this) | 1253 | lock (this) |
1110 | { | 1254 | { |
1111 | if (!m_scene.TryGetClient(agentID, out client)) | 1255 | if (!m_scene.TryGetClient(agentID, out client)) |
1112 | { | 1256 | { |
1113 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | 1257 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); |
1114 | 1258 | ||
1115 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | 1259 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
1116 | client.OnLogout += LogoutHandler; | 1260 | client.OnLogout += LogoutHandler; |
1117 | 1261 | ||
1118 | ((LLClientView)client).DisableFacelights = m_disableFacelights; | 1262 | ((LLClientView)client).DisableFacelights = m_disableFacelights; |
1119 | 1263 | ||
1120 | client.Start(); | 1264 | client.Start(); |
1121 | } | 1265 | } |
1122 | } | 1266 | } |
@@ -1155,7 +1299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1155 | // on to en-US to avoid number parsing issues | 1299 | // on to en-US to avoid number parsing issues |
1156 | Culture.SetCurrentCulture(); | 1300 | Culture.SetCurrentCulture(); |
1157 | 1301 | ||
1158 | while (base.IsRunning) | 1302 | while (IsRunningInbound) |
1159 | { | 1303 | { |
1160 | try | 1304 | try |
1161 | { | 1305 | { |
@@ -1170,7 +1314,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1170 | } | 1314 | } |
1171 | 1315 | ||
1172 | if (packetInbox.Dequeue(100, ref incomingPacket)) | 1316 | if (packetInbox.Dequeue(100, ref incomingPacket)) |
1317 | { | ||
1173 | ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); | 1318 | ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); |
1319 | |||
1320 | if (UsePools) | ||
1321 | m_incomingPacketPool.ReturnObject(incomingPacket); | ||
1322 | } | ||
1174 | } | 1323 | } |
1175 | catch (Exception ex) | 1324 | catch (Exception ex) |
1176 | { | 1325 | { |
@@ -1197,7 +1346,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1197 | // Action generic every round | 1346 | // Action generic every round |
1198 | Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; | 1347 | Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; |
1199 | 1348 | ||
1200 | while (base.IsRunning) | 1349 | while (base.IsRunningOutbound) |
1201 | { | 1350 | { |
1202 | try | 1351 | try |
1203 | { | 1352 | { |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 039379d..6e6b3ef 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | |||
@@ -30,6 +30,7 @@ using System.Net; | |||
30 | using System.Net.Sockets; | 30 | using System.Net.Sockets; |
31 | using System.Threading; | 31 | using System.Threading; |
32 | using log4net; | 32 | using log4net; |
33 | using OpenSim.Framework; | ||
33 | 34 | ||
34 | namespace OpenMetaverse | 35 | namespace OpenMetaverse |
35 | { | 36 | { |
@@ -58,17 +59,29 @@ namespace OpenMetaverse | |||
58 | /// <summary>Flag to process packets asynchronously or synchronously</summary> | 59 | /// <summary>Flag to process packets asynchronously or synchronously</summary> |
59 | private bool m_asyncPacketHandling; | 60 | private bool m_asyncPacketHandling; |
60 | 61 | ||
61 | /// <summary>The all important shutdown flag</summary> | 62 | /// <summary> |
62 | private volatile bool m_shutdownFlag = true; | 63 | /// Pool to use for handling data. May be null if UsePools = false; |
64 | /// </summary> | ||
65 | protected OpenSim.Framework.Pool<UDPPacketBuffer> m_pool; | ||
63 | 66 | ||
64 | /// <summary>Returns true if the server is currently listening, otherwise false</summary> | 67 | /// <summary> |
65 | public bool IsRunning { get { return !m_shutdownFlag; } } | 68 | /// Are we to use object pool(s) to reduce memory churn when receiving data? |
69 | /// </summary> | ||
70 | public bool UsePools { get; protected set; } | ||
71 | |||
72 | /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary> | ||
73 | public bool IsRunningInbound { get; private set; } | ||
74 | |||
75 | /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary> | ||
76 | /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks> | ||
77 | public bool IsRunningOutbound { get; private set; } | ||
66 | 78 | ||
67 | /// <summary> | 79 | /// <summary> |
68 | /// Default constructor | 80 | /// Default constructor |
69 | /// </summary> | 81 | /// </summary> |
70 | /// <param name="bindAddress">Local IP address to bind the server to</param> | 82 | /// <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> | 83 | /// <param name="port">Port to listening for incoming UDP packets on</param> |
84 | /// /// <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) | 85 | public OpenSimUDPBase(IPAddress bindAddress, int port) |
73 | { | 86 | { |
74 | m_localBindAddress = bindAddress; | 87 | m_localBindAddress = bindAddress; |
@@ -76,7 +89,7 @@ namespace OpenMetaverse | |||
76 | } | 89 | } |
77 | 90 | ||
78 | /// <summary> | 91 | /// <summary> |
79 | /// Start the UDP server | 92 | /// Start inbound UDP packet handling. |
80 | /// </summary> | 93 | /// </summary> |
81 | /// <param name="recvBufferSize">The size of the receive buffer for | 94 | /// <param name="recvBufferSize">The size of the receive buffer for |
82 | /// the UDP socket. This value is passed up to the operating system | 95 | /// the UDP socket. This value is passed up to the operating system |
@@ -91,11 +104,16 @@ namespace OpenMetaverse | |||
91 | /// manner (not throwing an exception when the remote side resets the | 104 | /// manner (not throwing an exception when the remote side resets the |
92 | /// connection). This call is ignored on Mono where the flag is not | 105 | /// connection). This call is ignored on Mono where the flag is not |
93 | /// necessary</remarks> | 106 | /// necessary</remarks> |
94 | public void Start(int recvBufferSize, bool asyncPacketHandling) | 107 | public void StartInbound(int recvBufferSize, bool asyncPacketHandling) |
95 | { | 108 | { |
109 | if (UsePools) | ||
110 | m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500); | ||
111 | else | ||
112 | m_pool = null; | ||
113 | |||
96 | m_asyncPacketHandling = asyncPacketHandling; | 114 | m_asyncPacketHandling = asyncPacketHandling; |
97 | 115 | ||
98 | if (m_shutdownFlag) | 116 | if (!IsRunningInbound) |
99 | { | 117 | { |
100 | const int SIO_UDP_CONNRESET = -1744830452; | 118 | const int SIO_UDP_CONNRESET = -1744830452; |
101 | 119 | ||
@@ -127,8 +145,7 @@ namespace OpenMetaverse | |||
127 | 145 | ||
128 | m_udpSocket.Bind(ipep); | 146 | m_udpSocket.Bind(ipep); |
129 | 147 | ||
130 | // we're not shutting down, we're starting up | 148 | IsRunningInbound = true; |
131 | m_shutdownFlag = false; | ||
132 | 149 | ||
133 | // kick off an async receive. The Start() method will return, the | 150 | // kick off an async receive. The Start() method will return, the |
134 | // actual receives will occur asynchronously and will be caught in | 151 | // actual receives will occur asynchronously and will be caught in |
@@ -138,28 +155,41 @@ namespace OpenMetaverse | |||
138 | } | 155 | } |
139 | 156 | ||
140 | /// <summary> | 157 | /// <summary> |
141 | /// Stops the UDP server | 158 | /// Start outbound UDP packet handling. |
142 | /// </summary> | 159 | /// </summary> |
143 | public void Stop() | 160 | public void StartOutbound() |
144 | { | 161 | { |
145 | if (!m_shutdownFlag) | 162 | IsRunningOutbound = true; |
163 | } | ||
164 | |||
165 | public void StopInbound() | ||
166 | { | ||
167 | if (IsRunningInbound) | ||
146 | { | 168 | { |
147 | // wait indefinitely for a writer lock. Once this is called, the .NET runtime | 169 | // wait indefinitely for a writer lock. Once this is called, the .NET runtime |
148 | // will deny any more reader locks, in effect blocking all other send/receive | 170 | // will deny any more reader locks, in effect blocking all other send/receive |
149 | // threads. Once we have the lock, we set shutdownFlag to inform the other | 171 | // threads. Once we have the lock, we set IsRunningInbound = false to inform the other |
150 | // threads that the socket is closed. | 172 | // threads that the socket is closed. |
151 | m_shutdownFlag = true; | 173 | IsRunningInbound = false; |
152 | m_udpSocket.Close(); | 174 | m_udpSocket.Close(); |
153 | } | 175 | } |
154 | } | 176 | } |
155 | 177 | ||
178 | public void StopOutbound() | ||
179 | { | ||
180 | IsRunningOutbound = false; | ||
181 | } | ||
182 | |||
156 | private void AsyncBeginReceive() | 183 | private void AsyncBeginReceive() |
157 | { | 184 | { |
158 | // allocate a packet buffer | 185 | UDPPacketBuffer buf; |
159 | //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); | 186 | |
160 | UDPPacketBuffer buf = new UDPPacketBuffer(); | 187 | if (UsePools) |
188 | buf = m_pool.GetObject(); | ||
189 | else | ||
190 | buf = new UDPPacketBuffer(); | ||
161 | 191 | ||
162 | if (!m_shutdownFlag) | 192 | if (IsRunningInbound) |
163 | { | 193 | { |
164 | try | 194 | try |
165 | { | 195 | { |
@@ -212,7 +242,7 @@ namespace OpenMetaverse | |||
212 | { | 242 | { |
213 | // Asynchronous receive operations will complete here through the call | 243 | // Asynchronous receive operations will complete here through the call |
214 | // to AsyncBeginReceive | 244 | // to AsyncBeginReceive |
215 | if (!m_shutdownFlag) | 245 | if (IsRunningInbound) |
216 | { | 246 | { |
217 | // Asynchronous mode will start another receive before the | 247 | // Asynchronous mode will start another receive before the |
218 | // callback for this packet is even fired. Very parallel :-) | 248 | // callback for this packet is even fired. Very parallel :-) |
@@ -221,8 +251,6 @@ namespace OpenMetaverse | |||
221 | 251 | ||
222 | // get the buffer that was created in AsyncBeginReceive | 252 | // get the buffer that was created in AsyncBeginReceive |
223 | // this is the received data | 253 | // this is the received data |
224 | //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState; | ||
225 | //UDPPacketBuffer buffer = wrappedBuffer.Instance; | ||
226 | UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; | 254 | UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; |
227 | 255 | ||
228 | try | 256 | try |
@@ -239,7 +267,8 @@ namespace OpenMetaverse | |||
239 | catch (ObjectDisposedException) { } | 267 | catch (ObjectDisposedException) { } |
240 | finally | 268 | finally |
241 | { | 269 | { |
242 | //wrappedBuffer.Dispose(); | 270 | if (UsePools) |
271 | m_pool.ReturnObject(buffer); | ||
243 | 272 | ||
244 | // Synchronous mode waits until the packet callback completes | 273 | // Synchronous mode waits until the packet callback completes |
245 | // before starting the receive to fetch another packet | 274 | // before starting the receive to fetch another packet |
@@ -252,7 +281,7 @@ namespace OpenMetaverse | |||
252 | 281 | ||
253 | public void AsyncBeginSend(UDPPacketBuffer buf) | 282 | public void AsyncBeginSend(UDPPacketBuffer buf) |
254 | { | 283 | { |
255 | if (!m_shutdownFlag) | 284 | if (IsRunningOutbound) |
256 | { | 285 | { |
257 | try | 286 | try |
258 | { | 287 | { |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index fc9406b..2a3d14f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | |||
@@ -31,6 +31,7 @@ using System.Reflection; | |||
31 | using OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using OpenMetaverse.Packets; | 32 | using OpenMetaverse.Packets; |
33 | using log4net; | 33 | using log4net; |
34 | using OpenSim.Framework.Monitoring; | ||
34 | 35 | ||
35 | namespace OpenSim.Region.ClientStack.LindenUDP | 36 | namespace OpenSim.Region.ClientStack.LindenUDP |
36 | { | 37 | { |
@@ -43,17 +44,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
43 | private bool packetPoolEnabled = true; | 44 | private bool packetPoolEnabled = true; |
44 | private bool dataBlockPoolEnabled = true; | 45 | private bool dataBlockPoolEnabled = true; |
45 | 46 | ||
47 | private PercentageStat m_packetsReusedStat = new PercentageStat( | ||
48 | "PacketsReused", | ||
49 | "Packets reused", | ||
50 | "clientstack", | ||
51 | "packetpool", | ||
52 | StatVerbosity.Debug, | ||
53 | "Number of packets reused out of all requests to the packet pool"); | ||
54 | |||
55 | private PercentageStat m_blocksReusedStat = new PercentageStat( | ||
56 | "BlocksReused", | ||
57 | "Blocks reused", | ||
58 | "clientstack", | ||
59 | "packetpool", | ||
60 | StatVerbosity.Debug, | ||
61 | "Number of data blocks reused out of all requests to the packet pool"); | ||
62 | |||
46 | /// <summary> | 63 | /// <summary> |
47 | /// Pool of packets available for reuse. | 64 | /// Pool of packets available for reuse. |
48 | /// </summary> | 65 | /// </summary> |
49 | private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); | 66 | private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); |
50 | 67 | ||
51 | private static Dictionary<Type, Stack<Object>> DataBlocks = | 68 | private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>(); |
52 | new Dictionary<Type, Stack<Object>>(); | ||
53 | |||
54 | static PacketPool() | ||
55 | { | ||
56 | } | ||
57 | 69 | ||
58 | public static PacketPool Instance | 70 | public static PacketPool Instance |
59 | { | 71 | { |
@@ -72,8 +84,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
72 | get { return dataBlockPoolEnabled; } | 84 | get { return dataBlockPoolEnabled; } |
73 | } | 85 | } |
74 | 86 | ||
87 | private PacketPool() | ||
88 | { | ||
89 | StatsManager.RegisterStat(m_packetsReusedStat); | ||
90 | StatsManager.RegisterStat(m_blocksReusedStat); | ||
91 | } | ||
92 | |||
93 | /// <summary> | ||
94 | /// Gets a packet of the given type. | ||
95 | /// </summary> | ||
96 | /// <param name='type'></param> | ||
97 | /// <returns>Guaranteed to always return a packet, whether from the pool or newly constructed.</returns> | ||
75 | public Packet GetPacket(PacketType type) | 98 | public Packet GetPacket(PacketType type) |
76 | { | 99 | { |
100 | m_packetsReusedStat.Consequent++; | ||
101 | |||
77 | Packet packet; | 102 | Packet packet; |
78 | 103 | ||
79 | if (!packetPoolEnabled) | 104 | if (!packetPoolEnabled) |
@@ -83,13 +108,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
83 | { | 108 | { |
84 | if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) | 109 | if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) |
85 | { | 110 | { |
111 | // m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type); | ||
112 | |||
86 | // Creating a new packet if we cannot reuse an old package | 113 | // Creating a new packet if we cannot reuse an old package |
87 | packet = Packet.BuildPacket(type); | 114 | packet = Packet.BuildPacket(type); |
88 | } | 115 | } |
89 | else | 116 | else |
90 | { | 117 | { |
118 | // m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type); | ||
119 | |||
91 | // Recycle old packages | 120 | // Recycle old packages |
92 | packet = (pool[type]).Pop(); | 121 | m_packetsReusedStat.Antecedent++; |
122 | |||
123 | packet = pool[type].Pop(); | ||
93 | } | 124 | } |
94 | } | 125 | } |
95 | 126 | ||
@@ -138,7 +169,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
138 | { | 169 | { |
139 | PacketType type = GetType(bytes); | 170 | PacketType type = GetType(bytes); |
140 | 171 | ||
141 | Array.Clear(zeroBuffer, 0, zeroBuffer.Length); | 172 | // Array.Clear(zeroBuffer, 0, zeroBuffer.Length); |
142 | 173 | ||
143 | int i = 0; | 174 | int i = 0; |
144 | Packet packet = GetPacket(type); | 175 | Packet packet = GetPacket(type); |
@@ -185,6 +216,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
185 | switch (packet.Type) | 216 | switch (packet.Type) |
186 | { | 217 | { |
187 | // List pooling packets here | 218 | // List pooling packets here |
219 | case PacketType.AgentUpdate: | ||
188 | case PacketType.PacketAck: | 220 | case PacketType.PacketAck: |
189 | case PacketType.ObjectUpdate: | 221 | case PacketType.ObjectUpdate: |
190 | case PacketType.ImprovedTerseObjectUpdate: | 222 | case PacketType.ImprovedTerseObjectUpdate: |
@@ -199,7 +231,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
199 | 231 | ||
200 | if ((pool[type]).Count < 50) | 232 | if ((pool[type]).Count < 50) |
201 | { | 233 | { |
202 | (pool[type]).Push(packet); | 234 | // m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); |
235 | |||
236 | pool[type].Push(packet); | ||
203 | } | 237 | } |
204 | } | 238 | } |
205 | break; | 239 | break; |
@@ -211,16 +245,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
211 | } | 245 | } |
212 | } | 246 | } |
213 | 247 | ||
214 | public static T GetDataBlock<T>() where T: new() | 248 | public T GetDataBlock<T>() where T: new() |
215 | { | 249 | { |
216 | lock (DataBlocks) | 250 | lock (DataBlocks) |
217 | { | 251 | { |
252 | m_blocksReusedStat.Consequent++; | ||
253 | |||
218 | Stack<Object> s; | 254 | Stack<Object> s; |
219 | 255 | ||
220 | if (DataBlocks.TryGetValue(typeof(T), out s)) | 256 | if (DataBlocks.TryGetValue(typeof(T), out s)) |
221 | { | 257 | { |
222 | if (s.Count > 0) | 258 | if (s.Count > 0) |
259 | { | ||
260 | m_blocksReusedStat.Antecedent++; | ||
223 | return (T)s.Pop(); | 261 | return (T)s.Pop(); |
262 | } | ||
224 | } | 263 | } |
225 | else | 264 | else |
226 | { | 265 | { |
@@ -231,7 +270,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
231 | } | 270 | } |
232 | } | 271 | } |
233 | 272 | ||
234 | public static void ReturnDataBlock<T>(T block) where T: new() | 273 | public void ReturnDataBlock<T>(T block) where T: new() |
235 | { | 274 | { |
236 | if (block == null) | 275 | if (block == null) |
237 | return; | 276 | return; |
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 | ||