Describes the circumstances of server shutdown.
Ejemplo n.º 1
0
        static void RaiseShutdownBeganEvent(ShutdownParams shutdownParams)
        {
            var h = ShutdownBegan;

            if (h != null)
            {
                h(null, new ShutdownEventArgs(shutdownParams));
            }
        }
Ejemplo n.º 2
0
        private static void RaiseShutdownEndedEvent(ShutdownParams shutdownParams)
        {
            var h = ShutdownEnded;

            if (h != null)
            {
                h(null, new ShutdownEventArgs(shutdownParams));
            }
        }
Ejemplo n.º 3
0
        static void RaiseShutdownEndedEvent(ShutdownParams shutdownParams)
        {
            var handler = ShutdownEnded;

            if (handler != null)
            {
                handler(null, new ShutdownEventArgs(shutdownParams));
            }
        }
        static void RestartHandler( Player player, Command cmd )
        {
            string delayString = cmd.Next();
            TimeSpan delayTime = DefaultShutdownTime;
            string reason = "";

            if( delayString != null ) {
                if( delayString.Equals( "abort", StringComparison.OrdinalIgnoreCase ) ) {
                    if( Server.CancelShutdown() ) {
                        Logger.Log( LogType.UserActivity,
                                    "Restart aborted by {0}.", player.Name );
                        Server.Message( "&WRestart aborted by {0}", player.ClassyName );
                    } else {
                        player.MessageNow( "Cannot abort restart - too late." );
                    }
                    return;
                } else if( !delayString.TryParseMiniTimespan( out delayTime ) ) {
                    CdShutdown.PrintUsage( player );
                    return;
                }
                reason = cmd.NextAll();
            }

            if( delayTime.TotalMilliseconds > Int32.MaxValue - 1 ) {
                player.Message( "Restart: Delay is too long, maximum is {0}",
                                TimeSpan.FromMilliseconds( Int32.MaxValue - 1 ).ToMiniString() );
                return;
            }

            Server.Message( "&WServer restarting in {0}", delayTime.ToMiniString() );

            if( String.IsNullOrEmpty( reason ) ) {
                Logger.Log( LogType.UserActivity,
                            "{0} scheduled a restart ({1} delay).",
                            player.Name, delayTime.ToCompactString() );
                ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delayTime, true, true );
                Server.Shutdown( sp, false );
            } else {
                Server.Message( "&WRestart reason: {0}", reason );
                Logger.Log( LogType.UserActivity,
                            "{0} scheduled a restart ({1} delay). Reason: {2}",
                            player.Name, delayTime.ToCompactString(), reason );
                ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delayTime, true, true, reason, player );
                Server.Shutdown( sp, false );
            }
        }
Ejemplo n.º 5
0
        /// <summary> Starts the server:
        /// Creates Console pseudo-player, loads the world list, starts listening for incoming connections,
        /// sets up scheduled tasks and starts the scheduler, starts the heartbeat, and connects to IRC.
        /// Raises Server.Starting and Server.Started events.
        /// May throw an exception on hard failure. </summary>
        /// <returns> True if server started normally, false on soft failure. </returns>
        /// <exception cref="System.InvalidOperationException"> Server is already running, or server/library have not been initialized. </exception>
        public static bool StartServer() {
            if( IsRunning ) {
                throw new InvalidOperationException( "Server is already running" );
            }
            if( !libraryInitialized || !serverInitialized ) {
                throw new InvalidOperationException(
                    "Server.InitLibrary and Server.InitServer must be called before Server.StartServer" );
            }

            StartTime = DateTime.UtcNow;
            cpuUsageStartingOffset = Process.GetCurrentProcess().TotalProcessorTime;
            Players = new Player[0];

            RaiseEvent( Starting );

            if( ConfigKey.BackupDataOnStartup.Enabled() ) {
                BackupData();
            }

            Player.Console = new Player( ConfigKey.ConsoleName.GetString() );
            Player.AutoRank = new Player( "(AutoRank)" );

            // Back up server data (PlayerDB, worlds, bans, config)
            if( ConfigKey.BlockDBEnabled.Enabled() ) {
                BlockDB.Init();
            }

            // Load the world list
            if( !WorldManager.LoadWorldList() ) return false;
            WorldManager.SaveWorldList();

            // Back up all worlds (if needed)
            if( ConfigKey.BackupOnStartup.Enabled() ) {
                foreach( World world in WorldManager.Worlds ) {
                    string backupFileName = String.Format( World.TimedBackupFormat,
                                                           world.Name, DateTime.Now ); // localized
                    world.SaveBackup( Path.Combine( Paths.BackupPath, backupFileName ) );
                }
            }

            // open the port
            Port = ConfigKey.Port.GetInt();
            InternalIP = IPAddress.Parse( ConfigKey.IP.GetString() );

            try {
                listener = new TcpListener( InternalIP, Port );
                listener.Start();

            } catch( Exception ex ) {
                // if the port is unavailable
                Logger.Log( LogType.Error,
                            "Could not start listening on port {0}, stopping. ({1})",
                            Port, ex.Message );
                if( !ConfigKey.IP.IsDefault() ) {
                    Logger.Log( LogType.Warning,
                                "Do not use the \"Designated IP\" setting unless you have multiple NICs or IPs." );
                }
                return false;
            }

            // Resolve internal and external IP addresses
            InternalIP = ( (IPEndPoint)listener.LocalEndpoint ).Address;
            IPAddress foundExternalIP = null;
            for( int i = 0; i < 3 && foundExternalIP == null; i++ ) {
                Logger.Log( LogType.SystemActivity, "Resolving external IP address... (try {0})", i + 1 );
                foundExternalIP = CheckExternalIP();
            }

            if( foundExternalIP != null ) {
                ExternalIP = foundExternalIP;
                Logger.Log( LogType.SystemActivity,
                            "Server.StartServer: now accepting connections at {0}:{1}",
                            ExternalIP, Port );
            } else {
                Logger.Log( LogType.SystemActivity,
                            "Server.StartServer: External IP could not be looked up. Now accepting connections on port {0}",
                            Port );
            }

            // list loaded worlds
            WorldManager.UpdateWorldList();
            Logger.Log( LogType.SystemActivity,
                        "All available worlds: {0}",
                        WorldManager.Worlds.JoinToString( ", ", w => w.Name ) );

            Logger.Log( LogType.SystemActivity,
                        "Main world: {0}; default rank: {1}",
                        WorldManager.MainWorld.Name, RankManager.DefaultRank.Name );

            // Check for incoming connections (every 250ms)
            checkConnectionsTask = Scheduler.NewTask( CheckConnections ).RunForever( CheckConnectionsInterval );

            // Check for idles (every 30s)
            checkIdlesTask = Scheduler.NewTask( CheckIdles ).RunForever( CheckIdlesInterval );

            // Monitor CPU usage (every 30s)
            try {
                MonitorProcessorUsage( null );
                Scheduler.NewTask( MonitorProcessorUsage ).RunForever( MonitorProcessorUsageInterval,
                                                                       MonitorProcessorUsageInterval );
            } catch( Exception ex ) {
                Logger.Log( LogType.Error,
                            "Server.StartServer: Could not start monitoring CPU use: {0}", ex );
            }

            // PlayerDB saving (every 90s)
            PlayerDB.StartSaveTask();

            // Announcements
            if( ConfigKey.AnnouncementInterval.GetInt() > 0 ) {
                TimeSpan announcementInterval = TimeSpan.FromMinutes( ConfigKey.AnnouncementInterval.GetInt() );
                Scheduler.NewTask( ShowRandomAnnouncement )
                         .RunForever( announcementInterval );
            }

            // garbage collection (every 60s)
            gcTask = Scheduler.NewTask( DoGC )
                              .RunForever( GCInterval, TimeSpan.FromSeconds( 45 ) );

            Heartbeat.Start();

            if( ConfigKey.IRCBotEnabled.Enabled() ) {
                IRC.Start();
            }

            if( ConfigKey.AutoRankEnabled.Enabled() ) {
                Scheduler.NewTask( AutoRankManager.TaskCallback )
                         .RunForever( AutoRankManager.TickInterval );
            }

            if( ConfigKey.RestartInterval.GetInt() > 0 ) {
                // schedule automatic restart
                TimeSpan restartIn = TimeSpan.FromSeconds( ConfigKey.RestartInterval.GetInt() );
                ShutdownParams sp = new ShutdownParams( ShutdownReason.RestartTimer, restartIn, true,
                                                        "Automatic Server Restart",
                                                        Player.Console );
                Shutdown( sp, false );
            }

            // start the main loop - server is now connectible
            Scheduler.Start();
            IsRunning = true;

            RaiseEvent( Started );
            return true;
        }
Ejemplo n.º 6
0
 static void RaiseShutdownEndedEvent( ShutdownParams shutdownParams )
 {
     var h = ShutdownEnded;
     if( h != null ) h( null, new ShutdownEventArgs( shutdownParams ) );
 }
Ejemplo n.º 7
0
        static void ShutdownHandler([NotNull] Player player, [NotNull] CommandReader cmd) {
            string delayString = cmd.Next();
            TimeSpan delayTime = DefaultShutdownTime;
            string reason = "";

            if (delayString != null) {
                if (delayString.Equals("abort", StringComparison.OrdinalIgnoreCase)) {
                    if (Server.CancelShutdown()) {
                        Logger.Log(LogType.UserActivity,
                                   "Shutdown aborted by {0}.",
                                   player.Name);
                        Server.Message("&WShutdown aborted by {0}", player.ClassyName);
                    } else {
                        player.MessageNow("Cannot abort shutdown - too late.");
                    }
                    return;
                } else if (!delayString.TryParseMiniTimeSpan(out delayTime)) {
                    CdShutdown.PrintUsage(player);
                    return;
                }
                if (delayTime > DateTimeUtil.MaxTimeSpan) {
                    player.MessageMaxTimeSpan();
                    return;
                }
                reason = cmd.NextAll();
            }

            if (delayTime.TotalMilliseconds > Int32.MaxValue - 1) {
                player.Message("WShutdown: Delay is too long, maximum is {0}",
                               TimeSpan.FromMilliseconds(Int32.MaxValue - 1).ToMiniString());
                return;
            }

            Server.Message("&WServer shutting down in {0}", delayTime.ToMiniString());

            if (String.IsNullOrWhiteSpace(reason)) {
                Logger.Log(LogType.UserActivity,
                           "{0} scheduled a shutdown ({1} delay).",
                           player.Name,
                           delayTime.ToCompactString());
                ShutdownParams sp = new ShutdownParams(ShutdownReason.ShutdownCommand, delayTime, false);
                Server.Shutdown(sp, false);
            } else {
                Server.Message("&SShutdown reason: {0}", reason);
                Logger.Log(LogType.UserActivity,
                           "{0} scheduled a shutdown ({1} delay). Reason: {2}",
                           player.Name,
                           delayTime.ToCompactString(),
                           reason);
                ShutdownParams sp = new ShutdownParams(ShutdownReason.ShutdownCommand, delayTime, false, reason, player);
                Server.Shutdown(sp, false);
            }
        }
Ejemplo n.º 8
0
 private static void RaiseShutdownBeganEvent( ShutdownParams shutdownParams )
 {
     var h = ShutdownBegan;
     if ( h != null )
         h( null, new ShutdownEventArgs( shutdownParams ) );
 }
Ejemplo n.º 9
0
        internal static void ShutdownNow( ShutdownParams shutdownParams ) {
            if( IsShuttingDown ) return; // to avoid starting shutdown twice
            if( shutdownParams == null ) throw new ArgumentNullException( "shutdownParams" );
            IsShuttingDown = true;
#if DEBUG
#else
            try {
#endif
                RaiseShutdownBeganEvent( shutdownParams );

                Scheduler.BeginShutdown();

                Logger.Log( "Server shutting down ({0})", LogType.SystemActivity,
                            shutdownParams.ReasonString );

                // stop accepting new players
                if( listener != null ) {
                    listener.Stop();
                    listener = null;
                }

                // kick all players
                lock( SessionLock ) {
                    foreach( Session s in Sessions ) {
                        // NOTE: kick packet delivery here is not currently guaranteed
                        s.Kick( "Server shutting down (" + shutdownParams.ReasonString + Color.White + ")", LeaveReason.ServerShutdown );
                    }
                    if( Sessions.Count > 0 ) {
                        // increase the chances of kick packets being delivered
                        Thread.Sleep( 1000 );
                    }
                }

                // kill IRC bot
                IRC.Disconnect();

                if( WorldManager.WorldList != null ) {
                    lock( WorldManager.WorldListLock ) {
                        // unload all worlds (includes saving)
                        foreach( World world in WorldManager.WorldList ) {
                            world.SaveMap();
                        }
                    }
                }

                Scheduler.EndShutdown();

                if( PlayerDB.IsLoaded ) PlayerDB.Save();
                if( IPBanList.IsLoaded ) IPBanList.Save();

                RaiseShutdownEndedEvent( shutdownParams );
#if DEBUG
#else
            } catch( Exception ex ) {
                Logger.LogAndReportCrash( "Error in Server.Shutdown", "fCraft", ex, true );
            }
#endif
        }
Ejemplo n.º 10
0
 /// <summary> Initiates the server shutdown with given parameters. </summary>
 /// <param name="shutdownParams"> Shutdown parameters </param>
 /// <param name="waitForShutdown"> If true, blocks the calling thread until shutdown is complete or cancelled. </param>
 public static void Shutdown( ShutdownParams shutdownParams, bool waitForShutdown ) {
     if( shutdownParams == null ) throw new ArgumentNullException( "shutdownParams" );
     if( !CancelShutdown() ) return;
     shutdownThread = new Thread( ShutdownThread ) {
         Name = "fCraft.Shutdown"
     };
     shutdownThread.Start( shutdownParams );
     if( waitForShutdown ) {
         ShutdownWaiter.WaitOne();
     }
 }
Ejemplo n.º 11
0
 static void AutoRestartCallback( SchedulerTask task ) {
     var shutdownParams = new ShutdownParams( ShutdownReason.Restarting, 5, true, true );
     Server.Shutdown( shutdownParams, false );
 }
Ejemplo n.º 12
0
        static void RestartHandler(Player player, CommandReader cmd)
        {
            string   delayString = cmd.Next();
            TimeSpan delayTime   = DefaultShutdownTime;
            string   reason      = "";

            if (delayString != null)
            {
                if (delayString.Equals("abort", StringComparison.OrdinalIgnoreCase))
                {
                    if (Server.CancelShutdown())
                    {
                        Logger.Log(LogType.UserActivity,
                                   "Restart aborted by {0}.", player.Name);
                        Server.Message("&WRestart aborted by {0}", player.ClassyName);
                    }
                    else
                    {
                        player.MessageNow("Cannot abort restart - too late.");
                    }
                    return;
                }
                else if (!delayString.TryParseMiniTimespan(out delayTime))
                {
                    CdShutdown.PrintUsage(player);
                    return;
                }
                if (delayTime > DateTimeUtil.MaxTimeSpan)
                {
                    player.MessageMaxTimeSpan();
                    return;
                }
                reason = cmd.NextAll();
            }

            if (delayTime.TotalMilliseconds > Int32.MaxValue - 1)
            {
                player.Message("Restart: Delay is too long, maximum is {0}",
                               TimeSpan.FromMilliseconds(Int32.MaxValue - 1).ToMiniString());
                return;
            }

            Server.Message("&WServer restarting in {0}", delayTime.ToMiniString());

            if (String.IsNullOrEmpty(reason))
            {
                Logger.Log(LogType.UserActivity,
                           "{0} scheduled a restart ({1} delay).",
                           player.Name, delayTime.ToCompactString());
                ShutdownParams sp = new ShutdownParams(ShutdownReason.Restarting, delayTime, true, true);
                Server.Shutdown(sp, false);
            }
            else
            {
                Server.Message("&WRestart reason: {0}", reason);
                Logger.Log(LogType.UserActivity,
                           "{0} scheduled a restart ({1} delay). Reason: {2}",
                           player.Name, delayTime.ToCompactString(), reason);
                ShutdownParams sp = new ShutdownParams(ShutdownReason.Restarting, delayTime, true, true, reason, player);
                Server.Shutdown(sp, false);
            }
        }
Ejemplo n.º 13
0
 static void RaiseShutdownEndedEvent( ShutdownParams shutdownParams ) {
     var handler = ShutdownEnded;
     if( handler != null ) handler( null, new ShutdownEventArgs( shutdownParams ) );
 }
Ejemplo n.º 14
0
        static void Restart( Player player, Command cmd ) {
            int delay;
            if( !cmd.NextInt( out delay ) ) {
                delay = 5;
                cmd.Rewind();
            }
            string reason = cmd.Next();

            Server.SendToAll( "&WServer restarting in {0} seconds.", delay );

            if( reason == null ) {
                Logger.Log( "{0} restarted the server ({1} second delay).", LogType.UserActivity,
                            player.Name, delay );
                ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delay, true, true );
                Server.Shutdown( sp, false );
            } else {
                Logger.Log( "{0} restarted the server ({1} second delay). Reason: {2}", LogType.UserActivity,
                            player.Name, delay, reason );
                ShutdownParams sp = new ShutdownParams( ShutdownReason.Restarting, delay, true, true, reason, player );
                Server.Shutdown( sp, false );
            }
        }
Ejemplo n.º 15
0
        static void Shutdown( Player player, Command cmd ) {
            int delay;
            if( !cmd.NextInt( out delay ) ) {
                delay = 5;
                cmd.Rewind();
            }
            string reason = cmd.NextAll();

            if( reason.Equals( "abort", StringComparison.OrdinalIgnoreCase ) ) {
                if( Server.CancelShutdown() ) {
                    Logger.Log( "Shutdown aborted by {0}.", LogType.UserActivity, player.Name );
                    Server.SendToAll( "&WShutdown aborted by {0}", player.GetClassyName() );
                } else {
                    player.MessageNow( "Cannot abort shutdown - too late." );
                }
                return;
            }

            Server.SendToAll( "&WServer shutting down in {0} seconds.", delay );

            if( String.IsNullOrEmpty( reason ) ) {
                Logger.Log( "{0} shut down the server ({1} second delay).", LogType.UserActivity,
                            player.Name, delay );
                ShutdownParams sp = new ShutdownParams( ShutdownReason.ShuttingDown, delay, true, false );
                Server.Shutdown( sp, false );
            } else {
                Server.SendToAll( "&WShutdown reason: {0}", reason );
                Logger.Log( "{0} shut down the server ({1} second delay). Reason: {2}", LogType.UserActivity,
                            player.Name, delay, reason );
                ShutdownParams sp = new ShutdownParams( ShutdownReason.ShuttingDown, delay, true, false, reason, player );
                Server.Shutdown( sp, false );
            }
        }