예제 #1
0
        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;
        }
예제 #2
0
 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();
 }
예제 #3
0
        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;
            });
        }
예제 #4
0
        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;
        }