| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- <?php
- /**
- * See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for
- * more information about Source RCON Packets
- *
- * PHP Version 7
- *
- * @copyright 2013-2017 Chris Churchwell
- * @author thedudeguy
- * @link https://github.com/thedudeguy/PHP-Minecraft-Rcon
- */
-
- class Rcon
- {
- private $host;
- private $port;
- private $password;
- private $timeout;
-
- private $socket;
-
- private $authorized = false;
- private $lastResponse = '';
-
- const PACKET_AUTHORIZE = 5;
- const PACKET_COMMAND = 6;
-
- const SERVERDATA_AUTH = 3;
- const SERVERDATA_AUTH_RESPONSE = 2;
- const SERVERDATA_EXECCOMMAND = 2;
- const SERVERDATA_RESPONSE_VALUE = 0;
-
- /**
- * Create a new instance of the Rcon class.
- *
- * @param string $host
- * @param integer $port
- * @param string $password
- * @param integer $timeout
- */
- public function __construct( $host, $port, $password, $timeout )
- {
- $this->host = $host;
- $this->port = $port;
- $this->password = $password;
- $this->timeout = $timeout;
- }
-
- /**
- * Get the latest response from the server.
- *
- * @return string
- */
- public function getResponse()
- {
- return $this->lastResponse;
- }
-
- /**
- * Connect to a server.
- *
- * @return boolean
- */
- public function connect()
- {
- $this->socket = fsockopen( $this->host, $this->port, $errno, $errstr, $this->timeout );
-
- if ( !$this->socket ) {
- $this->lastResponse = $errstr;
- return false;
- }
-
- //set timeout
- stream_set_timeout( $this->socket, 3, 0 );
-
- // check authorization
- return $this->authorize();
- }
-
- /**
- * Disconnect from server.
- *
- * @return void
- */
- public function disconnect()
- {
- if ( $this->socket ) {
- fclose( $this->socket );
- }
- $this->authorized = false;
- }
-
- /**
- * True if socket is connected and authorized.
- *
- * @return boolean
- */
- public function isConnected()
- {
- return $this->authorized;
- }
-
- /**
- * Send a command to the connected server.
- *
- * @param string $command
- *
- * @return boolean|mixed
- */
- public function sendCommand( $command )
- {
- if ( !$this->isConnected() ) {
- return false;
- }
-
- // send command packet
- $this->writePacket( self::PACKET_COMMAND, self::SERVERDATA_EXECCOMMAND, $command );
-
- // get response
- $response_packet = $this->readPacket();
- if ( $response_packet[ 'id' ] == self::PACKET_COMMAND ) {
- if ( $response_packet[ 'type' ] == self::SERVERDATA_RESPONSE_VALUE ) {
- $this->lastResponse = $response_packet[ 'body' ];
-
- return $response_packet[ 'body' ];
- }
- }
-
- return false;
- }
-
- /**
- * Log into the server with the given credentials.
- *
- * @return boolean
- */
- private function authorize()
- {
- $this->writePacket( self::PACKET_AUTHORIZE, self::SERVERDATA_AUTH, $this->password );
- $response_packet = $this->readPacket();
-
- if ( $response_packet[ 'type' ] == self::SERVERDATA_AUTH_RESPONSE ) {
- if ( $response_packet[ 'id' ] == self::PACKET_AUTHORIZE ) {
- $this->authorized = true;
-
- return true;
- }
- }
-
- $this->disconnect();
- return false;
- }
-
- /**
- * Writes a packet to the socket stream.
- *
- * @param $packetId
- * @param $packetType
- * @param string $packetBody
- *
- * @return void
- */
- private function writePacket( $packetId, $packetType, $packetBody )
- {
- /*
- Size 32-bit little-endian Signed Integer Varies, see below.
- ID 32-bit little-endian Signed Integer Varies, see below.
- Type 32-bit little-endian Signed Integer Varies, see below.
- Body Null-terminated ASCII String Varies, see below.
- Empty String Null-terminated ASCII String 0x00
- */
-
- //create packet
- $packet = pack( 'VV', $packetId, $packetType );
- $packet = $packet . $packetBody . "\x00";
- $packet = $packet . "\x00";
-
- // get packet size.
- $packet_size = strlen( $packet );
-
- // attach size to packet.
- $packet = pack( 'V', $packet_size ) . $packet;
-
- // write packet.
- fwrite( $this->socket, $packet, strlen( $packet ) );
- }
-
- /**
- * Read a packet from the socket stream.
- *
- * @return array
- */
- private function readPacket()
- {
- //get packet size.
- $size_data = fread( $this->socket, 4 );
- $size_pack = unpack( 'V1size', $size_data );
- $size = $size_pack[ 'size' ];
-
- // if size is > 4096, the response will be in multiple packets.
- // this needs to be address. get more info about multi-packet responses
- // from the RCON protocol specification at
- // https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
- // currently, this script does not support multi-packet responses.
-
- $packet_data = fread( $this->socket, $size );
- return unpack( 'V1id/V1type/a*body', $packet_data );
- }
- }
|