private bool ParseServerDetails(IPEndPoint remote, byte[] data) { string key = String.Format("{0}:{1}", remote.Address, remote.Port); string receivedData = Encoding.UTF8.GetString(data); //Console.WriteLine(receivedData.Replace("\x00", "\\x00").Replace("\x02", "\\x02")); // split by 000 (info/player separator) and 002 (players/teams separator) // the players/teams separator is really 00, but because 00 may also be used elsewhere (an empty value for example), we hardcode it to 002 // the 2 is the size of the teams, for BF2 this is always 2. string[] sections = receivedData.Split(new string[] { "\x00\x00\x00", "\x00\x00\x02" }, StringSplitOptions.None); //Console.WriteLine(sections.Length); if (sections.Length != 3 && !receivedData.EndsWith("\x00\x00")) return true; // true means we don't send back a response string serverVars = sections[0]; //string playerVars = sections[1]; //string teamVars = sections[2]; string[] serverVarsSplit = serverVars.Split(new string[] { "\x00" }, StringSplitOptions.None); GameServer server = new GameServer() { Valid = false, IPAddress = remote.Address.ToString(), QueryPort = remote.Port, LastRefreshed = DateTime.UtcNow, LastPing = DateTime.UtcNow }; // set the country based off ip address if (GeoIP.Instance == null || GeoIP.Instance.Reader == null) { server.country = "??"; } else { try { server.country = GeoIP.Instance.Reader.Omni(server.IPAddress).Country.IsoCode.ToUpperInvariant(); } catch (Exception e) { LogError(Category, e.ToString()); server.country = "??"; } } for (int i = 0; i < serverVarsSplit.Length - 1; i += 2) { PropertyInfo property = server.GetType().GetProperty(serverVarsSplit[i]); if (property == null) continue; if (property.Name == "hostname") { // strip consecutive whitespace from hostname property.SetValue(server, Regex.Replace(serverVarsSplit[i + 1], @"\s+", " ").Trim(), null); } else if (property.Name == "bf2_plasma") { // set plasma to true if the ip is in plasmaservers.txt if (PlasmaServers.Any(x => x.Equals(remote.Address))) property.SetValue(server, true, null); else property.SetValue(server, false, null); } else if (property.Name == "bf2_ranked") { // we're always a ranked server (helps for mods with a default bf2 main menu, and default filters wanting ranked servers) property.SetValue(server, true, null); } else if (property.Name == "bf2_pure") { // we're always a pure server property.SetValue(server, true, null); } else if (property.PropertyType == typeof(Boolean)) { // parse string to bool (values come in as 1 or 0) int value; if (Int32.TryParse(serverVarsSplit[i + 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) { property.SetValue(server, value != 0, null); } } else if (property.PropertyType == typeof(Int32)) { // parse string to int int value; if (Int32.TryParse(serverVarsSplit[i + 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) { property.SetValue(server, value, null); } } else if (property.PropertyType == typeof(Double)) { // parse string to double double value; if (Double.TryParse(serverVarsSplit[i + 1], NumberStyles.Float, CultureInfo.InvariantCulture, out value)) { property.SetValue(server, value, null); } } else if (property.PropertyType == typeof(String)) { // parse string to string property.SetValue(server, serverVarsSplit[i + 1], null); } } if (String.IsNullOrWhiteSpace(server.gamename) || !server.gamename.Equals("battlefield2", StringComparison.InvariantCultureIgnoreCase)) { // only allow servers with a gamename of battlefield2 return true; // true means we don't send back a response } else if (String.IsNullOrWhiteSpace(server.gamevariant) || !ModWhitelist.ToList().Any(x => SQLMethods.EvaluateIsLike(server.gamevariant, x))) { // only allow servers with a gamevariant of those listed in modwhitelist.txt, or (pr || pr_*) by default return true; // true means we don't send back a response } // you've got to have all these properties in order for your server to be valid if (!String.IsNullOrWhiteSpace(server.hostname) && !String.IsNullOrWhiteSpace(server.gamevariant) && !String.IsNullOrWhiteSpace(server.gamever) && !String.IsNullOrWhiteSpace(server.gametype) && !String.IsNullOrWhiteSpace(server.mapname) && server.hostport > 1024 && server.hostport <= UInt16.MaxValue && server.maxplayers > 0) { server.Valid = true; } // if the server list doesn't contain this server, we need to return false in order to send a challenge // if the server replies back with the good challenge, it'll be added in AddValidServer if (!Servers.ContainsKey(key)) return false; Servers.AddOrUpdate(key, server, (k, old) => { if (!old.Valid && server.Valid) { Log(Category, String.Format("Added new server at: {0}:{1} ({2}) ({3})", server.IPAddress, server.QueryPort, server.country, server.gamevariant)); } return server; }); return true; }
private static string GetField(GameServer server, string fieldName) { object value = server.GetType().GetProperty(fieldName).GetValue(server, null); if (value == null) return String.Empty; else if (value is Boolean) return (bool)value ? "1" : "0"; else return value.ToString(); }
private void AddValidServer(IPEndPoint remote) { string key = String.Format("{0}:{1}", remote.Address, remote.Port); GameServer server = new GameServer() { Valid = false, IPAddress = remote.Address.ToString(), QueryPort = remote.Port, LastRefreshed = DateTime.UtcNow, LastPing = DateTime.UtcNow }; Servers.AddOrUpdate(key, server, (k, old) => { return server; }); }
private bool ParseServerDetails(IPEndPoint remote, byte[] data) { string key = String.Format("{0}:{1}", remote.Address, remote.Port); string receivedData = Encoding.UTF8.GetString(data); //Console.WriteLine(receivedData.Replace("\x00", "\\x00").Replace("\x02", "\\x02")); // split by 000 (info/player separator) and 002 (players/teams separator) // the players/teams separator is really 00, but because 00 may also be used elsewhere (an empty value for example), we hardcode it to 002 // the 2 is the size of the teams, for BF2 this is always 2. string[] sections = receivedData.Split(new string[] { "\x00\x00\x00", "\x00\x00\x02" }, StringSplitOptions.None); //Console.WriteLine(sections.Length); if (sections.Length != 3 && !receivedData.EndsWith("\x00\x00")) return true; // true means we don't send back a response string serverVars = sections[0]; //string playerVars = sections[1]; //string teamVars = sections[2]; string[] serverVarsSplit = serverVars.Split(new string[] { "\x00" }, StringSplitOptions.None); GameServer server = new GameServer() { Valid = false, IPAddress = remote.Address.ToString(), QueryPort = remote.Port, LastRefreshed = DateTime.UtcNow, LastPing = DateTime.UtcNow }; // set the country based off ip address if (GeoIP.Instance == null || GeoIP.Instance.Reader == null) { server.country = "??"; } else { try { server.country = GeoIP.Instance.Reader.Omni(server.IPAddress).Country.IsoCode.ToUpperInvariant(); } catch (Exception e) { LogError(Category, e.ToString()); server.country = "??"; } } for (int i = 0; i < serverVarsSplit.Length - 1; i += 2) { PropertyInfo property = server.GetType().GetProperty(serverVarsSplit[i]); if (property == null) continue; if (property.Name == "hostname") { // strip consecutive whitespace from hostname property.SetValue(server, Regex.Replace(serverVarsSplit[i + 1], @"\s+", " ").Trim(), null); } else if (property.PropertyType == typeof(Boolean)) { // parse string to bool (values come in as 1 or 0) int value; if (Int32.TryParse(serverVarsSplit[i + 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) { property.SetValue(server, value != 0, null); } } else if (property.PropertyType == typeof(Int32)) { // parse string to int int value; if (Int32.TryParse(serverVarsSplit[i + 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) { property.SetValue(server, value, null); } } else if (property.PropertyType == typeof(Double)) { // parse string to double double value; if (Double.TryParse(serverVarsSplit[i + 1], NumberStyles.Float, CultureInfo.InvariantCulture, out value)) { property.SetValue(server, value, null); } } else if (property.PropertyType == typeof(String)) { // parse string to string property.SetValue(server, serverVarsSplit[i + 1], null); } } // XXX TODO FIXME check server.gamename to be a valid gamename if (String.IsNullOrWhiteSpace(server.gamename)) { Log(Category, String.Format("ParseServerDetails: server.gamename rejected {0}", server.gamename ?? "(null)")); return true; // true means we don't send back a response } // XXX TODO FIXME do we need to check server.gamevariant? I don't think so right now // you've got to have all these properties in order for your server to be valid if (!String.IsNullOrWhiteSpace(server.hostname) && //!String.IsNullOrWhiteSpace(server.gamevariant) && //!String.IsNullOrWhiteSpace(server.gamever) && //!String.IsNullOrWhiteSpace(server.gametype) && //!String.IsNullOrWhiteSpace(server.mapname) && server.hostport > 1024 && server.hostport <= UInt16.MaxValue /*&& server.maxplayers > 0*/) { server.Valid = true; server.groupid = null;//were "1", changed 28.09 } // if the server list doesn't contain this server, we need to return false in order to send a challenge // if the server replies back with the good challenge, it'll be added in AddValidServer // XXX Maybe we have to make all this conditional // Log(Category, String.Format("Trying to addOrUpdate: {0}, server.hostport: {1}, server.Valid: {2}, server.IPAddress: {3}, server.QueryPort: {4}, server.country: {5}, server.gamevariant: {6}", // key, server.hostport, server.Valid, server.IPAddress, server.QueryPort, server.country, server.gamevariant ?? "(null)")); Servers.AddOrUpdate(key, server, (k, old) => { if (!old.Valid && server.Valid) { Log(Category, String.Format("Added new server at: {0}:{1} ({2}) ({3})", server.IPAddress, server.QueryPort, server.country, server.gamevariant ?? "(null)")); } return server; }); return false; }