diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 97b79ce328..1d304db97c 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; @@ -278,16 +279,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), @@ -296,7 +302,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), @@ -305,8 +319,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(); } /// @@ -331,12 +350,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) @@ -353,6 +366,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 ", + "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 ", + "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 "); + 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 "); + 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) @@ -1239,7 +1327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // on to en-US to avoid number parsing issues Culture.SetCurrentCulture(); - while (base.IsRunning) + while (base.IsRunningInbound) { m_scene.ThreadAlive(1); try @@ -1282,7 +1370,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Action generic every round Action clientPacketHandler = ClientOutgoingPacketHandler; - while (base.IsRunning) + while (base.IsRunningOutbound) { m_scene.ThreadAlive(2); try diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index cfe7c9d09d..82775fd35c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -58,11 +58,12 @@ namespace OpenMetaverse /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; - /// The all important shutdown flag - private volatile bool m_shutdownFlag = true; + /// Returns true if the server is currently listening for inbound packets, otherwise false + public bool IsRunningInbound { get; private set; } - /// Returns true if the server is currently listening, otherwise false - public bool IsRunning { get { return !m_shutdownFlag; } } + /// Returns true if the server is currently sending outbound packets, otherwise false + /// If IsRunningOut = false, then any request to send a packet is simply dropped. + public bool IsRunningOutbound { get; private set; } /// /// Default constructor @@ -76,7 +77,7 @@ namespace OpenMetaverse } /// - /// Start the UDP server + /// Start inbound UDP packet handling. /// /// 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 - 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; @@ -123,8 +124,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 @@ -134,28 +134,38 @@ namespace OpenMetaverse } /// - /// Stops the UDP server + /// Start outbound UDP packet handling. /// - 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 wrappedBuffer = Pool.CheckOut(); UDPPacketBuffer buf = new UDPPacketBuffer(); - if (!m_shutdownFlag) + if (IsRunningInbound) { try { @@ -208,7 +218,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 :-) @@ -248,7 +258,7 @@ namespace OpenMetaverse public void AsyncBeginSend(UDPPacketBuffer buf) { - if (!m_shutdownFlag) + if (IsRunningOutbound) { try {