Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // A verbose version of server query. Requires enable-query=true in server.properties
- function full_stat($host, $port = 25565, $timeout_s = 0, $timeout_us = 50000)
- {
- $errno = 0;
- $errstr = "";
- //Set up our socket
- $fp = @fsockopen("udp://" . $host, $port, $errno, $errstr);
- if (! $fp)
- {
- //echo "no socket!<br />\n";
- return array();
- }
- // Handshake:
- // Get the challenge token; send 0xFE 0xFD 0x09 and a 4-byte session id
- $str1 = "\xFE\xFD\x09\x00\x00\x00\x01"; // Arbitrary session id at the end (4 bytes) (we use 00 00 00 01 here)
- fwrite($fp, $str1);
- // Set the time out limit
- stream_set_timeout($fp, $timeout_s, $timeout_us);
- $arr = stream_get_meta_data($fp);
- if ($arr['timed_out'])
- {
- //echo "timed out!<br />\n";
- return array();
- }
- $resp = fread($fp, 4096);
- // Check that we got something back
- if (strlen($resp) == 0)
- {
- //echo "empty response!<br />\n";
- return array();
- }
- // Check for a valid response
- if ($resp[0] != "\x09")
- {
- //echo "not a valid response!<br />\n";
- return array();
- }
- // Parse the challenge token from string to integer
- $token = 0;
- for ($i = 5; $i < (strlen($resp) - 1); $i++)
- {
- $token *= 10;
- $token += $resp[$i];
- }
- // Divide the int32 into 4 bytes
- $token_arr = array( 0 => ($token / (256*256*256)) % 256,
- 1 => ($token / (256*256)) % 256,
- 2 => ($token / 256) % 256,
- 3 => ($token % 256)
- );
- // Note that the challenge token is bound to your IP and port (as opposed to the [session ID]), and
- // lasts up to 30 seconds. You read that right, it's up to; it's not "your token will expire
- // after 30 seconds", it's "every token ever" is expired every 30 seconds. This means it's entirely
- // possible that you may get a token and use it within the same second and have it expire.
- // Get the full version of server status
- // Session ID and challenge tokens appended to magic header 0xFE 0xFD and command byte 0x00
- // Payload padded to 8 bytes
- $str = "\xFE\xFD\x00\x00\x00\x00\x01"
- . chr($token_arr[0]) . chr($token_arr[1]) . chr($token_arr[2]) . chr($token_arr[3])
- . "\x00\x00\x00\x00";
- fwrite($fp, $str);
- $data = fread($fp, 4096);
- $full_stat = substr($data, 16); // Strip the crap from the start
- $tmp = explode("\x00\x01player_\x00\x00", $full_stat); // First, split the payload in two parts
- $keysvalues = explode("\x00", $tmp[0]); // Divide the first part from every NULL-terminated string end into key1 val1 key2 val2...
- unset($keysvalues[count($keysvalues) - 1]); // Unset the last entry, because the are two 0x00 bytes at the end
- // Strip all the NULL-bytes from the end of the player list
- $tmp = $tmp[1];
- $i = strlen($tmp) - 1;
- while ($i >= 0)
- {
- if (ord($tmp[$i]) != 0)
- {
- break;
- }
- $i--;
- }
- // Split the player information (if any)
- if ($i > 0)
- {
- $tmp = substr($tmp, 0, $i + 1);
- $players = explode("\x00", $tmp); // Explode the player information from the NULL-byte positions
- }
- else
- {
- $tmp = FALSE;
- }
- // Arrange the key => value pairs into an array
- $info = array();
- for ($i = 0; $i < count($keysvalues); $i += 2)
- {
- if ($keysvalues[$i] == "")
- {
- break;
- }
- $info[$keysvalues[$i]] = $keysvalues[$i + 1];
- }
- // Collect all the information into one array
- $full_stat = $info;
- $full_stat['players'] = $players;
- return $full_stat;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement