Jump to content
GIGN Forum

[php] Steam Server Query


worm
 Share

Recommended Posts

Tīri piemēram uztaisīšu pirmo topiku un sniegšu nelielu ieskatu iekš servera monitoringa skriptiem un viņu problēmām. Sakarā ar to, ka es smagi pārtaisu serveru sadaļu, man nācās pārrakstīt serveru monitoringa skriptu no nulles. Kaut kad pirms laiciņa valve nolēma nākt pretī serveru uzturētajiem un sniedza informāciju par Source Server Query protokolu. Diemžēl normālas php implementācijas īsti pieejamas nav. Savukārt C++ versija, kas pieejama tajā pašā wiki lapā ir kaut kāda mūžveca un neuztur jaunāka protokola izmaiņas. Tāpēc es ķēros pie darba un uzrakstīju pats savu versiju. Visu skriptu nepiedāvāšu, bet es ticu, ka dažiem var šķist noderīga funkcija, kas veic pieprasījumu un apstrādā datus..

Kāpēc mana funkcija ir labāka par citām?

Jo:

  1. Tā pareizi apstrādā split-packets
  2. Tā konstatē to, ka packete ir kompresēta ar bz2 algoritmu
  3. Tā ņem vērā veco un jauno protokolu
Parametri, kam jābūt globāli definētiem:
  1. $sock - sokets, ko atver ar fsockopen
  2. $query_type - strings: goldsource (1.5 vai 1.6 neapdeitos engine) vai source (1.6 pēdējais engine vai tf2/css)
Note: Lai lietotu šo brīnumu, ir nepieciešams bzlib, lai varētu izmantot funkciju bzdecompress()

Mana implementācija:

PHP

<?

  

function getbyte(&$raw) {

    if (empty(

$raw)) return '';

    

$byte = substr($raw, 0, 1);

    

$raw = substr($raw, 1);

    return 

ord($byte);

  }

  function 

getshort(&$raw) {

    if (empty(

$raw)) return '';

    

$lo = getbyte($raw);

    

$hi = getbyte($raw);

    

$short = ($hi << 8) | $lo;

    return 

$short;

  }

  function 

getlong(&$raw) {

    if (empty(

$raw)) return '';

    

$lo = getshort($raw);

    

$hi = getshort($raw);

    

$long = ($hi << 16) | $lo;

    return 

$long;

  }

  function 

query($cmd) {

    global 

$sock, $query_type;

    

$command = pack("N", 0xFFFFFFFF) . $cmd;

    

fputs($sock, $command, strlen($command));

    

    

$expected = 0;

    

$crc = 0;

    do {

      

$reqnr = 0;

      do {   

        

$packet = fread($sock, 1500);

        

$reqnr++;

      } while ( 

strlen($packet) == 0 && $reqnr < 5 );

      

      if ( 

strlen($packet) == 0 )

        return 

false;

      

$header = substr($packet, 0, 4);

      

$ack = @unpack("N1split", $header);

      

$split = sprintf("%u", $ack['split']);

       

      if (

$split == 0xFeFFFFFF) {

        

getlong($packet);                                       // nahrenizejam headeri, 4bytes

        

$reqid          = getlong($packet);                     // nolasam requestaid, 4bytes  

        

$bziped         = $reqid & 0xf0000000;

        

        if ( 

$query_type == 'goldsource' ) {              // vecais source query: agriinaas cs1.6 un 1.5 versijas

          

$packetnr     = getbyte($packet);

          

          if ( !

$expected )

            

$expected = $packetnr & 0x0F;                       // The lower four bits represent the number of packets (2 to 15)

          

$seq = (int)($packetnr >> 4);                         // and the upper four bits represent the current packet starting with 0.

        

} elseif ( $query_type == 'source' ) {            // jaunais source query: css un tf2 kaa arii nopachotais cs1.6

          

$packetnr     = getshort($packet);

          

$splitsize    = getshort($packet);                    // size of the splits

          

          

if ( !$expected ) {

            

$expected = (int)($packetnr & 0xff);                // The lower byte is the number of packets

            

if ($bziped) {

              

$bzip_bytes       = getshort($packet);            // Number of bytes the data uses after decompression;

              

$bzip_crc         = getlong($packet);             // CRC32 checksum of the uncompressed data for validation

            

}

          }

            

          

$seq = (int)($packetnr >> 8);                         // the upper byte this current packet starting with 0

        

} else {

          return 

false;                                         // nezinaams query

        

}

        

        

$packets[$seq] = $packet;

      } else {

        

$packets[0] = $packet;

      } 

      

      

$expected--;

    } while (

$expected > 0);

    

    

ksort($packets, SORT_NUMERIC);

    

$raw = implode('',$packets);  

    

    if ( 

$bzip_crc ) {

      

$raw = bzdecompress($raw);

      

$crc2 = crc32($raw);

      if (

$crc2 != $bzip_crc )

        return 

false;

    }

    

    

getlong($raw);                                              // remuvojam 0xffffffff headeri

    

return $raw;

  }

?>

Funkcija atgriež atpakaļ raw veidā datus, kas protams pēctam ir jāapstrādā. Izsaukt funkciju var šādi:

PHP

<?

define

('A2A_PING', "x69");

$response = query(A2A_PING);

?>

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...