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);
    }
Exemplo n.º 2
0
    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));
            }
        }
    }