Dateien nach "rcon" hochladen
This commit is contained in:
102
rcon/Rcon.php
Normal file
102
rcon/Rcon.php
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Compact RCON client for Minecraft with improved read loop & timeouts.
|
||||||
|
*/
|
||||||
|
class Rcon {
|
||||||
|
private $host;
|
||||||
|
private $port;
|
||||||
|
private $password;
|
||||||
|
private $socket;
|
||||||
|
private $req_id;
|
||||||
|
private $timeout;
|
||||||
|
|
||||||
|
const SERVERDATA_AUTH = 3;
|
||||||
|
const SERVERDATA_EXECCOMMAND = 2;
|
||||||
|
|
||||||
|
public function __construct($host, $port, $password, $timeout = 3) {
|
||||||
|
$this->host = $host;
|
||||||
|
$this->port = intval($port);
|
||||||
|
$this->password = $password;
|
||||||
|
$this->timeout = $timeout;
|
||||||
|
$this->socket = null;
|
||||||
|
$this->req_id = random_int(1, 0x7fffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connect() {
|
||||||
|
$this->socket = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
|
||||||
|
if (!$this->socket) return false;
|
||||||
|
stream_set_timeout($this->socket, $this->timeout);
|
||||||
|
stream_set_blocking($this->socket, true);
|
||||||
|
|
||||||
|
$pkt = $this->buildPacket($this->req_id, self::SERVERDATA_AUTH, $this->password);
|
||||||
|
fwrite($this->socket, $pkt);
|
||||||
|
|
||||||
|
$resp = $this->readPacket();
|
||||||
|
if ($resp === false) { $this->disconnect(); return false; }
|
||||||
|
if (isset($resp['id']) && intval($resp['id']) == -1) { $this->disconnect(); return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disconnect() {
|
||||||
|
if ($this->socket) { fclose($this->socket); $this->socket = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendCommand($command) {
|
||||||
|
if (!$this->socket) return false;
|
||||||
|
$this->req_id = ($this->req_id + 1) & 0x7fffffff;
|
||||||
|
$pkt = $this->buildPacket($this->req_id, self::SERVERDATA_EXECCOMMAND, $command);
|
||||||
|
fwrite($this->socket, $pkt);
|
||||||
|
|
||||||
|
$out = '';
|
||||||
|
$start = time();
|
||||||
|
while (true) {
|
||||||
|
$resp = $this->readPacket();
|
||||||
|
if ($resp === false) break;
|
||||||
|
if (isset($resp['body'])) $out .= $resp['body'];
|
||||||
|
$meta = stream_get_meta_data($this->socket);
|
||||||
|
if ($meta['timed_out']) break;
|
||||||
|
if (time() - $start > $this->timeout) break;
|
||||||
|
if (strlen($resp['body']) < 4096) break;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildPacket($id, $type, $body) {
|
||||||
|
$payload = pack('V', $id) . pack('V', $type) . $body . "\x00\x00";
|
||||||
|
$size = strlen($payload);
|
||||||
|
return pack('V', $size) . $payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readPacket() {
|
||||||
|
$sizeData = $this->fread_all(4);
|
||||||
|
if ($sizeData === false) return false;
|
||||||
|
$sizeArr = unpack('Vsize', $sizeData);
|
||||||
|
$size = $sizeArr['size'];
|
||||||
|
if ($size <= 0) return false;
|
||||||
|
$payload = $this->fread_all($size);
|
||||||
|
if ($payload === false) return false;
|
||||||
|
$id = unpack('Vid', substr($payload, 0, 4))['id'] ?? 0;
|
||||||
|
$type = unpack('Vtype', substr($payload, 4, 4))['type'] ?? 0;
|
||||||
|
$body = substr($payload, 8, $size - 10);
|
||||||
|
return ['id' => $id, 'type' => $type, 'body' => $body];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fread_all($len) {
|
||||||
|
$data = '';
|
||||||
|
$read = 0;
|
||||||
|
$start = time();
|
||||||
|
while ($read < $len) {
|
||||||
|
$chunk = @fread($this->socket, $len - $read);
|
||||||
|
if ($chunk === false) return false;
|
||||||
|
if ($chunk === '') {
|
||||||
|
$meta = stream_get_meta_data($this->socket);
|
||||||
|
if ($meta['timed_out'] || (time() - $start) > $this->timeout) return false;
|
||||||
|
usleep(10000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$data .= $chunk;
|
||||||
|
$read += strlen($chunk);
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user