Skip to content
3 changes: 2 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ jobs:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@2.32.0
uses: shivammathur/setup-php@2.35.4
with:
php-version: ${{ matrix.php }}
extensions: encoding-pmmp/ext-encoding@1.0.0

- name: Cache Composer packages
id: composer-cache
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"php": "^8.1",
"php-ipv6": "*",
"php-64bit": "*",
"ext-encoding": "~1.0.0",
"ext-sockets": "*",
"pocketmine/log": "^0.3.0 || ^0.4.0",
"pocketmine/binaryutils": "^0.2.0"
"pocketmine/log": "^0.3.0 || ^0.4.0"
},
"require-dev": {
"phpstan/phpstan": "2.1.33",
Expand Down
11 changes: 6 additions & 5 deletions src/generic/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

namespace raklib\generic;

use pmmp\encoding\ByteBufferReader;
use pmmp\encoding\ByteBufferWriter;
use raklib\protocol\ACK;
use raklib\protocol\AcknowledgePacket;
use raklib\protocol\ConnectedPacket;
Expand All @@ -28,7 +30,6 @@
use raklib\protocol\NACK;
use raklib\protocol\Packet;
use raklib\protocol\PacketReliability;
use raklib\protocol\PacketSerializer;
use raklib\utils\InternetAddress;
use function hrtime;
use function intdiv;
Expand Down Expand Up @@ -220,13 +221,13 @@ public function update(float $time) : void{
}

protected function queueConnectedPacket(ConnectedPacket $packet, int $reliability, int $orderChannel, bool $immediate = false) : void{
$out = new PacketSerializer(); //TODO: reuse streams to reduce allocations
$out = new ByteBufferWriter(); //TODO: reuse streams to reduce allocations
$packet->encode($out);

$encapsulated = new EncapsulatedPacket();
$encapsulated->reliability = $reliability;
$encapsulated->orderChannel = $orderChannel;
$encapsulated->buffer = $out->getBuffer();
$encapsulated->buffer = $out->getData();

$this->sendLayer->addEncapsulatedToQueue($encapsulated, $immediate);
}
Expand All @@ -248,14 +249,14 @@ private function handleEncapsulatedPacketRoute(EncapsulatedPacket $packet) : voi
$this->handleRemoteDisconnect();
}elseif($id === MessageIdentifiers::ID_CONNECTED_PING){
$dataPacket = new ConnectedPing();
$dataPacket->decode(new PacketSerializer($packet->buffer));
$dataPacket->decode(new ByteBufferReader($packet->buffer));
$this->queueConnectedPacket(ConnectedPong::create(
$dataPacket->sendPingTime,
$this->getRakNetTimeMS()
), PacketReliability::UNRELIABLE, 0);
}elseif($id === MessageIdentifiers::ID_CONNECTED_PONG){
$dataPacket = new ConnectedPong();
$dataPacket->decode(new PacketSerializer($packet->buffer));
$dataPacket->decode(new ByteBufferReader($packet->buffer));

$this->handlePong($dataPacket->sendPingTime, $dataPacket->sendPongTime);
}
Expand Down
51 changes: 28 additions & 23 deletions src/protocol/AcknowledgePacket.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@

namespace raklib\protocol;

use pocketmine\utils\Binary;
use function chr;
use pmmp\encoding\BE;
use pmmp\encoding\Byte;
use pmmp\encoding\ByteBufferReader;
use pmmp\encoding\ByteBufferWriter;
use pmmp\encoding\LE;
use function count;
use function sort;
use function strlen;
use const SORT_NUMERIC;

abstract class AcknowledgePacket extends Packet{
Expand All @@ -29,8 +33,8 @@ abstract class AcknowledgePacket extends Packet{
/** @var int[] */
public array $packets = [];

protected function encodePayload(PacketSerializer $out) : void{
$payload = "";
protected function encodePayload(ByteBufferWriter $out) : void{
$subWriter = new ByteBufferWriter();
sort($this->packets, SORT_NUMERIC);
$count = count($this->packets);
$records = 0;
Expand All @@ -47,50 +51,51 @@ protected function encodePayload(PacketSerializer $out) : void{
$last = $current;
}elseif($diff > 1){ //Forget about duplicated packets (bad queues?)
if($start === $last){
$payload .= chr(self::RECORD_TYPE_SINGLE);
$payload .= Binary::writeLTriad($start);
Byte::writeUnsigned($subWriter, self::RECORD_TYPE_SINGLE);
LE::writeUnsignedTriad($subWriter, $start);
$start = $last = $current;
}else{
$payload .= chr(self::RECORD_TYPE_RANGE);
$payload .= Binary::writeLTriad($start);
$payload .= Binary::writeLTriad($last);
Byte::writeUnsigned($subWriter, self::RECORD_TYPE_RANGE);
LE::writeUnsignedTriad($subWriter, $start);
LE::writeUnsignedTriad($subWriter, $last);
$start = $last = $current;
}
++$records;
}
}

if($start === $last){
$payload .= chr(self::RECORD_TYPE_SINGLE);
$payload .= Binary::writeLTriad($start);
Byte::writeUnsigned($subWriter, self::RECORD_TYPE_SINGLE);
LE::writeUnsignedTriad($subWriter, $start);
}else{
$payload .= chr(self::RECORD_TYPE_RANGE);
$payload .= Binary::writeLTriad($start);
$payload .= Binary::writeLTriad($last);
Byte::writeUnsigned($subWriter, self::RECORD_TYPE_RANGE);
LE::writeUnsignedTriad($subWriter, $start);
LE::writeUnsignedTriad($subWriter, $last);
}
++$records;
}

$out->putShort($records);
$out->put($payload);
BE::writeUnsignedShort($out, $records);
$out->writeByteArray($subWriter->getData());
}

protected function decodePayload(PacketSerializer $in) : void{
$count = $in->getShort();
protected function decodePayload(ByteBufferReader $in) : void{
$count = BE::readUnsignedShort($in);
$this->packets = [];
$cnt = 0;
for($i = 0; $i < $count and !$in->feof() and $cnt < 4096; ++$i){
if($in->getByte() === self::RECORD_TYPE_RANGE){
$start = $in->getLTriad();
$end = $in->getLTriad();
$len = strlen($in->getData());
for($i = 0; $i < $count and $in->getOffset() < $len and $cnt < 4096; ++$i){
if(Byte::readUnsigned($in) === self::RECORD_TYPE_RANGE){
$start = LE::readUnsignedTriad($in);
$end = LE::readUnsignedTriad($in);
if(($end - $start) > 512){
$end = $start + 512;
}
for($c = $start; $c <= $end; ++$c){
$this->packets[$cnt++] = $c;
}
}else{
$this->packets[$cnt++] = $in->getLTriad();
$this->packets[$cnt++] = LE::readUnsignedTriad($in);
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions src/protocol/AdvertiseSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@

namespace raklib\protocol;

use pmmp\encoding\ByteBufferReader;
use pmmp\encoding\ByteBufferWriter;

class AdvertiseSystem extends Packet{
public static $ID = MessageIdentifiers::ID_ADVERTISE_SYSTEM;

public string $serverName;

protected function encodePayload(PacketSerializer $out) : void{
$out->putString($this->serverName);
protected function encodePayload(ByteBufferWriter $out) : void{
PacketSerializer::putString($out, $this->serverName);
}

protected function decodePayload(PacketSerializer $in) : void{
$this->serverName = $in->getString();
protected function decodePayload(ByteBufferReader $in) : void{
$this->serverName = PacketSerializer::getString($in);
}
}
12 changes: 8 additions & 4 deletions src/protocol/ConnectedPing.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

namespace raklib\protocol;

use pmmp\encoding\BE;
use pmmp\encoding\ByteBufferReader;
use pmmp\encoding\ByteBufferWriter;

class ConnectedPing extends ConnectedPacket{
public static $ID = MessageIdentifiers::ID_CONNECTED_PING;

Expand All @@ -27,11 +31,11 @@ public static function create(int $sendPingTime) : self{
return $result;
}

protected function encodePayload(PacketSerializer $out) : void{
$out->putLong($this->sendPingTime);
protected function encodePayload(ByteBufferWriter $out) : void{
BE::writeUnsignedLong($out, $this->sendPingTime);
}

protected function decodePayload(PacketSerializer $in) : void{
$this->sendPingTime = $in->getLong();
protected function decodePayload(ByteBufferReader $in) : void{
$this->sendPingTime = BE::readUnsignedLong($in);
}
}
16 changes: 10 additions & 6 deletions src/protocol/ConnectedPong.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

namespace raklib\protocol;

use pmmp\encoding\BE;
use pmmp\encoding\ByteBufferReader;
use pmmp\encoding\ByteBufferWriter;

class ConnectedPong extends ConnectedPacket{
public static $ID = MessageIdentifiers::ID_CONNECTED_PONG;

Expand All @@ -29,13 +33,13 @@ public static function create(int $sendPingTime, int $sendPongTime) : self{
return $result;
}

protected function encodePayload(PacketSerializer $out) : void{
$out->putLong($this->sendPingTime);
$out->putLong($this->sendPongTime);
protected function encodePayload(ByteBufferWriter $out) : void{
BE::writeUnsignedLong($out, $this->sendPingTime);
BE::writeUnsignedLong($out, $this->sendPongTime);
}

protected function decodePayload(PacketSerializer $in) : void{
$this->sendPingTime = $in->getLong();
$this->sendPongTime = $in->getLong();
protected function decodePayload(ByteBufferReader $in) : void{
$this->sendPingTime = BE::readUnsignedLong($in);
$this->sendPongTime = BE::readUnsignedLong($in);
}
}
21 changes: 13 additions & 8 deletions src/protocol/ConnectionRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,27 @@

namespace raklib\protocol;

use pmmp\encoding\BE;
use pmmp\encoding\Byte;
use pmmp\encoding\ByteBufferReader;
use pmmp\encoding\ByteBufferWriter;

class ConnectionRequest extends ConnectedPacket{
public static $ID = MessageIdentifiers::ID_CONNECTION_REQUEST;

public int $clientID;
public int $sendPingTime;
public bool $useSecurity = false;

protected function encodePayload(PacketSerializer $out) : void{
$out->putLong($this->clientID);
$out->putLong($this->sendPingTime);
$out->putByte($this->useSecurity ? 1 : 0);
protected function encodePayload(ByteBufferWriter $out) : void{
BE::writeUnsignedLong($out, $this->clientID);
BE::writeUnsignedLong($out, $this->sendPingTime);
Byte::writeUnsigned($out, $this->useSecurity ? 1 : 0);
}

protected function decodePayload(PacketSerializer $in) : void{
$this->clientID = $in->getLong();
$this->sendPingTime = $in->getLong();
$this->useSecurity = $in->getByte() !== 0;
protected function decodePayload(ByteBufferReader $in) : void{
$this->clientID = BE::readUnsignedLong($in);
$this->sendPingTime = BE::readUnsignedLong($in);
$this->useSecurity = Byte::readUnsigned($in) !== 0;
}
}
29 changes: 16 additions & 13 deletions src/protocol/ConnectionRequestAccepted.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

namespace raklib\protocol;

use pmmp\encoding\BE;
use pmmp\encoding\ByteBufferReader;
use pmmp\encoding\ByteBufferWriter;
use raklib\RakLib;
use raklib\utils\InternetAddress;
use function strlen;
Expand Down Expand Up @@ -45,31 +48,31 @@ public function __construct(){
$this->systemAddresses[] = new InternetAddress("127.0.0.1", 0, 4);
}

protected function encodePayload(PacketSerializer $out) : void{
$out->putAddress($this->address);
$out->putShort(0);
protected function encodePayload(ByteBufferWriter $out) : void{
PacketSerializer::putAddress($out, $this->address);
BE::writeUnsignedShort($out, 0);

$dummy = new InternetAddress("0.0.0.0", 0, 4);
for($i = 0; $i < RakLib::$SYSTEM_ADDRESS_COUNT; ++$i){
$out->putAddress($this->systemAddresses[$i] ?? $dummy);
PacketSerializer::putAddress($out, $this->systemAddresses[$i] ?? $dummy);
}

$out->putLong($this->sendPingTime);
$out->putLong($this->sendPongTime);
BE::writeUnsignedLong($out, $this->sendPingTime);
BE::writeUnsignedLong($out, $this->sendPongTime);
}

protected function decodePayload(PacketSerializer $in) : void{
$this->address = $in->getAddress();
$in->getShort(); //TODO: check this
protected function decodePayload(ByteBufferReader $in) : void{
$this->address = PacketSerializer::getAddress($in);
BE::readUnsignedShort($in); //TODO: check this

$len = strlen($in->getBuffer());
$len = strlen($in->getData());
$dummy = new InternetAddress("0.0.0.0", 0, 4);

for($i = 0; $i < RakLib::$SYSTEM_ADDRESS_COUNT; ++$i){
$this->systemAddresses[$i] = $in->getOffset() + 16 < $len ? $in->getAddress() : $dummy; //HACK: avoids trying to read too many addresses on bad data
$this->systemAddresses[$i] = $in->getOffset() + 16 < $len ? PacketSerializer::getAddress($in) : $dummy; //HACK: avoids trying to read too many addresses on bad data
}

$this->sendPingTime = $in->getLong();
$this->sendPongTime = $in->getLong();
$this->sendPingTime = BE::readUnsignedLong($in);
$this->sendPongTime = BE::readUnsignedLong($in);
}
}
27 changes: 17 additions & 10 deletions src/protocol/Datagram.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@

namespace raklib\protocol;

use pmmp\encoding\Byte;
use pmmp\encoding\ByteBufferReader;
use pmmp\encoding\ByteBufferWriter;
use pmmp\encoding\LE;
use function strlen;

class Datagram extends Packet{
public const BITFLAG_VALID = 0x80;
public const BITFLAG_ACK = 0x40;
Expand All @@ -36,14 +42,14 @@ class Datagram extends Packet{
public array $packets = [];
public int $seqNumber;

protected function encodeHeader(PacketSerializer $out) : void{
$out->putByte(self::BITFLAG_VALID | $this->headerFlags);
protected function encodeHeader(ByteBufferWriter $out) : void{
Byte::writeUnsigned($out, self::BITFLAG_VALID | $this->headerFlags);
}

protected function encodePayload(PacketSerializer $out) : void{
$out->putLTriad($this->seqNumber);
protected function encodePayload(ByteBufferWriter $out) : void{
LE::writeUnsignedTriad($out, $this->seqNumber);
foreach($this->packets as $packet){
$out->put($packet->toBinary());
$packet->toBinary($out);
}
}

Expand All @@ -59,14 +65,15 @@ public function length(){
return $length;
}

protected function decodeHeader(PacketSerializer $in) : void{
$this->headerFlags = $in->getByte();
protected function decodeHeader(ByteBufferReader $in) : void{
$this->headerFlags = Byte::readUnsigned($in);
}

protected function decodePayload(PacketSerializer $in) : void{
$this->seqNumber = $in->getLTriad();
protected function decodePayload(ByteBufferReader $in) : void{
$this->seqNumber = LE::readUnsignedTriad($in);

while(!$in->feof()){
$len = strlen($in->getData());
while($in->getOffset() < $len){
$this->packets[] = EncapsulatedPacket::fromBinary($in);
}
}
Expand Down
Loading