From 11cb56a2310d97e5c8811b79a2dbfed600c6c6e1 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Nov 2022 15:43:35 +0000 Subject: [PATCH 01/16] Split Session into generic and server-specific components preparing for introduction of client support --- src/generic/SendReliabilityLayer.php | 1 - src/{server => generic}/Session.php | 122 +++++++++++------------ src/server/Server.php | 24 ++--- src/server/ServerSession.php | 89 +++++++++++++++++ src/server/UnconnectedMessageHandler.php | 1 + 5 files changed, 159 insertions(+), 78 deletions(-) rename src/{server => generic}/Session.php (74%) create mode 100644 src/server/ServerSession.php diff --git a/src/generic/SendReliabilityLayer.php b/src/generic/SendReliabilityLayer.php index 7e9c930..479f8bc 100644 --- a/src/generic/SendReliabilityLayer.php +++ b/src/generic/SendReliabilityLayer.php @@ -22,7 +22,6 @@ use raklib\protocol\NACK; use raklib\protocol\PacketReliability; use raklib\protocol\SplitPacketInfo; -use raklib\server\Session; use function array_fill; use function count; use function str_split; diff --git a/src/server/Session.php b/src/generic/Session.php similarity index 74% rename from src/server/Session.php rename to src/generic/Session.php index 8fe927b..dff99c8 100644 --- a/src/server/Session.php +++ b/src/generic/Session.php @@ -14,31 +14,28 @@ declare(strict_types=1); -namespace raklib\server; +namespace raklib\generic; -use raklib\generic\ReceiveReliabilityLayer; -use raklib\generic\SendReliabilityLayer; use raklib\protocol\ACK; use raklib\protocol\AcknowledgePacket; use raklib\protocol\ConnectedPacket; use raklib\protocol\ConnectedPing; use raklib\protocol\ConnectedPong; -use raklib\protocol\ConnectionRequest; -use raklib\protocol\ConnectionRequestAccepted; use raklib\protocol\Datagram; use raklib\protocol\DisconnectionNotification; use raklib\protocol\EncapsulatedPacket; use raklib\protocol\MessageIdentifiers; use raklib\protocol\NACK; -use raklib\protocol\NewIncomingConnection; use raklib\protocol\Packet; use raklib\protocol\PacketReliability; use raklib\protocol\PacketSerializer; use raklib\utils\InternetAddress; +use function hrtime; +use function intdiv; use function microtime; use function ord; -class Session{ +abstract class Session{ public const MAX_SPLIT_PART_COUNT = 128; public const MAX_CONCURRENT_SPLIT_COUNT = 4; @@ -50,17 +47,14 @@ class Session{ public const MIN_MTU_SIZE = 400; - /** @var Server */ - private $server; - /** @var \Logger */ private $logger; /** @var InternetAddress */ - private $address; + protected $address; /** @var int */ - private $state = self::STATE_CONNECTING; + protected $state = self::STATE_CONNECTING; /** @var int */ private $id; @@ -71,7 +65,7 @@ class Session{ private $disconnectionTime = 0; /** @var bool */ - private $isTemporal = true; + protected $isTemporal = true; /** @var bool */ private $isActive = false; @@ -82,7 +76,7 @@ class Session{ private $lastPingMeasure = 1; /** @var int */ - private $internalId; + protected $internalId; /** @var ReceiveReliabilityLayer */ private $recvLayer; @@ -90,11 +84,10 @@ class Session{ /** @var SendReliabilityLayer */ private $sendLayer; - public function __construct(Server $server, \Logger $logger, InternetAddress $address, int $clientId, int $mtuSize, int $internalId){ + public function __construct(\Logger $logger, InternetAddress $address, int $clientId, int $mtuSize, int $internalId){ if($mtuSize < self::MIN_MTU_SIZE){ throw new \InvalidArgumentException("MTU size must be at least " . self::MIN_MTU_SIZE . ", got $mtuSize"); } - $this->server = $server; $this->logger = new \PrefixedLogger($logger, "Session: " . $address->toString()); $this->address = $address; $this->id = $clientId; @@ -120,16 +113,50 @@ function(Datagram $datagram) : void{ $this->sendPacket($datagram); }, function(int $identifierACK) : void{ - $this->server->getEventListener()->onPacketAck($this->internalId, $identifierACK); + $this->onPacketAck($identifierACK); } ); } /** - * Returns an ID used to identify this session across threads. + * Sends a packet in the appropriate way for the session type. + */ + abstract protected function sendPacket(Packet $packet) : void; + + /** + * Called when a packet for which an ACK was requested is ACKed. + */ + abstract protected function onPacketAck(int $identifierACK) : void; + + /** + * Called when the session is terminated for any reason. + */ + abstract protected function onDisconnect(string $reason) : void; + + /** + * Called when a packet is received while the session is in the "connecting" state. This should only handle RakNet + * connection packets. Any other packets should be ignored. + */ + abstract protected function handleRakNetConnectionPacket(string $packet) : void; + + /** + * Called when a user packet (ID >= ID_USER_PACKET_ENUM) is received from the remote peer. + * + * @see MessageIdentifiers::ID_USER_PACKET_ENUM */ - public function getInternalId() : int{ - return $this->internalId; + abstract protected function onPacketReceive(string $packet) : void; + + /** + * Called when a new ping measurement is recorded. + */ + abstract protected function onPingMeasure(int $pingMS) : void; + + /** + * Returns a monotonically increasing timestamp. It does not need to match UNIX time. + * This is used to calculate ping. + */ + protected function getRakNetTimeMS() : int{ + return intdiv(hrtime(true), 1_000_000); } public function getAddress() : InternetAddress{ @@ -192,7 +219,7 @@ public function update(float $time) : void{ } } - private function queueConnectedPacket(ConnectedPacket $packet, int $reliability, int $orderChannel, bool $immediate = false) : void{ + protected function queueConnectedPacket(ConnectedPacket $packet, int $reliability, int $orderChannel, bool $immediate = false) : void{ $out = new PacketSerializer(); //TODO: reuse streams to reduce allocations $packet->encode($out); @@ -208,52 +235,23 @@ public function addEncapsulatedToQueue(EncapsulatedPacket $packet, bool $immedia $this->sendLayer->addEncapsulatedToQueue($packet, $immediate); } - private function sendPacket(Packet $packet) : void{ - $this->server->sendPacket($packet, $this->address); - } - - private function sendPing(int $reliability = PacketReliability::UNRELIABLE) : void{ - $this->queueConnectedPacket(ConnectedPing::create($this->server->getRakNetTimeMS()), $reliability, 0, true); + protected function sendPing(int $reliability = PacketReliability::UNRELIABLE) : void{ + $this->queueConnectedPacket(ConnectedPing::create($this->getRakNetTimeMS()), $reliability, 0, true); } private function handleEncapsulatedPacketRoute(EncapsulatedPacket $packet) : void{ - if($this->server === null){ - return; - } - $id = ord($packet->buffer[0]); if($id < MessageIdentifiers::ID_USER_PACKET_ENUM){ //internal data packet if($this->state === self::STATE_CONNECTING){ - if($id === ConnectionRequest::$ID){ - $dataPacket = new ConnectionRequest(); - $dataPacket->decode(new PacketSerializer($packet->buffer)); - $this->queueConnectedPacket(ConnectionRequestAccepted::create( - $this->address, - [], - $dataPacket->sendPingTime, - $this->server->getRakNetTimeMS() - ), PacketReliability::UNRELIABLE, 0, true); - }elseif($id === NewIncomingConnection::$ID){ - $dataPacket = new NewIncomingConnection(); - $dataPacket->decode(new PacketSerializer($packet->buffer)); - - if($dataPacket->address->getPort() === $this->server->getPort() or !$this->server->portChecking){ - $this->state = self::STATE_CONNECTED; //FINALLY! - $this->isTemporal = false; - $this->server->openSession($this); - - //$this->handlePong($dataPacket->sendPingTime, $dataPacket->sendPongTime); //can't use this due to system-address count issues in MCPE >.< - $this->sendPing(); - } - } + $this->handleRakNetConnectionPacket($packet->buffer); }elseif($id === DisconnectionNotification::$ID){ - $this->onClientDisconnect(); + $this->handleRemoteDisconnect(); }elseif($id === ConnectedPing::$ID){ $dataPacket = new ConnectedPing(); $dataPacket->decode(new PacketSerializer($packet->buffer)); $this->queueConnectedPacket(ConnectedPong::create( $dataPacket->sendPingTime, - $this->server->getRakNetTimeMS() + $this->getRakNetTimeMS() ), PacketReliability::UNRELIABLE, 0); }elseif($id === ConnectedPong::$ID){ $dataPacket = new ConnectedPong(); @@ -262,7 +260,7 @@ private function handleEncapsulatedPacketRoute(EncapsulatedPacket $packet) : voi $this->handlePong($dataPacket->sendPingTime, $dataPacket->sendPongTime); } }elseif($this->state === self::STATE_CONNECTED){ - $this->server->getEventListener()->onPacketReceive($this->internalId, $packet->buffer); + $this->onPacketReceive($packet->buffer); }else{ //$this->logger->notice("Received packet before connection: " . bin2hex($packet->buffer)); } @@ -272,12 +270,12 @@ private function handleEncapsulatedPacketRoute(EncapsulatedPacket $packet) : voi * @param int $sendPongTime TODO: clock differential stuff */ private function handlePong(int $sendPingTime, int $sendPongTime) : void{ - $currentTime = $this->server->getRakNetTimeMS(); + $currentTime = $this->getRakNetTimeMS(); if($currentTime < $sendPingTime){ $this->logger->debug("Received invalid pong: timestamp is in the future by " . ($sendPingTime - $currentTime) . " ms"); }else{ $this->lastPingMeasure = $currentTime - $sendPingTime; - $this->server->getEventListener()->onPingMeasure($this->internalId, $this->lastPingMeasure); + $this->onPingMeasure($this->lastPingMeasure); } } @@ -301,7 +299,7 @@ public function initiateDisconnect(string $reason) : void{ if($this->isConnected()){ $this->state = self::STATE_DISCONNECT_PENDING; $this->disconnectionTime = microtime(true); - $this->server->getEventListener()->onClientDisconnect($this->internalId, $reason); + $this->onDisconnect($reason); $this->logger->debug("Requesting graceful disconnect because \"$reason\""); } } @@ -311,11 +309,11 @@ public function initiateDisconnect(string $reason) : void{ */ public function forciblyDisconnect(string $reason) : void{ $this->state = self::STATE_DISCONNECTED; - $this->server->getEventListener()->onClientDisconnect($this->internalId, $reason); + $this->onDisconnect($reason); $this->logger->debug("Forcibly disconnecting session due to \"$reason\""); } - private function onClientDisconnect() : void{ + private function handleRemoteDisconnect() : void{ //the client will expect an ACK for this; make sure it gets sent, because after forcible termination //there won't be any session ticks to update it $this->recvLayer->update(); @@ -323,7 +321,7 @@ private function onClientDisconnect() : void{ if($this->isConnected()){ //the client might have disconnected after the server sent a disconnect notification, but before the client //received it - in this case, we don't want to notify the event handler twice - $this->server->getEventListener()->onClientDisconnect($this->internalId, "client disconnect"); + $this->onDisconnect("client disconnect"); } $this->state = self::STATE_DISCONNECTED; $this->logger->debug("Terminating session due to client disconnect"); diff --git a/src/server/Server.php b/src/server/Server.php index 966463e..7aaa8c3 100644 --- a/src/server/Server.php +++ b/src/server/Server.php @@ -17,6 +17,7 @@ namespace raklib\server; use pocketmine\utils\BinaryDataException; +use raklib\generic\Session; use raklib\generic\Socket; use raklib\generic\SocketException; use raklib\protocol\ACK; @@ -59,9 +60,9 @@ class Server implements ServerInterface{ /** @var int */ protected $sendBytes = 0; - /** @var Session[] */ + /** @var ServerSession[] */ protected $sessionsByAddress = []; - /** @var Session[] */ + /** @var ServerSession[] */ protected $sessions = []; /** @var UnconnectedMessageHandler */ @@ -123,13 +124,6 @@ public function __construct(int $serverId, \Logger $logger, Socket $socket, int $this->unconnectedMessageHandler = new UnconnectedMessageHandler($this, $protocolAcceptor); } - /** - * Returns the time in milliseconds since server start. - */ - public function getRakNetTimeMS() : int{ - return ((int) (microtime(true) * 1000)) - $this->startTimeMS; - } - public function getPort() : int{ return $this->socket->getBindAddress()->getPort(); } @@ -392,7 +386,7 @@ public function addRawPacketFilter(string $regex) : void{ $this->rawPacketFilters[] = $regex; } - public function getSessionByAddress(InternetAddress $address) : ?Session{ + public function getSessionByAddress(InternetAddress $address) : ?ServerSession{ return $this->sessionsByAddress[$address->toString()] ?? null; } @@ -400,7 +394,7 @@ public function sessionExists(InternetAddress $address) : bool{ return isset($this->sessionsByAddress[$address->toString()]); } - public function createSession(InternetAddress $address, int $clientId, int $mtuSize) : Session{ + public function createSession(InternetAddress $address, int $clientId, int $mtuSize) : ServerSession{ $existingSession = $this->sessionsByAddress[$address->toString()] ?? null; if($existingSession !== null){ $existingSession->forciblyDisconnect("client reconnect"); @@ -414,7 +408,7 @@ public function createSession(InternetAddress $address, int $clientId, int $mtuS $this->nextSessionId &= 0x7fffffff; //we don't expect more than 2 billion simultaneous connections, and this fits in 4 bytes } - $session = new Session($this, $this->logger, clone $address, $clientId, $mtuSize, $this->nextSessionId); + $session = new ServerSession($this, $this->logger, clone $address, $clientId, $mtuSize, $this->nextSessionId); $this->sessionsByAddress[$address->toString()] = $session; $this->sessions[$this->nextSessionId] = $session; $this->logger->debug("Created session for $address with MTU size $mtuSize"); @@ -422,11 +416,11 @@ public function createSession(InternetAddress $address, int $clientId, int $mtuS return $session; } - private function removeSessionInternal(Session $session) : void{ + private function removeSessionInternal(ServerSession $session) : void{ unset($this->sessionsByAddress[$session->getAddress()->toString()], $this->sessions[$session->getInternalId()]); } - public function openSession(Session $session) : void{ + public function openSession(ServerSession $session) : void{ $address = $session->getAddress(); $this->eventListener->onClientConnect($session->getInternalId(), $address->getIp(), $address->getPort(), $session->getID()); } @@ -444,7 +438,7 @@ private function checkSessions() : void{ } } - public function notifyACK(Session $session, int $identifierACK) : void{ + public function notifyACK(ServerSession $session, int $identifierACK) : void{ $this->eventListener->onPacketAck($session->getInternalId(), $identifierACK); } diff --git a/src/server/ServerSession.php b/src/server/ServerSession.php new file mode 100644 index 0000000..e57b290 --- /dev/null +++ b/src/server/ServerSession.php @@ -0,0 +1,89 @@ + + * + * RakLib is not affiliated with Jenkins Software LLC nor RakNet. + * + * RakLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + */ + +declare(strict_types=1); + +namespace raklib\server; + +use raklib\generic\Session; +use raklib\protocol\ConnectionRequest; +use raklib\protocol\ConnectionRequestAccepted; +use raklib\protocol\NewIncomingConnection; +use raklib\protocol\Packet; +use raklib\protocol\PacketReliability; +use raklib\protocol\PacketSerializer; +use raklib\utils\InternetAddress; +use function ord; + +class ServerSession extends Session{ + private Server $server; + + public function __construct(Server $server, \Logger $logger, InternetAddress $address, int $clientId, int $mtuSize, int $internalId){ + $this->server = $server; + parent::__construct($logger, $address, $clientId, $mtuSize, $internalId); + } + + /** + * Returns an ID used to identify this session across threads. + */ + public function getInternalId() : int{ + return $this->internalId; + } + + final protected function sendPacket(Packet $packet) : void{ + $this->server->sendPacket($packet, $this->address); + } + + protected function onPacketAck(int $identifierACK) : void{ + $this->server->getEventListener()->onPacketAck($this->internalId, $identifierACK); + } + + protected function onDisconnect(string $reason) : void{ + $this->server->getEventListener()->onClientDisconnect($this->internalId, $reason); + } + + final protected function handleRakNetConnectionPacket(string $packet) : void{ + $id = ord($packet[0]); + if($id === ConnectionRequest::$ID){ + $dataPacket = new ConnectionRequest(); + $dataPacket->decode(new PacketSerializer($packet)); + $this->queueConnectedPacket(ConnectionRequestAccepted::create( + $this->address, + [], + $dataPacket->sendPingTime, + $this->getRakNetTimeMS() + ), PacketReliability::UNRELIABLE, 0, true); + }elseif($id === NewIncomingConnection::$ID){ + $dataPacket = new NewIncomingConnection(); + $dataPacket->decode(new PacketSerializer($packet)); + + if($dataPacket->address->getPort() === $this->server->getPort() or !$this->server->portChecking){ + $this->state = self::STATE_CONNECTED; //FINALLY! + $this->isTemporal = false; + $this->server->openSession($this); + + //$this->handlePong($dataPacket->sendPingTime, $dataPacket->sendPongTime); //can't use this due to system-address count issues in MCPE >.< + $this->sendPing(); + } + } + } + + protected function onPacketReceive(string $packet) : void{ + $this->server->getEventListener()->onPacketReceive($this->internalId, $packet); + } + + protected function onPingMeasure(int $pingMS) : void{ + $this->server->getEventListener()->onPingMeasure($this->internalId, $pingMS); + } +} diff --git a/src/server/UnconnectedMessageHandler.php b/src/server/UnconnectedMessageHandler.php index 582d97c..fd0dab1 100644 --- a/src/server/UnconnectedMessageHandler.php +++ b/src/server/UnconnectedMessageHandler.php @@ -17,6 +17,7 @@ namespace raklib\server; use pocketmine\utils\BinaryDataException; +use raklib\generic\Session; use raklib\protocol\IncompatibleProtocolVersion; use raklib\protocol\OfflineMessage; use raklib\protocol\OpenConnectionReply1; From a131a94650fc252afb1f340f542327506ba536ca Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Nov 2022 15:46:35 +0000 Subject: [PATCH 02/16] Move internalID to where it belongs --- src/generic/Session.php | 7 +------ src/server/ServerSession.php | 4 +++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/generic/Session.php b/src/generic/Session.php index dff99c8..3f8c88e 100644 --- a/src/generic/Session.php +++ b/src/generic/Session.php @@ -75,16 +75,13 @@ abstract class Session{ /** @var int */ private $lastPingMeasure = 1; - /** @var int */ - protected $internalId; - /** @var ReceiveReliabilityLayer */ private $recvLayer; /** @var SendReliabilityLayer */ private $sendLayer; - public function __construct(\Logger $logger, InternetAddress $address, int $clientId, int $mtuSize, int $internalId){ + public function __construct(\Logger $logger, InternetAddress $address, int $clientId, int $mtuSize){ if($mtuSize < self::MIN_MTU_SIZE){ throw new \InvalidArgumentException("MTU size must be at least " . self::MIN_MTU_SIZE . ", got $mtuSize"); } @@ -94,8 +91,6 @@ public function __construct(\Logger $logger, InternetAddress $address, int $clie $this->lastUpdate = microtime(true); - $this->internalId = $internalId; - $this->recvLayer = new ReceiveReliabilityLayer( $this->logger, function(EncapsulatedPacket $pk) : void{ diff --git a/src/server/ServerSession.php b/src/server/ServerSession.php index e57b290..d63f25b 100644 --- a/src/server/ServerSession.php +++ b/src/server/ServerSession.php @@ -28,10 +28,12 @@ class ServerSession extends Session{ private Server $server; + private int $internalId; public function __construct(Server $server, \Logger $logger, InternetAddress $address, int $clientId, int $mtuSize, int $internalId){ $this->server = $server; - parent::__construct($logger, $address, $clientId, $mtuSize, $internalId); + $this->internalId = $internalId; + parent::__construct($logger, $address, $clientId, $mtuSize); } /** From 93ab9fb700cf0b8b18cbc9023d72978603c78cfd Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Nov 2022 15:51:00 +0000 Subject: [PATCH 03/16] Simplify temporary session checking --- src/generic/Session.php | 7 ++----- src/server/Server.php | 2 +- src/server/ServerSession.php | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/generic/Session.php b/src/generic/Session.php index 3f8c88e..9da2894 100644 --- a/src/generic/Session.php +++ b/src/generic/Session.php @@ -64,9 +64,6 @@ abstract class Session{ /** @var float */ private $disconnectionTime = 0; - /** @var bool */ - protected $isTemporal = true; - /** @var bool */ private $isActive = false; @@ -166,8 +163,8 @@ public function getState() : int{ return $this->state; } - public function isTemporal() : bool{ - return $this->isTemporal; + public function isTemporary() : bool{ + return $this->state === self::STATE_CONNECTING; } public function isConnected() : bool{ diff --git a/src/server/Server.php b/src/server/Server.php index 7aaa8c3..2472baf 100644 --- a/src/server/Server.php +++ b/src/server/Server.php @@ -428,7 +428,7 @@ public function openSession(ServerSession $session) : void{ private function checkSessions() : void{ if(count($this->sessions) > 4096){ foreach($this->sessions as $sessionId => $session){ - if($session->isTemporal()){ + if($session->isTemporary()){ $this->removeSessionInternal($session); if(count($this->sessions) <= 4096){ break; diff --git a/src/server/ServerSession.php b/src/server/ServerSession.php index d63f25b..5b5f7c7 100644 --- a/src/server/ServerSession.php +++ b/src/server/ServerSession.php @@ -72,7 +72,6 @@ final protected function handleRakNetConnectionPacket(string $packet) : void{ if($dataPacket->address->getPort() === $this->server->getPort() or !$this->server->portChecking){ $this->state = self::STATE_CONNECTED; //FINALLY! - $this->isTemporal = false; $this->server->openSession($this); //$this->handlePong($dataPacket->sendPingTime, $dataPacket->sendPongTime); //can't use this due to system-address count issues in MCPE >.< From eababfbfc60106cbfa01167b0af225c5fff79ce9 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Nov 2022 15:51:26 +0000 Subject: [PATCH 04/16] Remove dead code --- src/server/Server.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/server/Server.php b/src/server/Server.php index 2472baf..1629bf3 100644 --- a/src/server/Server.php +++ b/src/server/Server.php @@ -438,10 +438,6 @@ private function checkSessions() : void{ } } - public function notifyACK(ServerSession $session, int $identifierACK) : void{ - $this->eventListener->onPacketAck($session->getInternalId(), $identifierACK); - } - public function getName() : string{ return $this->name; } From 34db358850469752dafa30df947d7fbd669f85c9 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Nov 2022 20:21:04 +0000 Subject: [PATCH 05/16] Split Socket into client and server specialized parts --- src/client/ClientSocket.php | 75 ++++++++++++++++++++++++++++++++++ src/generic/Socket.php | 79 ++++++++++-------------------------- src/server/Server.php | 6 +-- src/server/ServerSocket.php | 81 +++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 61 deletions(-) create mode 100644 src/client/ClientSocket.php create mode 100644 src/server/ServerSocket.php diff --git a/src/client/ClientSocket.php b/src/client/ClientSocket.php new file mode 100644 index 0000000..73a2b6d --- /dev/null +++ b/src/client/ClientSocket.php @@ -0,0 +1,75 @@ + + * + * RakLib is not affiliated with Jenkins Software LLC nor RakNet. + * + * RakLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + */ + +declare(strict_types=1); + +namespace raklib\client; + +use raklib\generic\Socket; +use raklib\generic\SocketException; +use raklib\utils\InternetAddress; +use function socket_connect; +use function socket_last_error; +use function socket_recv; +use function socket_send; +use function socket_strerror; +use function strlen; +use function trim; + +class ClientSocket extends Socket{ + + public function __construct( + private InternetAddress $connectAddress + ){ + parent::__construct($this->connectAddress->getVersion() === 6); + + if(!@socket_connect($this->socket, $this->connectAddress->getIp(), $this->connectAddress->getPort())){ + $error = socket_last_error($this->socket); + throw new SocketException("Failed to connect to " . $this->connectAddress . ": " . trim(socket_strerror($error)), $error); + } + //TODO: is an 8 MB buffer really appropriate for a client?? + $this->setSendBuffer(1024 * 1024 * 8)->setRecvBuffer(1024 * 1024 * 8); + } + + public function getConnectAddress() : InternetAddress{ + return $this->connectAddress; + } + + /** + * @throws SocketException + */ + public function readPacket() : ?string{ + $buffer = ""; + if(@socket_recv($this->socket, $buffer, 65535, 0) === false){ + $errno = socket_last_error($this->socket); + if($errno === SOCKET_EWOULDBLOCK){ + return null; + } + throw new SocketException("Failed to recv (errno $errno): " . trim(socket_strerror($errno)), $errno); + } + return $buffer; + } + + /** + * @throws SocketException + */ + public function writePacket(string $buffer) : int{ + $result = @socket_send($this->socket, $buffer, strlen($buffer), 0); + if($result === false){ + $errno = socket_last_error($this->socket); + throw new SocketException("Failed to send packet (errno $errno): " . trim(socket_strerror($errno)), $errno); + } + return $result; + } +} diff --git a/src/generic/Socket.php b/src/generic/Socket.php index b88bf9a..cf0a570 100644 --- a/src/generic/Socket.php +++ b/src/generic/Socket.php @@ -16,17 +16,13 @@ namespace raklib\generic; -use raklib\utils\InternetAddress; -use function socket_bind; use function socket_close; use function socket_create; use function socket_last_error; -use function socket_recvfrom; -use function socket_sendto; +use function socket_set_block; use function socket_set_nonblock; use function socket_set_option; use function socket_strerror; -use function strlen; use function trim; use const AF_INET; use const AF_INET6; @@ -34,46 +30,26 @@ use const SO_RCVBUF; use const SO_SNDBUF; use const SOCK_DGRAM; -use const SOCKET_EADDRINUSE; -use const SOCKET_EWOULDBLOCK; use const SOL_SOCKET; use const SOL_UDP; -class Socket{ +abstract class Socket{ /** @var \Socket */ protected $socket; - /** @var InternetAddress */ - private $bindAddress; /** * @throws SocketException */ - public function __construct(InternetAddress $bindAddress){ - $this->bindAddress = $bindAddress; - $socket = @socket_create($bindAddress->getVersion() === 4 ? AF_INET : AF_INET6, SOCK_DGRAM, SOL_UDP); + protected function __construct(bool $ipv6){ + $socket = @socket_create($ipv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, SOL_UDP); if($socket === false){ throw new \RuntimeException("Failed to create socket: " . trim(socket_strerror(socket_last_error()))); } $this->socket = $socket; - if($bindAddress->getVersion() === 6){ + if($ipv6){ socket_set_option($this->socket, IPPROTO_IPV6, IPV6_V6ONLY, 1); //Don't map IPv4 to IPv6, the implementation can create another RakLib instance to handle IPv4 } - - if(@socket_bind($this->socket, $bindAddress->getIp(), $bindAddress->getPort()) === true){ - $this->setSendBuffer(1024 * 1024 * 8)->setRecvBuffer(1024 * 1024 * 8); - }else{ - $error = socket_last_error($this->socket); - if($error === SOCKET_EADDRINUSE){ //platform error messages aren't consistent - throw new SocketException("Failed to bind socket: Something else is already running on $bindAddress", $error); - } - throw new SocketException("Failed to bind to " . $bindAddress . ": " . trim(socket_strerror($error)), $error); - } - socket_set_nonblock($this->socket); - } - - public function getBindAddress() : InternetAddress{ - return $this->bindAddress; } /** @@ -92,40 +68,19 @@ public function getLastError() : int{ } /** - * @param string $source reference parameter - * @param int $port reference parameter - * - * @throws SocketException + * @return $this */ - public function readPacket(?string &$source, ?int &$port) : ?string{ - $buffer = ""; - if(@socket_recvfrom($this->socket, $buffer, 65535, 0, $source, $port) === false){ - $errno = socket_last_error($this->socket); - if($errno === SOCKET_EWOULDBLOCK){ - return null; - } - throw new SocketException("Failed to recv (errno $errno): " . trim(socket_strerror($errno)), $errno); - } - return $buffer; - } + public function setSendBuffer(int $size){ + @socket_set_option($this->socket, SOL_SOCKET, SO_SNDBUF, $size); - /** - * @throws SocketException - */ - public function writePacket(string $buffer, string $dest, int $port) : int{ - $result = @socket_sendto($this->socket, $buffer, strlen($buffer), 0, $dest, $port); - if($result === false){ - $errno = socket_last_error($this->socket); - throw new SocketException("Failed to send to $dest $port (errno $errno): " . trim(socket_strerror($errno)), $errno); - } - return $result; + return $this; } /** * @return $this */ - public function setSendBuffer(int $size){ - @socket_set_option($this->socket, SOL_SOCKET, SO_SNDBUF, $size); + public function setRecvBuffer(int $size){ + @socket_set_option($this->socket, SOL_SOCKET, SO_RCVBUF, $size); return $this; } @@ -133,9 +88,17 @@ public function setSendBuffer(int $size){ /** * @return $this */ - public function setRecvBuffer(int $size){ - @socket_set_option($this->socket, SOL_SOCKET, SO_RCVBUF, $size); + public function setRecvTimeout(int $seconds, int $microseconds = 0){ + @socket_set_option($this->socket, SOL_SOCKET, SO_RCVTIMEO, ["sec" => $seconds, "usec" => $microseconds]); return $this; } + + public function setBlocking(bool $blocking) : void{ + if($blocking){ + socket_set_block($this->socket); + }else{ + socket_set_nonblock($this->socket); + } + } } diff --git a/src/server/Server.php b/src/server/Server.php index 1629bf3..f932424 100644 --- a/src/server/Server.php +++ b/src/server/Server.php @@ -18,7 +18,6 @@ use pocketmine\utils\BinaryDataException; use raklib\generic\Session; -use raklib\generic\Socket; use raklib\generic\SocketException; use raklib\protocol\ACK; use raklib\protocol\Datagram; @@ -46,7 +45,7 @@ class Server implements ServerInterface{ private const RAKLIB_TPS = 100; private const RAKLIB_TIME_PER_TICK = 1 / self::RAKLIB_TPS; - /** @var Socket */ + /** @var ServerSocket */ protected $socket; /** @var \Logger */ @@ -107,13 +106,14 @@ class Server implements ServerInterface{ /** @var ExceptionTraceCleaner */ private $traceCleaner; - public function __construct(int $serverId, \Logger $logger, Socket $socket, int $maxMtuSize, ProtocolAcceptor $protocolAcceptor, ServerEventSource $eventSource, ServerEventListener $eventListener, ExceptionTraceCleaner $traceCleaner){ + public function __construct(int $serverId, \Logger $logger, ServerSocket $socket, int $maxMtuSize, ProtocolAcceptor $protocolAcceptor, ServerEventSource $eventSource, ServerEventListener $eventListener, ExceptionTraceCleaner $traceCleaner){ if($maxMtuSize < Session::MIN_MTU_SIZE){ throw new \InvalidArgumentException("MTU size must be at least " . Session::MIN_MTU_SIZE . ", got $maxMtuSize"); } $this->serverId = $serverId; $this->logger = $logger; $this->socket = $socket; + $this->socket->setBlocking(false); $this->maxMtuSize = $maxMtuSize; $this->eventSource = $eventSource; $this->eventListener = $eventListener; diff --git a/src/server/ServerSocket.php b/src/server/ServerSocket.php new file mode 100644 index 0000000..f83fdbe --- /dev/null +++ b/src/server/ServerSocket.php @@ -0,0 +1,81 @@ + + * + * RakLib is not affiliated with Jenkins Software LLC nor RakNet. + * + * RakLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + */ + +declare(strict_types=1); + +namespace raklib\server; + +use raklib\generic\Socket; +use raklib\generic\SocketException; +use raklib\utils\InternetAddress; +use function socket_bind; +use function socket_last_error; +use function socket_recvfrom; +use function socket_sendto; +use function socket_strerror; +use function strlen; +use function trim; + +class ServerSocket extends Socket{ + + public function __construct( + private InternetAddress $bindAddress + ){ + parent::__construct($this->bindAddress->getVersion() === 6); + + if(@socket_bind($this->socket, $this->bindAddress->getIp(), $this->bindAddress->getPort()) === true){ + $this->setSendBuffer(1024 * 1024 * 8)->setRecvBuffer(1024 * 1024 * 8); + }else{ + $error = socket_last_error($this->socket); + if($error === SOCKET_EADDRINUSE){ //platform error messages aren't consistent + throw new SocketException("Failed to bind socket: Something else is already running on $this->bindAddress", $error); + } + throw new SocketException("Failed to bind to " . $this->bindAddress . ": " . trim(socket_strerror($error)), $error); + } + } + + public function getBindAddress() : InternetAddress{ + return $this->bindAddress; + } + + /** + * @param string $source reference parameter + * @param int $port reference parameter + * + * @throws SocketException + */ + public function readPacket(?string &$source, ?int &$port) : ?string{ + $buffer = ""; + if(@socket_recvfrom($this->socket, $buffer, 65535, 0, $source, $port) === false){ + $errno = socket_last_error($this->socket); + if($errno === SOCKET_EWOULDBLOCK){ + return null; + } + throw new SocketException("Failed to recv (errno $errno): " . trim(socket_strerror($errno)), $errno); + } + return $buffer; + } + + /** + * @throws SocketException + */ + public function writePacket(string $buffer, string $dest, int $port) : int{ + $result = @socket_sendto($this->socket, $buffer, strlen($buffer), 0, $dest, $port); + if($result === false){ + $errno = socket_last_error($this->socket); + throw new SocketException("Failed to send to $dest $port (errno $errno): " . trim(socket_strerror($errno)), $errno); + } + return $result; + } +} From ebc0e735e96f9c45895617dc2ebad7e991574a12 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Nov 2022 15:00:51 +0000 Subject: [PATCH 06/16] Server: remove unused field --- src/server/Server.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/server/Server.php b/src/server/Server.php index f932424..5fd9873 100644 --- a/src/server/Server.php +++ b/src/server/Server.php @@ -89,9 +89,6 @@ class Server implements ServerInterface{ /** @var bool */ public $portChecking = false; - /** @var int */ - protected $startTimeMS; - /** @var int */ protected $maxMtuSize; @@ -119,8 +116,6 @@ public function __construct(int $serverId, \Logger $logger, ServerSocket $socket $this->eventListener = $eventListener; $this->traceCleaner = $traceCleaner; - $this->startTimeMS = (int) (microtime(true) * 1000); - $this->unconnectedMessageHandler = new UnconnectedMessageHandler($this, $protocolAcceptor); } From b872ec8a99d8b6820f88314f31fbfd45583187f7 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Nov 2022 15:01:46 +0000 Subject: [PATCH 07/16] Modernize code --- src/RakLib.php | 2 +- src/generic/ReceiveReliabilityLayer.php | 70 +++++------------ src/generic/ReliableCacheEntry.php | 10 +-- src/generic/SendReliabilityLayer.php | 51 ++++-------- src/generic/Session.php | 40 ++++------ src/generic/Socket.php | 8 +- src/protocol/AcknowledgePacket.php | 2 +- src/protocol/AdvertiseSystem.php | 2 +- src/protocol/ConnectedPing.php | 3 +- src/protocol/ConnectedPong.php | 4 +- src/protocol/ConnectionRequest.php | 6 +- src/protocol/ConnectionRequestAccepted.php | 8 +- src/protocol/Datagram.php | 6 +- src/protocol/EncapsulatedPacket.php | 16 ++-- src/protocol/IncompatibleProtocolVersion.php | 4 +- src/protocol/NewIncomingConnection.php | 8 +- src/protocol/OfflineMessage.php | 2 +- src/protocol/OpenConnectionReply1.php | 9 +-- src/protocol/OpenConnectionReply2.php | 12 +-- src/protocol/OpenConnectionRequest1.php | 6 +- src/protocol/OpenConnectionRequest2.php | 9 +-- src/protocol/SplitPacketInfo.php | 16 ++-- src/protocol/UnconnectedPing.php | 6 +- src/protocol/UnconnectedPong.php | 9 +-- src/server/Server.php | 82 +++++++------------- src/server/ServerSession.php | 5 +- src/server/SimpleProtocolAcceptor.php | 9 +-- src/server/UnconnectedMessageHandler.php | 22 +++--- src/utils/ExceptionTraceCleaner.php | 18 ++--- src/utils/InternetAddress.php | 17 ++-- 30 files changed, 163 insertions(+), 299 deletions(-) diff --git a/src/RakLib.php b/src/RakLib.php index 6db00f1..6f32ae3 100644 --- a/src/RakLib.php +++ b/src/RakLib.php @@ -27,5 +27,5 @@ abstract class RakLib{ * Regular RakNet uses 10 by default. MCPE uses 20. Configure this value as appropriate. * @var int */ - public static $SYSTEM_ADDRESS_COUNT = 20; + public static int $SYSTEM_ADDRESS_COUNT = 20; } diff --git a/src/generic/ReceiveReliabilityLayer.php b/src/generic/ReceiveReliabilityLayer.php index 90a306d..415f5e2 100644 --- a/src/generic/ReceiveReliabilityLayer.php +++ b/src/generic/ReceiveReliabilityLayer.php @@ -28,71 +28,44 @@ final class ReceiveReliabilityLayer{ - /** @var int */ - public static $WINDOW_SIZE = 2048; + public static int $WINDOW_SIZE = 2048; - /** @var \Logger */ - private $logger; - - /** - * @var \Closure - * @phpstan-var \Closure(EncapsulatedPacket) : void - */ - private $onRecv; - - /** - * @var \Closure - * @phpstan-var \Closure(AcknowledgePacket) : void - */ - private $sendPacket; - - /** @var int */ - private $windowStart; - /** @var int */ - private $windowEnd; - /** @var int */ - private $highestSeqNumber = -1; + private int $windowStart; + private int $windowEnd; + private int $highestSeqNumber = -1; /** @var int[] */ - private $ACKQueue = []; + private array $ACKQueue = []; /** @var int[] */ - private $NACKQueue = []; + private array $NACKQueue = []; - /** @var int */ - private $reliableWindowStart; - /** @var int */ - private $reliableWindowEnd; + private int $reliableWindowStart; + private int $reliableWindowEnd; /** @var bool[] */ - private $reliableWindow = []; + private array $reliableWindow = []; /** @var int[] */ - private $receiveOrderedIndex; + private array $receiveOrderedIndex; /** @var int[] */ - private $receiveSequencedHighestIndex; + private array $receiveSequencedHighestIndex; /** @var EncapsulatedPacket[][] */ - private $receiveOrderedPackets; + private array $receiveOrderedPackets; /** @var (EncapsulatedPacket|null)[][] */ - private $splitPackets = []; - - /** - * @var int - * @phpstan-var positive-int - */ - private $maxSplitPacketPartCount; - /** @var int */ - private $maxConcurrentSplitPackets; + private array $splitPackets = []; /** * @phpstan-param positive-int $maxSplitPacketPartCount * @phpstan-param \Closure(EncapsulatedPacket) : void $onRecv * @phpstan-param \Closure(AcknowledgePacket) : void $sendPacket */ - public function __construct(\Logger $logger, \Closure $onRecv, \Closure $sendPacket, int $maxSplitPacketPartCount = PHP_INT_MAX, int $maxConcurrentSplitPackets = PHP_INT_MAX){ - $this->logger = $logger; - $this->onRecv = $onRecv; - $this->sendPacket = $sendPacket; - + public function __construct( + private \Logger $logger, + private \Closure $onRecv, + private \Closure $sendPacket, + private int $maxSplitPacketPartCount = PHP_INT_MAX, + private int $maxConcurrentSplitPackets = PHP_INT_MAX + ){ $this->windowStart = 0; $this->windowEnd = self::$WINDOW_SIZE; @@ -103,9 +76,6 @@ public function __construct(\Logger $logger, \Closure $onRecv, \Closure $sendPac $this->receiveSequencedHighestIndex = array_fill(0, PacketReliability::MAX_ORDER_CHANNELS, 0); $this->receiveOrderedPackets = array_fill(0, PacketReliability::MAX_ORDER_CHANNELS, []); - - $this->maxSplitPacketPartCount = $maxSplitPacketPartCount; - $this->maxConcurrentSplitPackets = $maxConcurrentSplitPackets; } private function handleEncapsulatedPacketRoute(EncapsulatedPacket $pk) : void{ diff --git a/src/generic/ReliableCacheEntry.php b/src/generic/ReliableCacheEntry.php index d674972..1d2c1e3 100644 --- a/src/generic/ReliableCacheEntry.php +++ b/src/generic/ReliableCacheEntry.php @@ -21,16 +21,14 @@ final class ReliableCacheEntry{ - /** @var EncapsulatedPacket[] */ - private $packets; - /** @var float */ - private $timestamp; + private float $timestamp; /** * @param EncapsulatedPacket[] $packets */ - public function __construct(array $packets){ - $this->packets = $packets; + public function __construct( + private array $packets + ){ $this->timestamp = microtime(true); } diff --git a/src/generic/SendReliabilityLayer.php b/src/generic/SendReliabilityLayer.php index 479f8bc..c8909d6 100644 --- a/src/generic/SendReliabilityLayer.php +++ b/src/generic/SendReliabilityLayer.php @@ -29,60 +29,39 @@ use function time; final class SendReliabilityLayer{ - - /** - * @var \Closure - * @phpstan-var \Closure(Datagram) : void - */ - private $sendDatagramCallback; - /** - * @var \Closure - * @phpstan-var \Closure(int) : void - */ - private $onACK; - - /** - * @var int - * @phpstan-var int - */ - private $mtuSize; - /** @var EncapsulatedPacket[] */ - private $sendQueue = []; + private array $sendQueue = []; - /** @var int */ - private $splitID = 0; + private int $splitID = 0; - /** @var int */ - private $sendSeqNumber = 0; + private int $sendSeqNumber = 0; - /** @var int */ - private $messageIndex = 0; + private int $messageIndex = 0; /** @var int[] */ - private $sendOrderedIndex; + private array $sendOrderedIndex; /** @var int[] */ - private $sendSequencedIndex; + private array $sendSequencedIndex; /** @var ReliableCacheEntry[] */ - private $resendQueue = []; + private array $resendQueue = []; /** @var ReliableCacheEntry[] */ - private $reliableCache = []; + private array $reliableCache = []; /** @var int[][] */ - private $needACK = []; + private array $needACK = []; /** * @phpstan-param int $mtuSize - * @phpstan-param \Closure(Datagram) : void $sendDatagram + * @phpstan-param \Closure(Datagram) : void $sendDatagramCallback * @phpstan-param \Closure(int) : void $onACK */ - public function __construct(int $mtuSize, \Closure $sendDatagram, \Closure $onACK){ - $this->mtuSize = $mtuSize; - $this->sendDatagramCallback = $sendDatagram; - $this->onACK = $onACK; - + public function __construct( + private int $mtuSize, + private \Closure $sendDatagramCallback, + private \Closure $onACK + ){ $this->sendOrderedIndex = array_fill(0, PacketReliability::MAX_ORDER_CHANNELS, 0); $this->sendSequencedIndex = array_fill(0, PacketReliability::MAX_ORDER_CHANNELS, 0); } diff --git a/src/generic/Session.php b/src/generic/Session.php index 9da2894..ba7334a 100644 --- a/src/generic/Session.php +++ b/src/generic/Session.php @@ -47,36 +47,26 @@ abstract class Session{ public const MIN_MTU_SIZE = 400; - /** @var \Logger */ - private $logger; + private \Logger $logger; - /** @var InternetAddress */ - protected $address; + protected InternetAddress $address; - /** @var int */ - protected $state = self::STATE_CONNECTING; + protected int $state = self::STATE_CONNECTING; - /** @var int */ - private $id; + private int $id; - /** @var float */ - private $lastUpdate; - /** @var float */ - private $disconnectionTime = 0; + private float $lastUpdate; + private float $disconnectionTime = 0; - /** @var bool */ - private $isActive = false; + private bool $isActive = false; - /** @var float */ - private $lastPingTime = -1; - /** @var int */ - private $lastPingMeasure = 1; + private float $lastPingTime = -1; - /** @var ReceiveReliabilityLayer */ - private $recvLayer; + private int $lastPingMeasure = 1; - /** @var SendReliabilityLayer */ - private $sendLayer; + private ReceiveReliabilityLayer $recvLayer; + + private SendReliabilityLayer $sendLayer; public function __construct(\Logger $logger, InternetAddress $address, int $clientId, int $mtuSize){ if($mtuSize < self::MIN_MTU_SIZE){ @@ -236,16 +226,16 @@ private function handleEncapsulatedPacketRoute(EncapsulatedPacket $packet) : voi if($id < MessageIdentifiers::ID_USER_PACKET_ENUM){ //internal data packet if($this->state === self::STATE_CONNECTING){ $this->handleRakNetConnectionPacket($packet->buffer); - }elseif($id === DisconnectionNotification::$ID){ + }elseif($id === MessageIdentifiers::ID_DISCONNECTION_NOTIFICATION){ $this->handleRemoteDisconnect(); - }elseif($id === ConnectedPing::$ID){ + }elseif($id === MessageIdentifiers::ID_CONNECTED_PING){ $dataPacket = new ConnectedPing(); $dataPacket->decode(new PacketSerializer($packet->buffer)); $this->queueConnectedPacket(ConnectedPong::create( $dataPacket->sendPingTime, $this->getRakNetTimeMS() ), PacketReliability::UNRELIABLE, 0); - }elseif($id === ConnectedPong::$ID){ + }elseif($id === MessageIdentifiers::ID_CONNECTED_PONG){ $dataPacket = new ConnectedPong(); $dataPacket->decode(new PacketSerializer($packet->buffer)); diff --git a/src/generic/Socket.php b/src/generic/Socket.php index cf0a570..7f710c9 100644 --- a/src/generic/Socket.php +++ b/src/generic/Socket.php @@ -34,8 +34,7 @@ use const SOL_UDP; abstract class Socket{ - /** @var \Socket */ - protected $socket; + protected \Socket $socket; /** * @throws SocketException @@ -52,10 +51,7 @@ protected function __construct(bool $ipv6){ } } - /** - * @return \Socket - */ - public function getSocket(){ + public function getSocket() : \Socket{ return $this->socket; } diff --git a/src/protocol/AcknowledgePacket.php b/src/protocol/AcknowledgePacket.php index 654d4aa..6a18733 100644 --- a/src/protocol/AcknowledgePacket.php +++ b/src/protocol/AcknowledgePacket.php @@ -27,7 +27,7 @@ abstract class AcknowledgePacket extends Packet{ private const RECORD_TYPE_SINGLE = 1; /** @var int[] */ - public $packets = []; + public array $packets = []; protected function encodePayload(PacketSerializer $out) : void{ $payload = ""; diff --git a/src/protocol/AdvertiseSystem.php b/src/protocol/AdvertiseSystem.php index a1ecf81..a28e3bd 100644 --- a/src/protocol/AdvertiseSystem.php +++ b/src/protocol/AdvertiseSystem.php @@ -20,7 +20,7 @@ class AdvertiseSystem extends Packet{ public static $ID = MessageIdentifiers::ID_ADVERTISE_SYSTEM; /** @var string */ - public $serverName; + public string $serverName; protected function encodePayload(PacketSerializer $out) : void{ $out->putString($this->serverName); diff --git a/src/protocol/ConnectedPing.php b/src/protocol/ConnectedPing.php index d8280f0..82830af 100644 --- a/src/protocol/ConnectedPing.php +++ b/src/protocol/ConnectedPing.php @@ -19,8 +19,7 @@ class ConnectedPing extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_CONNECTED_PING; - /** @var int */ - public $sendPingTime; + public int $sendPingTime; public static function create(int $sendPingTime) : self{ $result = new self; diff --git a/src/protocol/ConnectedPong.php b/src/protocol/ConnectedPong.php index b188ccc..b0e0001 100644 --- a/src/protocol/ConnectedPong.php +++ b/src/protocol/ConnectedPong.php @@ -20,9 +20,9 @@ class ConnectedPong extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_CONNECTED_PONG; /** @var int */ - public $sendPingTime; + public int $sendPingTime; /** @var int */ - public $sendPongTime; + public int $sendPongTime; public static function create(int $sendPingTime, int $sendPongTime) : self{ $result = new self; diff --git a/src/protocol/ConnectionRequest.php b/src/protocol/ConnectionRequest.php index 966400c..501b354 100644 --- a/src/protocol/ConnectionRequest.php +++ b/src/protocol/ConnectionRequest.php @@ -20,11 +20,11 @@ class ConnectionRequest extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_CONNECTION_REQUEST; /** @var int */ - public $clientID; + public int $clientID; /** @var int */ - public $sendPingTime; + public int $sendPingTime; /** @var bool */ - public $useSecurity = false; + public bool $useSecurity = false; protected function encodePayload(PacketSerializer $out) : void{ $out->putLong($this->clientID); diff --git a/src/protocol/ConnectionRequestAccepted.php b/src/protocol/ConnectionRequestAccepted.php index 8f5775b..c077bd3 100644 --- a/src/protocol/ConnectionRequestAccepted.php +++ b/src/protocol/ConnectionRequestAccepted.php @@ -24,14 +24,14 @@ class ConnectionRequestAccepted extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_CONNECTION_REQUEST_ACCEPTED; /** @var InternetAddress */ - public $address; + public InternetAddress $address; /** @var InternetAddress[] */ - public $systemAddresses = []; + public array $systemAddresses = []; /** @var int */ - public $sendPingTime; + public int $sendPingTime; /** @var int */ - public $sendPongTime; + public int $sendPongTime; /** * @param InternetAddress[] $systemAddresses diff --git a/src/protocol/Datagram.php b/src/protocol/Datagram.php index ad9a3b7..11abc2f 100644 --- a/src/protocol/Datagram.php +++ b/src/protocol/Datagram.php @@ -32,13 +32,13 @@ class Datagram extends Packet{ public const HEADER_SIZE = 1 + 3; //header flags (1) + sequence number (3) /** @var int */ - public $headerFlags = 0; + public int $headerFlags = 0; /** @var EncapsulatedPacket[] */ - public $packets = []; + public array $packets = []; /** @var int */ - public $seqNumber; + public int $seqNumber; protected function encodeHeader(PacketSerializer $out) : void{ $out->putByte(self::BITFLAG_VALID | $this->headerFlags); diff --git a/src/protocol/EncapsulatedPacket.php b/src/protocol/EncapsulatedPacket.php index 79bdd48..2f15d0d 100644 --- a/src/protocol/EncapsulatedPacket.php +++ b/src/protocol/EncapsulatedPacket.php @@ -30,21 +30,21 @@ class EncapsulatedPacket{ private const SPLIT_FLAG = 0b00010000; /** @var int */ - public $reliability; + public int $reliability; /** @var int|null */ - public $messageIndex; + public ?int $messageIndex = null; /** @var int|null */ - public $sequenceIndex; + public ?int $sequenceIndex = null; /** @var int|null */ - public $orderIndex; + public ?int $orderIndex = null; /** @var int|null */ - public $orderChannel; + public ?int $orderChannel = null; /** @var SplitPacketInfo|null */ - public $splitInfo = null; + public ?SplitPacketInfo $splitInfo = null; /** @var string */ - public $buffer = ""; + public string $buffer = ""; /** @var int|null */ - public $identifierACK = null; + public ?int $identifierACK = null; /** * @throws BinaryDataException diff --git a/src/protocol/IncompatibleProtocolVersion.php b/src/protocol/IncompatibleProtocolVersion.php index b9b9452..0f187b2 100644 --- a/src/protocol/IncompatibleProtocolVersion.php +++ b/src/protocol/IncompatibleProtocolVersion.php @@ -20,9 +20,9 @@ class IncompatibleProtocolVersion extends OfflineMessage{ public static $ID = MessageIdentifiers::ID_INCOMPATIBLE_PROTOCOL_VERSION; /** @var int */ - public $protocolVersion; + public int $protocolVersion; /** @var int */ - public $serverId; + public int $serverId; public static function create(int $protocolVersion, int $serverId) : self{ $result = new self; diff --git a/src/protocol/NewIncomingConnection.php b/src/protocol/NewIncomingConnection.php index 4394ac5..dd2ad77 100644 --- a/src/protocol/NewIncomingConnection.php +++ b/src/protocol/NewIncomingConnection.php @@ -24,15 +24,15 @@ class NewIncomingConnection extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_NEW_INCOMING_CONNECTION; /** @var InternetAddress */ - public $address; + public InternetAddress $address; /** @var InternetAddress[] */ - public $systemAddresses = []; + public array $systemAddresses = []; /** @var int */ - public $sendPingTime; + public int $sendPingTime; /** @var int */ - public $sendPongTime; + public int $sendPongTime; protected function encodePayload(PacketSerializer $out) : void{ $out->putAddress($this->address); diff --git a/src/protocol/OfflineMessage.php b/src/protocol/OfflineMessage.php index dd229f2..25e9536 100644 --- a/src/protocol/OfflineMessage.php +++ b/src/protocol/OfflineMessage.php @@ -27,7 +27,7 @@ abstract class OfflineMessage extends Packet{ private const MAGIC = "\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78"; /** @var string */ - protected $magic; + protected string $magic; /** * @return void diff --git a/src/protocol/OpenConnectionReply1.php b/src/protocol/OpenConnectionReply1.php index 22cd0f0..eaa227c 100644 --- a/src/protocol/OpenConnectionReply1.php +++ b/src/protocol/OpenConnectionReply1.php @@ -19,12 +19,9 @@ class OpenConnectionReply1 extends OfflineMessage{ public static $ID = MessageIdentifiers::ID_OPEN_CONNECTION_REPLY_1; - /** @var int */ - public $serverID; - /** @var bool */ - public $serverSecurity = false; - /** @var int */ - public $mtuSize; + public int $serverID; + public bool $serverSecurity = false; + public int $mtuSize; public static function create(int $serverId, bool $serverSecurity, int $mtuSize) : self{ $result = new self; diff --git a/src/protocol/OpenConnectionReply2.php b/src/protocol/OpenConnectionReply2.php index 5f60fe6..f0eff65 100644 --- a/src/protocol/OpenConnectionReply2.php +++ b/src/protocol/OpenConnectionReply2.php @@ -21,14 +21,10 @@ class OpenConnectionReply2 extends OfflineMessage{ public static $ID = MessageIdentifiers::ID_OPEN_CONNECTION_REPLY_2; - /** @var int */ - public $serverID; - /** @var InternetAddress */ - public $clientAddress; - /** @var int */ - public $mtuSize; - /** @var bool */ - public $serverSecurity = false; + public int $serverID; + public InternetAddress $clientAddress; + public int $mtuSize; + public bool $serverSecurity = false; public static function create(int $serverId, InternetAddress $clientAddress, int $mtuSize, bool $serverSecurity) : self{ $result = new self; diff --git a/src/protocol/OpenConnectionRequest1.php b/src/protocol/OpenConnectionRequest1.php index c1d23d6..fc9d8e6 100644 --- a/src/protocol/OpenConnectionRequest1.php +++ b/src/protocol/OpenConnectionRequest1.php @@ -23,10 +23,8 @@ class OpenConnectionRequest1 extends OfflineMessage{ public static $ID = MessageIdentifiers::ID_OPEN_CONNECTION_REQUEST_1; - /** @var int */ - public $protocol = RakLib::DEFAULT_PROTOCOL_VERSION; - /** @var int */ - public $mtuSize; + public int $protocol = RakLib::DEFAULT_PROTOCOL_VERSION; + public int $mtuSize; protected function encodePayload(PacketSerializer $out) : void{ $this->writeMagic($out); diff --git a/src/protocol/OpenConnectionRequest2.php b/src/protocol/OpenConnectionRequest2.php index 0a97e80..bc22183 100644 --- a/src/protocol/OpenConnectionRequest2.php +++ b/src/protocol/OpenConnectionRequest2.php @@ -21,12 +21,9 @@ class OpenConnectionRequest2 extends OfflineMessage{ public static $ID = MessageIdentifiers::ID_OPEN_CONNECTION_REQUEST_2; - /** @var int */ - public $clientID; - /** @var InternetAddress */ - public $serverAddress; - /** @var int */ - public $mtuSize; + public int $clientID; + public InternetAddress $serverAddress; + public int $mtuSize; protected function encodePayload(PacketSerializer $out) : void{ $this->writeMagic($out); diff --git a/src/protocol/SplitPacketInfo.php b/src/protocol/SplitPacketInfo.php index 3fbcf4c..179043c 100644 --- a/src/protocol/SplitPacketInfo.php +++ b/src/protocol/SplitPacketInfo.php @@ -17,18 +17,12 @@ namespace raklib\protocol; final class SplitPacketInfo{ - /** @var int */ - private $id; - /** @var int */ - private $partIndex; - /** @var int */ - private $totalPartCount; - - public function __construct(int $id, int $partIndex, int $totalPartCount){ + public function __construct( + private int $id, + private int $partIndex, + private int $totalPartCount + ){ //TODO: argument validation - $this->id = $id; - $this->partIndex = $partIndex; - $this->totalPartCount = $totalPartCount; } public function getId() : int{ diff --git a/src/protocol/UnconnectedPing.php b/src/protocol/UnconnectedPing.php index 9fb6097..cc47423 100644 --- a/src/protocol/UnconnectedPing.php +++ b/src/protocol/UnconnectedPing.php @@ -19,10 +19,8 @@ class UnconnectedPing extends OfflineMessage{ public static $ID = MessageIdentifiers::ID_UNCONNECTED_PING; - /** @var int */ - public $sendPingTime; - /** @var int */ - public $clientId; + public int $sendPingTime; + public int $clientId; protected function encodePayload(PacketSerializer $out) : void{ $out->putLong($this->sendPingTime); diff --git a/src/protocol/UnconnectedPong.php b/src/protocol/UnconnectedPong.php index c23b6b7..827652d 100644 --- a/src/protocol/UnconnectedPong.php +++ b/src/protocol/UnconnectedPong.php @@ -19,12 +19,9 @@ class UnconnectedPong extends OfflineMessage{ public static $ID = MessageIdentifiers::ID_UNCONNECTED_PONG; - /** @var int */ - public $sendPingTime; - /** @var int */ - public $serverId; - /** @var string */ - public $serverName; + public int $sendPingTime; + public int $serverId; + public string $serverName; public static function create(int $sendPingTime, int $serverId, string $serverName) : self{ $result = new self; diff --git a/src/server/Server.php b/src/server/Server.php index 5fd9873..471f434 100644 --- a/src/server/Server.php +++ b/src/server/Server.php @@ -45,76 +45,50 @@ class Server implements ServerInterface{ private const RAKLIB_TPS = 100; private const RAKLIB_TIME_PER_TICK = 1 / self::RAKLIB_TPS; - /** @var ServerSocket */ - protected $socket; - - /** @var \Logger */ - protected $logger; - - /** @var int */ - protected $serverId; - - /** @var int */ - protected $receiveBytes = 0; - /** @var int */ - protected $sendBytes = 0; + protected int $receiveBytes = 0; + protected int $sendBytes = 0; /** @var ServerSession[] */ - protected $sessionsByAddress = []; + protected array $sessionsByAddress = []; /** @var ServerSession[] */ - protected $sessions = []; + protected array $sessions = []; - /** @var UnconnectedMessageHandler */ - protected $unconnectedMessageHandler; - /** @var string */ - protected $name = ""; + protected UnconnectedMessageHandler $unconnectedMessageHandler; - /** @var int */ - protected $packetLimit = 200; + protected string $name = ""; - /** @var bool */ - protected $shutdown = false; + protected int $packetLimit = 200; - /** @var int */ - protected $ticks = 0; + protected bool $shutdown = false; + + protected int $ticks = 0; /** @var int[] string (address) => int (unblock time) */ - protected $block = []; + protected array $block = []; /** @var int[] string (address) => int (number of packets) */ - protected $ipSec = []; + protected array $ipSec = []; /** @var string[] regex filters used to block out unwanted raw packets */ - protected $rawPacketFilters = []; - - /** @var bool */ - public $portChecking = false; - - /** @var int */ - protected $maxMtuSize; - - /** @var int */ - protected $nextSessionId = 0; - - /** @var ServerEventSource */ - private $eventSource; - /** @var ServerEventListener */ - private $eventListener; - - /** @var ExceptionTraceCleaner */ - private $traceCleaner; - - public function __construct(int $serverId, \Logger $logger, ServerSocket $socket, int $maxMtuSize, ProtocolAcceptor $protocolAcceptor, ServerEventSource $eventSource, ServerEventListener $eventListener, ExceptionTraceCleaner $traceCleaner){ + protected array $rawPacketFilters = []; + + public bool $portChecking = false; + + protected int $nextSessionId = 0; + + public function __construct( + protected int $serverId, + protected \Logger $logger, + protected ServerSocket $socket, + protected int $maxMtuSize, + ProtocolAcceptor $protocolAcceptor, + private ServerEventSource $eventSource, + private ServerEventListener $eventListener, + private ExceptionTraceCleaner $traceCleaner + ){ if($maxMtuSize < Session::MIN_MTU_SIZE){ throw new \InvalidArgumentException("MTU size must be at least " . Session::MIN_MTU_SIZE . ", got $maxMtuSize"); } - $this->serverId = $serverId; - $this->logger = $logger; - $this->socket = $socket; $this->socket->setBlocking(false); - $this->maxMtuSize = $maxMtuSize; - $this->eventSource = $eventSource; - $this->eventListener = $eventListener; - $this->traceCleaner = $traceCleaner; $this->unconnectedMessageHandler = new UnconnectedMessageHandler($this, $protocolAcceptor); } diff --git a/src/server/ServerSession.php b/src/server/ServerSession.php index 5b5f7c7..499697b 100644 --- a/src/server/ServerSession.php +++ b/src/server/ServerSession.php @@ -19,6 +19,7 @@ use raklib\generic\Session; use raklib\protocol\ConnectionRequest; use raklib\protocol\ConnectionRequestAccepted; +use raklib\protocol\MessageIdentifiers; use raklib\protocol\NewIncomingConnection; use raklib\protocol\Packet; use raklib\protocol\PacketReliability; @@ -57,7 +58,7 @@ protected function onDisconnect(string $reason) : void{ final protected function handleRakNetConnectionPacket(string $packet) : void{ $id = ord($packet[0]); - if($id === ConnectionRequest::$ID){ + if($id === MessageIdentifiers::ID_CONNECTION_REQUEST){ $dataPacket = new ConnectionRequest(); $dataPacket->decode(new PacketSerializer($packet)); $this->queueConnectedPacket(ConnectionRequestAccepted::create( @@ -66,7 +67,7 @@ final protected function handleRakNetConnectionPacket(string $packet) : void{ $dataPacket->sendPingTime, $this->getRakNetTimeMS() ), PacketReliability::UNRELIABLE, 0, true); - }elseif($id === NewIncomingConnection::$ID){ + }elseif($id === MessageIdentifiers::ID_NEW_INCOMING_CONNECTION){ $dataPacket = new NewIncomingConnection(); $dataPacket->decode(new PacketSerializer($packet)); diff --git a/src/server/SimpleProtocolAcceptor.php b/src/server/SimpleProtocolAcceptor.php index 9db5253..245bbec 100644 --- a/src/server/SimpleProtocolAcceptor.php +++ b/src/server/SimpleProtocolAcceptor.php @@ -18,12 +18,9 @@ final class SimpleProtocolAcceptor implements ProtocolAcceptor{ - /** @var int */ - private $protocolVersion; - - public function __construct(int $protocolVersion){ - $this->protocolVersion = $protocolVersion; - } + public function __construct( + private int $protocolVersion + ){} public function accepts(int $protocolVersion) : bool{ return $this->protocolVersion === $protocolVersion; diff --git a/src/server/UnconnectedMessageHandler.php b/src/server/UnconnectedMessageHandler.php index fd0dab1..2ab7bad 100644 --- a/src/server/UnconnectedMessageHandler.php +++ b/src/server/UnconnectedMessageHandler.php @@ -19,6 +19,7 @@ use pocketmine\utils\BinaryDataException; use raklib\generic\Session; use raklib\protocol\IncompatibleProtocolVersion; +use raklib\protocol\MessageIdentifiers; use raklib\protocol\OfflineMessage; use raklib\protocol\OpenConnectionReply1; use raklib\protocol\OpenConnectionReply2; @@ -36,20 +37,17 @@ use function substr; class UnconnectedMessageHandler{ - /** @var Server */ - private $server; /** * @var OfflineMessage[]|\SplFixedArray * @phpstan-var \SplFixedArray */ - private $packetPool; - /** @var ProtocolAcceptor */ - private $protocolAcceptor; + private \SplFixedArray $packetPool; - public function __construct(Server $server, ProtocolAcceptor $protocolAcceptor){ + public function __construct( + private Server $server, + private ProtocolAcceptor $protocolAcceptor + ){ $this->registerPackets(); - $this->server = $server; - $this->protocolAcceptor = $protocolAcceptor; } /** @@ -131,10 +129,10 @@ public function getPacketFromPool(string $buffer) : ?OfflineMessage{ private function registerPackets() : void{ $this->packetPool = new \SplFixedArray(256); - $this->registerPacket(UnconnectedPing::$ID, UnconnectedPing::class); - $this->registerPacket(UnconnectedPingOpenConnections::$ID, UnconnectedPingOpenConnections::class); - $this->registerPacket(OpenConnectionRequest1::$ID, OpenConnectionRequest1::class); - $this->registerPacket(OpenConnectionRequest2::$ID, OpenConnectionRequest2::class); + $this->registerPacket(MessageIdentifiers::ID_UNCONNECTED_PING, UnconnectedPing::class); + $this->registerPacket(MessageIdentifiers::ID_UNCONNECTED_PING_OPEN_CONNECTIONS, UnconnectedPingOpenConnections::class); + $this->registerPacket(MessageIdentifiers::ID_OPEN_CONNECTION_REQUEST_1, OpenConnectionRequest1::class); + $this->registerPacket(MessageIdentifiers::ID_OPEN_CONNECTION_REQUEST_2, OpenConnectionRequest2::class); } } diff --git a/src/utils/ExceptionTraceCleaner.php b/src/utils/ExceptionTraceCleaner.php index 53c5b2c..d19517a 100644 --- a/src/utils/ExceptionTraceCleaner.php +++ b/src/utils/ExceptionTraceCleaner.php @@ -28,12 +28,9 @@ use function xdebug_get_function_stack; final class ExceptionTraceCleaner{ - /** @var string */ - private $mainPath; - - public function __construct(string $mainPath){ - $this->mainPath = $mainPath; - } + public function __construct( + private string $mainPath + ){} /** * @param int $start @@ -41,7 +38,7 @@ public function __construct(string $mainPath){ * * @return list */ - public function getTrace($start = 0, $trace = null){ + public function getTrace(int $start = 0, ?array $trace = null) : array{ if($trace === null){ if(function_exists("xdebug_get_function_stack")){ $trace = array_reverse(xdebug_get_function_stack()); @@ -71,12 +68,7 @@ public function getTrace($start = 0, $trace = null){ return $messages; } - /** - * @param string $path - * - * @return string - */ - public function cleanPath($path){ + public function cleanPath(string $path) : string{ return str_replace(["\\", ".php", "phar://", str_replace(["\\", "phar://"], ["/", ""], $this->mainPath)], ["/", "", "", ""], $path); } } diff --git a/src/utils/InternetAddress.php b/src/utils/InternetAddress.php index f1ba161..4e90961 100644 --- a/src/utils/InternetAddress.php +++ b/src/utils/InternetAddress.php @@ -17,21 +17,14 @@ namespace raklib\utils; final class InternetAddress{ - - /** @var string */ - private $ip; - /** @var int */ - private $port; - /** @var int */ - private $version; - - public function __construct(string $address, int $port, int $version){ - $this->ip = $address; + public function __construct( + private string $ip, + private int $port, + private int $version + ){ if($port < 0 or $port > 65535){ throw new \InvalidArgumentException("Invalid port range"); } - $this->port = $port; - $this->version = $version; } public function getIp() : string{ From dc3c4c32fcf3c42a61c63be0dd94c8455292de58 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Nov 2022 15:04:11 +0000 Subject: [PATCH 08/16] Fix CS --- src/RakLib.php | 1 - src/protocol/AdvertiseSystem.php | 1 - src/protocol/ConnectedPong.php | 2 -- src/protocol/ConnectionRequest.php | 3 --- src/protocol/ConnectionRequestAccepted.php | 4 ---- src/protocol/Datagram.php | 4 ---- src/protocol/EncapsulatedPacket.php | 8 -------- src/protocol/IncompatibleProtocolVersion.php | 2 -- src/protocol/NewIncomingConnection.php | 5 ----- src/protocol/OfflineMessage.php | 1 - src/utils/ExceptionTraceCleaner.php | 1 - 11 files changed, 32 deletions(-) diff --git a/src/RakLib.php b/src/RakLib.php index 6f32ae3..fc609fb 100644 --- a/src/RakLib.php +++ b/src/RakLib.php @@ -25,7 +25,6 @@ abstract class RakLib{ /** * Regular RakNet uses 10 by default. MCPE uses 20. Configure this value as appropriate. - * @var int */ public static int $SYSTEM_ADDRESS_COUNT = 20; } diff --git a/src/protocol/AdvertiseSystem.php b/src/protocol/AdvertiseSystem.php index a28e3bd..e6beca3 100644 --- a/src/protocol/AdvertiseSystem.php +++ b/src/protocol/AdvertiseSystem.php @@ -19,7 +19,6 @@ class AdvertiseSystem extends Packet{ public static $ID = MessageIdentifiers::ID_ADVERTISE_SYSTEM; - /** @var string */ public string $serverName; protected function encodePayload(PacketSerializer $out) : void{ diff --git a/src/protocol/ConnectedPong.php b/src/protocol/ConnectedPong.php index b0e0001..bd42c87 100644 --- a/src/protocol/ConnectedPong.php +++ b/src/protocol/ConnectedPong.php @@ -19,9 +19,7 @@ class ConnectedPong extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_CONNECTED_PONG; - /** @var int */ public int $sendPingTime; - /** @var int */ public int $sendPongTime; public static function create(int $sendPingTime, int $sendPongTime) : self{ diff --git a/src/protocol/ConnectionRequest.php b/src/protocol/ConnectionRequest.php index 501b354..94a888f 100644 --- a/src/protocol/ConnectionRequest.php +++ b/src/protocol/ConnectionRequest.php @@ -19,11 +19,8 @@ class ConnectionRequest extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_CONNECTION_REQUEST; - /** @var int */ public int $clientID; - /** @var int */ public int $sendPingTime; - /** @var bool */ public bool $useSecurity = false; protected function encodePayload(PacketSerializer $out) : void{ diff --git a/src/protocol/ConnectionRequestAccepted.php b/src/protocol/ConnectionRequestAccepted.php index c077bd3..275ec96 100644 --- a/src/protocol/ConnectionRequestAccepted.php +++ b/src/protocol/ConnectionRequestAccepted.php @@ -23,14 +23,10 @@ class ConnectionRequestAccepted extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_CONNECTION_REQUEST_ACCEPTED; - /** @var InternetAddress */ public InternetAddress $address; /** @var InternetAddress[] */ public array $systemAddresses = []; - - /** @var int */ public int $sendPingTime; - /** @var int */ public int $sendPongTime; /** diff --git a/src/protocol/Datagram.php b/src/protocol/Datagram.php index 11abc2f..e93e299 100644 --- a/src/protocol/Datagram.php +++ b/src/protocol/Datagram.php @@ -31,13 +31,9 @@ class Datagram extends Packet{ public const HEADER_SIZE = 1 + 3; //header flags (1) + sequence number (3) - /** @var int */ public int $headerFlags = 0; - /** @var EncapsulatedPacket[] */ public array $packets = []; - - /** @var int */ public int $seqNumber; protected function encodeHeader(PacketSerializer $out) : void{ diff --git a/src/protocol/EncapsulatedPacket.php b/src/protocol/EncapsulatedPacket.php index 2f15d0d..10e4225 100644 --- a/src/protocol/EncapsulatedPacket.php +++ b/src/protocol/EncapsulatedPacket.php @@ -29,21 +29,13 @@ class EncapsulatedPacket{ private const SPLIT_FLAG = 0b00010000; - /** @var int */ public int $reliability; - /** @var int|null */ public ?int $messageIndex = null; - /** @var int|null */ public ?int $sequenceIndex = null; - /** @var int|null */ public ?int $orderIndex = null; - /** @var int|null */ public ?int $orderChannel = null; - /** @var SplitPacketInfo|null */ public ?SplitPacketInfo $splitInfo = null; - /** @var string */ public string $buffer = ""; - /** @var int|null */ public ?int $identifierACK = null; /** diff --git a/src/protocol/IncompatibleProtocolVersion.php b/src/protocol/IncompatibleProtocolVersion.php index 0f187b2..c3575cd 100644 --- a/src/protocol/IncompatibleProtocolVersion.php +++ b/src/protocol/IncompatibleProtocolVersion.php @@ -19,9 +19,7 @@ class IncompatibleProtocolVersion extends OfflineMessage{ public static $ID = MessageIdentifiers::ID_INCOMPATIBLE_PROTOCOL_VERSION; - /** @var int */ public int $protocolVersion; - /** @var int */ public int $serverId; public static function create(int $protocolVersion, int $serverId) : self{ diff --git a/src/protocol/NewIncomingConnection.php b/src/protocol/NewIncomingConnection.php index dd2ad77..5ae4e55 100644 --- a/src/protocol/NewIncomingConnection.php +++ b/src/protocol/NewIncomingConnection.php @@ -23,15 +23,10 @@ class NewIncomingConnection extends ConnectedPacket{ public static $ID = MessageIdentifiers::ID_NEW_INCOMING_CONNECTION; - /** @var InternetAddress */ public InternetAddress $address; - /** @var InternetAddress[] */ public array $systemAddresses = []; - - /** @var int */ public int $sendPingTime; - /** @var int */ public int $sendPongTime; protected function encodePayload(PacketSerializer $out) : void{ diff --git a/src/protocol/OfflineMessage.php b/src/protocol/OfflineMessage.php index 25e9536..1c0ce95 100644 --- a/src/protocol/OfflineMessage.php +++ b/src/protocol/OfflineMessage.php @@ -26,7 +26,6 @@ abstract class OfflineMessage extends Packet{ */ private const MAGIC = "\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78"; - /** @var string */ protected string $magic; /** diff --git a/src/utils/ExceptionTraceCleaner.php b/src/utils/ExceptionTraceCleaner.php index d19517a..cfa2c6f 100644 --- a/src/utils/ExceptionTraceCleaner.php +++ b/src/utils/ExceptionTraceCleaner.php @@ -33,7 +33,6 @@ public function __construct( ){} /** - * @param int $start * @param list>|null $trace * * @return list From ea78240d54075e7ca4eab88c32d8f06a9b6e3c97 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Nov 2022 15:04:32 +0000 Subject: [PATCH 09/16] OfflineMessage: symmetric encode/decode for magic --- src/protocol/OfflineMessage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocol/OfflineMessage.php b/src/protocol/OfflineMessage.php index 1c0ce95..d157d0f 100644 --- a/src/protocol/OfflineMessage.php +++ b/src/protocol/OfflineMessage.php @@ -26,7 +26,7 @@ abstract class OfflineMessage extends Packet{ */ private const MAGIC = "\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78"; - protected string $magic; + protected string $magic = self::MAGIC; /** * @return void @@ -40,7 +40,7 @@ protected function readMagic(BinaryStream $in){ * @return void */ protected function writeMagic(BinaryStream $out){ - $out->put(self::MAGIC); + $out->put($this->magic); } public function isValid() : bool{ From 116f31539e05cab04545ba0b0b58586574c68fb8 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Nov 2022 15:41:41 +0000 Subject: [PATCH 10/16] Added a basic proxy bridge tool this isn't a fancy proxy - it just bridges a client and server. This is sometimes useful for debugging purposes, or for working around bugs - for example, MC on Windows currently can't connect directly to a BDS instance inside WSL, but can do so from a proxy tunnel. --- phpstan.neon.dist | 1 + tools/proxy.php | 210 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 tools/proxy.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index eed79df..bf55dcb 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -6,6 +6,7 @@ parameters: level: 9 paths: - src + - tools reportUnmatchedIgnoredErrors: false #enabling this makes build results too volatile when phpstan bugs get fixed ignoreErrors: - diff --git a/tools/proxy.php b/tools/proxy.php new file mode 100644 index 0000000..e0a7b89 --- /dev/null +++ b/tools/proxy.php @@ -0,0 +1,210 @@ +warning("You may experience problems connecting to PocketMine-MP servers on ports other than 19132 if the server has port checking enabled"); +} + +\GlobalLogger::get()->info("Opening listen socket"); +try{ + $proxyToServerUnconnectedSocket = new ClientSocket(new InternetAddress($serverAddress, $serverPort, 4)); + $proxyToServerUnconnectedSocket->setBlocking(false); +}catch(SocketException $e){ + \GlobalLogger::get()->emergency("Can't connect to $serverAddress on port $serverPort, is the server online?"); + \GlobalLogger::get()->emergency($e->getMessage()); + exit(1); +} +socket_getsockname($proxyToServerUnconnectedSocket->getSocket(), $proxyAddr, $proxyPort); +\GlobalLogger::get()->info("Listening on $bindAddr:$bindPort, sending from $proxyAddr:$proxyPort, sending to $serverAddress:$serverPort"); + +try{ + $clientProxySocket = new ServerSocket(new InternetAddress($bindAddr, $bindPort, 4)); + $clientProxySocket->setBlocking(false); +}catch(SocketException $e){ + \GlobalLogger::get()->emergency("Can't bind to $bindAddr on port $bindPort, is something already using that port?"); + \GlobalLogger::get()->emergency($e->getMessage()); + exit(1); +} + +\GlobalLogger::get()->info("Press CTRL+C to stop the proxy"); + +$clientAddr = $clientPort = null; + +class ClientSession{ + private int $lastUsedTime; + + public function __construct( + private InternetAddress $address, + private ClientSocket $proxyToServerSocket + ){ + $this->lastUsedTime = time(); + } + + public function getAddress() : InternetAddress{ + return $this->address; + } + + public function getSocket() : ClientSocket{ + return $this->proxyToServerSocket; + } + + public function setActive() : void{ + $this->lastUsedTime = time(); + } + + public function isActive() : bool{ + return time() - $this->lastUsedTime < 10; + } +} + +function serverToClientRelay(ClientSession $client, ServerSocket $clientProxySocket) : void{ + $buffer = $client->getSocket()->readPacket(); + if($buffer !== null){ + $clientProxySocket->writePacket($buffer, $client->getAddress()->getIp(), $client->getAddress()->getPort()); + } +} + +/** @var ClientSession[][] $clients */ +$clients = []; + +$serverId = mt_rand(0, Limits::INT32_MAX); +$mostRecentPong = null; + +while(true){ + $k = 0; + $r = []; + $r[++$k] = $clientProxySocket->getSocket(); + $r[++$k] = $proxyToServerUnconnectedSocket->getSocket(); + $clientIndex = []; + foreach($clients as $ipClients){ + foreach($ipClients as $client){ + $key = ++$k; + $r[$key] = $client->getSocket()->getSocket(); + $clientIndex[$key] = $client; + } + } + $w = $e = null; + if(socket_select($r, $w, $e, 10) > 0){ + foreach($r as $key => $socket){ + if(isset($clientIndex[$key])){ + serverToClientRelay($clientIndex[$key], $clientProxySocket); + }elseif($socket === $proxyToServerUnconnectedSocket->getSocket()){ + $buffer = $proxyToServerUnconnectedSocket->readPacket(); + if($buffer !== null && $buffer !== "" && ord($buffer[0]) === MessageIdentifiers::ID_UNCONNECTED_PONG){ + $mostRecentPong = $buffer; + \GlobalLogger::get()->info("Caching ping response from server: " . $buffer); + } + }elseif($socket === $clientProxySocket->getSocket()){ + try{ + $buffer = $clientProxySocket->readPacket($recvAddr, $recvPort); + }catch(SocketException $e){ + $error = $e->getCode(); + if($error === SOCKET_ECONNRESET){ //client disconnected improperly, maybe crash or lost connection + continue; + } + + \GlobalLogger::get()->error("Socket error: " . $e->getMessage()); + continue; + } + + if($buffer === null || $buffer === ""){ + continue; + } + if(isset($clients[$recvAddr][$recvPort])){ + $client = $clients[$recvAddr][$recvPort]; + $client->setActive(); + $client->getSocket()->writePacket($buffer); + }elseif(ord($buffer[0]) === MessageIdentifiers::ID_UNCONNECTED_PING){ + \GlobalLogger::get()->info("Got ping from $recvAddr on port $recvPort, pinging server"); + $proxyToServerUnconnectedSocket->writePacket($buffer); + + if($mostRecentPong !== null){ + $clientProxySocket->writePacket($mostRecentPong, $recvAddr, $recvPort); + }else{ + \GlobalLogger::get()->info("No cached ping response, waiting for server to respond"); + } + }elseif(ord($buffer[0]) === MessageIdentifiers::ID_OPEN_CONNECTION_REQUEST_1){ + \GlobalLogger::get()->info("Got connection from $recvAddr on port $recvPort"); + $proxyToServerUnconnectedSocket->writePacket($buffer); + $client = new ClientSession(new InternetAddress($recvAddr, $recvPort, 4), new ClientSocket(new InternetAddress($serverAddress, $serverPort, 4))); + $client->getSocket()->setBlocking(false); + $clients[$recvAddr][$recvPort] = $client; + socket_getsockname($client->getSocket()->getSocket(), $proxyAddr, $proxyPort); + \GlobalLogger::get()->info("Established connection: $recvAddr:$recvPort <-> $proxyAddr:$proxyPort <-> $serverAddress:$serverPort"); + }else{ + \GlobalLogger::get()->warning("Unexpected packet from unconnected client $recvAddr on port $recvPort: " . bin2hex($buffer)); + } + }else{ + throw new \LogicException("Unexpected socket in select result"); + } + } + } + foreach($clients as $ip => $ipClients){ + foreach($ipClients as $port => $client){ + if(!$client->isActive()){ + \GlobalLogger::get()->info("Closing session for client $ip:$port"); + unset($clients[$ip][$port]); + } + } + } +} \ No newline at end of file From 515880b5870e830f789e1b05baa848233411cffe Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Nov 2022 16:46:22 +0000 Subject: [PATCH 11/16] proxy.php: fix autoloader --- tools/proxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/proxy.php b/tools/proxy.php index e0a7b89..6ef9045 100644 --- a/tools/proxy.php +++ b/tools/proxy.php @@ -33,7 +33,7 @@ use raklib\utils\InternetAddress; use raklib\generic\Socket; -require '../vendor/autoload.php'; +require dirname(__DIR__) . '/vendor/autoload.php'; $bindAddr = "0.0.0.0"; $bindPort = 19132; From 31f72d031e32c77d53860f5ba5c438eaae7aba88 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Nov 2022 16:47:24 +0000 Subject: [PATCH 12/16] Added tool to scan broadcast addresses for servers Example usage: php tools/scan.php 192.168.0.255 19132 --- tools/scan.php | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tools/scan.php diff --git a/tools/scan.php b/tools/scan.php new file mode 100644 index 0000000..f9f3f3c --- /dev/null +++ b/tools/scan.php @@ -0,0 +1,57 @@ + " . PHP_EOL; + exit(1); +} + +if(str_contains($broadcastAddress, ".")){ + $bindAddress = new InternetAddress("0.0.0.0", 0, 4); +}else{ + $bindAddress = new InternetAddress("::", 0, 6); +} + +$socket = new ServerSocket($bindAddress); +$clientId = mt_rand(0, Limits::INT32_MAX); +\GlobalLogger::get()->info("Listening on " . $bindAddress); +\GlobalLogger::get()->info("Press CTRL+C to stop"); + +function sendPing(ServerSocket $socket, string $broadcastAddress, int $port, int $clientId) : void{ + $ping = new UnconnectedPing(); + $ping->clientId = $clientId; + $ping->sendPingTime = intdiv(hrtime(true), 1_000_000); + + $serializer = new PacketSerializer(); + $ping->encode($serializer); + $socket->writePacket($serializer->getBuffer(), $broadcastAddress, $port); +} +sendPing($socket, $broadcastAddress, $port, $clientId); + +socket_set_option($socket->getSocket(), SOL_SOCKET, SO_RCVTIMEO, ["sec" => 1, "usec" => 0]); +while(true){ //@phpstan-ignore-line + try{ + $pong = $socket->readPacket($serverIp, $serverPort); + if($pong !== null && ord($pong[0]) === MessageIdentifiers::ID_UNCONNECTED_PONG){ + \GlobalLogger::get()->info("Pong received from $serverIp:$serverPort: " . $pong); + } + }catch(SocketException $e){ + if($e->getCode() === SOCKET_ETIMEDOUT){ + sendPing($socket, $broadcastAddress, $port, $clientId); + } + } +} \ No newline at end of file From 086b5f7afd94e90ce888f15bcd921d2c162cbc22 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 19 Jan 2023 15:40:19 +0000 Subject: [PATCH 13/16] ServerSocket: added methods to enable and disable SO_BROADCAST --- src/server/ServerSocket.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/server/ServerSocket.php b/src/server/ServerSocket.php index f83fdbe..dadb07c 100644 --- a/src/server/ServerSocket.php +++ b/src/server/ServerSocket.php @@ -49,6 +49,14 @@ public function getBindAddress() : InternetAddress{ return $this->bindAddress; } + public function enableBroadcast() : bool{ + return socket_set_option($this->socket, SOL_SOCKET, SO_BROADCAST, 1); + } + + public function disableBroadcast() : bool{ + return socket_set_option($this->socket, SOL_SOCKET, SO_BROADCAST, 0); + } + /** * @param string $source reference parameter * @param int $port reference parameter From 5e80b8915a95769228f8b38526d60d2e361fff2f Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 19 Jan 2023 15:41:00 +0000 Subject: [PATCH 14/16] tools/scan.php: enable broadcasting for some reason this just magically works on Windows, but probably won't on Linux. --- tools/scan.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/scan.php b/tools/scan.php index f9f3f3c..1f3a6f0 100644 --- a/tools/scan.php +++ b/tools/scan.php @@ -27,6 +27,7 @@ } $socket = new ServerSocket($bindAddress); +$socket->enableBroadcast(); $clientId = mt_rand(0, Limits::INT32_MAX); \GlobalLogger::get()->info("Listening on " . $bindAddress); \GlobalLogger::get()->info("Press CTRL+C to stop"); From dab90c57c605c8d90a57076156ac153e34d2f186 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 13 Feb 2023 12:16:48 +0000 Subject: [PATCH 15/16] =?UTF-8?q?Fix=20CS=C3=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RakLib.php | 4 +--- src/generic/DisconnectReason.php | 36 +++++++++++++++++++++++++++++ src/generic/Session.php | 29 +++++++++++++++++------ src/server/Server.php | 7 +++--- src/server/ServerEventListener.php | 10 +++++++- src/server/ServerSession.php | 2 +- src/server/ServerSocket.php | 1 + src/utils/ExceptionTraceCleaner.php | 1 + 8 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 src/generic/DisconnectReason.php diff --git a/src/RakLib.php b/src/RakLib.php index fc609fb..fce15cb 100644 --- a/src/RakLib.php +++ b/src/RakLib.php @@ -23,8 +23,6 @@ abstract class RakLib{ */ public const DEFAULT_PROTOCOL_VERSION = 6; - /** - * Regular RakNet uses 10 by default. MCPE uses 20. Configure this value as appropriate. - */ + /** Regular RakNet uses 10 by default. MCPE uses 20. Configure this value as appropriate. */ public static int $SYSTEM_ADDRESS_COUNT = 20; } diff --git a/src/generic/DisconnectReason.php b/src/generic/DisconnectReason.php new file mode 100644 index 0000000..d03c3b5 --- /dev/null +++ b/src/generic/DisconnectReason.php @@ -0,0 +1,36 @@ + + * + * RakLib is not affiliated with Jenkins Software LLC nor RakNet. + * + * RakLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + */ + +declare(strict_types=1); + +namespace raklib\generic; + +final class DisconnectReason{ + public const CLIENT_DISCONNECT = 0; + public const SERVER_DISCONNECT = 1; + public const PEER_TIMEOUT = 2; + public const CLIENT_RECONNECT = 3; + public const SERVER_SHUTDOWN = 4; //TODO: do we really need a separate reason for this in addition to SERVER_DISCONNECT? + + public static function toString(int $reason) : string{ + return match($reason){ + self::CLIENT_DISCONNECT => "client disconnect", + self::SERVER_DISCONNECT => "server disconnect", + self::PEER_TIMEOUT => "timeout", + self::CLIENT_RECONNECT => "new session established on same address and port", + self::SERVER_SHUTDOWN => "server shutdown", + default => "Unknown reason $reason" + }; + } +} diff --git a/src/generic/Session.php b/src/generic/Session.php index ba7334a..fc92e8e 100644 --- a/src/generic/Session.php +++ b/src/generic/Session.php @@ -112,8 +112,13 @@ abstract protected function onPacketAck(int $identifierACK) : void; /** * Called when the session is terminated for any reason. + * + * @param int $reason one of the DisconnectReason::* constants + * @phpstan-param DisconnectReason::* $reason + * + * @see DisconnectReason */ - abstract protected function onDisconnect(string $reason) : void; + abstract protected function onDisconnect(int $reason) : void; /** * Called when a packet is received while the session is in the "connecting" state. This should only handle RakNet @@ -166,7 +171,7 @@ public function isConnected() : bool{ public function update(float $time) : void{ if(!$this->isActive and ($this->lastUpdate + 10) < $time){ - $this->forciblyDisconnect("timeout"); + $this->forciblyDisconnect(DisconnectReason::PEER_TIMEOUT); return; } @@ -276,23 +281,33 @@ public function handlePacket(Packet $packet) : void{ /** * Initiates a graceful asynchronous disconnect which ensures both parties got all packets. + * + * @param int $reason one of the DisconnectReason constants + * @phpstan-param DisconnectReason::* $reason + * + * @see DisconnectReason */ - public function initiateDisconnect(string $reason) : void{ + public function initiateDisconnect(int $reason) : void{ if($this->isConnected()){ $this->state = self::STATE_DISCONNECT_PENDING; $this->disconnectionTime = microtime(true); $this->onDisconnect($reason); - $this->logger->debug("Requesting graceful disconnect because \"$reason\""); + $this->logger->debug("Requesting graceful disconnect because \"" . DisconnectReason::toString($reason) . "\""); } } /** * Disconnects the session with immediate effect, regardless of current session state. Usually used in timeout cases. + * + * @param int $reason one of the DisconnectReason constants + * @phpstan-param DisconnectReason::* $reason + * + * @see DisconnectReason */ - public function forciblyDisconnect(string $reason) : void{ + public function forciblyDisconnect(int $reason) : void{ $this->state = self::STATE_DISCONNECTED; $this->onDisconnect($reason); - $this->logger->debug("Forcibly disconnecting session due to \"$reason\""); + $this->logger->debug("Forcibly disconnecting session due to " . DisconnectReason::toString($reason)); } private function handleRemoteDisconnect() : void{ @@ -303,7 +318,7 @@ private function handleRemoteDisconnect() : void{ if($this->isConnected()){ //the client might have disconnected after the server sent a disconnect notification, but before the client //received it - in this case, we don't want to notify the event handler twice - $this->onDisconnect("client disconnect"); + $this->onDisconnect(DisconnectReason::CLIENT_DISCONNECT); } $this->state = self::STATE_DISCONNECTED; $this->logger->debug("Terminating session due to client disconnect"); diff --git a/src/server/Server.php b/src/server/Server.php index 471f434..95eb9fd 100644 --- a/src/server/Server.php +++ b/src/server/Server.php @@ -17,6 +17,7 @@ namespace raklib\server; use pocketmine\utils\BinaryDataException; +use raklib\generic\DisconnectReason; use raklib\generic\Session; use raklib\generic\SocketException; use raklib\protocol\ACK; @@ -145,7 +146,7 @@ public function waitShutdown() : void{ } foreach($this->sessions as $session){ - $session->initiateDisconnect("server shutdown"); + $session->initiateDisconnect(DisconnectReason::SERVER_SHUTDOWN); } while(count($this->sessions) > 0){ @@ -316,7 +317,7 @@ public function sendRaw(string $address, int $port, string $payload) : void{ public function closeSession(int $sessionId) : void{ if(isset($this->sessions[$sessionId])){ - $this->sessions[$sessionId]->initiateDisconnect("server disconnect"); + $this->sessions[$sessionId]->initiateDisconnect(DisconnectReason::SERVER_DISCONNECT); } } @@ -366,7 +367,7 @@ public function sessionExists(InternetAddress $address) : bool{ public function createSession(InternetAddress $address, int $clientId, int $mtuSize) : ServerSession{ $existingSession = $this->sessionsByAddress[$address->toString()] ?? null; if($existingSession !== null){ - $existingSession->forciblyDisconnect("client reconnect"); + $existingSession->forciblyDisconnect(DisconnectReason::CLIENT_RECONNECT); $this->removeSessionInternal($existingSession); } diff --git a/src/server/ServerEventListener.php b/src/server/ServerEventListener.php index d36cc78..9e2d4d4 100644 --- a/src/server/ServerEventListener.php +++ b/src/server/ServerEventListener.php @@ -16,11 +16,19 @@ namespace raklib\server; +use raklib\generic\DisconnectReason; + interface ServerEventListener{ public function onClientConnect(int $sessionId, string $address, int $port, int $clientID) : void; - public function onClientDisconnect(int $sessionId, string $reason) : void; + /** + * @param int $reason one of the DisconnectReason constants + * @phpstan-param DisconnectReason::* $reason + * + * @see DisconnectReason + */ + public function onClientDisconnect(int $sessionId, int $reason) : void; public function onPacketReceive(int $sessionId, string $packet) : void; diff --git a/src/server/ServerSession.php b/src/server/ServerSession.php index 499697b..1c7df86 100644 --- a/src/server/ServerSession.php +++ b/src/server/ServerSession.php @@ -52,7 +52,7 @@ protected function onPacketAck(int $identifierACK) : void{ $this->server->getEventListener()->onPacketAck($this->internalId, $identifierACK); } - protected function onDisconnect(string $reason) : void{ + protected function onDisconnect(int $reason) : void{ $this->server->getEventListener()->onClientDisconnect($this->internalId, $reason); } diff --git a/src/server/ServerSocket.php b/src/server/ServerSocket.php index dadb07c..0cd7852 100644 --- a/src/server/ServerSocket.php +++ b/src/server/ServerSocket.php @@ -23,6 +23,7 @@ use function socket_last_error; use function socket_recvfrom; use function socket_sendto; +use function socket_set_option; use function socket_strerror; use function strlen; use function trim; diff --git a/src/utils/ExceptionTraceCleaner.php b/src/utils/ExceptionTraceCleaner.php index fdac4a4..8e71b3a 100644 --- a/src/utils/ExceptionTraceCleaner.php +++ b/src/utils/ExceptionTraceCleaner.php @@ -17,6 +17,7 @@ namespace raklib\utils; use function array_reverse; +use function count; use function function_exists; use function get_class; use function gettype; From 0742715fd5e52caeea3497d5ede4c1876ba3c471 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 13 Feb 2023 12:29:37 +0000 Subject: [PATCH 16/16] Fixed weird bitmask check, closes #44 I wasn't able to find any other remaining occurrences of this. Looks like they've all long since been removed. --- src/protocol/EncapsulatedPacket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/EncapsulatedPacket.php b/src/protocol/EncapsulatedPacket.php index 10e4225..f9bfc85 100644 --- a/src/protocol/EncapsulatedPacket.php +++ b/src/protocol/EncapsulatedPacket.php @@ -46,7 +46,7 @@ public static function fromBinary(BinaryStream $stream) : EncapsulatedPacket{ $flags = $stream->getByte(); $packet->reliability = $reliability = ($flags & self::RELIABILITY_FLAGS) >> self::RELIABILITY_SHIFT; - $hasSplit = ($flags & self::SPLIT_FLAG) > 0; + $hasSplit = ($flags & self::SPLIT_FLAG) !== 0; $length = (int) ceil($stream->getShort() / 8); if($length === 0){