public byte[] CompileResponse() { //https://github.com/derkalle4/gamespy-masterserver/blob/master/GamespyMasterserver/constants.vb byte[] buf = { 0, 0, GS_MS_SERVER_CMD_PUSHSERVER, 0 }; //2 bytes for the len, cmd, 1 for the flags //Setting up the bitwise-flags: byte flags = (byte)0; if (gServer.PortClosed) { //restrictive NAT/FW -> use natneg this.ToggleFlag(flags, GS_FLAG_CONNECT_NEGOTIATE_FLAG); //check if there's indeed some NAT or just a FW: if (gServer.IsNatted) { this.ToggleFlag(flags, GS_FLAG_PRIVATE_IP); this.ToggleFlag(flags, GS_FLAG_NONSTANDARD_PRIVATE_PORT); } } this.ToggleFlag(flags, GS_FLAG_ICMP_IP); //Allow ICMP-Ping this.ToggleFlag(flags, GS_FLAG_NONSTANDARD_PORT); //Just send the port every time this.ToggleFlag(flags, GS_FLAG_HAS_FULL_RULES); //We're sending everything we know //WITH gServer //Attach requested IPEP ConcatArray(queryIPEP.Address.GetAddressBytes(), buf); ConcatArray(BuildInvertedUInt16Array(queryIPEP.Port), buf); if (gServer.PortClosed) { IPAddress ip0 = null; //Attaching the public ip for "natneg w/o NAT" (firewall bypass) if (!IPAddress.TryParse(gServer.GetValue("localip0"), ip0)) { ip0 = IPAddress.Parse(gServer.PublicIP); } //Attach local IPEP ConcatArray(ip0.GetAddressBytes, buf); ConcatArray(BuildInvertedUInt16Array(UInt16.Parse(gServer.HostPort)), buf); } //Attach ICMP IP ConcatArray(queryIPEP.Address.GetAddressBytes(), buf); //END WITH buf[3] = flags; //Assign the flags at the offset we've already allocated earlier this.AttachFullRuleSet(buf); //NEED TO DIG INTO PARENT CLASS FOR THIS //Attach the packet lenght Array.Copy(BuildInvertedUInt16Array(buf.Length), buf, 2); //Dim s As String = BuildNiceString(buf) return(buf); }
private void AttachServer(GamespyGameserver server, byte[] buffer) { if (server.PortClosed && this.ParameterArray.Length < 2) { return; } byte serverFlags = (byte)0; IPAddress ip0 = null; bool hasLocalIP = IPAddress.TryParse(server.GetValue("localip0"), ip0); ToggleFlag(serverFlags, GS_FLAG_CONNECT_NEGOTIATE_FLAG); ToggleFlag(serverFlags, GS_FLAG_NONSTANDARD_PORT); if (this.Options == GS_FLAG_SEND_FIELDS_FOR_ALL) { ToggleFlag(serverFlags, GS_FLAG_PRIVATE_IP); ToggleFlag(serverFlags, GS_FLAG_NONSTANDARD_PRIVATE_PORT); ToggleFlag(serverFlags, GS_FLAG_HAS_KEYS); ToggleFlag(serverFlags, GS_FLAG_ICMP_IP); } else { //TODO: fix //GS_FLAG_NONSTANDARD_PRIVATE_PORT needed for PeerchatRoomMangle! if (server.IsNatted && !server.PortCosed && this.Options != 4) //85 { ToggleFlag(serverFlags, GS_FLAG_PRIVATE_IP); ToggleFlag(serverFlags, GS_FLAG_HAS_KEYS); ToggleFlag(serverFlags, GS_FLAG_UNSOLICITED_UDP); } else if (server.PortClosed) //126 { ToggleFlag(serverFlags, GS_FLAG_PRIVATE_IP); ToggleFlag(serverFlags, GS_FLAG_NONSTANDARD_PRIVATE_PORT); ToggleFlag(serverFlags, GS_FLAG_HAS_KEYS); ToggleFlag(serverFlags, GS_FLAG_ICMP_IP); } else //21 { ToggleFlag(serverFlags, GS_FLAG_UNSOLICITED_UDP); } } //Don't accept direct Querys for homeservers, they'll only slow down the SBQEngine ConcatArray(new byte[] { serverFlags }, buffer); //TODO: add compatibility for peerchat-lobbys //This implementation is critical: changing to the localip will cause wrong hash-calculations //for the peerchat lobby-system -> maybe detect peerchat games if (server.PublicIP == this.client.RemoteIPEP.Address.ToString() && server.IsNatted && !server.PortClosed && this.hasLocalIP) { ConcatArray(ip0.GetAddressBytes(), buffer); //it seems to depend on the game which port is used if (server.HasKey("localport")) { ConcatArray(ArrayFunctions.BuildInvertedUInt16Array(UInt16.Parse(server.GetValue("localport"))), buffer); } else { ConcatArray(ArrayFunctions.BuildInvertedUInt16Array(UInt16.Parse(server.HostPort)), buffer); } } else { ConcatArray(IPAddress.Parse(server.PublicIP).GetAddressBytes, buffer); //IP-Address ConcatArray(ArrayFunctions.BuildInvertedUInt16Array(UInt16.Parse(server.PublicPort)), buffer); //Port } if (serverFlags != null && GS_FLAG_PRIVATE_IP) //Attach natneg-params { if (!hasLocalIP) { return; } ushort lport = server.PublicPort; //UInt16.TryParse(server.GetValue("localport"), lport) ConcatArray(ip0.GetAddressBytes(), buffer); ConcatArray(ArrayFunctions.BuildInvertedUInt16Array(lport), buffer); } if (serverFlags != null && GS_FLAG_ICMP_IP) { ConcatArray(Net.IPAddress.Parse(server.PublicIP).GetAddressBytes, buffer); } //Attaching server details (for servers which aren't queried directly) if (serverFlags != null && GS_FLAG_HAS_KEYS) { ConcatArray(new byte[] { 255 }, buffer); //Attach a delimeter indicating that there's new data here for (int i = 1; i < this.ParameterArray.Length - 1; i++) //Try to attach every desired param { string val = server.GetValue(this.ParameterArray(i)); this.PushString(buffer, val, (i = this.ParameterArray.Length - 1)); } } }