public static serverStatus checkServer(string serveraddress, string gametype, int serverport) { serverStatus returnValues = new serverStatus(); // query the selected server GameServerInfo.GameType type = (GameServerInfo.GameType)Enum.Parse(typeof(GameServerInfo.GameType), gametype.First().ToString().ToUpper() + gametype.Substring(1)); GameServerInfo.GameServer server = new GameServerInfo.GameServer(serveraddress, serverport, type); // Enable or disable debugmode (writes lastquery.dat to disk) server.DebugMode = false; var watch = System.Diagnostics.Stopwatch.StartNew(); server.QueryServer(); watch.Stop(); returnValues.scanTime = watch.ElapsedMilliseconds; var testD = server.Parameters["sv_maxclients"]; // Clear old stuff if (!server.IsOnline) { // Server is offline or not responding returnValues.serverOnline = false; return(returnValues); } else { returnValues.serverOnline = true; returnValues.playersConnected = server.NumPlayers; returnValues.maxPlayers = server.MaxPlayers; returnValues.serverName = server.Name; returnValues.serverMod = server.Mod; returnValues.serverMap = server.Map; returnValues.serverHasPassword = server.Passworded; // returnValues.serverType = server._type; return(returnValues); } }
static void Main(string[] args) { /* Command line options to do * discover gameservers on given hostname / IP? * Autodetect game type on given port? * Give game type name Cod4 instead of gametype (quake3 e.g.) * load servers from json or txt? * linux compatibility? */ Console.CancelKeyPress += delegate { // no cleanup necessary currently Environment.Exit(1); }; // these variables will be set when the command line is parsed bool shouldShowHelp = false; List <string> servers = new List <string>(); List <string> types = new List <string>(); List <int> ports = new List <int>(); // console = default, autorefresh, xml (prtg) string outputFormat = "console"; bool autorefresh = false; int waitTime = 10; List <string> validGameTypes = GenerateValidGameTypes(); // these are the available options, not that they set the variables var options = new OptionSet { { "s|server=", "the server name (FQDN) or IP address.", s => servers.Add(s) }, { "t|type=", "the server type (protocol).", t => types.Add(t.ToLower()) }, { "p|port=", "the server port.", (int p) => ports.Add(p) }, { "o|output=", "output formatting.", o => outputFormat = o }, { "w|wait=", "wait time between checks - only for autorefresh.", (int w) => waitTime = w }, { "v", "increase debug message verbosity", v => { if (v != null) { ++verbosity; } } }, { "h|help", "show this message and exit", h => shouldShowHelp = h != null }, }; // parse extra command line arguments List <string> extra; try { // parse the command line extra = options.Parse(args); } catch (OptionException e) { // output some error message Console.ForegroundColor = ConsoleColor.DarkRed; Console.Write("Error: "); switch (e.OptionName) { case "-s": Console.WriteLine("-s needs to a valid hostname or IP address"); break; case "-p": Console.WriteLine("-p needs to be a number"); break; case "-t": Console.WriteLine("-t needs to be a valid game type"); break; case "-o": Console.WriteLine("-o needs to be a valid game type"); break; case "-w": Console.WriteLine("-w needs to be a number"); break; } //Console.WriteLine(e.Message); Console.ResetColor(); Console.WriteLine("Try `--help' for more information."); return; } // Show help if help parameter is set if (shouldShowHelp) { ShowHelp(options); return; } // Validate command line arguments // check if amount of given arguments is divisible by 3 without remainder (ensures equal amount of arguments are given per server) int equalAmount = servers.Count + types.Count + ports.Count; if ((servers.Count >= 1 && types.Count >= 1 && ports.Count >= 1) && equalAmount % 3 == 0) { // at least 1 required parameter set given // check server name / ip against RFC 1123 specification Regex ValidIpAddressRegex = new Regex(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"); Regex ValidHostnameRegex = new Regex(@"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"); foreach (var server in servers) { Match MatchIP = ValidIpAddressRegex.Match(server); Match MatchHostname = ValidHostnameRegex.Match(server); if (MatchIP.Success || MatchHostname.Success) { // valid hostname or IP found } else { // invalid hostname or IP found DisplayParameterError("Error: " + server + " is not a valid hostname or IP!", options); } } // check if game type is valid // fix upper / lowercase issues first foreach (var type in types) { string result = FindValidGameType(type, validGameTypes); if (result == "") { DisplayParameterError("Error: " + type + " is not a valid game type!", options); } } } else { // not enough parameters for a valid set given // exit and display help message DisplayParameterError("Error: Not enough arguments given. Required are a set per server (hostname / IP, port and type)", options); } // Enable continuous check if (outputFormat.Equals("autorefresh")) { autorefresh = true; } while (true) { // Check each server given via command line options and output the result to the console int servercounter = 0; string output = ""; AutoUpdate(autorefresh, servers.Count(), waitTime); while (servercounter < servers.Count()) { string errorMsg = ""; string errorDetail = ""; serverStatus status = new serverStatus(); if (CheckReachable(servers.ElementAt(servercounter).ToString())) { status = checkServer(servers.ElementAt(servercounter).ToString(), FindValidGameType(types.ElementAt(servercounter).ToString(), validGameTypes), ports.ElementAt(servercounter)); } else { status = new serverStatus(); status.serverOnline = false; } if (status.serverOnline) { // Remove color codes for better readability. maybe add colors to console later on //status.serverName = Regex.Replace(status.serverName, @"\^[0-9]{1}", ""); switch (outputFormat) { case "console": printColored("Server: " + servers.ElementAt(servercounter).ToString() + " (" + status.serverName + ") is online: " + "Scan time " + status.scanTime + "ms and " + status.playersConnected + "/" + status.maxPlayers + " players are connected. Map: " + status.serverMap, ConsoleColor.DarkGreen); break; case "autorefresh": printColored("Server: " + servers.ElementAt(servercounter).ToString() + " (" + status.serverName + ") is online: " + "Scan time " + status.scanTime + "ms and " + status.playersConnected + "/" + status.maxPlayers + " players are connected. Map: " + status.serverMap, ConsoleColor.DarkGreen); break; case "xml": output += "<prtg>" + "<result>" + "<channel>Server scan time</channel>" + "<value>" + status.scanTime + "</value>" + "<unit>TimeResponse</unit>" + "</result>" + "<result>" + "<channel>Players connected</channel>" + "<value>" + status.playersConnected + "</value>" + "<unit>Count</unit>" + "<LimitMaxWarning>" + (status.maxPlayers - 1) + "</LimitMaxWarning>" + "</result>" + "</prtg>"; break; } Console.ResetColor(); } else { // return error message Console.ForegroundColor = ConsoleColor.DarkRed; switch (outputFormat) { case "console": Console.WriteLine("Server: " + servers.ElementAt(servercounter).ToString() + " is offline: " + "Scan time " + status.scanTime); break; case "autorefresh": Console.WriteLine("Server: " + servers.ElementAt(servercounter).ToString() + " is offline: " + "Scan time " + status.scanTime); break; case "xml": output += "<prtg>" + "<error>" + errorMsg + "</error>" + "<text>Can't reach server: " + errorDetail + "</text>" + "</prtg>"; break; } Console.ResetColor(); } //Console.WriteLine(message, server); servercounter++; } Console.Write(output); if (!autorefresh) { break; } else { // Sleep for waitTime seconds before checking servers again Thread.Sleep(waitTime * 1000); } //Console.ReadLine(); } }