Moved batch packet handling into BatchPacket->handle(), fixed data packet receive timings to include MCPE packet decode time

This commit is contained in:
Dylan K. Taylor 2017-03-20 10:20:54 +00:00
parent 9c350dbe47
commit 6ba4a8fe5c
5 changed files with 42 additions and 64 deletions

View File

@ -112,7 +112,6 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\ChangeDimensionPacket; use pocketmine\network\mcpe\protocol\ChangeDimensionPacket;
@ -1959,11 +1958,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return false; return false;
} }
public function handleBatch(BatchPacket $packet) : bool{
$this->server->getNetwork()->processBatch($packet, $this);
return true;
}
public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool{ public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool{
return false; return false;
} }
@ -3303,6 +3297,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$timings = Timings::getReceiveDataPacketTimings($packet); $timings = Timings::getReceiveDataPacketTimings($packet);
$timings->startTiming(); $timings->startTiming();
$packet->decode();
assert($packet->feof(), "Still " . strlen(substr($packet->buffer, $packet->offset)) . " bytes unread in " . get_class($packet));
$this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet)); $this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet));
if(!$ev->isCancelled() and !$packet->handle($this)){ if(!$ev->isCancelled() and !$packet->handle($this)){
$this->server->getLogger()->debug("Unhandled " . get_class($packet) . " received from " . $this->getName()); $this->server->getLogger()->debug("Unhandled " . get_class($packet) . " received from " . $this->getName());

View File

@ -55,16 +55,15 @@ use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\ExplodePacket; use pocketmine\network\mcpe\protocol\ExplodePacket;
use pocketmine\network\mcpe\protocol\FullChunkDataPacket; use pocketmine\network\mcpe\protocol\FullChunkDataPacket;
use pocketmine\network\mcpe\protocol\HurtArmorPacket; use pocketmine\network\mcpe\protocol\HurtArmorPacket;
use pocketmine\network\mcpe\protocol\MapInfoRequestPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\InteractPacket; use pocketmine\network\mcpe\protocol\InteractPacket;
use pocketmine\network\mcpe\protocol\InventoryActionPacket; use pocketmine\network\mcpe\protocol\InventoryActionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\LoginPacket; use pocketmine\network\mcpe\protocol\LoginPacket;
use pocketmine\network\mcpe\protocol\MobEquipmentPacket; use pocketmine\network\mcpe\protocol\MapInfoRequestPacket;
use pocketmine\network\mcpe\protocol\MobArmorEquipmentPacket; use pocketmine\network\mcpe\protocol\MobArmorEquipmentPacket;
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\MoveEntityPacket; use pocketmine\network\mcpe\protocol\MoveEntityPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\PlayerActionPacket; use pocketmine\network\mcpe\protocol\PlayerActionPacket;
@ -72,6 +71,7 @@ use pocketmine\network\mcpe\protocol\PlayerFallPacket;
use pocketmine\network\mcpe\protocol\PlayerInputPacket; use pocketmine\network\mcpe\protocol\PlayerInputPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\PlayStatusPacket; use pocketmine\network\mcpe\protocol\PlayStatusPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\RemoveBlockPacket; use pocketmine\network\mcpe\protocol\RemoveBlockPacket;
use pocketmine\network\mcpe\protocol\RemoveEntityPacket; use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
use pocketmine\network\mcpe\protocol\ReplaceItemInSlotPacket; use pocketmine\network\mcpe\protocol\ReplaceItemInSlotPacket;
@ -103,9 +103,7 @@ use pocketmine\network\mcpe\protocol\UnknownPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateTradePacket; use pocketmine\network\mcpe\protocol\UpdateTradePacket;
use pocketmine\network\mcpe\protocol\UseItemPacket; use pocketmine\network\mcpe\protocol\UseItemPacket;
use pocketmine\Player;
use pocketmine\Server; use pocketmine\Server;
use pocketmine\utils\BinaryStream;
class Network{ class Network{
@ -232,50 +230,6 @@ class Network{
return $this->server; return $this->server;
} }
/**
* Decodes a batch packet and does handling for it.
*
* TODO: Move this out of here
*
* @param BatchPacket $packet
* @param Player $player
*
* @throws \InvalidArgumentException|\InvalidStateException
*/
public function processBatch(BatchPacket $packet, Player $p){
$rawLen = strlen($packet->payload);
if($rawLen === 0){
throw new \InvalidArgumentException("BatchPacket payload is empty or packet decode error");
}elseif($rawLen < 3){
throw new \InvalidArgumentException("Not enough bytes, expected zlib header");
}
$str = zlib_decode($packet->payload, 1024 * 1024 * 64); //Max 64MB
$len = strlen($str);
if($len === 0){
throw new \InvalidStateException("Decoded BatchPacket payload is empty");
}
$stream = new BinaryStream($str);
while($stream->offset < $len){
$buf = $stream->getString();
if(($pk = $this->getPacket(ord($buf{0}))) !== null){
if(!$pk->canBeBatched()){
throw new \InvalidStateException("Received invalid " . get_class($pk) . " inside BatchPacket");
}
$pk->setBuffer($buf, 1);
$pk->decode();
assert($pk->feof(), "Still " . strlen(substr($pk->buffer, $pk->offset)) . " bytes unread in " . get_class($pk));
$p->handleDataPacket($pk);
}
}
}
/** /**
* @param $id * @param $id
* *

View File

@ -32,7 +32,6 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\ChangeDimensionPacket; use pocketmine\network\mcpe\protocol\ChangeDimensionPacket;
@ -47,6 +46,7 @@ use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
use pocketmine\network\mcpe\protocol\ContainerSetSlotPacket; use pocketmine\network\mcpe\protocol\ContainerSetSlotPacket;
use pocketmine\network\mcpe\protocol\CraftingDataPacket; use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\network\mcpe\protocol\CraftingEventPacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket; use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\DropItemPacket; use pocketmine\network\mcpe\protocol\DropItemPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\EntityEventPacket;
@ -103,9 +103,17 @@ use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateTradePacket; use pocketmine\network\mcpe\protocol\UpdateTradePacket;
use pocketmine\network\mcpe\protocol\UseItemPacket; use pocketmine\network\mcpe\protocol\UseItemPacket;
use pocketmine\Server;
interface NetworkSession{ interface NetworkSession{
/**
* @return Server
*/
public function getServer();
public function handleDataPacket(DataPacket $pk);
public function handleLogin(LoginPacket $packet) : bool; public function handleLogin(LoginPacket $packet) : bool;
public function handlePlayStatus(PlayStatusPacket $packet) : bool; public function handlePlayStatus(PlayStatusPacket $packet) : bool;
@ -116,8 +124,6 @@ interface NetworkSession{
public function handleDisconnect(DisconnectPacket $packet) : bool; public function handleDisconnect(DisconnectPacket $packet) : bool;
public function handleBatch(BatchPacket $packet) : bool;
public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool; public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool;
public function handleResourcePackStack(ResourcePackStackPacket $packet) : bool; public function handleResourcePackStack(ResourcePackStackPacket $packet) : bool;

View File

@ -132,12 +132,8 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{
try{ try{
if($packet->buffer !== ""){ if($packet->buffer !== ""){
$pk = $this->getPacket($packet->buffer); $pk = $this->getPacket($packet->buffer);
if($pk !== null){
$pk->decode();
assert($pk->feof(), "Still " . strlen(substr($pk->buffer, $pk->offset)) . " bytes unread!");
$this->players[$identifier]->handleDataPacket($pk); $this->players[$identifier]->handleDataPacket($pk);
} }
}
}catch(\Throwable $e){ }catch(\Throwable $e){
if(\pocketmine\DEBUG > 1 and isset($pk)){ if(\pocketmine\DEBUG > 1 and isset($pk)){
$logger = $this->server->getLogger(); $logger = $this->server->getLogger();

View File

@ -45,7 +45,32 @@ class BatchPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ public function handle(NetworkSession $session) : bool{
return $session->handleBatch($this); if(strlen($this->payload) < 2){
throw new \InvalidStateException("Not enough bytes in payload, expected zlib header");
}
$str = zlib_decode($this->payload, 1024 * 1024 * 64); //Max 64MB
$len = strlen($str);
if($len === 0){
throw new \InvalidStateException("Decoded BatchPacket payload is empty");
}
$this->setBuffer($str, 0);
$network = $session->getServer()->getNetwork();
while(!$this->feof()){
$buf = $this->getString();
$pk = $network->getPacket(ord($buf{0}));
if(!$pk->canBeBatched()){
throw new \InvalidArgumentException("Received invalid " . get_class($pk) . " inside BatchPacket");
}
$pk->setBuffer($buf, 1);
$session->handleDataPacket($pk);
}
return true;
} }
} }