From 6990d6239eca9c83c08763d5494307db24777e51 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 24 Mar 2019 18:02:19 +0000 Subject: [PATCH] Network: Added RawPacketHandler interface, query handler is now a component --- src/pocketmine/Server.php | 25 +-------- src/pocketmine/network/Network.php | 55 ++++++++++++++++++- src/pocketmine/network/RawPacketHandler.php | 46 ++++++++++++++++ .../network/mcpe/RakLibInterface.php | 2 +- src/pocketmine/network/query/QueryHandler.php | 8 ++- 5 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 src/pocketmine/network/RawPacketHandler.php diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index f0a9af271..6f33abae0 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -62,7 +62,6 @@ use pocketmine\nbt\BigEndianNbtSerializer; use pocketmine\nbt\NbtDataException; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\TreeRoot; -use pocketmine\network\AdvancedNetworkInterface; use pocketmine\network\mcpe\CompressBatchPromise; use pocketmine\network\mcpe\CompressBatchTask; use pocketmine\network\mcpe\NetworkCipher; @@ -106,7 +105,6 @@ use function array_key_exists; use function array_shift; use function array_sum; use function base64_encode; -use function bin2hex; use function copy; use function count; use function define; @@ -280,9 +278,6 @@ class Server{ /** @var string[] */ private $uniquePlayers = []; - /** @var QueryHandler */ - private $queryHandler; - /** @var QueryRegenerateEvent */ private $queryRegenerateTask = null; @@ -1201,7 +1196,7 @@ class Server{ $this->getLogger()->debug("Server unique id: " . $this->getServerUniqueId()); $this->getLogger()->debug("Machine unique id: " . Utils::getMachineUniqueId()); - $this->network = new Network(); + $this->network = new Network($this->logger); $this->network->setName($this->getMotd()); @@ -1327,7 +1322,7 @@ class Server{ $this->enablePlugins(PluginLoadOrder::POSTWORLD); if($this->getConfigBool("enable-query", true)){ - $this->queryHandler = new QueryHandler(); + $this->network->registerRawPacketHandler(new QueryHandler()); } foreach($this->getIPBans()->getEntries() as $entry){ @@ -1953,22 +1948,6 @@ class Server{ Timings::$titleTickTimer->stopTiming(); } - /** - * @param AdvancedNetworkInterface $interface - * @param string $address - * @param int $port - * @param string $payload - * - * TODO: move this to Network - */ - public function handlePacket(AdvancedNetworkInterface $interface, string $address, int $port, string $payload) : void{ - if($this->queryHandler === null or !$this->queryHandler->handle($interface, $address, $port, $payload)){ - $this->logger->debug("Unhandled raw packet from $address $port: " . bin2hex($payload)); - } - //TODO: add raw packet events - } - - /** * Tries to execute a server tick */ diff --git a/src/pocketmine/network/Network.php b/src/pocketmine/network/Network.php index 552423263..529a689f1 100644 --- a/src/pocketmine/network/Network.php +++ b/src/pocketmine/network/Network.php @@ -29,7 +29,9 @@ namespace pocketmine\network; use pocketmine\event\server\NetworkInterfaceRegisterEvent; use pocketmine\event\server\NetworkInterfaceUnregisterEvent; use pocketmine\network\mcpe\protocol\PacketPool; +use function bin2hex; use function get_class; +use function preg_match; use function spl_object_id; class Network{ @@ -39,6 +41,9 @@ class Network{ /** @var AdvancedNetworkInterface[] */ private $advancedInterfaces = []; + /** @var RawPacketHandler[] */ + private $rawPacketHandlers = []; + private $upload = 0; private $download = 0; @@ -48,9 +53,13 @@ class Network{ /** @var NetworkSessionManager */ private $sessionManager; - public function __construct(){ + /** @var \Logger */ + private $logger; + + public function __construct(\Logger $logger){ PacketPool::init(); $this->sessionManager = new NetworkSessionManager(); + $this->logger = $logger; } public function addStatistics(float $upload, float $download) : void{ @@ -181,9 +190,51 @@ class Network{ } } - public function addRawPacketFilter(string $regex) : void{ + /** + * Registers a raw packet handler on the network. + * + * @param RawPacketHandler $handler + */ + public function registerRawPacketHandler(RawPacketHandler $handler) : void{ + $this->rawPacketHandlers[spl_object_id($handler)] = $handler; + + $regex = $handler->getPattern(); foreach($this->advancedInterfaces as $interface){ $interface->addRawPacketFilter($regex); } } + + /** + * Unregisters a previously-registered raw packet handler. + * + * @param RawPacketHandler $handler + */ + public function unregisterRawPacketHandler(RawPacketHandler $handler) : void{ + unset($this->rawPacketHandlers[spl_object_id($handler)]); + } + + /** + * @param AdvancedNetworkInterface $interface + * @param string $address + * @param int $port + * @param string $packet + */ + public function processRawPacket(AdvancedNetworkInterface $interface, string $address, int $port, string $packet) : void{ + $handled = false; + foreach($this->rawPacketHandlers as $handler){ + if(preg_match($handler->getPattern(), $packet) === 1){ + $handled = true; + try{ + $handler->handle($interface, $address, $port, $packet); + }catch(BadPacketException $e){ + $this->logger->error("Bad raw packet from /$address:$port: " . $e->getMessage()); + $this->blockAddress($address, 600); + break; + } + } + } + if(!$handled){ + $this->logger->debug("Unhandled raw packet from /$address:$port: " . bin2hex($packet)); + } + } } diff --git a/src/pocketmine/network/RawPacketHandler.php b/src/pocketmine/network/RawPacketHandler.php new file mode 100644 index 000000000..e73d1f30e --- /dev/null +++ b/src/pocketmine/network/RawPacketHandler.php @@ -0,0 +1,46 @@ +server->handlePacket($this, $address, $port, $payload); + $this->network->processRawPacket($this, $address, $port, $payload); } public function sendRawPacket(string $address, int $port, string $payload) : void{ diff --git a/src/pocketmine/network/query/QueryHandler.php b/src/pocketmine/network/query/QueryHandler.php index 9092e1546..7722c709e 100644 --- a/src/pocketmine/network/query/QueryHandler.php +++ b/src/pocketmine/network/query/QueryHandler.php @@ -28,6 +28,7 @@ declare(strict_types=1); namespace pocketmine\network\query; use pocketmine\network\AdvancedNetworkInterface; +use pocketmine\network\RawPacketHandler; use pocketmine\Server; use pocketmine\utils\Binary; use pocketmine\utils\BinaryDataException; @@ -38,7 +39,7 @@ use function random_bytes; use function strlen; use function substr; -class QueryHandler{ +class QueryHandler implements RawPacketHandler{ /** @var Server */ private $server; /** @var string */ @@ -51,7 +52,6 @@ class QueryHandler{ public function __construct(){ $this->server = Server::getInstance(); - $this->server->getNetwork()->addRawPacketFilter('/^\xfe\xfd.+$/s'); $this->server->getLogger()->info($this->server->getLanguage()->translateString("pocketmine.server.query.start")); $addr = $this->server->getIp(); $port = $this->server->getPort(); @@ -70,6 +70,10 @@ class QueryHandler{ $this->server->getLogger()->info($this->server->getLanguage()->translateString("pocketmine.server.query.running", [$addr, $port])); } + public function getPattern() : string{ + return '/^\xfe\xfd.+$/s'; + } + private function debug(string $message) : void{ //TODO: replace this with a proper prefixed logger $this->server->getLogger()->debug("[Query] $message");