From db4ca57590db44aba7d19530285091c7ea4c082c Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Tue, 16 Oct 2012 21:55:00 +0100
Subject: Make it possible to separate start and stop lludp packet processing
 from the console for debug processes.

This is controlled via the "debug lludp start <in|out|all>" and "debug lludp stop <in|out|all>" region console commands.
The command "debug lludp status" will show current status.
---
 .../Region/ClientStack/Linden/UDP/LLUDPServer.cs   | 116 ++++++++++++++++++---
 .../ClientStack/Linden/UDP/OpenSimUDPBase.cs       |  44 +++++---
 2 files changed, 129 insertions(+), 31 deletions(-)

(limited to 'OpenSim/Region')

diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index e3f4679..fc6dd4d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,6 +37,7 @@ using log4net;
 using Nini.Config;
 using OpenMetaverse.Packets;
 using OpenSim.Framework;
+using OpenSim.Framework.Console;
 using OpenSim.Framework.Monitoring;
 using OpenSim.Region.Framework.Scenes;
 using OpenMetaverse;
@@ -274,16 +275,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
         public void Start()
         {
-            if (m_scene == null)
-                throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
+            StartInbound();
+            StartOutbound();
 
+            m_elapsedMSSinceLastStatReport = Environment.TickCount;
+        }
+
+        private void StartInbound()
+        {
             m_log.InfoFormat(
-                "[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
+                "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode",
                 m_asyncPacketHandling ? "asynchronous" : "synchronous");
 
-            base.Start(m_recvBufferSize, m_asyncPacketHandling);
+            base.StartInbound(m_recvBufferSize, m_asyncPacketHandling);
 
-            // Start the packet processing threads
+            // This thread will process the packets received that are placed on the packetInbox
             Watchdog.StartThread(
                 IncomingPacketHandler,
                 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -292,7 +298,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                 true,
                 GetWatchdogIncomingAlarmData,
                 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
+        }
 
+        private void StartOutbound()
+        {
+            m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server");
+
+            base.StartOutbound();
+
+            // This thread will process the packets received that are placed on the packetInbox
             Watchdog.StartThread(
                 OutgoingPacketHandler,
                 string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -301,8 +315,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                 true,
                 GetWatchdogOutgoingAlarmData,
                 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
+        }
 
-            m_elapsedMSSinceLastStatReport = Environment.TickCount;
+        public new void Stop()
+        {
+            m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
+            base.StopOutbound();
+            base.StopInbound();
         }
 
         /// <summary>
@@ -327,12 +346,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
         }
 
-        public new void Stop()
-        {
-            m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
-            base.Stop();
-        }
-
         public void AddScene(IScene scene)
         {
             if (m_scene != null)
@@ -349,6 +362,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
             m_scene = (Scene)scene;
             m_location = new Location(m_scene.RegionInfo.RegionHandle);
+
+            MainConsole.Instance.Commands.AddCommand(
+                "Debug",
+                false,
+                "debug lludp start",
+                "debug lludp start <in|out|all>",
+                "Control LLUDP packet processing.",
+                "No effect if packet processing has already started.\n"
+                    + "in  - start inbound processing.\n"
+                    + "out - start outbound processing.\n"
+                    + "all - start in and outbound processing.\n",
+                HandleStartCommand);
+
+            MainConsole.Instance.Commands.AddCommand(
+                "Debug",
+                false,
+                "debug lludp stop",
+                "debug lludp stop <in|out|all>",
+                "Stop LLUDP packet processing.",
+                "No effect if packet processing has already stopped.\n"
+                    + "in  - stop inbound processing.\n"
+                    + "out - stop outbound processing.\n"
+                    + "all - stop in and outbound processing.\n",
+                HandleStopCommand);
+
+            MainConsole.Instance.Commands.AddCommand(
+                "Debug",
+                false,
+                "debug lludp status",
+                "debug lludp status",
+                "Return status of LLUDP packet processing.",
+                HandleStatusCommand);
+        }
+
+        private void HandleStartCommand(string module, string[] args)
+        {
+            if (args.Length != 4)
+            {
+                MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
+                return;
+            }
+
+            string subCommand = args[3];
+
+            if (subCommand == "in" || subCommand == "all")
+                StartInbound();
+
+            if (subCommand == "out" || subCommand == "all")
+                StartOutbound();
+        }
+
+        private void HandleStopCommand(string module, string[] args)
+        {
+            if (args.Length != 4)
+            {
+                MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
+                return;
+            }
+
+            string subCommand = args[3];
+
+            if (subCommand == "in" || subCommand == "all")
+                StopInbound();
+
+            if (subCommand == "out" || subCommand == "all")
+                StopOutbound();
+        }
+
+        private void HandleStatusCommand(string module, string[] args)
+        {
+            MainConsole.Instance.OutputFormat(
+                "IN  LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
+
+            MainConsole.Instance.OutputFormat(
+                "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
         }
 
         public bool HandlesRegion(Location x)
@@ -1174,7 +1262,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             // on to en-US to avoid number parsing issues
             Culture.SetCurrentCulture();
 
-            while (base.IsRunning)
+            while (base.IsRunningInbound)
             {
                 try
                 {
@@ -1216,7 +1304,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             // Action generic every round
             Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
 
-            while (base.IsRunning)
+            while (base.IsRunningOutbound)
             {
                 try
                 {
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 039379d..828c23c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -58,11 +58,12 @@ namespace OpenMetaverse
         /// <summary>Flag to process packets asynchronously or synchronously</summary>
         private bool m_asyncPacketHandling;
 
-        /// <summary>The all important shutdown flag</summary>
-        private volatile bool m_shutdownFlag = true;
+        /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
+        public bool IsRunningInbound { get; private set; }
 
-        /// <summary>Returns true if the server is currently listening, otherwise false</summary>
-        public bool IsRunning { get { return !m_shutdownFlag; } }
+        /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary>
+        /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks>
+        public bool IsRunningOutbound { get; private set; }
 
         /// <summary>
         /// Default constructor
@@ -76,7 +77,7 @@ namespace OpenMetaverse
         }
 
         /// <summary>
-        /// Start the UDP server
+        /// Start inbound UDP packet handling.
         /// </summary>
         /// <param name="recvBufferSize">The size of the receive buffer for 
         /// the UDP socket. This value is passed up to the operating system 
@@ -91,11 +92,11 @@ namespace OpenMetaverse
         /// manner (not throwing an exception when the remote side resets the
         /// connection). This call is ignored on Mono where the flag is not
         /// necessary</remarks>
-        public void Start(int recvBufferSize, bool asyncPacketHandling)
+        public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
         {
             m_asyncPacketHandling = asyncPacketHandling;
 
-            if (m_shutdownFlag)
+            if (!IsRunningInbound)
             {
                 const int SIO_UDP_CONNRESET = -1744830452;
 
@@ -127,8 +128,7 @@ namespace OpenMetaverse
 
                 m_udpSocket.Bind(ipep);
 
-                // we're not shutting down, we're starting up
-                m_shutdownFlag = false;
+                IsRunningInbound = true;
 
                 // kick off an async receive.  The Start() method will return, the
                 // actual receives will occur asynchronously and will be caught in
@@ -138,28 +138,38 @@ namespace OpenMetaverse
         }
 
         /// <summary>
-        /// Stops the UDP server
+        /// Start outbound UDP packet handling.
         /// </summary>
-        public void Stop()
+        public void StartOutbound()
         {
-            if (!m_shutdownFlag)
+            IsRunningOutbound = true;
+        }
+
+        public void StopInbound()
+        {
+            if (IsRunningInbound)
             {
                 // wait indefinitely for a writer lock.  Once this is called, the .NET runtime
                 // will deny any more reader locks, in effect blocking all other send/receive
-                // threads.  Once we have the lock, we set shutdownFlag to inform the other
+                // threads.  Once we have the lock, we set IsRunningInbound = false to inform the other
                 // threads that the socket is closed.
-                m_shutdownFlag = true;
+                IsRunningInbound = false;
                 m_udpSocket.Close();
             }
         }
 
+        public void StopOutbound()
+        {
+            IsRunningOutbound = false;
+        }
+
         private void AsyncBeginReceive()
         {
             // allocate a packet buffer
             //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
             UDPPacketBuffer buf = new UDPPacketBuffer();
 
-            if (!m_shutdownFlag)
+            if (IsRunningInbound)
             {
                 try
                 {
@@ -212,7 +222,7 @@ namespace OpenMetaverse
         {
             // Asynchronous receive operations will complete here through the call
             // to AsyncBeginReceive
-            if (!m_shutdownFlag)
+            if (IsRunningInbound)
             {
                 // Asynchronous mode will start another receive before the
                 // callback for this packet is even fired. Very parallel :-)
@@ -252,7 +262,7 @@ namespace OpenMetaverse
 
         public void AsyncBeginSend(UDPPacketBuffer buf)
         {
-            if (!m_shutdownFlag)
+            if (IsRunningOutbound)
             {
                 try
                 {
-- 
cgit v1.1