/// <summary> /// Create a new validation context with the specified properties /// </summary> /// <param name="contextID">(Optional) identifier used to track this context</param> /// <param name="validator">Validator which owns this context</param> /// <param name="validationHelper">Helper object which is being used in this context</param> /// <param name="salt">Validation salt</param> public ValidationContext(string contextID, ICDKeyValidator validator, object validationHelper, int salt) { ContextID = contextID; Validator = validator; ValidationHelper = validationHelper; Salt = salt; KeyHash = ""; SaltedKeyHash = ""; ClientType = "NONE"; ClientVersion = 0; }
/// <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> /// 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> /// 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> /// Constructor, called by the Connection class when it has established that this connection is to a /// server and has performed the initial authentication handshake. At this point the remote server /// should still be in the waiting for heartbeat State. /// </summary> /// <param name="serverList"></param> /// <param name="socket"></param> /// <param name="banFile"></param> public ServerConnection(Connection parentConnection, Socket socket, IConnectionLogWriter logWriter, ServerList serverList, GeoIP geoip, OperatingSystem operatingSystem, string locale, bool bStatLogging, MD5Manager md5Manager, ICDKeyValidator cdKeyValidator, IGameStatsLog gameStats) : base(socket, logWriter, serverList, geoip) { this.outerConnection = parentConnection; this.operatingSystem = operatingSystem; this.locale = locale; this.md5Manager = md5Manager; this.cdKeyValidator = cdKeyValidator; this.gameStats = gameStats; // Socket ID for logging SocketID = String.Format("{0}:{1}", (socket.RemoteEndPoint as IPEndPoint).Address, (socket.RemoteEndPoint as IPEndPoint).Port); // Set socket timeout socket.ReceiveTimeout = socketTimeoutSeconds * 1000; MasterServer.Log("[{0}] Accepting new server connection. Version={1}", (socket.RemoteEndPoint as IPEndPoint).Address.ToString(), parentConnection.Version); int matchID = serverList.GetMatchID(null); // Create the server object and register it with the server list server = new Server(this, parentConnection.Version, (socket.RemoteEndPoint as IPEndPoint).Address, parentConnection.CDKeyHash, geoip, serverList.GetHeartbeatCode(), bStatLogging, operatingSystem, locale, matchID); serverList.Add(server); }
/// <summary> /// Get configured modules from the module manager /// </summary> /// <param name="gameStats">GameStats module will be returned in this variable</param> /// <param name="cdKeyValidator">CD Key Validator module will be returned in this variable</param> /// <returns>True if all modules were loaded correctly</returns> private static bool LoadConfiguredModules(out IGameStatsLog gameStats, out ICDKeyValidator cdKeyValidator) { Console.WriteLine("Initialising log writer module..."); logWriter = ModuleManager.GetModule <ILogWriter>(); ConsoleColor oldColour = Console.ForegroundColor; // Warn if the CD key validator module was not loaded if (logWriter == null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Configuration error: the specified log writer module was not loaded"); Console.ForegroundColor = oldColour; MasterServer.Log("Configuration error: the specified log writer module was not loaded"); if (!ConsoleUtilities.InConsoleSession()) { WinForms.MessageBox.Show("Configuration error: the specified log writer module was not loaded", "Configuration error", WinForms.MessageBoxButtons.OK); } } Console.WriteLine("Initialising GameStats module..."); gameStats = ModuleManager.GetModule <IGameStatsLog>(); // Warn if the GameStats module was not loaded if (gameStats == null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Configuration error: the specified gamestats module was not loaded"); Console.ForegroundColor = oldColour; MasterServer.Log("Configuration error: the specified gamestats module was not loaded"); if (!ConsoleUtilities.InConsoleSession()) { WinForms.MessageBox.Show("Configuration error: the specified gamestats module was not loaded", "Configuration error", WinForms.MessageBoxButtons.OK); } } Console.WriteLine("Initialising CD key validator module..."); cdKeyValidator = ModuleManager.GetModule <ICDKeyValidator>(); // Can't continue without a CD key validator module if (cdKeyValidator == null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Configuration error: the specified CD key validator module was not loaded"); Console.WriteLine("Critical. Master server shutting down"); Console.ForegroundColor = oldColour; if (!ConsoleUtilities.InConsoleSession()) { WinForms.MessageBox.Show("Configuration error: the specified CD key validator module was not loaded", "Critical error", WinForms.MessageBoxButtons.OK); } ReleaseModules(); return(false); } Console.WriteLine(); return(true); }