done
This commit is contained in:
243
mumble-ping.php
Executable file
243
mumble-ping.php
Executable file
@@ -0,0 +1,243 @@
|
||||
<?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");
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
Reference in New Issue
Block a user