User:Pizzahut/msqp.php: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (This seems to be fixed on Valve's end - getting 130 to 150 servers now.)
(Added seeding for long server lists (more than 231 servers).)
Line 1: Line 1:
This is a code example for querying a Half-Life master server using the PHP language. For querying more than 231 servers it needs to be extended. The purpose of this program is to get a list of TFC servers, there are only about 150 left at the time of writing so it doesn't check for more.
This is a code example for querying a Half-Life master server using the PHP language.
<pre>
<pre>
<?php
<?php


/*   Version history
/*
 
Version history


1    Initial release.
1    Initial release.
2    Added option to retry same server if timeout occurs.
2    Added option to retry same server if timeout occurs.
      (This is just a minor update, I should have released it as v1.1.)
2.1  Added more master servers.
2.1  Added more master servers.
2.1.1 Fixed a bug, program didn't terminate if all master servers time out.
2.1.1 Fixed a bug, program didn't terminate if all master servers time out.
2.1.2 Removed a now redundant variable.
2.1.2 Removed a now redundant variable.
2.2  Seeding for long server lists.
*/
*/


// Method 1: Try a different server if one is timing out.
$master_servers = array("72.165.61.136", "68.142.72.250", "72.165.61.189",
// Method 2: Retry the same server if a timeout occurs.
"72.165.61.190", "69.28.151.162");
$method = 1;


$servers = array(
function query_timeout(&$socket, $seed)
"72.165.61.136:27010",
"68.142.72.250:27010",
"72.165.61.189:27010",
"72.165.61.190:27010",
"69.28.151.162:27010");
 
$server = "hl1master.steampowered.com";
 
function master_server_timeout(&$fp, $ip)
{
{
  $port = 27010;
   // region=world, filter: game=Half-Life
  $timeout = 1;
   if (!fwrite($socket, "1\xFF$seed\0\\gamedir\\valve\0"))
 
  echo "Connecting to master server \"$ip\".\n";
 
  $fp = fsockopen("udp://$ip", $port, $errno, $errstr, $timeout);
  if (!$fp) exit("Error $errno : $errstr");
  stream_set_timeout($fp, $timeout);
 
   // region=world, filter: game=Team Fortress Classic
   if (!fwrite($fp, "1\xFF0.0.0.0:0\0\\gamedir\\tfc\0"))
   {
   {
       fclose($fp);
       fclose($socket);
       exit("fwrite error\n");
       exit("fwrite error\n");
   }
   }


   $s = bin2hex(fread($fp, 6));
   $s = bin2hex(fread($socket, 6));
   $info = stream_get_meta_data($fp);
   $info = stream_get_meta_data($socket);
   if ($info['timed_out'])
   if ($info['timed_out'])
   {
   {
       echo "Master server \"$ip\" timed out.\n";
       echo "Master server \"$seed\" timed out.\n";
       fclose($fp);
       fclose($socket);
   } else {
   }
       if ($s !== "ffffffff660a") {
  else
         fclose($fp);
  {
       if ($s !== "ffffffff660a")
      {
         fclose($socket);
         exit("Expected ff ff ff ff 66 0a (hex) but got $s.");
         exit("Expected ff ff ff ff 66 0a (hex) but got $s.");
       }
       }
Line 59: Line 46:
}
}


if ($method == 1)
// Connect to master server, return timeout info.
// The socket is passed as reference and thus returned as well.
 
function master_server_timeout(&$socket, $ip)
{
{
   $abort = 1;
   $port = 27010;
   foreach ($servers as $server_address)
  $timeout = 1;
   {
 
      if (!master_server_timeout($fp, $server_address))
  echo "Connecting to master server \"$ip\".\n";
       {
 
        $abort = 0;
   $socket = fsockopen("udp://$ip", $port, $errno, $errstr, $timeout);
        break;
   if (!$socket)
      }
       exit("Error $errno : $errstr \n");
   }
  stream_set_timeout($socket, $timeout);
  if ($abort == 1)
 
      exit("All servers timed out, aborting.\n");
   return query_timeout($socket, "0.0.0.0:0");
}
}


if ($method == 2)
// Try all master servers unless we find one that isn't timing out.
 
$abort = 1;
foreach ($master_servers as $ip)
{
{
   for ($i = 1; $i <= 10; $i++)
   if (!master_server_timeout($socket, $ip))
   {
   {
       if (!master_server_timeout($fp, $server))
       $abort = 0;
        break;
       break;
      if ($i == 10)
        exit("Giving up after 10 tries.\n");
       else
        echo "Retrying ($i).\n";
   }
   }
}
}
if ($abort == 1)
  exit("All master servers timed out, aborting.\n");
// Read list with server addresses (IP:port).


$count = 0;
$count = 0;
do {
do
   $a1 = ord(fread($fp,1));
{
   $info = stream_get_meta_data($fp);
   $new_a1 = ord(fread($socket,1));
   if ($info['timed_out']) {
   $info = stream_get_meta_data($socket);
       echo "Time out occured.\n";
   if ($info['timed_out'])
       break;
  {
       if (query_timeout($socket, "$a1.$a2.$a3.$a4:$a5"))
        break;
      $a1 = ord(fread($socket,1));
      $info = stream_get_meta_data($socket);
      if ($info['timed_out'])
      {
        echo "Timeout occured.\n";
        break;
      }
      echo "New seed, decreasing count.\n";
       $count--;
   }
   }
  else
      $a1 = $new_a1;


   // Let's always read the rest of the address, even if it starts with 0.
   if ($a1 != 0)
   // This may avoid subsequent problems, but I'm paranoid here.
   {
  $a2 = ord(fread($fp,1));
      $a2 = ord(fread($socket,1));
  $a3 = ord(fread($fp,1));
      $a3 = ord(fread($socket,1));
  $a4 = ord(fread($fp,1));
      $a4 = ord(fread($socket,1));
  $a5 = ord(fread($fp,1))*256 + ord(fread($fp,1));
      $a5 = ord(fread($socket,1))*256 + ord(fread($socket,1));
 
  if ($a1 != 0) {
       $count++;
       $count++;
       echo "$count $a1.$a2.$a3.$a4:$a5\n";
       echo "$count $a1.$a2.$a3.$a4:$a5\n";
   }
   }
} while ($a1 != 0);
} while ($a1 != 0);
echo "Retrieved $count servers.\n";
fclose($socket);
echo "Retrieved $count server addresses.\n";


fclose($fp);
?>
?>
</pre>
</pre>

Revision as of 11:29, 11 December 2010

This is a code example for querying a Half-Life master server using the PHP language.

<?php

/*

Version history

1     Initial release.
2     Added option to retry same server if timeout occurs.
2.1   Added more master servers.
2.1.1 Fixed a bug, program didn't terminate if all master servers time out.
2.1.2 Removed a now redundant variable.
2.2   Seeding for long server lists.

*/

$master_servers = array("72.165.61.136", "68.142.72.250", "72.165.61.189",
"72.165.61.190", "69.28.151.162");

function query_timeout(&$socket, $seed)
{
   // region=world, filter: game=Half-Life
   if (!fwrite($socket, "1\xFF$seed\0\\gamedir\\valve\0"))
   {
      fclose($socket);
      exit("fwrite error\n");
   }

   $s = bin2hex(fread($socket, 6));
   $info = stream_get_meta_data($socket);
   if ($info['timed_out'])
   {
      echo "Master server \"$seed\" timed out.\n";
      fclose($socket);
   }
   else
   {
      if ($s !== "ffffffff660a")
      {
         fclose($socket);
         exit("Expected ff ff ff ff 66 0a (hex) but got $s.");
      }
   }
   return $info['timed_out'];
}

// Connect to master server, return timeout info.
// The socket is passed as reference and thus returned as well.

function master_server_timeout(&$socket, $ip)
{
   $port = 27010;
   $timeout = 1;

   echo "Connecting to master server \"$ip\".\n";

   $socket = fsockopen("udp://$ip", $port, $errno, $errstr, $timeout);
   if (!$socket)
      exit("Error $errno : $errstr \n");
   stream_set_timeout($socket, $timeout);

   return query_timeout($socket, "0.0.0.0:0");
}

// Try all master servers unless we find one that isn't timing out.

$abort = 1;
foreach ($master_servers as $ip)
{
   if (!master_server_timeout($socket, $ip))
   {
      $abort = 0;
      break;
   }
}
if ($abort == 1)
   exit("All master servers timed out, aborting.\n");

// Read list with server addresses (IP:port).

$count = 0;
do
{
   $new_a1 = ord(fread($socket,1));
   $info = stream_get_meta_data($socket);
   if ($info['timed_out'])
   {
      if (query_timeout($socket, "$a1.$a2.$a3.$a4:$a5"))
         break;
      $a1 = ord(fread($socket,1));
      $info = stream_get_meta_data($socket);
      if ($info['timed_out'])
      {
         echo "Timeout occured.\n";
         break;
      }
      echo "New seed, decreasing count.\n";
      $count--;
   }
   else
      $a1 = $new_a1;

   if ($a1 != 0)
   {
      $a2 = ord(fread($socket,1));
      $a3 = ord(fread($socket,1));
      $a4 = ord(fread($socket,1));
      $a5 = ord(fread($socket,1))*256 + ord(fread($socket,1));
      $count++;
      echo "$count $a1.$a2.$a3.$a4:$a5\n";
   }
} while ($a1 != 0);
fclose($socket);
echo "Retrieved $count server addresses.\n";

?>