#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]
}
}