From e09dd49e43ce3cf6046891b68650dcd108a402d2 Mon Sep 17 00:00:00 2001 From: Lloyd Dilley Date: Sat, 25 Feb 2023 16:31:11 -0500 Subject: [PATCH] Add SRV support (PHP) Related to #142. --- PHP/minestat.php | 61 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/PHP/minestat.php b/PHP/minestat.php index f5908f2..e601e16 100644 --- a/PHP/minestat.php +++ b/PHP/minestat.php @@ -54,6 +54,8 @@ class MineStat private $address; // hostname or IP address of the Minecraft server private $port; // port number the Minecraft server accepts connections on + private $srv_address; // server address from DNS SRV record + private $srv_port; // server TCP port from DNS SRV record private $online; // online or offline? private $version; // Minecraft server version private $mode; // game mode (Bedrock/Pocket Edition only) @@ -71,8 +73,10 @@ class MineStat private $request_type; // protocol version private $connection_status; // status of connection ("Success", "Fail", "Timeout", or "Unknown") private $try_all; // try all protocols? + private $srv_enabled; // enable SRV resolution? + private $srv_succeeded; // SRV resolution successful? - public function __construct($address, $port = MineStat::DEFAULT_TCP_PORT, $timeout = MineStat::DEFAULT_TIMEOUT, $request_type = MineStat::REQUEST_NONE) + public function __construct($address, $port = MineStat::DEFAULT_TCP_PORT, $timeout = MineStat::DEFAULT_TIMEOUT, $request_type = MineStat::REQUEST_NONE, $srv_enabled = true) { $this->address = $address; $this->port = $port; @@ -80,6 +84,11 @@ public function __construct($address, $port = MineStat::DEFAULT_TCP_PORT, $timeo $this->online = false; if($request_type == MineStat::REQUEST_NONE) $this->try_all = true; + $this->srv_enabled = $srv_enabled; + $this->srv_succeeded = false; + + if($this->srv_enabled) + $this->srv_succeeded = $this->resolve_srv(); switch($request_type) { @@ -129,6 +138,10 @@ public function get_address() { return $this->address; } public function get_port() { return $this->port; } + public function get_srv_address() { return $this->srv_address; } + + public function get_srv_port() { return $this->srv_port; } + public function is_online() { return $this->online; } public function get_version() { return $this->version; } @@ -157,6 +170,36 @@ public function get_request_type() { return $this->request_type; } public function get_connection_status() { return $this->connection_status; } + public function is_srv_enabled() { return $this->srv_enabled; } + + public function is_srv_success() { return $this->srv_succeeded; } + + /* Attempts to resolve DNS SRV records */ + private function resolve_srv() + { + try + { + $result = dns_get_record("_minecraft._tcp." . $this->address, DNS_SRV); + if(!empty($result)) + { + if(isset($result[0]['target']) && isset($result[0]['port'])) + { + $this->srv_address = $result[0]['target']; + $this->srv_port = $result[0]['port']; + return true; + } + else + return false; + } + else + return false; + } + catch(Exception $e) + { + return false; + } + } + /* Sets connection status */ private function set_connection_status($retval) { @@ -212,7 +255,19 @@ private function connect() socket_set_nonblock($this->socket); $time = time(); $start_time = microtime(true); - while(!@socket_connect($this->socket, $this->address, $this->port)) + $connect_address; + $connect_port; + if($this->request_type != MineStat::REQUEST_BEDROCK && $this->request_type != "Bedrock/Pocket Edition" && $this->srv_enabled && $this->srv_succeeded) + { + $connect_address = $this->srv_address; + $connect_port = $this->srv_port; + } + else + { + $connect_address = $this->address; + $connect_port = $this->port; + } + while(!@socket_connect($this->socket, $connect_address, $connect_port)) { if((time() - $time) >= $this->timeout) { @@ -221,7 +276,7 @@ private function connect() } usleep(0); } - $result = @socket_connect($this->socket, $this->address, $this->port); + $result = @socket_connect($this->socket, $connect_address, $connect_port); $this->latency = round((microtime(true) - $start_time) * 1000); socket_set_block($this->socket); if($result === false && socket_last_error($this->socket) != SOCKET_EISCONN)