#region Arthea License /*********************************************************************** * Arthea MUD by R. Jennings (2007) http://arthea.googlecode.com/ * * By using this code you comply with the Artistic and GPLv2 Licenses. * ***********************************************************************/ #endregion using System; using System.Collections.Generic; using System.Net.Sockets; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; #if !MONO using System.Runtime.Remoting.Channels.Tcp; #endif using Arthea.Connections; using Arthea.Connections.Enums; using Arthea.Connections.Players; using Arthea.Environment; namespace Arthea.Commands.Admin { /// <summary> /// Implementation of a reboot command. /// </summary> public class RebootCommand : Command { #region [rgn] Constructors (1) /// <summary> /// Initializes a new instance of the <see cref="RebootCommand"/> class. /// </summary> public RebootCommand() : base("reboot", "reboots the game, keeping connections", Levels.Admin) { } #endregion [rgn] #region [rgn] Methods (1) // [rgn] Public Methods (1) /// <summary> /// Processes the command for a player. /// </summary> /// <param name="player">The player.</param> /// <param name="argument">The argument.</param> public override void Process(Player player, String argument) { #if MONO player.WriteLine("Reboot not available on this server."); #else Log.Info("Reboot by {0}...", player.Name); player.Act(null, null, Act.ToWorld, "$n has initiated a reboot."); player.WriteLine("Reboot activated..."); TcpChannel channel = new TcpChannel(RebootRecovery.Port); ChannelServices.RegisterChannel(channel, false); //register channel //register remote object RemotingConfiguration.RegisterWellKnownServiceType( typeof (RebootRecovery), "RebootRecovery", WellKnownObjectMode.SingleCall); System.Diagnostics.Process.Start( System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName, "-reboot"); while (!RebootRecovery.Done) { } ChannelServices.UnregisterChannel(channel); Server.Instance.State = ServerState.Stopping; #endif } #endregion [rgn] } /// <summary> /// Implementation of a reboot recovery. /// </summary> public class RebootRecovery : MarshalByRefObject { #region [rgn] Fields (2) /// <summary> /// Signals this recovery is done /// </summary> public static bool Done = false; /// <summary> /// The port to use. /// </summary> public static int Port = 4010; #endregion [rgn] #region [rgn] Methods (2) // [rgn] Public Methods (2) /// <summary> /// Signales the recovery is done. /// </summary> public void Finished() { Done = true; } /// <summary> /// Transfers the connections. /// </summary> /// <param name="processId">The process id.</param> /// <returns></returns> public Dictionary<string, SocketInformation> TransferConnections(int processId) { Log.Info("Transferring connections..."); Dictionary<string, SocketInformation> connections = new Dictionary<string, SocketInformation>(); foreach (Connection con in Lists.Connections) { if (con.State != ConnectionState.Playing) { continue; } connections.Add(con.Player.Name, con.Socket.DuplicateAndClose(processId)); } return connections; } #endregion [rgn] } }