1

I'm trying to write a PHP TCP client to connect to an Unreal Engine 5 RCON server. I'm using an existing C# project on GitHub as a reference but I'm having trouble preparing packets to send. The GitHub project prepares a byte array which is then sent to the server. I've tried to re-write the function in PHP but I'm not sure I've done it correctly. But the bigger problem is socket_write() socket_send() and fwrite() all want a string and I now have an array. I believe I can format my array as a string to represent the bytes using pack() but I'm not sure how.

Here is the C# function from https://github.com/Sp1rit/ArkRcon/blob/master/Rcon/RconPacket.cs So this shows what I need to send.

    public static implicit operator byte[](RconPacket packet)
    {
        byte[] buffer = new byte[packet.Size + 4];

        packet.Size.ToLittleEndian().CopyTo(buffer, 0);
        packet.Id.ToLittleEndian().CopyTo(buffer, 4);
        ((int)packet.Type).ToLittleEndian().CopyTo(buffer, 8);
        Encoding.ASCII.GetBytes(packet.Body).CopyTo(buffer, 12);

        return buffer;
    }

Here is my attempt at converting that (See ConvertToArray() below). I did use __invoke but as there's also a reverse function and it wouldn't let me use __invoke twice. I've provided the whole class so you can see the full picture and you can see some commented code where I've tried different things.

class RconPacket
{

    private static int $idCounter = 1;

    public $Id;
    public int $Type;
    public $Body;

    public function GetSize()
    {
        return (!empty($Body) ? strlen($Body) + 10 : 0);
    }

    public function __construct($type, $body)
    {
        $this->Id = RconPacket::$idCounter++;
        $this->Type = $type;
        $this->Body = $body;
    }

    public function ConvertToArray(): array
    {
        $buffer = array(); //array_fill(0, $this->GetSize() + 4, 0);
        $buffer[] = pack('V', $this->GetSize() + 4); //->copy($buffer, 0);
        $buffer[] = pack('V', $this->Id); //->copy($buffer, 4);
        $buffer[] = pack('V', (int)$this->Type); //->copy($buffer, 8);
        $buffer = array_merge($buffer, array_map(fn($c) => ord($c), str_split($this->Body)));
    
        //$buffer[] = str_split($this->Body)->map(fn($c, $i) => ord($c)); //->copy($buffer, 12);

        return $buffer;
    }

    public static function ConvertToRconPacket(string $data): RconPacket
    {
        $size = unpack('V', $data)[1];
        $id = unpack('V', $data, 4)[1];
        $type = unpack('V', $data, 8)[1];
        $body = substr($data, 12, $size - 10);

        return new RconPacket($id, $type, $body);
    }
}

I've tried converting the array to a string using pack("a", $buffer); but pack() also requires a string

1 Answer 1

0

A basic knowledge: string in PHP is actually a binary array (e.g. $str[3] is the 4th byte), so you don't have to use a PHP array, you can just use the string packed by the pack function.

$data = pack('V3a*',
             $this->GetSize(),
             $this->Id,
             (int)$this->Type,
             $this->Body);
fwrite($fp, $data);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.