├── .gitignore ├── LICENSE ├── README.md ├── composer.json └── src └── Rcon.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | /vendor 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Chris Churchwell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PHP-Minecraft-Rcon 2 | ================== 3 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/thedudeguy/PHP-Minecraft-Rcon/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/thedudeguy/PHP-Minecraft-Rcon/?branch=master) 4 | 5 | Simple Rcon class for php. 6 | 7 | ## Installation 8 | ### Using Composer 9 | This Rcon library may be installed by issuing the following command: 10 | ```bash 11 | $ composer require thedudeguy/rcon 12 | ``` 13 | ### Not Using Composer 14 | If not using Composer, just place the Rcon.php file in your project and include it in your PHP script: 15 | ```php 16 | require_once('Rcon.php'); 17 | ``` 18 | 19 | ## Example 20 | For this script to work, rcon must be enabled on the server, by setting `enable-rcon=true` in the server's `server.properties` file. A password must also be set, and provided in the script. 21 | 22 | ```php 23 | $host = 'some.minecraftserver.com'; // Server host name or IP 24 | $port = 25575; // Port rcon is listening on 25 | $password = 'server-rcon-password'; // rcon.password setting set in server.properties 26 | $timeout = 3; // How long to timeout. 27 | 28 | use Thedudeguy\Rcon; 29 | 30 | $rcon = new Rcon($host, $port, $password, $timeout); 31 | 32 | if ($rcon->connect()) 33 | { 34 | $rcon->sendCommand("say Hello World!"); 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "thedudeguy/rcon", 3 | "description": "Simple Rcon class for php.", 4 | "keywords": ["rcon", "minecraft"], 5 | "homepage": "https://github.com/thedudeguy/PHP-Minecraft-Rcon", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Chris Churchwell", 10 | "homepage": "http://chrischurchwell.com", 11 | "email": "chris@chrischurchwell.com" 12 | } 13 | ], 14 | "support": { 15 | "issues": "https://github.com/thedudeguy/PHP-Minecraft-Rcon/issues", 16 | "source": "https://github.com/thedudeguy/PHP-Minecraft-Rcon/tree/master" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "Thedudeguy\\": "src/" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Rcon.php: -------------------------------------------------------------------------------- 1 | host = $host; 46 | $this->port = $port; 47 | $this->password = $password; 48 | $this->timeout = $timeout; 49 | } 50 | 51 | /** 52 | * Get the latest response from the server. 53 | * 54 | * @return string 55 | */ 56 | public function getResponse() 57 | { 58 | return $this->lastResponse; 59 | } 60 | 61 | /** 62 | * Connect to a server. 63 | * 64 | * @return boolean 65 | */ 66 | public function connect() 67 | { 68 | $this->socket = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); 69 | 70 | if (!$this->socket) { 71 | $this->lastResponse = $errstr; 72 | return false; 73 | } 74 | 75 | //set timeout 76 | stream_set_timeout($this->socket, 3, 0); 77 | 78 | // check authorization 79 | return $this->authorize(); 80 | } 81 | 82 | /** 83 | * Disconnect from server. 84 | * 85 | * @return void 86 | */ 87 | public function disconnect() 88 | { 89 | if ($this->socket) { 90 | fclose($this->socket); 91 | } 92 | } 93 | 94 | /** 95 | * True if socket is connected and authorized. 96 | * 97 | * @return boolean 98 | */ 99 | public function isConnected() 100 | { 101 | return $this->authorized; 102 | } 103 | 104 | /** 105 | * Send a command to the connected server. 106 | * 107 | * @param string $command 108 | * 109 | * @return boolean|mixed 110 | */ 111 | public function sendCommand($command) 112 | { 113 | if (!$this->isConnected()) { 114 | return false; 115 | } 116 | 117 | // send command packet 118 | $this->writePacket(self::PACKET_COMMAND, self::SERVERDATA_EXECCOMMAND, $command); 119 | 120 | // get response 121 | $response_packet = $this->readPacket(); 122 | if ($response_packet['id'] == self::PACKET_COMMAND) { 123 | if ($response_packet['type'] == self::SERVERDATA_RESPONSE_VALUE) { 124 | $this->lastResponse = $response_packet['body']; 125 | 126 | return $response_packet['body']; 127 | } 128 | } 129 | 130 | return false; 131 | } 132 | 133 | /** 134 | * Log into the server with the given credentials. 135 | * 136 | * @return boolean 137 | */ 138 | private function authorize() 139 | { 140 | $this->writePacket(self::PACKET_AUTHORIZE, self::SERVERDATA_AUTH, $this->password); 141 | $response_packet = $this->readPacket(); 142 | 143 | if ($response_packet['type'] == self::SERVERDATA_AUTH_RESPONSE) { 144 | if ($response_packet['id'] == self::PACKET_AUTHORIZE) { 145 | $this->authorized = true; 146 | 147 | return true; 148 | } 149 | } 150 | 151 | $this->disconnect(); 152 | return false; 153 | } 154 | 155 | /** 156 | * Writes a packet to the socket stream. 157 | * 158 | * @param $packetId 159 | * @param $packetType 160 | * @param string $packetBody 161 | * 162 | * @return void 163 | */ 164 | private function writePacket($packetId, $packetType, $packetBody) 165 | { 166 | /* 167 | Size 32-bit little-endian Signed Integer Varies, see below. 168 | ID 32-bit little-endian Signed Integer Varies, see below. 169 | Type 32-bit little-endian Signed Integer Varies, see below. 170 | Body Null-terminated ASCII String Varies, see below. 171 | Empty String Null-terminated ASCII String 0x00 172 | */ 173 | 174 | //create packet 175 | $packet = pack('VV', $packetId, $packetType); 176 | $packet = $packet.$packetBody."\x00"; 177 | $packet = $packet."\x00"; 178 | 179 | // get packet size. 180 | $packet_size = strlen($packet); 181 | 182 | // attach size to packet. 183 | $packet = pack('V', $packet_size).$packet; 184 | 185 | // write packet. 186 | fwrite($this->socket, $packet, strlen($packet)); 187 | } 188 | 189 | /** 190 | * Read a packet from the socket stream. 191 | * 192 | * @return array 193 | */ 194 | private function readPacket() 195 | { 196 | //get packet size. 197 | $size_data = fread($this->socket, 4); 198 | $size_pack = unpack('V1size', $size_data); 199 | $size = $size_pack['size']; 200 | 201 | // if size is > 4096, the response will be in multiple packets. 202 | // this needs to be address. get more info about multi-packet responses 203 | // from the RCON protocol specification at 204 | // https://developer.valvesoftware.com/wiki/Source_RCON_Protocol 205 | // currently, this script does not support multi-packet responses. 206 | 207 | $packet_data = fread($this->socket, $size); 208 | $packet_pack = unpack('V1id/V1type/a*body', $packet_data); 209 | 210 | return $packet_pack; 211 | } 212 | } 213 | --------------------------------------------------------------------------------