/// <summary> /// Master server constructor. Initialises child objects, helpers and listeners /// </summary> /// <param name="statusDisplay"></param> /// <param name="commandInterface"></param> private MasterServer(IStatusDisplay statusDisplay, ICommandInterface commandInterface, ICDKeyValidator cdKeyValidator, IGameStatsLog gameStats, ILogWriter logWriter) { if (MasterServer.instance != null) { throw new InvalidOperationException("Attempted to create a Master Server instance whilst another instance was still active"); } // Assign static references MasterServer.instance = this; MasterServer.logWriter = logWriter; // Assign instance references this.statusDisplay = statusDisplay; this.commandInterface = commandInterface; this.cdKeyValidator = cdKeyValidator; this.gameStats = gameStats; // Initialise the command interface if we have one if (commandInterface != null) { commandInterface.OnChange += new EventHandler(DisplayCommandInterface); } // GeoIP resolver is used to resolve IP addresses to locations geoIP = new GeoIP(); // MD5 database is used to download new MD5 package data to connecting servers md5Manager = new MD5Manager(); // IP ban manager used to ban clients from accessing the server banManager = new IPBanManager(); // Create the Server List object serverList = new ServerList(this); // Create the web server webServer = new WebServer(banManager); // Initialise the status display module if we have one if (statusDisplay != null) { logBufferSize = statusDisplay.LogBufferSize; logBufferWrap = statusDisplay.LogBufferWrap; displayTimer = new Timer(new TimerCallback(this.Display)); Display(null); } // Load the GeoIP database, MD5 database and ban list from the files (this happens last because they may take a while) geoIP.Load(MasterServer.Settings.GeoIPDataFile); md5Manager.Load(MasterServer.Settings.MD5DataFile); banManager.Load(MasterServer.Settings.BanListFile); }
/// <summary> /// Constructor. Loads request handler classes from the current assembly. /// </summary> public WebServer(IPBanManager banManager) { this.banManager = banManager; WebServer.ListenPorts = "-"; // Determine web root string assemblyPath = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName; WebServer.WebRoot = Path.Combine(assemblyPath, MasterServer.Settings.WebRootFolder); // Register as a handler for console commands ModuleManager.RegisterCommandListener(this); }
/// <summary> /// Shut down this listener and all child threads /// </summary> public void Shutdown() { aborted = true; this.serverList = null; this.geoIP = null; this.cdKeyValidator = null; this.gameStats = null; this.md5Manager = null; this.banManager = null; if (listenThread != null) { // Try to close the listen socket if (listenSocket != null) { try { listenSocket.Close(); } catch { } } // Try to forcibly abort the listen thread listenThread.Abort(); listenThread.Join(); listenThread = null; MasterServer.Log("[NET] Query listener socket {0} shut down.", endpoint.Port); } // Abort active connections ConnectionManager.AbortAll(endpoint.Port); // Release log writer ModuleManager.ReleaseModule <IConnectionLogWriter>(); }
/// <summary> /// Constructor, create a new query listener at the specified endpoint /// </summary> /// <param name="endpoint">Endpoint for this listener</param> /// <param name="serverList">Server list object to pass to new connections</param> /// <param name="geoIP">GeoIP resolver to pass to new connections</param> /// <param name="md5Manager">MD5 manager to pass to new connections</param> /// <param name="banManager">IP ban manager to pass to new connections</param> /// <param name="cdKeyValidator">CD key validator module to pass to new connections</param> /// <param name="gameStats">Game stats module to pass to new connections</param> public QueryListener(IPEndPoint endpoint, ServerList serverList, GeoIP geoIP, MD5Manager md5Manager, IPBanManager banManager, ICDKeyValidator cdKeyValidator, IGameStatsLog gameStats) { // Endpoint to listen this.endpoint = endpoint; // These objects are passed to new connections this.serverList = serverList; this.geoIP = geoIP; this.md5Manager = md5Manager; this.banManager = banManager; this.cdKeyValidator = cdKeyValidator; this.gameStats = gameStats; // Get configured connection log writer module this.logWriter = ModuleManager.GetModule <IConnectionLogWriter>(); // Bind the listen socket ready to begin listening listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); listenSocket.Bind(this.Endpoint); // Create and start the listen thread listenThread = new Thread(ListenThreadProc); listenThread.Start(); }
/// <summary> /// Create a new connection instance to handle an inbound connection /// </summary> /// <param name="socket">TCP socket for communicating with the remote server</param> /// <param name="connectionLogWriter">Log writer module</param> /// <param name="serverList">Server List object</param> /// <param name="geoIP">GeoIP resolver</param> /// <param name="md5Manager">MD5 database manager</param> /// <param name="banManager">IP ban manager</param> /// <param name="cdKeyValidator">CD key validator</param> /// <param name="gameStats">Game stats module</param> public Connection(Socket socket, IConnectionLogWriter logWriter, ServerList serverList, GeoIP geoIP, MD5Manager md5Manager, IPBanManager banManager, ICDKeyValidator cdKeyValidator, IGameStatsLog gameStats) : this(socket, logWriter, serverList, geoIP) { // Raise the NewConnection event for connected packet analysers OnNewConnection(); // Check whether the remote host is banned if (banManager.IsBanned((socket.RemoteEndPoint as IPEndPoint).Address)) { ConnectionLog("BANNED"); socket.Close(); return; } this.md5Manager = md5Manager; this.cdKeyValidator = cdKeyValidator; this.gameStats = gameStats; // Handle this connection in a new thread ConnectionThreadManager.CreateStart(new ThreadStart(Handle)); }
/// <summary> /// Release any resources used /// </summary> public void Dispose() { banManager = null; ModuleManager.UnregisterCommandListener(this); }
/// <summary> /// Shut down the master server instance /// </summary> private void Shutdown() { // End listen thread and close the listen sockets EndListening(); // Web server if (webServer != null) { webServer.Dispose(); webServer = null; } // Shut down the server list if (serverList != null) { serverList.Shutdown(); serverList = null; } // Ban manager if (banManager != null) { banManager.Dispose(); banManager = null; } // MD5 database if (md5Manager != null) { md5Manager.Dispose(); md5Manager = null; } // GeoIP resolver if (geoIP != null) { geoIP.Dispose(); geoIP = null; } // Display update timer if (displayTimer != null) { displayTimer.Change(Timeout.Infinite, Timeout.Infinite); displayTimer.Dispose(); displayTimer = null; } // Shut down the status display if we have one if (statusDisplay != null) { statusDisplay.Notify("EXIT"); ModuleManager.ReleaseModule <IStatusDisplay>(); statusDisplay = null; } // Shut down the command interface if we have one if (commandInterface != null) { commandInterface.OnChange -= new EventHandler(DisplayCommandInterface); ModuleManager.ReleaseModule <ICommandInterface>(); commandInterface = null; } }