1: <?php
2: namespace aliuly\common;
3:
4:
5:
6:
7: 8: 9: 10: 11: 12:
13: abstract class Rcon {
14: const RCTYPE_COMMAND = 2;
15: const RCTYPE_AUTH = 3;
16:
17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
28: static public function connect($host,$port,$auth) {
29: if (!($sock = @fsockopen($host,$port, $errno, $errstr, 30))) {
30: return "Unable to open socket: $errstr ($errno)";
31: }
32: stream_set_timeout($sock,3,0);
33: $id = 0;
34:
35: $pktid = self::writePkt(self::RCTYPE_AUTH,$auth,$sock,$id);
36: $ret = [self::readPkt($sock)];
37: if (is_null($ret)) return "Protocol error";
38: if ($ret[0] == -1) return "Authentication failure";
39:
40: return [$sock,$id];
41: }
42:
43: 44: 45: 46: 47: 48: 49:
50: static public function writePkt($type,$payload,$sock,&$id) {
51: $myid = ++$id;
52: $data = pack("VVV",strlen($payload),$myid,$type).
53: ($payload === "" ? "\x00" : $payload)."\x00";
54: fwrite($sock,$data);
55: return $myid;
56: }
57: 58: 59: 60:
61: static public function readPkt($sock) {
62: $d = fread($sock, 4);
63: if ($d === false || $d === "" || strlen($d) < 4) return NULL;
64: list($size) = array_values(unpack("V1",$d));
65: if ($size < 0 or $size > 65535) return NULL;
66: list($id) = array_values(unpack("V1", fread($sock, 4)));
67: list($type) = array_values(unpack("V1", fread($sock, 4)));
68: $payload = rtrim(fread($sock,$size-8));
69: return [$id,$type,$payload];
70: }
71: 72: 73: 74: 75: 76: 77: 78: 79:
80: static public function cmd($cmd,$sock,&$id) {
81: $myid = self::writePkt(self::RCTYPE_COMMAND,$cmd,$sock,$id);
82: $ret = self::readPkt($sock);
83: if (is_null($ret)) return "Protocol error";
84: list ($rid,$type,$payload) = $ret;
85: if ($rid !== $myid) return "Sequencing error";
86: return [$payload,$type];
87: }
88: }
89: