I requested some information from a server:
<?php
const cloudwards_servers = ["178.32.116.43"];
const masterlist = "http://master.vc-mp.org/servers/";
class Server
{
public $ip = "0.0.0.0";
public $port = 0;
public $version = "Unknown";
public $passworded = false;
public $players = 0;
public $max_players = 0;
public $success = false;
public function __construct($ip, $port)
{
//Create stream
$ip_array = explode(".", $ip);
array_map("intval", $ip_array);
$client = stream_socket_client("udp://{$ip}:{$port}");
stream_set_timeout($client, 1);
//Send request
if ($client === false) return;
$message = "";
$message .= "MP04"; //Magic
$message .= chr($ip_array[0]); //IP byte 0
$message .= chr($ip_array[1]); //IP byte 1
$message .= chr($ip_array[2]); //IP byte 2
$message .= chr($ip_array[3]); //IP byte 3
$message .= chr($port & 0xFF); //Port byte 0
$message .= chr($port >> 8 & 0xFF); //Port byte 1
$message .= "i"; //Opcode information
fwrite($client, $message);
//Receive information
$header = fread($client, 42);
if (strlen($header) < 42) return;
$magic = substr($header, 0, 4); //Magic
$ip = ""; //IP
$ip .= ord(substr($header, 4, 1)); //IP byte 0
$ip .= "."; //IP byte seperator
$ip .= ord(substr($header, 5, 1)); //IP byte 1
$ip .= "."; //IP byte seperator
$ip .= ord(substr($header, 6, 1)); //IP byte 2
$ip .= "."; //IP byte seperator
$ip .= ord(substr($header, 7, 1)); //IP byte 3
$port_1 = ord(substr($header, 8, 1)); //Port byte 0
$port_2 = ord(substr($header, 9, 1)); //Port byte 1
$opcode = substr(10, 1);
}
}
$server = new Server("46.105.184.128", "8194");
And it doesn't feel like replying for some reason, since strlen($header) returns 0.
What am I doing wrong here?
Solved by changing the magic from 'MP04' to 'VCMP'.
Okay, new problem.
I can't convert some lengths into integers.
This works fine:
<?php //for syntax highlighting, not present in actual code
$_max_players = fread($client, 2);
if (strlen($_max_players) < 2) return;
$max_players = 0;
$max_players += ord(substr($_max_players, 0, 1));
$max_players += ord(substr($_max_players, 1, 1)) << 8;
However, this, which uses the same logic, doesn't:
<?php //for syntax highlighting, not present in actual code
$_name_len = fread($client, 4);
if (strlen($_name_len) < 4) return;
$name_len = 0;
$name_len += ord(substr($_name_len, 0, 1));
$name_len += ord(substr($_name_len, 1, 1)) << 8;
$name_len += ord(substr($_name_len, 2, 1)) << 16;
$name_len += ord(substr($_name_len, 3, 1)) << 24;
How should I deal with this?
Its so good that I had added to my fav list in Github:
https://github.com/Rhytz/LU-WebSDK
Use an existing library. That will make your work easier. You can view the code and see how it does those things :)
Quote from: KAKAN on Apr 22, 2017, 04:32 PMIts so good that I had added to my fav list in Github:
https://github.com/Rhytz/LU-WebSDK
Use an existing library. That will make your work easier. You can view the code and see how it does those things :)
This uses a custom SDK which doesn't have to deal with those things and instead passes data directly as a JSON string.
However, I can't force a script into every server to query it.
Solved, I forgot to read the player count.
Here is the class if anyone wants to experiment with it:
<?php
class Server
{
public $ip = "0.0.0.0";
public $port = 0;
public $name = "Unknown";
public $version = "Unknown";
public $passworded = false;
public $players = 0;
public $max_players = 0;
public $map = "Unknown";
public $success = false;
public function __construct($ip, $port)
{
//Set IP and port
$this->ip = $ip;
$this->port = $port;
//Load
$this->Refresh();
}
public function Refresh()
{
$this->success = false;
//Create stream
$ip_array = explode(".", $this->ip);
array_map("intval", $ip_array);
$client = stream_socket_client("udp://{$this->ip}:{$this->port}");
stream_set_timeout($client, 1);
//Send request
if ($client === false) return;
$message = "";
$message .= "VCMP"; //Magic
$message .= chr($ip_array[0]); //IP byte 0
$message .= chr($ip_array[1]); //IP byte 1
$message .= chr($ip_array[2]); //IP byte 2
$message .= chr($ip_array[3]); //IP byte 3
$message .= chr($this->port & 0xFF); //Port byte 0
$message .= chr($this->port >> 8 & 0xFF); //Port byte 1
$message .= "i"; //Opcode 'information'
fwrite($client, $message);
//Receive information
//Header
$header = fread($client, 11);
if (strlen($header) < 11) return;
$magic = substr($header, 0, 4); //Magic
$server_ip = ""; //IP
$server_ip .= ord(substr($header, 4, 1)); //IP byte 0
$server_ip .= "."; //IP byte seperator
$server_ip .= ord(substr($header, 5, 1)); //IP byte 1
$server_ip .= "."; //IP byte seperator
$server_ip .= ord(substr($header, 6, 1)); //IP byte 2
$server_ip .= "."; //IP byte seperator
$server_ip .= ord(substr($header, 7, 1)); //IP byte 3
$server_port = 0;
$server_port += ord(substr($header, 8, 1)); //Port byte 0
$server_port += ord(substr($header, 9, 1)) << 8; //Port byte 1
$opcode = substr($header, 10, 1);
//Authencity checks
if ($magic != "MP04") return;
if ($server_ip != $this->ip) return;
if ($server_port != $this->port) return;
if ($opcode != "i") return;
//Version
$_version = fread($client, 12);
if (strlen($_version) < 12) return;
$version = str_replace("\0", "", $_version);
//Password
$_passworded = fread($client, 1);
if (strlen($_passworded) < 1) return;
$passworded = ord($_passworded) == 1;
//Players
$_players = fread($client, 2);
if (strlen($_players) < 2) return;
$players = 0;
$players += ord(substr($_players, 0, 1));
$players += ord(substr($_players, 1, 1)) << 8;
//Max players
$_max_players = fread($client, 2);
if (strlen($_max_players) < 2) return;
$max_players = 0;
$max_players += ord(substr($_max_players, 0, 1));
$max_players += ord(substr($_max_players, 1, 1)) << 8;
//Server name
$_name_len = fread($client, 4);
if (strlen($_name_len) < 4) return;
$name_len = 0;
$name_len += ord(substr($_name_len, 0, 1));
$name_len += ord(substr($_name_len, 1, 1)) << 8;
$name_len += ord(substr($_name_len, 2, 1)) << 16;
$name_len += ord(substr($_name_len, 3, 1)) << 24;
$name = fread($client, $name_len);
if (strlen($name) < $name_len) return;
//Gamemode
$_gamemode_len = fread($client, 4);
if (strlen($_gamemode_len) < 4) return;
$gamemode_len = 0;
$gamemode_len += ord(substr($_gamemode_len, 0, 1));
$gamemode_len += ord(substr($_gamemode_len, 1, 1)) << 8;
$gamemode_len += ord(substr($_gamemode_len, 2, 1)) << 16;
$gamemode_len += ord(substr($_gamemode_len, 3, 1)) << 24;
$gamemode = fread($client, $gamemode_len);
if (strlen($gamemode) < $gamemode_len) return;
//Map namespace
$_map_len = fread($client, 4);
if (strlen($_map_len) < 4) return;
$map_len = 0;
$map_len += ord(substr($_map_len, 0, 1));
$map_len += ord(substr($_map_len, 1, 1)) << 8;
$map_len += ord(substr($_map_len, 2, 1)) << 16;
$map_len += ord(substr($_map_len, 3, 1)) << 24;
$map = fread($client, $map_len);
if (strlen($map) < $map_len) return;
//We know everything now
fclose($client);
//Load it
$this->name = $name;
$this->version = $version;
$this->passworded = $passworded;
$this->players = $players;
$this->max_players = $max_players;
$this->map = $map;
$this->success = true;
}
}
Usage:
<?php
$server = new Server("127.0.0.1", 8192);
http://pastie.org/9501000
??
:edit: That website seems off. So, this: https://pastebin.com/jkj8RWZL
Quote from: KAKAN on Apr 23, 2017, 05:05 AMThat website seems off.
One of the reasons I had to write my own...
Quote from: EK.IceFlake on Apr 23, 2017, 05:34 AMOne of the reasons I had to write my own...
https://pastebin.com/jkj8RWZL
https://pastebin.com/jkj8RWZL
https://pastebin.com/jkj8RWZL
https://pastebin.com/jkj8RWZL
Couldn't you see that? I've never seen pastebin go off someday. IIRC, I've seen another VCMP Query'ng PHP script.
Instead of wasting 2 days on your PHP script, you could've just searched. 2 days work done in 1 minute :)
Quote from: KAKAN on Apr 23, 2017, 07:18 AMQuote from: EK.IceFlake on Apr 23, 2017, 05:34 AMOne of the reasons I had to write my own...
https://pastebin.com/jkj8RWZL
https://pastebin.com/jkj8RWZL
https://pastebin.com/jkj8RWZL
https://pastebin.com/jkj8RWZL
Couldn't you see that? I've never seen pastebin go off someday. IIRC, I've seen another VCMP Query'ng PHP script.
Instead of wasting 2 days on your PHP script, you could've just searched. 2 days work done in 1 minute :)
I searched for it and couldn't find it...