Serving a payment option for my minecraft server so I don't have to pay for it all alone
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

RCon.class.php 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <?php
  2. /**
  3. * See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for
  4. * more information about Source RCON Packets
  5. *
  6. * PHP Version 7
  7. *
  8. * @copyright 2013-2017 Chris Churchwell
  9. * @author thedudeguy
  10. * @link https://github.com/thedudeguy/PHP-Minecraft-Rcon
  11. */
  12. class Rcon
  13. {
  14. private $host;
  15. private $port;
  16. private $password;
  17. private $timeout;
  18. private $socket;
  19. private $authorized = false;
  20. private $lastResponse = '';
  21. const PACKET_AUTHORIZE = 5;
  22. const PACKET_COMMAND = 6;
  23. const SERVERDATA_AUTH = 3;
  24. const SERVERDATA_AUTH_RESPONSE = 2;
  25. const SERVERDATA_EXECCOMMAND = 2;
  26. const SERVERDATA_RESPONSE_VALUE = 0;
  27. /**
  28. * Create a new instance of the Rcon class.
  29. *
  30. * @param string $host
  31. * @param integer $port
  32. * @param string $password
  33. * @param integer $timeout
  34. */
  35. public function __construct($host, $port, $password, $timeout)
  36. {
  37. $this->host = $host;
  38. $this->port = $port;
  39. $this->password = $password;
  40. $this->timeout = $timeout;
  41. }
  42. /**
  43. * Get the latest response from the server.
  44. *
  45. * @return string
  46. */
  47. public function getResponse()
  48. {
  49. return $this->lastResponse;
  50. }
  51. /**
  52. * Connect to a server.
  53. *
  54. * @return boolean
  55. */
  56. public function connect()
  57. {
  58. $this->socket = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
  59. if (!$this->socket) {
  60. $this->lastResponse = $errstr;
  61. return false;
  62. }
  63. //set timeout
  64. stream_set_timeout($this->socket, 3, 0);
  65. // check authorization
  66. return $this->authorize();
  67. }
  68. /**
  69. * Disconnect from server.
  70. *
  71. * @return void
  72. */
  73. public function disconnect()
  74. {
  75. if ($this->socket) {
  76. fclose($this->socket);
  77. }
  78. $this->authorized = false;
  79. }
  80. /**
  81. * True if socket is connected and authorized.
  82. *
  83. * @return boolean
  84. */
  85. public function isConnected()
  86. {
  87. return $this->authorized;
  88. }
  89. /**
  90. * Send a command to the connected server.
  91. *
  92. * @param string $command
  93. *
  94. * @return boolean|mixed
  95. */
  96. public function sendCommand($command)
  97. {
  98. if (!$this->isConnected()) {
  99. return false;
  100. }
  101. // send command packet
  102. $this->writePacket(self::PACKET_COMMAND, self::SERVERDATA_EXECCOMMAND, $command);
  103. // get response
  104. $response_packet = $this->readPacket();
  105. if ($response_packet['id'] == self::PACKET_COMMAND) {
  106. if ($response_packet['type'] == self::SERVERDATA_RESPONSE_VALUE) {
  107. $this->lastResponse = $response_packet['body'];
  108. return $response_packet['body'];
  109. }
  110. }
  111. return false;
  112. }
  113. /**
  114. * Log into the server with the given credentials.
  115. *
  116. * @return boolean
  117. */
  118. private function authorize()
  119. {
  120. $this->writePacket(self::PACKET_AUTHORIZE, self::SERVERDATA_AUTH, $this->password);
  121. $response_packet = $this->readPacket();
  122. if ($response_packet['type'] == self::SERVERDATA_AUTH_RESPONSE) {
  123. if ($response_packet['id'] == self::PACKET_AUTHORIZE) {
  124. $this->authorized = true;
  125. return true;
  126. }
  127. }
  128. $this->disconnect();
  129. return false;
  130. }
  131. /**
  132. * Writes a packet to the socket stream.
  133. *
  134. * @param $packetId
  135. * @param $packetType
  136. * @param string $packetBody
  137. *
  138. * @return void
  139. */
  140. private function writePacket($packetId, $packetType, $packetBody)
  141. {
  142. /*
  143. Size 32-bit little-endian Signed Integer Varies, see below.
  144. ID 32-bit little-endian Signed Integer Varies, see below.
  145. Type 32-bit little-endian Signed Integer Varies, see below.
  146. Body Null-terminated ASCII String Varies, see below.
  147. Empty String Null-terminated ASCII String 0x00
  148. */
  149. //create packet
  150. $packet = pack('VV', $packetId, $packetType);
  151. $packet = $packet.$packetBody."\x00";
  152. $packet = $packet."\x00";
  153. // get packet size.
  154. $packet_size = strlen($packet);
  155. // attach size to packet.
  156. $packet = pack('V', $packet_size).$packet;
  157. // write packet.
  158. fwrite($this->socket, $packet, strlen($packet));
  159. }
  160. /**
  161. * Read a packet from the socket stream.
  162. *
  163. * @return array
  164. */
  165. private function readPacket()
  166. {
  167. //get packet size.
  168. $size_data = fread($this->socket, 4);
  169. $size_pack = unpack('V1size', $size_data);
  170. $size = $size_pack['size'];
  171. // if size is > 4096, the response will be in multiple packets.
  172. // this needs to be address. get more info about multi-packet responses
  173. // from the RCON protocol specification at
  174. // https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
  175. // currently, this script does not support multi-packet responses.
  176. $packet_data = fread($this->socket, $size);
  177. $packet_pack = unpack('V1id/V1type/a*body', $packet_data);
  178. return $packet_pack;
  179. }
  180. }