User:Pizzahut/msqp.php: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(Added seeding for long server lists (more than 231 servers).)
m (bug fixes)
Line 13: Line 13:
2.1.2 Removed a now redundant variable.
2.1.2 Removed a now redundant variable.
2.2  Seeding for long server lists.
2.2  Seeding for long server lists.
 
2.2.1 Bug fix: Timeout showed wrong master server IP.
      Bug fix: Check whether the new seed starts with a duplicate or not.
*/
*/


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


function query_timeout(&$socket, $seed)
function query_timeout(&$socket, $seed)
Line 32: Line 33:
   if ($info['timed_out'])
   if ($info['timed_out'])
   {
   {
       echo "Master server \"$seed\" timed out.\n";
       echo "Master server timed out.\n";
       fclose($socket);
       fclose($socket);
   }
   }
Line 52: Line 53:
{
{
   $port = 27010;
   $port = 27010;
   $timeout = 1;
   $timeout = 2;


   echo "Connecting to master server \"$ip\".\n";
   echo "Connecting to master server \"$ip\".\n";
Line 81: Line 82:


$count = 0;
$count = 0;
$close_socket = 1;
$check_for_duplicate = 0;
$old_a1 = 0; $old_a2 = 0; $old_a3 = 0; $old_a4 = 0; $old_a5 = 0;
do
do
{
{
   $new_a1 = ord(fread($socket,1));
   $a1 = ord(fread($socket,1));
   $info = stream_get_meta_data($socket);
   $info = stream_get_meta_data($socket);
   if ($info['timed_out'])
   if ($info['timed_out'])
   {
   {
       if (query_timeout($socket, "$a1.$a2.$a3.$a4:$a5"))
       if (query_timeout($socket, "$old_a1.$old_a2.$old_a3.$old_a4:$old_a5"))
      {
        $close_socket = 0;
         break;
         break;
      }
       $a1 = ord(fread($socket,1));
       $a1 = ord(fread($socket,1));
       $info = stream_get_meta_data($socket);
       $info = stream_get_meta_data($socket);
Line 96: Line 103:
         break;
         break;
       }
       }
      echo "New seed, decreasing count.\n";
       $check_for_duplicate = 1;
       $count--;
   }
   }
  else
      $a1 = $new_a1;


   if ($a1 != 0)
   if ($a1 != 0)
Line 108: Line 112:
       $a4 = ord(fread($socket,1));
       $a4 = ord(fread($socket,1));
       $a5 = ord(fread($socket,1))*256 + ord(fread($socket,1));
       $a5 = ord(fread($socket,1))*256 + ord(fread($socket,1));
       $count++;
       if (($check_for_duplicate==0)||($a1!=$old_a1)||($a2!=$old_a2)||
      echo "$count $a1.$a2.$a3.$a4:$a5\n";
      ($a3!=$old_a3)||($a4!=$old_a4)||($a5!=$old_a5))
      {
        $count++;
        echo "$count $a1.$a2.$a3.$a4:$a5\n";
      }
      $check_for_duplicate = 0;
      $old_a1 = $a1; $old_a2 = $a2; $old_a3 = $a3; $old_a4 = $a4; $old_a5 = $a5;
   }
   }
} while ($a1 != 0);
} while ($a1 != 0);
fclose($socket);
if ($close_socket == 1)
  fclose($socket);
echo "Retrieved $count server addresses.\n";
echo "Retrieved $count server addresses.\n";


?>
?>
</pre>
</pre>

Revision as of 14:55, 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.
2.2.1 Bug fix: Timeout showed wrong master server IP.
      Bug fix: Check whether the new seed starts with a duplicate or not.
*/

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

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 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 = 2;

   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;
$close_socket = 1;
$check_for_duplicate = 0;
$old_a1 = 0; $old_a2 = 0; $old_a3 = 0; $old_a4 = 0; $old_a5 = 0;
do
{
   $a1 = ord(fread($socket,1));
   $info = stream_get_meta_data($socket);
   if ($info['timed_out'])
   {
      if (query_timeout($socket, "$old_a1.$old_a2.$old_a3.$old_a4:$old_a5"))
      {
         $close_socket = 0;
         break;
      }
      $a1 = ord(fread($socket,1));
      $info = stream_get_meta_data($socket);
      if ($info['timed_out'])
      {
         echo "Timeout occured.\n";
         break;
      }
      $check_for_duplicate = 1;
   }

   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));
      if (($check_for_duplicate==0)||($a1!=$old_a1)||($a2!=$old_a2)||
      ($a3!=$old_a3)||($a4!=$old_a4)||($a5!=$old_a5))
      {
         $count++;
         echo "$count $a1.$a2.$a3.$a4:$a5\n";
      }
      $check_for_duplicate = 0;
      $old_a1 = $a1; $old_a2 = $a2; $old_a3 = $a3; $old_a4 = $a4; $old_a5 = $a5;
   }
} while ($a1 != 0);
if ($close_socket == 1)
   fclose($socket);
echo "Retrieved $count server addresses.\n";

?>