public function __construct($stream, LoopInterface $loop) { parent::__construct($stream, $loop); $this->lastPacket = $this->currentTime(); $this->connectionTimer = $loop->addPeriodicTimer(1, function () { $currentTime = $this->currentTime(); if ($currentTime - $this->lastPacket > 10000) { $this->disconnectClient((new DisconnectPacket())->setReason('Connection timed out')); } }); //default stage is handshake $this->stage = Stage::HANDSHAKE(); //setup the default stage=>packetID=>class map TODO allow passing values in in constructor $this->packetClassMap = [STAGE::HANDSHAKE()->getValue() => [0x0 => 'PublicUHC\\MinecraftAuth\\Protocol\\Packets\\HandshakePacket'], STAGE::STATUS()->getValue() => [0x0 => 'PublicUHC\\MinecraftAuth\\Protocol\\Packets\\StatusRequestPacket', 0x1 => 'PublicUHC\\MinecraftAuth\\Protocol\\Packets\\PingRequestPacket'], STAGE::LOGIN()->getValue() => [0x0 => 'PublicUHC\\MinecraftAuth\\Protocol\\Packets\\LoginStartPacket', 0x1 => 'PublicUHC\\MinecraftAuth\\Protocol\\Packets\\EncryptionResponsePacket']]; //call $this->onData whenever there is data available $this->on('data', [$this, 'onData']); }
/** * Get the stage this packet is for * @return Stage */ public function getStage() { return Stage::STATUS(); }
/** * Parse the raw data * @param $data String the raw data to parse (minus packet ID and packet length * @throws InvalidDataException */ function fromRawData($data) { $versionVarInt = VarInt::readUnsignedVarInt($data); $data = substr($data, $versionVarInt->getDataLength()); $addressStringLength = VarInt::readUnsignedVarInt($data); $data = substr($data, $addressStringLength->getDataLength()); $address = substr($data, 0, $addressStringLength->getValue()); $data = substr($data, $addressStringLength->getValue()); $portShort = unpack('nshort', substr($data, 0, 2))['short']; $data = substr($data, 2); $nextVarInt = VarInt::readUnsignedVarInt($data); try { $nextStage = Stage::get($nextVarInt->getValue()); //disconnect if not a valid stage if ($nextStage != Stage::LOGIN() && $nextStage != Stage::STATUS()) { throw new InvalidDataException('Stage must be LOGIN or STATUS on handshake'); } //set all of the data $this->setNextStage($nextStage)->setServerPort($portShort)->setProtocolVersion($versionVarInt->getValue())->setServerAddress($address); } catch (InvalidArgumentException $ex) { throw new InvalidDataException('Stage is not a valid number'); } }