public function decode() { parent::decode(); $this->clientID = Binary::readLong($this->get(8)); $this->session = Binary::readLong($this->get(8)); $this->unknown = $this->get(1); }
public function decode() { parent::decode(); $this->clientID = Binary::readLong($this->get(8)); $this->sendPing = Binary::readLong($this->get(8)); $this->useSecurity = \ord($this->get(1)) > 0; }
public function decode() { parent::decode(); $this->pingID = Binary::readLong($this->get(8)); $this->serverID = Binary::readLong($this->get(8)); $this->offset += 16; //magic $this->serverName = $this->getString(); }
public function decode() { parent::decode(); $this->offset += 16; //Magic $this->getAddress($this->serverAddress, $this->serverPort); $this->mtuSize = \unpack("n", $this->get(2))[1]; $this->clientID = Binary::readLong($this->get(8)); }
public function decode() { parent::decode(); $this->offset += 16; //Magic $this->serverID = Binary::readLong($this->get(8)); $this->clientPort = unpack("n", $this->get(2))[1]; $this->mtuSize = unpack("n", $this->get(2))[1]; //server security }
public function decode() { parent::decode(); $this->offset += 16; //Magic $this->serverID = Binary::readLong($this->get(8)); \ord($this->get(1)); //security $this->mtuSize = \unpack("n", $this->get(2))[1]; }
public function encode() { parent::encode(); $this->putAddress($this->address, $this->port, 4); $this->buffer .= pack("n", 0); for ($i = 0; $i < 10; ++$i) { $this->putAddress($this->systemAddresses[$i][0], $this->systemAddresses[$i][1], $this->systemAddresses[$i][2]); } $this->buffer .= Binary::writeLong($this->sendPing); $this->buffer .= Binary::writeLong($this->sendPong); }
public function decode() { parent::decode(); $this->getAddress($this->address, $this->port); for ($i = 0; $i < 10; ++$i) { $this->getAddress($addr, $port, $version); $this->systemAddresses[$i] = [$addr, $port, $version]; } $this->sendPing = Binary::readLong($this->get(8)); $this->sendPong = Binary::readLong($this->get(8)); }
public function decode() { parent::decode(); $this->cookie = $this->get(4); $this->security = $this->get(1); $this->port = unpack("n", $this->get(2))[1]; $this->dataArray0 = $this->get(ord($this->get(1))); $this->dataArray = $this->getDataArray(9); $this->timestamp = $this->get(2); $this->session2 = Binary::readLong($this->get(8)); $this->session = Binary::readLong($this->get(8)); }
public function encode() { parent::encode(); $this->buffer .= "?Wþ"; //cookie $this->buffer .= "Í"; //security flags $this->buffer .= pack("n", $this->port); $this->putDataArray(["õÿÿõ", "ÿÿÿÿ", "ÿÿÿÿ", "ÿÿÿÿ", "ÿÿÿÿ", "ÿÿÿÿ", "ÿÿÿÿ", "ÿÿÿÿ", "ÿÿÿÿ", "ÿÿÿÿ"]); $this->buffer .= ""; $this->buffer .= Binary::writeLong($this->session); $this->buffer .= Binary::writeLong($this->session2); }
public function encode() { parent::encode(); $payload = ""; sort($this->packets, SORT_NUMERIC); $count = count($this->packets); $records = 0; if ($count > 0) { $pointer = 1; $start = $this->packets[0]; $last = $this->packets[0]; while ($pointer < $count) { $current = $this->packets[$pointer++]; $diff = $current - $last; if ($diff === 1) { $last = $current; } elseif ($diff > 1) { //Forget about duplicated packets (bad queues?) if ($start === $last) { $payload .= ""; $payload .= Binary::writeLTriad($start); $start = $last = $current; } else { $payload .= ""; $payload .= Binary::writeLTriad($start); $payload .= Binary::writeLTriad($last); $start = $last = $current; } ++$records; } } if ($start === $last) { $payload .= ""; $payload .= Binary::writeLTriad($start); } else { $payload .= ""; $payload .= Binary::writeLTriad($start); $payload .= Binary::writeLTriad($last); } ++$records; } $this->putShort($records); $this->buffer .= $payload; }
/** * @param $chunkX * @param $chunkZ * @param $payload * * @return DataPacket */ public static function getChunkCacheFromData($chunkX, $chunkZ, $payload, $ordering = FullChunkDataPacket::ORDER_COLUMNS) { $pk = new FullChunkDataPacket(); $pk->chunkX = $chunkX; $pk->chunkZ = $chunkZ; $pk->order = $ordering; $pk->data = $payload; $pk->encode(); $batch = new BatchPacket(); $batch->payload = zlib_encode(Binary::writeInt(strlen($pk->getBuffer())) . $pk->getBuffer(), ZLIB_ENCODING_DEFLATE, Server::getInstance()->networkCompressionLevel); $batch->encode(); $batch->isEncoded = true; return $batch; }
/** * @param bool $internal * * @return string */ public function toBinary($internal = false) { $binary = chr($this->reliability << 5 | ($this->hasSplit ? 0b10000 : 0)); if ($internal) { $binary .= Binary::writeInt(strlen($this->buffer)); $binary .= Binary::writeInt($this->identifierACK); } else { $binary .= Binary::writeShort(strlen($this->buffer) << 3); } if ($this->reliability === 2 or $this->reliability === 3 or $this->reliability === 4 or $this->reliability === 6 or $this->reliability === 7) { $binary .= Binary::writeLTriad($this->messageIndex); } if ($this->reliability === 1 or $this->reliability === 3 or $this->reliability === 4 or $this->reliability === 7) { $binary .= Binary::writeLTriad($this->orderIndex) . chr($this->orderChannel); } if ($this->hasSplit) { $binary .= Binary::writeInt($this->splitCount) . Binary::writeShort($this->splitID) . Binary::writeInt($this->splitIndex); } return $binary . $this->buffer; }
protected function streamOpen(Session $session) { $identifier = $session->getAddress() . ":" . $session->getPort(); $buffer = \chr(RakLib::PACKET_OPEN_SESSION) . \chr(\strlen($identifier)) . $identifier . \chr(\strlen($session->getAddress())) . $session->getAddress() . \pack("n", $session->getPort()) . Binary::writeLong($session->getID()); $this->server->pushThreadToMainPacket($buffer); }
public function saveChunkToDisk($x, $z, $payload, $ordering = FullChunkDataPacket::ORDER_COLUMNS) { /** @var Player $player */ if (file_exists("chunk_cache/" . $this->getName() . "/" . $x . "_" . $z . ".dat")) { $this->loadChunkFromDisk($x, $z); return true; } $pk = new FullChunkDataPacket(); $pk->chunkX = $x; $pk->chunkZ = $z; $pk->order = $ordering; $pk->data = $payload; $pk->encode(); $data = zlib_encode(Binary::writeInt(strlen($pk->buffer)) . $pk->buffer, ZLIB_ENCODING_DEFLATE, 6); $this->chunkCache[$x . ":" . $z] = $data; if (!$this->server->getKatana()->getProperty("cache.save-to-disk", true)) { return true; } file_put_contents("chunk_cache/" . $this->getName() . "/" . $x . "_" . $z . ".dat", $data); return true; }
public function receiveStream() { if (strlen($packet = $this->server->readMainToThreadPacket()) > 0) { $id = ord($packet[0]); $offset = 1; if ($id === RakLib::PACKET_ENCAPSULATED) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; if (isset($this->sessions[$identifier])) { $flags = ord($packet[$offset++]); $buffer = substr($packet, $offset); $this->sessions[$identifier]->addEncapsulatedToQueue(EncapsulatedPacket::fromBinary($buffer, true), $flags); } else { $this->streamInvalid($identifier); } } elseif ($id === RakLib::PACKET_RAW) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $port = Binary::readShort(substr($packet, $offset, 2)); $offset += 2; $payload = substr($packet, $offset); $this->socket->writePacket($payload, $address, $port); } elseif ($id === RakLib::PACKET_CLOSE_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); if (isset($this->sessions[$identifier])) { $this->removeSession($this->sessions[$identifier]); } else { $this->streamInvalid($identifier); } } elseif ($id === RakLib::PACKET_INVALID_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); if (isset($this->sessions[$identifier])) { $this->removeSession($this->sessions[$identifier]); } } elseif ($id === RakLib::PACKET_SET_OPTION) { $len = ord($packet[$offset++]); $name = substr($packet, $offset, $len); $offset += $len; $value = substr($packet, $offset); switch ($name) { case "name": $this->name = $value; break; case "portChecking": $this->portChecking = (bool) $value; break; case "packetLimit": $this->packetLimit = (int) $value; break; } } elseif ($id === RakLib::PACKET_BLOCK_ADDRESS) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $timeout = Binary::readInt(substr($packet, $offset, 4)); $this->blockAddress($address, $timeout); } elseif ($id === RakLib::PACKET_SHUTDOWN) { foreach ($this->sessions as $session) { $this->removeSession($session); } $this->socket->close(); $this->shutdown = true; } elseif ($id === RakLib::PACKET_EMERGENCY_SHUTDOWN) { $this->shutdown = true; } else { return false; } return true; } return false; }
protected function getLong($signed = \true) { return Binary::readLong($this->get(8), $signed); }
/** * @param bool $internal * * @return string */ public function toBinary($internal = false) { return chr($this->reliability << 5 | ($this->hasSplit ? 0b10000 : 0)) . ($internal ? Binary::writeInt(strlen($this->buffer)) . Binary::writeInt($this->identifierACK) : Binary::writeShort(strlen($this->buffer) << 3)) . ($this->reliability > 0 ? (($this->reliability >= 2 and $this->reliability !== 5) ? Binary::writeLTriad($this->messageIndex) : "") . (($this->reliability <= 4 and $this->reliability !== 2) ? Binary::writeLTriad($this->orderIndex) . chr($this->orderChannel) : "") : "") . ($this->hasSplit ? Binary::writeInt($this->splitCount) . Binary::writeShort($this->splitID) . Binary::writeInt($this->splitIndex) : "") . $this->buffer; }
/** * Batch a Data packet * * @param DataPacket $packet * * @return bool */ public function batchDataPacket(DataPacket $packet) { $str = ""; if ($packet instanceof DataPacket) { if (!$packet->isEncoded) { $packet->encode(); } $str .= Binary::writeInt(strlen($packet->buffer)) . $packet->buffer; } else { $str .= Binary::writeInt(strlen($packet)) . $packet; } $pk = new BatchPacket(); $pk->payload = zlib_encode($str, ZLIB_ENCODING_DEFLATE, 7); $pk->encode(); $pk->isEncoded = true; $this->dataPacket($pk); }
/** * @param bool $internal * * @return string */ public function toBinary($internal = false) { return chr($this->reliability << 5 | ($this->hasSplit ? 0b10000 : 0)) . ($internal ? Binary::writeInt(strlen($this->buffer)) . Binary::writeInt($this->identifierACK) : Binary::writeShort(strlen($this->buffer) << 3)) . ($this->reliability > PacketReliability::UNRELIABLE ? (($this->reliability >= PacketReliability::RELIABLE and $this->reliability !== PacketReliability::UNRELIABLE_WITH_ACK_RECEIPT) ? Binary::writeLTriad($this->messageIndex) : "") . (($this->reliability <= PacketReliability::RELIABLE_SEQUENCED and $this->reliability !== PacketReliability::RELIABLE) ? Binary::writeLTriad($this->orderIndex) . chr($this->orderChannel) : "") : "") . ($this->hasSplit ? Binary::writeInt($this->splitCount) . Binary::writeShort($this->splitID) . Binary::writeInt($this->splitIndex) : "") . $this->buffer; }
protected function putLong($v) { $this->buffer .= Binary::writeLong($v); }
/** * @return bool */ public function handlePacket() { if (strlen($packet = $this->server->readThreadToMainPacket()) > 0) { $id = ord($packet[0]); $offset = 1; if ($id === RakLib::PACKET_ENCAPSULATED) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; $flags = ord($packet[$offset++]); $buffer = substr($packet, $offset); $this->instance->handleEncapsulated($identifier, EncapsulatedPacket::fromBinary($buffer, true), $flags); } elseif ($id === RakLib::PACKET_RAW) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $port = unpack("n", substr($packet, $offset, 2))[1]; $offset += 2; $payload = substr($packet, $offset); $this->instance->handleRaw($address, $port, $payload); } elseif ($id === RakLib::PACKET_SET_OPTION) { $len = ord($packet[$offset++]); $name = substr($packet, $offset, $len); $offset += $len; $value = substr($packet, $offset); $this->instance->handleOption($name, $value); } elseif ($id === RakLib::PACKET_OPEN_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $port = unpack("n", substr($packet, $offset, 2))[1]; $offset += 2; $clientID = Binary::readLong(substr($packet, $offset, 8)); $this->instance->openSession($identifier, $address, $port, $clientID); } elseif ($id === RakLib::PACKET_CLOSE_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; $len = ord($packet[$offset++]); $reason = substr($packet, $offset, $len); $this->instance->closeSession($identifier, $reason); } elseif ($id === RakLib::PACKET_INVALID_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $this->instance->closeSession($identifier, "Invalid session"); } elseif ($id === RakLib::PACKET_ACK_NOTIFICATION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; $identifierACK = PHP_INT_SIZE === 8 ? unpack("N", substr($packet, $offset, 4))[1] << 32 >> 32 : unpack("N", substr($packet, $offset, 4))[1]; $this->instance->notifyACK($identifier, $identifierACK); } return true; } return false; }
public function requestChunkTask($x, $z) { $chunk = $this->getChunk($x, $z, false); if (!$chunk instanceof Chunk) { throw new ChunkException("Invalid Chunk sent"); } $tiles = ""; $nbt = new NBT(NBT::LITTLE_ENDIAN); foreach ($chunk->getTiles() as $tile) { if ($tile instanceof Spawnable) { $nbt->setData($tile->getSpawnCompound()); $tiles .= $nbt->write(); } } $extraData = new BinaryStream(); $extraData->putLInt(count($chunk->getBlockExtraDataArray())); foreach ($chunk->getBlockExtraDataArray() as $key => $value) { $extraData->putLInt($key); $extraData->putLShort($value); } $ordered = $chunk->getBlockIdArray() . $chunk->getBlockDataArray() . $chunk->getBlockSkyLightArray() . $chunk->getBlockLightArray() . pack("C*", ...$chunk->getHeightMapArray()) . pack("N*", ...$chunk->getBiomeColorArray()) . $extraData->getBuffer() . $tiles; $pk = new FullChunkDataPacket(); $pk->chunkX = $x; $pk->chunkZ = $z; $pk->order = FullChunkDataPacket::ORDER_COLUMNS; $pk->data = $ordered; $pk->encode(); $str = ""; $str .= Binary::writeInt(strlen($pk->buffer)) . $pk->buffer; $this->getLevel()->chunkRequestCallback($x, $z, zlib_encode($str, ZLIB_ENCODING_DEFLATE, 7)); return null; }
protected function handleEncapsulatedPacketRoute(EncapsulatedPacket $packet) { if ($this->sessionManager === null) { return; } $id = ord($packet->buffer[0]); if ($id < 0x80) { //internal data packet if ($this->state === self::STATE_CONNECTING_2) { if ($id === CLIENT_CONNECT_DataPacket::$ID) { $dataPacket = new CLIENT_CONNECT_DataPacket(); $dataPacket->buffer = $packet->buffer; $dataPacket->decode(); $pk = new SERVER_HANDSHAKE_DataPacket(); $pk->port = $this->port; $pk->session = $dataPacket->session; $pk->session2 = Binary::readLong("D\v©"); $pk->encode(); $sendPacket = new EncapsulatedPacket(); $sendPacket->reliability = 0; $sendPacket->buffer = $pk->buffer; $this->addToQueue($sendPacket, RakLib::PRIORITY_IMMEDIATE); } elseif ($id === CLIENT_HANDSHAKE_DataPacket::$ID) { $dataPacket = new CLIENT_HANDSHAKE_DataPacket(); $dataPacket->buffer = $packet->buffer; $dataPacket->decode(); if ($dataPacket->port === $this->sessionManager->getPort() or !$this->sessionManager->portChecking) { $this->state = self::STATE_CONNECTED; //FINALLY! $this->sessionManager->openSession($this); foreach ($this->preJoinQueue as $p) { $this->sessionManager->streamEncapsulated($this, $p); } $this->preJoinQueue = []; } } } elseif ($id === CLIENT_DISCONNECT_DataPacket::$ID) { $this->disconnect("client disconnect"); } elseif ($id === PING_DataPacket::$ID) { $dataPacket = new PING_DataPacket(); $dataPacket->buffer = $packet->buffer; $dataPacket->decode(); $pk = new PONG_DataPacket(); $pk->pingID = $dataPacket->pingID; $pk->encode(); $sendPacket = new EncapsulatedPacket(); $sendPacket->reliability = 0; $sendPacket->buffer = $pk->buffer; $this->addToQueue($sendPacket); } //TODO: add PING/PONG (0x00/0x03) automatic latency measure } elseif ($this->state === self::STATE_CONNECTED) { $this->sessionManager->streamEncapsulated($this, $packet); //TODO: split packet handling //TODO: stream channels } else { $this->preJoinQueue[] = $packet; } }
protected function putLTriad($v) { $this->buffer .= Binary::writeLTriad($v); }
public function saveChunkToDisk($x, $z, $payload, $ordering = FullChunkDataPacket::ORDER_COLUMNS) { // When the payload of the chunk has been calculated it, save it if possible to save future CPU cycles /** @var Player $player */ if (file_exists("chunk_cache/" . $this->getName() . "/" . $x . "_" . $z . ".dat")) { $this->loadChunkFromDisk($x, $z); return true; } $pk = new FullChunkDataPacket(); $pk->chunkX = $x; $pk->chunkZ = $z; $pk->order = $ordering; $pk->data = $payload; $pk->encode(); // all chunks are zlib_encoded, level is arbitrary but 6 is a good match between device CPU power needed // and bandwidth $data = zlib_encode(Binary::writeInt(strlen($pk->buffer)) . $pk->buffer, ZLIB_ENCODING_DEFLATE, 6); $this->chunkCache[$x . ":" . $z] = $data; if (!$this->server->getKatana()->getProperty("cache.save-to-disk", true)) { return true; } file_put_contents("chunk_cache/" . $this->getName() . "/" . $x . "_" . $z . ".dat", $data); return true; }
public function decode() { parent::decode(); $this->pingID = Binary::readLong($this->get(8)); }
public function receiveStream() { if (strlen($packet = $this->server->readMainToThreadPacket()) > 0) { $id = ord($packet[0]); $offset = 1; if ($id === RakLib::PACKET_ENCAPSULATED) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; if (isset($this->sessions[$identifier])) { $flags = ord($packet[$offset++]); $buffer = substr($packet, $offset); $this->sessions[$identifier]->addEncapsulatedToQueue(EncapsulatedPacket::fromBinary($buffer, true), $flags); } else { $this->streamInvalid($identifier); } } elseif ($id === RakLib::PACKET_RAW) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $port = Binary::readShort(substr($packet, $offset, 2)); $offset += 2; $payload = substr($packet, $offset); $this->socket->writePacket($payload, $address, $port); } elseif ($id === RakLib::PACKET_TICK) { $time = microtime(true); foreach ($this->sessions as $session) { $session->update($time); } foreach ($this->ipSec as $address => $count) { if ($count >= $this->packetLimit) { $this->blockAddress($address); } } $this->ipSec = []; if (($this->ticks & 0b1111) === 0) { $diff = max(0.005, $time - $this->lastMeasure); $this->streamOption("bandwidth", serialize(["up" => $this->sendBytes / $diff, "down" => $this->receiveBytes / $diff])); $this->lastMeasure = $time; $this->sendBytes = 0; $this->receiveBytes = 0; if (count($this->block) > 0) { asort($this->block); $now = microtime(true); foreach ($this->block as $address => $timeout) { if ($timeout <= $now) { unset($this->block[$address]); } else { break; } } } gc_collect_cycles(); } ++$this->ticks; } elseif ($id === RakLib::PACKET_CLOSE_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); if (isset($this->sessions[$identifier])) { $this->removeSession($this->sessions[$identifier]); } else { $this->streamInvalid($identifier); } } elseif ($id === RakLib::PACKET_INVALID_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); if (isset($this->sessions[$identifier])) { $this->removeSession($this->sessions[$identifier]); } } elseif ($id === RakLib::PACKET_SET_OPTION) { $len = ord($packet[$offset++]); $name = substr($packet, $offset, $len); $offset += $len; $value = substr($packet, $offset); switch ($name) { case "name": $this->name = $value; break; case "portChecking": $this->portChecking = (bool) $value; break; case "packetLimit": $this->packetLimit = (int) $value; break; } } elseif ($id === RakLib::PACKET_BLOCK_ADDRESS) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $timeout = Binary::readInt(substr($packet, $offset, 4)); $this->blockAddress($address, $timeout); } elseif ($id === RakLib::PACKET_SHUTDOWN) { foreach ($this->sessions as $session) { $this->removeSession($session); } $this->socket->close(); $this->shutdown = true; } elseif ($id === RakLib::PACKET_EMERGENCY_SHUTDOWN) { $this->shutdown = true; } else { return false; } return true; } return false; }