User:Pizzahut/msqp.php: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (Timeout turned out to be too short.)
(Getting an error when changing the source code, so I put the update on PasteBin.)
Tag: Replaced
 
(25 intermediate revisions by the same user not shown)
Line 1: Line 1:
This is a code example for querying a Half-Life master server using the PHP language.
This is a code example for querying a Half-Life master server using the PHP language.<br>
<pre>
See also [[User:Pizzahut/test.php]] - a test script in PHP to check which master servers respond.
<?php


/*
* https://pastebin.com/D2mjg9Nb
 
Version history
 
1    - Initial release.
2    - Added option to use the official domain name instead of IPs and retry if
        a 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.
      - Removed the domain name because it's often better to try different
        servers.
2.2.1 - Bug fix: Timeout showed wrong master server IP.
      - Bug fix: Check whether the new seed starts with a duplicate or not.
      - Bug fix: Don't close socket twice.
2.3  - Retry queries on timeout if the first query was successful.
2.3.1 - Reading the whole address again if it starts with a zero.
      - Increased timeout to avoid a communication issue.
      - Removed maximum number of timeouts for testing.
*/
 
$master_servers = array("68.142.72.250", "69.28.151.162", "72.165.61.190",
"72.165.61.189");
 
define("TIMEOUT", 2.0);
define("WORLD", "\xFF");
define("PORT", 27010);
 
function query_timeout(&$socket, $seed)
{
  echo "Sending query to master server.\n";
  stream_set_timeout($socket, TIMEOUT);
  $region = WORLD;
  if (!fwrite($socket, "1$region$seed\0\\gamedir\\cstrike\0"))
  {
      fclose($socket);
      exit("fwrite error\n");
  }
 
  echo "Reading response header.\n";
  stream_set_timeout($socket, TIMEOUT);
  $s = bin2hex(fread($socket, 6));
  $info = stream_get_meta_data($socket);
  if ($info['timed_out'])
      echo "Master server timed out.\n";
  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)
{
  echo "Connecting to master server \"$ip:".PORT."\".\n";
  $socket = fsockopen("udp://$ip", PORT, $errno, $errstr, TIMEOUT);
  if (!$socket)
      exit("Error $errno : $errstr \n");
 
  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;
  }
  else
      fclose($socket);
}
if ($abort == 1)
  exit("All master servers timed out, aborting.\n");
 
// Read list with server addresses (IP:port).
 
$count = 0;
$old_a1 = 0; $old_a2 = 0; $old_a3 = 0; $old_a4 = 0; $old_a5 = 0;
$max_timeouts = 6;
do
{
  stream_set_timeout($socket, TIMEOUT);
  $a1 = ord(fread($socket,1));
  $info = stream_get_meta_data($socket);
  if ($info['timed_out'])
  {
      $seed = "$old_a1.$old_a2.$old_a3.$old_a4:$old_a5";
      echo "Seed: $seed\n";
      while (query_timeout($socket, $seed));
      stream_set_timeout($socket, TIMEOUT);
      $a1 = ord(fread($socket,1));
      $info = stream_get_meta_data($socket);
      if ($info['timed_out'])
      {
        echo "Timeout occured.\n";
        break;
      }
      $check_for_duplicate = 1;
  }
  else
      $check_for_duplicate = 0;
 
  // Let's always read the rest of the address (even if it starts with 0) in
  // order to empty the master server's write buffer. This may avoid subsequent
  // problems, but I'm paranoid here.
  $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 ($a1 != 0)
  {
      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";
      }
      $old_a1 = $a1; $old_a2 = $a2; $old_a3 = $a3; $old_a4 = $a4; $old_a5 = $a5;
  }
} while ($a1 != 0);
fclose($socket);
echo "Retrieved $count server addresses.\n";
 
?>
</pre>

Latest revision as of 08:48, 16 October 2021

This is a code example for querying a Half-Life master server using the PHP language.
See also User:Pizzahut/test.php - a test script in PHP to check which master servers respond.