mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-07 04:17:07 +00:00
Implemented QueryPacket and QueryHandler
This commit is contained in:
parent
b9aa3a0e70
commit
7c12f6ce8a
@ -28,7 +28,8 @@ class ServerAPI{
|
|||||||
private $apiList = array();
|
private $apiList = array();
|
||||||
private $asyncCnt = 0;
|
private $asyncCnt = 0;
|
||||||
private $rcon;
|
private $rcon;
|
||||||
private $query;
|
|
||||||
|
public $query;
|
||||||
|
|
||||||
//TODO: Instead of hard-coding functions, use PHPDoc-compatible methods to load APIs.
|
//TODO: Instead of hard-coding functions, use PHPDoc-compatible methods to load APIs.
|
||||||
|
|
||||||
@ -139,6 +140,13 @@ class ServerAPI{
|
|||||||
define("DEBUG", $this->getProperty("debug", 1));
|
define("DEBUG", $this->getProperty("debug", 1));
|
||||||
define("ADVANCED_CACHE", $this->getProperty("enable-advanced-cache", false));
|
define("ADVANCED_CACHE", $this->getProperty("enable-advanced-cache", false));
|
||||||
define("MAX_CHUNK_RATE", 20 / $this->getProperty("max-chunks-per-second", 8)); //Default rate ~512 kB/s
|
define("MAX_CHUNK_RATE", 20 / $this->getProperty("max-chunks-per-second", 8)); //Default rate ~512 kB/s
|
||||||
|
if(ADVANCED_CACHE == true){
|
||||||
|
console("[INFO] Advanced cache enabled");
|
||||||
|
}
|
||||||
|
if($this->getProperty("upnp-forwarding") == true){
|
||||||
|
console("[INFO] [UPnP] Trying to port forward...");
|
||||||
|
UPnP_PortForward($this->getProperty("server-port"));
|
||||||
|
}
|
||||||
|
|
||||||
$this->server = new PocketMinecraftServer($this->getProperty("server-name"), $this->getProperty("gamemode"), ($seed = $this->getProperty("level-seed")) != "" ? (int) $seed:false, $this->getProperty("server-port"), ($ip = $this->getProperty("server-ip")) != "" ? $ip:"0.0.0.0");
|
$this->server = new PocketMinecraftServer($this->getProperty("server-name"), $this->getProperty("gamemode"), ($seed = $this->getProperty("level-seed")) != "" ? (int) $seed:false, $this->getProperty("server-port"), ($ip = $this->getProperty("server-ip")) != "" ? $ip:"0.0.0.0");
|
||||||
$this->server->api = $this;
|
$this->server->api = $this;
|
||||||
@ -146,15 +154,6 @@ class ServerAPI{
|
|||||||
console("[INFO] This server is running PocketMine-MP version ".($version->isDev() ? FORMAT_YELLOW:"").MAJOR_VERSION.FORMAT_RESET." \"".CODENAME."\" (MCPE: ".CURRENT_MINECRAFT_VERSION.") (API ".CURRENT_API_VERSION.")", true, true, 0);
|
console("[INFO] This server is running PocketMine-MP version ".($version->isDev() ? FORMAT_YELLOW:"").MAJOR_VERSION.FORMAT_RESET." \"".CODENAME."\" (MCPE: ".CURRENT_MINECRAFT_VERSION.") (API ".CURRENT_API_VERSION.")", true, true, 0);
|
||||||
console("[INFO] PocketMine-MP is distributed under the LGPL License", true, true, 0);
|
console("[INFO] PocketMine-MP is distributed under the LGPL License", true, true, 0);
|
||||||
|
|
||||||
if(ADVANCED_CACHE == true){
|
|
||||||
console("[INFO] Advanced cache enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->getProperty("upnp-forwarding") === true){
|
|
||||||
console("[INFO] [UPnP] Trying to port forward...");
|
|
||||||
UPnP_PortForward($this->getProperty("server-port"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){
|
if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){
|
||||||
console("[INFO] Checking for new server version");
|
console("[INFO] Checking for new server version");
|
||||||
console("[INFO] Last check: ".FORMAT_AQUA.date("Y-m-d H:i:s", $this->getProperty("last-update"))."\x1b[0m");
|
console("[INFO] Last check: ".FORMAT_AQUA.date("Y-m-d H:i:s", $this->getProperty("last-update"))."\x1b[0m");
|
||||||
@ -348,7 +347,7 @@ class ServerAPI{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($this->getProperty("enable-query") === true){
|
if($this->getProperty("enable-query") === true){
|
||||||
$this->query = new Query();
|
$this->query = new QueryHandler();
|
||||||
}
|
}
|
||||||
CraftingRecipes::init();
|
CraftingRecipes::init();
|
||||||
$this->server->init();
|
$this->server->init();
|
||||||
|
@ -64,7 +64,7 @@ class PocketMinecraftServer{
|
|||||||
$this->saveEnabled = true;
|
$this->saveEnabled = true;
|
||||||
$this->tickMeasure = array_fill(0, 40, 0);
|
$this->tickMeasure = array_fill(0, 40, 0);
|
||||||
$this->setType("normal");
|
$this->setType("normal");
|
||||||
$this->interface = new MinecraftInterface($this, "255.255.255.255", $this->port, true, false, $this->serverip);
|
$this->interface = new MinecraftInterface("255.255.255.255", $this->port, $this->serverip);
|
||||||
$this->stop = false;
|
$this->stop = false;
|
||||||
$this->ticks = 0;
|
$this->ticks = 0;
|
||||||
if(!defined("NO_THREADS")){
|
if(!defined("NO_THREADS")){
|
||||||
|
@ -20,18 +20,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class MinecraftInterface{
|
class MinecraftInterface{
|
||||||
public $client;
|
|
||||||
public $bandwidth;
|
public $bandwidth;
|
||||||
private $socket;
|
private $socket;
|
||||||
private $packets;
|
private $packets;
|
||||||
function __construct($object, $server, $port = 25565, $listen = false, $client = false, $serverip = "0.0.0.0"){
|
function __construct($server, $port = 25565, $serverip = "0.0.0.0"){
|
||||||
$this->socket = new UDPSocket($server, $port, (bool) $listen, $serverip);
|
$this->socket = new UDPSocket($server, $port, true, $serverip);
|
||||||
if($this->socket->connected === false){
|
if($this->socket->connected === false){
|
||||||
console("[SEVERE] Couldn't bind to $serverip:".$port, true, true, 0);
|
console("[SEVERE] Couldn't bind to $serverip:".$port, true, true, 0);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
$this->bandwidth = array(0, 0, microtime(true));
|
$this->bandwidth = array(0, 0, microtime(true));
|
||||||
$this->client = (bool) $client;
|
|
||||||
$this->start = microtime(true);
|
$this->start = microtime(true);
|
||||||
$this->packets = array();
|
$this->packets = array();
|
||||||
}
|
}
|
||||||
@ -65,6 +63,12 @@ class MinecraftInterface{
|
|||||||
return $parser->packet;
|
return $parser->packet;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
}elseif($pid === 0xfe and $buffer{1} === "\xfd" and ServerAPI::request()->api->query instanceof QueryHandler){
|
||||||
|
$packet = new QueryPacket;
|
||||||
|
$packet->ip = $source;
|
||||||
|
$packet->port = $port;
|
||||||
|
$packet->buffer = $buffer;
|
||||||
|
ServerAPI::request()->api->query->handle($packet);
|
||||||
}else{
|
}else{
|
||||||
$packet = new Packet();
|
$packet = new Packet();
|
||||||
$packet->ip = $source;
|
$packet->ip = $source;
|
||||||
|
@ -24,7 +24,7 @@ Implementation of the UT3 Query Protocol (GameSpot)
|
|||||||
Source: http://wiki.unrealadmin.org/UT3_query_protocol
|
Source: http://wiki.unrealadmin.org/UT3_query_protocol
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Query{
|
class QueryHandler{
|
||||||
private $socket, $server, $lastToken, $token, $longData, $timeout;
|
private $socket, $server, $lastToken, $token, $longData, $timeout;
|
||||||
|
|
||||||
public function __construct(){
|
public function __construct(){
|
||||||
@ -41,7 +41,7 @@ class Query{
|
|||||||
Then, the Query class handles itself sending the packets in raw form, because
|
Then, the Query class handles itself sending the packets in raw form, because
|
||||||
packets can conflict with the MCPE ones.
|
packets can conflict with the MCPE ones.
|
||||||
*/
|
*/
|
||||||
$this->server->addHandler("server.unknownpacket.254", array($this, "packetHandler"), 50);
|
|
||||||
$this->server->schedule(20 * 30, array($this, "regenerateToken"), array(), true);
|
$this->server->schedule(20 * 30, array($this, "regenerateToken"), array(), true);
|
||||||
$this->regenerateToken();
|
$this->regenerateToken();
|
||||||
$this->lastToken = $this->token;
|
$this->lastToken = $this->token;
|
||||||
@ -94,48 +94,41 @@ class Query{
|
|||||||
$this->token = Utils::readInt("\x00".Utils::getRandomBytes(3, false));
|
$this->token = Utils::readInt("\x00".Utils::getRandomBytes(3, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function packetHandler($packet, $event){
|
public function handle(QueryPacket $packet){
|
||||||
if($event !== "server.unknownpacket.254"){
|
$packet->decode();
|
||||||
return;
|
switch($packet->packetType){
|
||||||
}
|
case QueryPacket::HANDSHAKE: //Handshake
|
||||||
$magic = substr($packet->buffer, 0, 2);
|
$pk = new QueryPacket;
|
||||||
$offset = 2;
|
|
||||||
if($magic !== "\xfe\xfd"){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$type = ord($packet->buffer{2});
|
|
||||||
++$offset;
|
|
||||||
$sessionID = Utils::readInt(substr($packet->buffer, $offset, 4));
|
|
||||||
$offset += 4;
|
|
||||||
$payload = substr($packet->buffer, $offset);
|
|
||||||
switch($type){
|
|
||||||
case 9: //Handshake
|
|
||||||
$pk = new Packet;
|
|
||||||
$pk->ip = $packet->ip;
|
$pk->ip = $packet->ip;
|
||||||
$pk->port = $packet->port;
|
$pk->port = $packet->port;
|
||||||
$pk->buffer = chr(9).Utils::writeInt($sessionID).$this->token."\x00";
|
$pk->packetType = QueryPacket::HANDSHAKE;
|
||||||
|
$pk->sessionID = $packet->sessionID;
|
||||||
|
$pk->payload = $this->token."\x00";
|
||||||
|
$pk->encode();
|
||||||
$this->server->send($pk);
|
$this->server->send($pk);
|
||||||
break;
|
break;
|
||||||
case 0: //Stat
|
case QueryPacket::STATISTICS: //Stat
|
||||||
$token = Utils::readInt(substr($payload, 0, 4));
|
$token = Utils::readInt(substr($packet->payload, 0, 4));
|
||||||
if($token !== $this->token and $token !== $this->lastToken){
|
if($token !== $this->token and $token !== $this->lastToken){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$pk = new Packet;
|
$pk = new QueryPacket;
|
||||||
$pk->ip = $packet->ip;
|
$pk->ip = $packet->ip;
|
||||||
$pk->port = $packet->port;
|
$pk->port = $packet->port;
|
||||||
if(strlen($payload) === 8){
|
$pk->packetType = QueryPacket::STATISTICS;
|
||||||
|
$pk->sessionID = $packet->sessionID;
|
||||||
|
if(strlen($packet->payload) === 8){
|
||||||
if($this->timeout < microtime(true)){
|
if($this->timeout < microtime(true)){
|
||||||
$this->regenerateInfo();
|
$this->regenerateInfo();
|
||||||
}
|
}
|
||||||
$pk->buffer = chr(0).Utils::writeInt($sessionID).$this->longData;
|
$pk->payload = $this->longData;
|
||||||
}else{
|
}else{
|
||||||
$pk->buffer = chr(0).Utils::writeInt($sessionID).$this->server->name."\x00".(($this->server->gamemode & 0x01) === 0 ? "SMP":"CMP")."\x00".$this->server->api->level->getDefault()->getName()."\x00".count($this->server->clients)."\x00".$this->server->maxClients."\x00".Utils::writeLShort($this->server->api->getProperty("server-port")).$this->server->api->getProperty("server-ip", "0.0.0.0")."\x00";
|
$pk->payload = $this->server->name."\x00".(($this->server->gamemode & 0x01) === 0 ? "SMP":"CMP")."\x00".$this->server->api->level->getDefault()->getName()."\x00".count($this->server->clients)."\x00".$this->server->maxClients."\x00".Utils::writeLShort($this->server->api->getProperty("server-port")).$this->server->api->getProperty("server-ip", "0.0.0.0")."\x00";
|
||||||
}
|
}
|
||||||
|
$pk->encode();
|
||||||
$this->server->send($pk);
|
$this->server->send($pk);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
41
src/network/query/QueryPacket.php
Normal file
41
src/network/query/QueryPacket.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class QueryPacket extends Packet{
|
||||||
|
const HANDSHAKE = 9;
|
||||||
|
const STATISTICS = 0;
|
||||||
|
|
||||||
|
public $packetType;
|
||||||
|
public $sessionID;
|
||||||
|
public $payload;
|
||||||
|
|
||||||
|
public function decode(){
|
||||||
|
$this->packetType = ord($this->buffer{2});
|
||||||
|
$this->sessionID = Utils::readInt(substr($this->buffer, 3, 4));
|
||||||
|
$this->payload = substr($this->buffer, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(){
|
||||||
|
$this->buffer .= chr($this->packetType);
|
||||||
|
$this->buffer .= Utils::writeInt($this->sessionID);
|
||||||
|
$this->buffer .= $this->payload;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user