244 lines
4.5 KiB
PHP
244 lines
4.5 KiB
PHP
|
<?php
|
||
|
|
||
|
require "geoip2.phar";
|
||
|
use GeoIp2\Database\Reader;
|
||
|
|
||
|
class mumble{
|
||
|
|
||
|
public function __construct($reader_location = "GeoLite2-Country.mmdb"){
|
||
|
|
||
|
$this->reader = new Reader($reader_location);
|
||
|
}
|
||
|
|
||
|
public function ping($domain = "0.0.0.0", $port = 64738){
|
||
|
|
||
|
if(($ip = $this->validate_domain($domain)) === false){
|
||
|
|
||
|
throw new Exception("Server IP points to bad host");
|
||
|
}
|
||
|
|
||
|
$port = (int)$port;
|
||
|
|
||
|
if(!is_int($port)){
|
||
|
|
||
|
throw new Exception("Invalid port specified");
|
||
|
}
|
||
|
|
||
|
$this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||
|
|
||
|
// packet timeout
|
||
|
socket_set_option($this->socket, SOL_SOCKET, SO_RCVTIMEO, ["sec" => 2, "usec" => 0]);
|
||
|
socket_set_option($this->socket, SOL_SOCKET, SO_SNDTIMEO, ["sec" => 2, "usec" => 0]);
|
||
|
|
||
|
$data = [
|
||
|
"version" => null,
|
||
|
//"ident" => null,
|
||
|
"online" => null,
|
||
|
"max" => null,
|
||
|
"bandwidth" => null
|
||
|
];
|
||
|
|
||
|
if(!@socket_connect($this->socket, $ip, $port)){
|
||
|
|
||
|
// could not connect!
|
||
|
socket_close($this->socket);
|
||
|
throw new Exception("Server is offline");
|
||
|
}
|
||
|
|
||
|
$payload = null;
|
||
|
|
||
|
$payload .= pack("i", 0); // request type (int)
|
||
|
$payload .= pack("q", 0); // identify response (long long)
|
||
|
|
||
|
socket_write($this->socket, $payload);
|
||
|
|
||
|
$data["ping"] = microtime(true);
|
||
|
$this->socket_recv($rawdata, 24);
|
||
|
|
||
|
$data["ping"] = round((microtime(true) - $data["ping"]) * 1000);
|
||
|
|
||
|
// separate data
|
||
|
$zero = true;
|
||
|
|
||
|
for($i=0; $i<4; $i++){
|
||
|
|
||
|
$str = hexdec(bin2hex($rawdata[$i]));
|
||
|
|
||
|
if(
|
||
|
$zero === true &&
|
||
|
$str != 0
|
||
|
){
|
||
|
$zero = false;
|
||
|
}
|
||
|
|
||
|
if($zero === false){
|
||
|
$data["version"] .= $str;
|
||
|
|
||
|
if($i !== 3){
|
||
|
|
||
|
$data["version"] .= ".";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if($data["version"] == null){
|
||
|
|
||
|
$data["version"] = "1.0.0";
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
for($i=4; $i<12; $i++){
|
||
|
|
||
|
$data["ident"] .= $rawdata[$i];
|
||
|
}*/
|
||
|
|
||
|
for($i=12; $i<16; $i++){
|
||
|
|
||
|
$data["online"] .= $rawdata[$i];
|
||
|
}
|
||
|
|
||
|
for($i=16; $i<20; $i++){
|
||
|
|
||
|
$data["max"] .= $rawdata[$i];
|
||
|
}
|
||
|
|
||
|
for($i=20; $i<24; $i++){
|
||
|
|
||
|
$data["bandwidth"] .= $rawdata[$i];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Get name and website
|
||
|
*/
|
||
|
$stream = fopen("list.json", "r");
|
||
|
$json = fread($stream, filesize("list.json"));
|
||
|
fclose($stream);
|
||
|
|
||
|
$json = json_decode($json, true);
|
||
|
|
||
|
$offset = -1;
|
||
|
|
||
|
for($i=0; $i<count($json); $i++){
|
||
|
|
||
|
for($k=0; $k<count($json[$i]["ip"]); $k++){
|
||
|
|
||
|
if(
|
||
|
(
|
||
|
$json[$i]["ip"][$k] == $domain ||
|
||
|
$json[$i]["ip"][$k] == $ip
|
||
|
) &&
|
||
|
$json[$i]["port"] === $port
|
||
|
){
|
||
|
|
||
|
$offset = $i;
|
||
|
break 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if($offset !== -1){
|
||
|
|
||
|
$data["name"] = $json[$offset]["name"];
|
||
|
$data["website"] = $json[$offset]["url"];
|
||
|
|
||
|
if(!preg_match('/^https?:\/\//', $data["website"])){
|
||
|
|
||
|
$data["website"] = "https://" . $data["website"];
|
||
|
}
|
||
|
|
||
|
$data["domains"] = $json[$offset]["ip"];
|
||
|
}else{
|
||
|
|
||
|
$data["name"] = null;
|
||
|
$data["website"] = null;
|
||
|
|
||
|
$data["domains"][] = $domain;
|
||
|
if($domain != $ip){
|
||
|
|
||
|
$data["domains"][] = $ip;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// get country
|
||
|
try{
|
||
|
$db = $this->reader->country($ip);
|
||
|
|
||
|
$data["countryname"] = $db->country->name;
|
||
|
$data["countrycode"] = $db->country->isoCode;
|
||
|
}catch(Exception $error){
|
||
|
|
||
|
$data["countryname"] = "Unknown";
|
||
|
$data["countrycode"] = "UN";
|
||
|
}
|
||
|
|
||
|
// unpack
|
||
|
$data = [
|
||
|
"status" => "ok",
|
||
|
"server" => [
|
||
|
"name" => $data["name"],
|
||
|
"domains" => $data["domains"],
|
||
|
"ping" => $data["ping"],
|
||
|
"online" => hexdec(bin2hex($data["online"])),
|
||
|
"max" => hexdec(bin2hex($data["max"])),
|
||
|
//"ident" => unpack("q", $data["ident"])[1],
|
||
|
"bandwidth" => (hexdec(bin2hex($data["bandwidth"])) / 1000) . " kbit/s",
|
||
|
"country" => [
|
||
|
"name" => $data["countryname"],
|
||
|
"code" => $data["countrycode"],
|
||
|
],
|
||
|
"version" => $data["version"],
|
||
|
"website" => $data["website"]
|
||
|
]
|
||
|
];
|
||
|
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
|
||
|
private function validate_domain($url){
|
||
|
|
||
|
$ip =
|
||
|
str_replace(
|
||
|
["[", "]"], // handle ipv6
|
||
|
"",
|
||
|
$url
|
||
|
);
|
||
|
|
||
|
// if its not an IP
|
||
|
if(!filter_var($ip, FILTER_VALIDATE_IP)){
|
||
|
|
||
|
// resolve domain's IP
|
||
|
try{
|
||
|
$ip = gethostbyname($url . ".");
|
||
|
|
||
|
}catch(Exception $error){
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// check if its localhost
|
||
|
return filter_var(
|
||
|
$ip,
|
||
|
FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
private function socket_recv(&$data, $len){
|
||
|
|
||
|
error_reporting(0);
|
||
|
$bytes = socket_recv($this->socket, $data, $len, MSG_WAITALL);
|
||
|
error_reporting(1);
|
||
|
|
||
|
if(
|
||
|
$bytes === false || // no data
|
||
|
$bytes === 0 // disconnected by remote peer
|
||
|
){
|
||
|
|
||
|
throw new Exception("Timed out");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
?>
|