-
Notifications
You must be signed in to change notification settings - Fork 0
/
minecraftRcon.class.php
122 lines (92 loc) · 3.03 KB
/
minecraftRcon.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php
/*
GITHUB IVKOS/MINECRAFT-QUERY-FOR-PHP <https://github.com/ivkos/Minecraft-Query-for-PHP>
This class was originally written by xPaw. Modifications and additions by ivkos.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
*/
class minecraftRconException extends Exception
{
// Exception thrown by MinecraftRcon class
}
class minecraftRcon
{
/*
* Originally written by xPaw
* Modifications and additions by ivkos
*
* GitHub: https://github.com/ivkos/Minecraft-Query-for-PHP
* Protocol: https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
*/
// Sending
const SERVERDATA_EXECCOMMAND = 2;
const SERVERDATA_AUTH = 3;
// Receiving
const SERVERDATA_RESPONSE_VALUE = 0;
const SERVERDATA_AUTH_RESPONSE = 2;
private $socket;
private $requestID;
public function __destruct()
{
$this->disconnect();
}
public function connect($IP, $port = 25575, $password, $timeout = 3)
{
$this->requestID = 0;
if ($this->socket = fsockopen($IP, (int) $port)) {
socket_set_timeout($this->socket, $timeout);
if (!$this->auth($password)) {
$this->disconnect();
throw new minecraftRconException("Authorization failed.");
}
} else {
throw new MinecraftRconException("Can't open socket.");
}
}
public function disconnect()
{
if ($this->socket) {
fclose($this->socket);
$this->socket = null;
}
}
public function command($String)
{
if (!$this->writeData(self::SERVERDATA_EXECCOMMAND, $String)) {
return false;
}
$data = $this->readData();
if ($data['RequestId'] < 1 || $data['Response'] != self::SERVERDATA_RESPONSE_VALUE) {
return false;
}
return $data['String'];
}
private function auth($password)
{
if (!$this->writeData(self::SERVERDATA_AUTH, $password)) {
return false;
}
$data = $this->readData();
return $data['RequestId'] > -1 && $data['Response'] == self::SERVERDATA_AUTH_RESPONSE;
}
private function readData()
{
$packet = array();
$size = fread($this->socket, 4);
$size = unpack('V1Size', $size);
$size = $size['Size'];
// TODO: Add multiple packets (Source)
$packet = fread($this->socket, $size);
$packet = unpack('V1RequestId/V1Response/a*String/a*String2', $packet);
return $packet;
}
private function writeData($command, $string = "")
{
// Pack the packet together
$data = pack('VV', $this->requestID++, $command) . $string . "\x00\x00\x00";
// Prepend packet length
$data = pack('V', strlen($data)) . $data;
$length = strlen($data);
return $length === fwrite($this->socket, $data, $length);
}
}