RCON : Lecture de packets sur socket UDP
Fermé
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
-
Modifié le 15 août 2018 à 21:04
Exileur Messages postés 1475 Date d'inscription mercredi 31 août 2011 Statut Membre Dernière intervention 16 décembre 2022 - 19 août 2018 à 02:46
Exileur Messages postés 1475 Date d'inscription mercredi 31 août 2011 Statut Membre Dernière intervention 16 décembre 2022 - 19 août 2018 à 02:46
4 réponses
yg_be
Messages postés
23462
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
6 février 2025
Ambassadeur
1 568
18 août 2018 à 15:04
18 août 2018 à 15:04
tu peux aussi réutiliser, ou t'inspirer de ceci:
https://github.com/thedudeguy/PHP-Minecraft-Rcon/blob/master/src/Rcon.php
https://github.com/thedudeguy/PHP-Minecraft-Rcon/blob/master/src/Rcon.php
yg_be
Messages postés
23462
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
6 février 2025
Ambassadeur
1 568
Modifié le 16 août 2018 à 13:25
Modifié le 16 août 2018 à 13:25
bonjour, le plus simple n'est-il pas de lire jusqu'à recevoir tout ce que tu attends?
ne devrais-tu pas inverser le test dans le while?
ne devrais-tu pas inverser le test dans le while?
yg_be
Messages postés
23462
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
6 février 2025
1 568
Modifié le 16 août 2018 à 14:49
Modifié le 16 août 2018 à 14:49
exemple:
do { $buffer = fread ($this->socket, 1000); if ($buffer == '') return 'Error'; $result .= $buffer; } while ! (substr($result, - 9) == "\x20\x20\x20\x20\x20\x20\x0a\x00\x00");
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
150
Modifié le 16 août 2018 à 19:28
Modifié le 16 août 2018 à 19:28
Hello,
Enfaite, mon while ce base sur la donnée même et non pas la structure du packet.
J'en ai parlé au boulot vite fais, a priori, je me suis pas asser penché sur le proto.
Je viens de choper une trame (proto plus rececnt) sur le site de steam https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
Mon collegue m'a aussi conseillé de changer de methode et de plutot regarder du coté :
https://www.php.net/unpack
http://php.net/manual/fr/function.socket-create.php
https://www.php.net/manual/fr/function.socket-bind.php
https://www.php.net/manual/fr/function.socket-sendto.php
https://www.php.net/manual/fr/function.socket-select.php
https://www.php.net/manual/fr/function.socket-recv.php
Je te tiens au courant.
A plus
Enfaite, mon while ce base sur la donnée même et non pas la structure du packet.
J'en ai parlé au boulot vite fais, a priori, je me suis pas asser penché sur le proto.
Je viens de choper une trame (proto plus rececnt) sur le site de steam https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
Mon collegue m'a aussi conseillé de changer de methode et de plutot regarder du coté :
https://www.php.net/unpack
http://php.net/manual/fr/function.socket-create.php
https://www.php.net/manual/fr/function.socket-bind.php
https://www.php.net/manual/fr/function.socket-sendto.php
https://www.php.net/manual/fr/function.socket-select.php
https://www.php.net/manual/fr/function.socket-recv.php
Je te tiens au courant.
A plus
yg_be
Messages postés
23462
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
6 février 2025
1 568
>
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
18 août 2018 à 09:07
18 août 2018 à 09:07
le mieux me semble alors de lire les 4 premiers octets, qui contiennent la taille du message restant. et ensuite de lire jusqu'à obtenir cette taille.
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
150
Modifié le 18 août 2018 à 11:29
Modifié le 18 août 2018 à 11:29
Salut,
La methode utilisée pour l'ouverture de mon socket était
En utilisant
Ducoup :
Me retourne :
En soit, j'ai maintenant toutes les infos qu'il me faut sur le packet. Sauf que c'est de l'UDP et que j'ai bien peur de ne pas pouvoir techniquement répondre à la problématique, je ne sais pas combien de packet vont arriver.
Et vu que ça n'a pas l'air d'étre géré dans le protocole suppérieur je suis pas sure de pouvoir faire ce que je veux.
Il va surement faloir que je m'oriente vers une boucle infinie dans un thread ou qq chose comme ça.
Je continue de chercher.
A plus,
La methode utilisée pour l'ouverture de mon socket était
fsockopen()
En utilisant
socket_create ( AF_INET, SOCK_RAW, SOL_UDP ), je peux avoir les header IP, et UDP.
Ducoup :
include 'IpHeader.php'; include 'UDPHeader.php'; const PROTO_UDP = '17'; const PROTO_TCP = '6'; // Socket UDP if (($socket = @socket_create ( AF_INET, SOCK_RAW, SOL_UDP )) === FALSE) { echo "Could not create socket !"; exit ( 1 ); } socket_set_nonblock ( $socket ); echo "Starting sniffing...\n"; while ( TRUE ) { if ((socket_recv ( $socket, $raw, 65536, 0 )) > 0) { $packet = IpHeader::getHeader ( $raw ); print_r($packet); if ($packet [IpHeader::PROTO] == PROTO_UDP) { // Datagram UDP $payload = UdpHeader::getHeader ( $packet [IpHeader::PAYLOAD] ); print_r ( $payload ); } } usleep ( 100 ); }
Me retourne :
Array ( [ip_ver_len] => 5 [tos] => 0 [tot_len] => 75 [identification] => 3833 [indic_frag_offset] => 16384 [ttl] => 64 [protocol] => 17 [checksum] => 11635 [src_addr] => 127.0.0.53 [dst_addr] => 127.0.0.1 [payload] => 0035a9690037fe7e75278180000100000000000012636f6e6e65637469766974792d636865636b067562756e747503636f6d00001c0001 ) Array ( [src_port] => 53 [dst_port] => 43369 [length] => 55 [checksum] => 65150 [data] => 75278180000100000000000012636f6e6e65637469766974792d636865636b067562756e747503636f6d00001c0001 )
En soit, j'ai maintenant toutes les infos qu'il me faut sur le packet. Sauf que c'est de l'UDP et que j'ai bien peur de ne pas pouvoir techniquement répondre à la problématique, je ne sais pas combien de packet vont arriver.
Et vu que ça n'a pas l'air d'étre géré dans le protocole suppérieur je suis pas sure de pouvoir faire ce que je veux.
Il va surement faloir que je m'oriente vers une boucle infinie dans un thread ou qq chose comme ça.
Je continue de chercher.
A plus,
yg_be
Messages postés
23462
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
6 février 2025
1 568
18 août 2018 à 12:09
18 août 2018 à 12:09
tout cela est intéressant, mais inutile.
si tu lis les 4 premiers octets via fread, tu connaitras le nombre d'octets à lire ensuite.
exemple pour lire les 4 premiers octets:
si tu lis les 4 premiers octets via fread, tu connaitras le nombre d'octets à lire ensuite.
exemple pour lire les 4 premiers octets:
$result = ''; do { $buffer = fread ($this->socket, 4-strlen($result)); if ($buffer == '') return 'Error'; $result .= $buffer; } while ( len($result) <> 4 );
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
150
18 août 2018 à 20:11
18 août 2018 à 20:11
ok, comme ça je peux récupéré les 4 premier octer (donc les 32 premier bit)
Concrétement, dérière, je fais :
Beh tout mes packet font :
Concrétement, dérière, je fais :
$size = unpack("Vsize", substr($buf, 0, 4)); var_dump($size);
Beh tout mes packet font :
array(1) {
["size"]=>
int(4294967295)
}
array(1) {
["size"]=>
int(4294967295)
}
array(1) {
["size"]=>
int(4294967295)
}
array(1) {
["size"]=>
int(4294967295)
}
yg_be
Messages postés
23462
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
6 février 2025
1 568
>
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
18 août 2018 à 20:48
18 août 2018 à 20:48
Beh, comment obtiens-tu "tous tes paquets"?
Peux-tu partager ton code complet, il n'est pas impossible que tu aies fait une erreur quelque part.
Utile aussi de faire
Peux-tu partager ton code complet, il n'est pas impossible que tu aies fait une erreur quelque part.
Utile aussi de faire
var_dump($sbuf);, ne penses-tu pas?
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
150
19 août 2018 à 00:07
19 août 2018 à 00:07
C'est 'un fork' de la class rcon_hl_net.php
La fonction en cause est Communicate($command)
Pour l'instant je :
- Execute la commande voulu
- Execute une commande vide
- Lit le premier packet reçu
- Check si ce packet est est une réponse ou le packet de kerator
- Check si d'autre packet sont en attente
Soit le résultat est complet,
Soit ça plante avec un "Could not receive response after 3 try: [11] Resource temporarily unavailable",
Soit le résultat est tronqué.
La fonction en cause est Communicate($command)
Pour l'instant je :
- Execute la commande voulu
- Execute une commande vide
- Lit le premier packet reçu
- Check si ce packet est est une réponse ou le packet de kerator
- Check si d'autre packet sont en attente
Soit le résultat est complet,
Soit ça plante avec un "Could not receive response after 3 try: [11] Resource temporarily unavailable",
Soit le résultat est tronqué.
<?php class Rcon { var $challenge_number; var $connected; var $server_ip; var $server_password; var $server_port; var $socket; function Rcon() { $this->challenge_number = 0; $this->connected = true; $this->server_ip = ""; $this->server_port = 27015; $this->server_password = ""; } function Connect($server_ip, $server_port, $server_password = "") { $this->server_ip = gethostbyname($server_ip); $this->server_port = $server_port; $this->server_password = $server_password; $sock = socket_create(AF_INET, SOCK_DGRAM, 0); $timeout = array('sec'=>3, 'usec'=>0); socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,$timeout); if(is_resource($sock)) { echo "Connected to " .$this->server_ip .PHP_EOL; $this->connected = true; } else { $this->connected = false; echo "Can't connect to " .$this->server_ip. " : " .PHP_EOL; return false; } $this->socket = $sock; return true; } function Disconnect() { socket_close($this->socket); $connected = false; } function IsConnected() { return $this->connected; } function ServerInfo() { if(!$this->connected) return $this->connected; $status = $this->RconCommand("status"); if(!$status || trim($status) == "Bad rcon_password.") return $status; $line = explode("\n", $status); $map = substr($line[3], strpos($line[3], ":") + 1); $players = trim(substr($line[4], strpos($line[4], ":") + 1)); $active = explode(" ", $players); $result["ip"] = trim(substr($line[2], strpos($line[2], ":") + 1)); $result["name"] = trim(substr($line[0], strpos($line[0], ":") + 1)); $result["map"] = trim(substr($map, 0, strpos($map, "at:"))); $result["mod"] = "Counterstrike " . trim(substr($line[1], strpos($line[1], ":") + 1)); $result["game"] = "Halflife"; $result["activeplayers"] = $active[0]; $result["maxplayers"] = substr($active[2], 1); //format player info for($i = 1; $i <= $result["activeplayers"]; $i++) { $tmp = $line[$i + 6]; if(substr_count($tmp, "#") <= 0) break; $begin = strpos($tmp, "\"") + 1; $end = strrpos($tmp, "\""); $result[$i]["name"] = substr($tmp, $begin, $end - $begin); $tmp = trim(substr($tmp, $end + 1)); $end = strpos($tmp, " "); $result[$i]["id"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["wonid"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["frag"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["time"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["ping"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $tmp = trim(substr($tmp, $end)); $result[$i]["adress"] = $tmp; } return $result; } function ServerMaps($pagenumber = 0) { if(!$this->connected) return $this->connected; $maps = $this->RconCommand("maps *", $pagenumber); if(!$maps || trim($maps) == "Bad rcon_password.") return $maps; $line = explode("\n", $maps); $count = sizeof($line) - 4; for($i = 0; $i <= $count; $i++) { $text = $line[$i]; if(strstr($text, "Dir:")) { $mapcount = 0; $directory = strstr($text, " "); } else if(strstr($text, "(fs)")) { $mappath = strstr($text, " "); if(!($tmpmap = strrchr($mappath, "/"))) $tmpmap = $mappath; $result[$directory][$i] = substr($tmpmap, 1, strpos($tmpmap, ".") - 1); } } return $result; } function Info() { if(!$this->connected) return $this->connected; $command = "\xff\xff\xff\xffTSource Engine Query\0\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; echo 'DC INFOS' .PHP_EOL; return false; } $buffer = explode("\x00", $buffer); $result["ip"] = substr($buffer[0], 5); $result["name"] = $buffer[1]; $result["map"] = $buffer[2]; $result["mod"] = $buffer[3]; $result["game"] = $buffer[4]; $result["activeplayers"] = (strlen($buffer[5]) > 1)?ord($buffer[5][0]):"0"; $result["maxplayers"] = (strlen($buffer[5]) > 1)?ord($buffer[5][1]):"0"; return $result; } function Players() { if(!$this->connected) return $this->connected; $command = "\xff\xff\xff\xffD\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; echo 'DC PLAYERS' .PHP_EOL; return false; } $buffer = substr($buffer, 1); for($i = 1; strlen($buffer) > 0; $i++) { $tmp = strpos($buffer, "\x00"); $result[$i]["name"] = substr($buffer, 1, $tmp); $result[$i]["frag"] = ord($buffer[$tmp + 1]) + (ord($buffer[$tmp + 2]) << 8) + (ord($buffer[$tmp + 3]) << 16) + (ord($buffer[$tmp + 4]) << 24); $tmptime = @unpack('ftime', substr($buffer, $tmp + 5, 4)); $result[$i]["time"] = date('i:s', round($tmptime['time'], 0) + 82800); $buffer = substr($buffer, $tmp + 9); } return $result; } function ServerRules() { if(!$this->connected) return $this->connected; $command = "\xff\xff\xff\xffE\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; return false; } $buffer = substr($buffer, 2); $buffer = explode("\x00", $buffer); $buffer_count = floor(sizeof($buffer) / 2); for($i = 0; $i < $buffer_count; $i++) { $result[$buffer[2 * $i]] = $buffer[2 * $i + 1]; } ksort($result); return $result; } function GetChallenge() { socket_sendto($this->socket, "\xff\xff\xff\xffchallenge rcon\n", strlen("\xff\xff\xff\xffchallenge rcon\n") , 0 , $this->server_ip , $this->server_port); socket_recvfrom($this->socket, $buffer, 4096, 0, $server, $port); if(trim($buffer) == "") { $this->connected = false; return false; } //get challenge number $buffer = explode(" ", $buffer); $this->challenge_number = trim($buffer[2]); } function RconCommand($command) { if(!$this->connected) return $this->connected; if($this->challenge_number == "") { $this->GetChallenge(); } $command = "\xff\xff\xff\xffrcon $this->challenge_number \"$this->server_password\" $command\n"; $result = $this->Communicate($command); return trim($result); } function Communicate($command) { if(!$this->connected) return $this->connected; if($command != "") { if( ! socket_sendto($this->socket, $command , strlen($command) , 0 , $this->server_ip , $this->server_port)) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not send data: [$errorcode] $errormsg \n"); } $cmd_validation = "\xff\xff\xff\xffrcon $this->challenge_number \"$this->server_password\"\n"; if( ! socket_sendto($this->socket, $cmd_validation, strlen($cmd_validation) , 0 , $this->server_ip , $this->server_port)) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not send validation: [$errorcode] $errormsg \n"); } } usleep(500); $result = ''; $tryNb = 0; $stayInWhile = TRUE; $packetWaiting = TRUE; do { if(socket_recvfrom($this->socket, $buf, 4096, 0, $server, $port) === FALSE) { $tryNb++; if ($tryNb >= 3 ) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not receive response after $tryNb try: [$errorcode] $errormsg \n"); } } $result .= substr($buf, 5); $toDump[] = bin2hex($buf); $read = array($this->socket); $write = NULL; $except = NULL; $packetWaiting = socket_select($read, $write, $except, 0); if (bin2hex($buf) == 'ffffffff6c0000') $stayInWhile = FALSE; if ($packetWaiting > 0) $packetWaiting = TRUE; else $packetWaiting = FALSE; usleep(300); } while ($stayInWhile || $packetWaiting ); var_dump($toDump); usleep(500); return $result; } //function Communicate($buffer) } $server = 'X.X.X.X'; $port = 27015; $M = new Rcon; $M->connect($server, $port, "Password"); print_r($M->ServerInfo()); print_r($M->RconCommand("meta")); print_r($M->RconCommand("meta cvars")); $M->disconnect(); ?>
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
150
Modifié le 19 août 2018 à 00:41
Modifié le 19 août 2018 à 00:41
Je viens de modifier l'ouverture du socket.
Comme concrétement, je ne veux pas un flux, mais seulement la réponse à ma requette, j'ouvre et ferme le flux seulement quand necessaire. Donc inséré dans Communication()
J'ai modifier la condition du while aussi.
Comme concrétement, je ne veux pas un flux, mais seulement la réponse à ma requette, j'ouvre et ferme le flux seulement quand necessaire. Donc inséré dans Communication()
J'ai modifier la condition du while aussi.
<?php class Rcon { var $challenge_number; var $connected; var $server_ip; var $server_password; var $server_port; var $socket; function Rcon() { $this->challenge_number = 0; $this->connected = true; $this->server_ip = ""; $this->server_port = 27015; $this->server_password = ""; } function __construct($server_ip, $server_port, $server_password = "") { $this->server_ip = gethostbyname($server_ip); $this->server_port = $server_port; $this->server_password = $server_password; } function Connect() { $sock = socket_create(AF_INET, SOCK_DGRAM, 0); $timeout = array('sec'=>1, 'usec'=>0); socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,$timeout); socket_set_block($sock); if(is_resource($sock)) { echo "Connected to " .$this->server_ip .PHP_EOL; $this->connected = true; } else { $this->connected = false; echo "Can't connect to " .$this->server_ip. " : " .PHP_EOL; return false; } $this->socket = $sock; return true; } function Disconnect() { socket_close($this->socket); $connected = false; } function IsConnected() { return $this->connected; } function ServerInfo() { $status = $this->RconCommand("status"); if(!$status || trim($status) == "Bad rcon_password.") return $status; $line = explode("\n", $status); $map = substr($line[3], strpos($line[3], ":") + 1); $players = trim(substr($line[4], strpos($line[4], ":") + 1)); $active = explode(" ", $players); $result["ip"] = trim(substr($line[2], strpos($line[2], ":") + 1)); $result["name"] = trim(substr($line[0], strpos($line[0], ":") + 1)); $result["map"] = trim(substr($map, 0, strpos($map, "at:"))); $result["mod"] = "Counterstrike " . trim(substr($line[1], strpos($line[1], ":") + 1)); $result["game"] = "Halflife"; $result["activeplayers"] = $active[0]; $result["maxplayers"] = substr($active[2], 1); //format player info for($i = 1; $i <= $result["activeplayers"]; $i++) { $tmp = $line[$i + 6]; if(substr_count($tmp, "#") <= 0) break; $begin = strpos($tmp, "\"") + 1; $end = strrpos($tmp, "\""); $result[$i]["name"] = substr($tmp, $begin, $end - $begin); $tmp = trim(substr($tmp, $end + 1)); $end = strpos($tmp, " "); $result[$i]["id"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["wonid"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["frag"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["time"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["ping"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $tmp = trim(substr($tmp, $end)); $result[$i]["adress"] = $tmp; } return $result; } function ServerMaps($pagenumber = 0) { $maps = $this->RconCommand("maps *", $pagenumber); if(!$maps || trim($maps) == "Bad rcon_password.") return $maps; $line = explode("\n", $maps); $count = sizeof($line) - 4; for($i = 0; $i <= $count; $i++) { $text = $line[$i]; if(strstr($text, "Dir:")) { $mapcount = 0; $directory = strstr($text, " "); } else if(strstr($text, "(fs)")) { $mappath = strstr($text, " "); if(!($tmpmap = strrchr($mappath, "/"))) $tmpmap = $mappath; $result[$directory][$i] = substr($tmpmap, 1, strpos($tmpmap, ".") - 1); } } return $result; } function Info() { $command = "\xff\xff\xff\xffTSource Engine Query\0\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; echo 'DC INFOS' .PHP_EOL; return false; } $buffer = explode("\x00", $buffer); $result["ip"] = substr($buffer[0], 5); $result["name"] = $buffer[1]; $result["map"] = $buffer[2]; $result["mod"] = $buffer[3]; $result["game"] = $buffer[4]; $result["activeplayers"] = (strlen($buffer[5]) > 1)?ord($buffer[5][0]):"0"; $result["maxplayers"] = (strlen($buffer[5]) > 1)?ord($buffer[5][1]):"0"; return $result; } function Players() { $command = "\xff\xff\xff\xffD\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; echo 'DC PLAYERS' .PHP_EOL; return false; } $buffer = substr($buffer, 1); for($i = 1; strlen($buffer) > 0; $i++) { $tmp = strpos($buffer, "\x00"); $result[$i]["name"] = substr($buffer, 1, $tmp); $result[$i]["frag"] = ord($buffer[$tmp + 1]) + (ord($buffer[$tmp + 2]) << 8) + (ord($buffer[$tmp + 3]) << 16) + (ord($buffer[$tmp + 4]) << 24); $tmptime = @unpack('ftime', substr($buffer, $tmp + 5, 4)); $result[$i]["time"] = date('i:s', round($tmptime['time'], 0) + 82800); $buffer = substr($buffer, $tmp + 9); } return $result; } function ServerRules() { $command = "\xff\xff\xff\xffE\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; return false; } $buffer = substr($buffer, 2); $buffer = explode("\x00", $buffer); $buffer_count = floor(sizeof($buffer) / 2); for($i = 0; $i < $buffer_count; $i++) { $result[$buffer[2 * $i]] = $buffer[2 * $i + 1]; } ksort($result); return $result; } function GetChallenge() { $this->Connect(); socket_sendto($this->socket, "\xff\xff\xff\xffchallenge rcon\n", strlen("\xff\xff\xff\xffchallenge rcon\n") , 0 , $this->server_ip , $this->server_port); socket_recvfrom($this->socket, $buffer, 4096, 0, $server, $port); $this->Disconnect(); if(trim($buffer) == "") { $this->connected = false; return false; } //get challenge number $buffer = explode(" ", $buffer); $this->challenge_number = trim($buffer[2]); } function RconCommand($command) { if($this->challenge_number == "") { $this->GetChallenge(); } $command = "\xff\xff\xff\xffrcon $this->challenge_number \"$this->server_password\" $command\n"; $result = $this->Communicate($command); return trim($result); } function Communicate($command) { $this->Connect(); if(!$this->connected) return $this->connected; if($command != "") { if( ! socket_sendto($this->socket, $command , strlen($command) , 0 , $this->server_ip , $this->server_port)) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not send data: [$errorcode] $errormsg \n"); } $cmd_validation = "\xff\xff\xff\xffrcon $this->challenge_number \"$this->server_password\"\n"; if( ! socket_sendto($this->socket, $cmd_validation, strlen($cmd_validation) , 0 , $this->server_ip , $this->server_port)) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not send validation: [$errorcode] $errormsg \n"); } } usleep(500); $result = ''; $tryNb = 0; $stayInWhile = TRUE; $packetWaiting = TRUE; do { if(socket_recvfrom($this->socket, $buf, 4096, 0, $server, $port) === FALSE) { $tryNb++; if ($tryNb >= 3 ) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not receive response after $tryNb try: [$errorcode] $errormsg \n"); } } $result .= substr($buf, 5); $read = array($this->socket); $write = NULL; $except = NULL; $packetWaiting = socket_select($read, $write, $except, 0); if (bin2hex($buf) == 'ffffffff6c0000') $stayInWhile = FALSE; if ($packetWaiting > 0) $packetWaiting = TRUE; else $packetWaiting = FALSE; usleep(300); } while (($stayInWhile && $packetWaiting) || $packetWaiting ); usleep(500); $this->Disconnect(); return $result; } //function Communicate($buffer) } $server = 'X.X.X.X'; $port = 27015; $M = new Rcon($server, $port, "Password"); echo "server_info" .PHP_EOL; print_r($M->ServerInfo()); echo "meta" .PHP_EOL; print_r($M->RconCommand("meta")); echo PHP_EOL. "meta_cvars" .PHP_EOL; print_r($M->RconCommand("meta cvars")); ?>
Exileur
Messages postés
1475
Date d'inscription
mercredi 31 août 2011
Statut
Membre
Dernière intervention
16 décembre 2022
150
19 août 2018 à 02:46
19 août 2018 à 02:46
Bon je vais au lit ..
J'ai ajouté un constructeur, joué un peu avec la condition du while.
Quitte a faire de la merde, j'ai ajouté une seconde commande vide pour généré un autre packet dont je peux être certain du contenu.
Je pense que ma connexion (trés moisi) est en cause de perte de packet ou autre. J'essaierai sur le serveur directement demain voir si ça tourne mieux.
Le code maintenant :
J'ai ajouté un constructeur, joué un peu avec la condition du while.
Quitte a faire de la merde, j'ai ajouté une seconde commande vide pour généré un autre packet dont je peux être certain du contenu.
Je pense que ma connexion (trés moisi) est en cause de perte de packet ou autre. J'essaierai sur le serveur directement demain voir si ça tourne mieux.
Le code maintenant :
<?php class Rcon { var $challenge_number; var $connected; var $server_ip; var $server_password; var $server_port; var $socket; function Rcon() { $this->challenge_number = 0; $this->connected = true; $this->server_ip = ""; $this->server_port = 27015; $this->server_password = ""; } function __construct($server_ip, $server_port, $server_password = "") { $this->server_ip = gethostbyname($server_ip); $this->server_port = $server_port; $this->server_password = $server_password; } function Connect() { $sock = socket_create(AF_INET, SOCK_DGRAM, 0); $timeout = array('sec'=>2, 'usec'=>0); socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,$timeout); socket_set_block($sock); if(is_resource($sock)) { echo "Connected to " .$this->server_ip .PHP_EOL; $this->connected = true; } else { $this->connected = false; echo "Can't connect to " .$this->server_ip. " : " .PHP_EOL; return false; } $this->socket = $sock; return true; } function Disconnect() { socket_close($this->socket); $this->challenge_number = ''; $this->socket = ''; $this->connected = false; } function IsConnected() { return $this->connected; } function ServerInfo() { $status = $this->RconCommand("status"); if(!$status || trim($status) == "Bad rcon_password.") return $status; $line = explode("\n", $status); $map = substr($line[3], strpos($line[3], ":") + 1); $players = trim(substr($line[4], strpos($line[4], ":") + 1)); $active = explode(" ", $players); $result["ip"] = trim(substr($line[2], strpos($line[2], ":") + 1)); $result["name"] = trim(substr($line[0], strpos($line[0], ":") + 1)); $result["map"] = trim(substr($map, 0, strpos($map, "at:"))); $result["mod"] = "Counterstrike " . trim(substr($line[1], strpos($line[1], ":") + 1)); $result["game"] = "Halflife"; $result["activeplayers"] = $active[0]; $result["maxplayers"] = substr($active[2], 1); //format player info for($i = 1; $i <= $result["activeplayers"]; $i++) { $tmp = $line[$i + 6]; if(substr_count($tmp, "#") <= 0) break; $begin = strpos($tmp, "\"") + 1; $end = strrpos($tmp, "\""); $result[$i]["name"] = substr($tmp, $begin, $end - $begin); $tmp = trim(substr($tmp, $end + 1)); $end = strpos($tmp, " "); $result[$i]["id"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["wonid"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["frag"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["time"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $end = strpos($tmp, " "); $result[$i]["ping"] = substr($tmp, 0, $end); $tmp = trim(substr($tmp, $end)); $tmp = trim(substr($tmp, $end)); $result[$i]["adress"] = $tmp; } return $result; } function ServerMaps($pagenumber = 0) { $maps = $this->RconCommand("maps *", $pagenumber); if(!$maps || trim($maps) == "Bad rcon_password.") return $maps; $line = explode("\n", $maps); $count = sizeof($line) - 4; for($i = 0; $i <= $count; $i++) { $text = $line[$i]; if(strstr($text, "Dir:")) { $mapcount = 0; $directory = strstr($text, " "); } else if(strstr($text, "(fs)")) { $mappath = strstr($text, " "); if(!($tmpmap = strrchr($mappath, "/"))) $tmpmap = $mappath; $result[$directory][$i] = substr($tmpmap, 1, strpos($tmpmap, ".") - 1); } } return $result; } function Info() { $command = "\xff\xff\xff\xffTSource Engine Query\0\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; echo 'DC INFOS' .PHP_EOL; return false; } $buffer = explode("\x00", $buffer); $result["ip"] = substr($buffer[0], 5); $result["name"] = $buffer[1]; $result["map"] = $buffer[2]; $result["mod"] = $buffer[3]; $result["game"] = $buffer[4]; $result["activeplayers"] = (strlen($buffer[5]) > 1)?ord($buffer[5][0]):"0"; $result["maxplayers"] = (strlen($buffer[5]) > 1)?ord($buffer[5][1]):"0"; return $result; } function Players() { $command = "\xff\xff\xff\xffD\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; echo 'DC PLAYERS' .PHP_EOL; return false; } $buffer = substr($buffer, 1); for($i = 1; strlen($buffer) > 0; $i++) { $tmp = strpos($buffer, "\x00"); $result[$i]["name"] = substr($buffer, 1, $tmp); $result[$i]["frag"] = ord($buffer[$tmp + 1]) + (ord($buffer[$tmp + 2]) << 8) + (ord($buffer[$tmp + 3]) << 16) + (ord($buffer[$tmp + 4]) << 24); $tmptime = @unpack('ftime', substr($buffer, $tmp + 5, 4)); $result[$i]["time"] = date('i:s', round($tmptime['time'], 0) + 82800); $buffer = substr($buffer, $tmp + 9); } return $result; } function ServerRules() { $command = "\xff\xff\xff\xffE\x00"; $buffer = $this->Communicate($command); if(trim($buffer) == "") { $this->connected = false; return false; } $buffer = substr($buffer, 2); $buffer = explode("\x00", $buffer); $buffer_count = floor(sizeof($buffer) / 2); for($i = 0; $i < $buffer_count; $i++) { $result[$buffer[2 * $i]] = $buffer[2 * $i + 1]; } ksort($result); return $result; } function GetChallenge() { $this->Connect(); socket_sendto($this->socket, "\xff\xff\xff\xffchallenge rcon\n", strlen("\xff\xff\xff\xffchallenge rcon\n") , 0 , $this->server_ip , $this->server_port); socket_recvfrom($this->socket, $buffer, 4096, 0, $server, $port); $this->Disconnect(); if(trim($buffer) == "") { $this->connected = false; return false; } //get challenge number $buffer = explode(" ", $buffer); $this->challenge_number = trim($buffer[2]); } function RconCommand($command) { if($this->challenge_number == "") { $this->GetChallenge(); } $command = "\xff\xff\xff\xffrcon $this->challenge_number \"$this->server_password\" $command\n"; $result = $this->Communicate($command); return trim($result); } function Communicate($command) { $this->Connect(); if(!$this->connected) return $this->connected; if($command != "") { if( ! socket_sendto($this->socket, $command , strlen($command) , 0 , $this->server_ip , $this->server_port)) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not send data: [$errorcode] $errormsg \n"); } usleep(200); $cmd_validation = "\xff\xff\xff\xffrcon $this->challenge_number \"$this->server_password\"\n"; if( ! socket_sendto($this->socket, $cmd_validation, strlen($cmd_validation) , 0 , $this->server_ip , $this->server_port)) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not send validation: [$errorcode] $errormsg \n"); } } usleep(500); $result = ''; $tryNb = 0; $stayInWhile = TRUE; $packetWaiting = TRUE; do { sleep(1); if(socket_recvfrom($this->socket, $buf, 4096, 0, $server, $port) === FALSE) { $tryNb++; $stayInWhile = FALSE; if ($tryNb == 3 ) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not receive response after $tryNb try: [$errorcode] $errormsg \n"); } } $read = array($this->socket); $write = NULL; $except = NULL; if (bin2hex($buf) == 'ffffffff6c0000') { $packetWaiting = socket_select($read, $write, $except, 0); if($stayInWhile) { if( ! socket_sendto($this->socket, $cmd_validation, strlen($cmd_validation) , 0 , $this->server_ip , $this->server_port)) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die ("Could not send revalidation: [$errorcode] $errormsg \n"); } $packetWaiting = 1; } $stayInWhile = FALSE; } else { $result .= substr($buf, 5); $packetWaiting = socket_select($read, $write, $except, 0); } if ($packetWaiting > 0) { $packetWaiting = TRUE; } else { $packetWaiting = FALSE; } usleep(30000); print_r("pkt wait : ".$packetWaiting.PHP_EOL); print_r("stay in : ".$stayInWhile.PHP_EOL); } while (( $stayInWhile/* && $packetWaiting*/) || $packetWaiting ); $this->Disconnect(); return $result; } //function Communicate($buffer) } $server = 'X.X.X.X'; $port = 27015; $M = new Rcon($server, $port, "Password"); echo "server_info" .PHP_EOL; print_r($M->ServerInfo()); echo "meta" .PHP_EOL; print_r($M->RconCommand("meta")); echo PHP_EOL. "meta_cvars" .PHP_EOL; print_r($M->RconCommand("meta cvars")); ?>
Modifié le 18 août 2018 à 16:27
J'avais déja vu ce dépot, puis suivi ce lien.
Seulement, la fatigue, surement, m'avais arrété à :
et les quelques trames.
Et quelque ligne plus bas, on peut lire ça :
Je vais tester !