139 lines
3.5 KiB
PHP
139 lines
3.5 KiB
PHP
<?php
|
|
|
|
namespace NAE\Valve\Rcon;
|
|
|
|
class ValveRcon {
|
|
|
|
private $ip;
|
|
private $port;
|
|
private $password;
|
|
private $timeout;
|
|
|
|
private $socket;
|
|
private $err;
|
|
|
|
public function __construct(string $ip, int $port, string $password, int $timeout=2) {
|
|
$this->ip = $ip;
|
|
$this->port = $port;
|
|
$this->password = $password;
|
|
$this->timeout = $timeout;
|
|
}
|
|
|
|
private function connect() : bool {
|
|
|
|
$errno = null;
|
|
$errmsg = "";
|
|
|
|
$this->socket = fsockopen(
|
|
"udp://{$this->ip}",
|
|
$this->port,
|
|
$errno,
|
|
$errmsg,
|
|
$this->timeout
|
|
);
|
|
|
|
if(!$this->socket) {
|
|
$this->err = [
|
|
"code" => $errno,
|
|
"message" => "Socket connection failed: $errmsg"
|
|
];
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
private function disconnect() : void {
|
|
|
|
if ( $this->isConnected() ) {
|
|
fclose($this->socket);
|
|
$this->socket = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
private function isConnected() : bool {
|
|
|
|
return ( get_resource_type($this->socket) !== null ); // check if socket is resource type, as it should be
|
|
|
|
}
|
|
|
|
private function read() : ?string {
|
|
|
|
if (!$this->isConnected()) {
|
|
return null;
|
|
}
|
|
|
|
stream_set_timeout($this->socket, 0, $this->timeout * 100000); // set timeout
|
|
|
|
$response = '';
|
|
while ($buffer = fread($this->socket, 4096)) { // loop while there's more data
|
|
list($header, $content) = explode("\n", $buffer, 2); // split into header and content
|
|
$response .= $content; // append content to response
|
|
}
|
|
|
|
$response = trim($response); // remove whitespaces around the response
|
|
|
|
if (empty($response)) // no data received, return null
|
|
return null;
|
|
|
|
return preg_replace("/\^./","", $response); // return response without prefix
|
|
|
|
}
|
|
|
|
private function write(string $cmd) : bool {
|
|
|
|
if (!$this->isConnected()) {
|
|
return false;
|
|
}
|
|
|
|
if( false === fwrite($this->socket, str_repeat(chr(255), 4) . "rcon {$this->password} {$cmd}\n") ) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
public function sendCommand(string $cmd, bool $read=false) : ?string {
|
|
|
|
$this->connect();
|
|
if(!$this->write($cmd)) { // sending the command
|
|
$this->err = [
|
|
"code" => 0,
|
|
"message" => "Command could not be sent"
|
|
];
|
|
$this->disconnect();
|
|
return null;
|
|
}
|
|
|
|
if (!$read) {
|
|
$this->disconnect();
|
|
return null;
|
|
}
|
|
|
|
if(!$res = $this->read()) { // reading the response
|
|
$this->err = [
|
|
"code" => 0,
|
|
"message" => "Response could not be read"
|
|
];
|
|
}
|
|
$this->disconnect();
|
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
public function getError() :?object {
|
|
|
|
if($this->err === null) {
|
|
return null; // no error has occurred, return null
|
|
}
|
|
|
|
return json_decode(json_encode($this->err)); // return last error as object
|
|
|
|
}
|
|
|
|
|
|
} |