PHP-cli-factorio-updater/scripts/class.ValveRcon.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
}
}