Advertisement
pizzahut2

msqp.php

Oct 16th, 2021 (edited)
395
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.69 KB | None | 1 0
  1. <?php
  2.  
  3. /*
  4.  
  5. Version history
  6.  
  7. 1     - Initial release.
  8. 2     - Added option to use the official domain name instead of IPs and retry if
  9.         a timeout occurs.
  10. 2.1   - Added more master servers.
  11. 2.1.1 - Fixed a bug, program didn't terminate if all master servers time out.
  12. 2.1.2 - Removed a now redundant variable.
  13. 2.2   - Seeding for long server lists.
  14.       - Removed the domain name because it's often better to try different
  15.         servers.
  16. 2.2.1 - Bug fix: Timeout showed wrong master server IP.
  17.       - Bug fix: Check whether the new seed starts with a duplicate or not.
  18.       - Bug fix: Don't close socket twice.
  19. 2.3   - Retry queries on timeout if the first query was successful.
  20. 2.3.1 - Reading the whole address again if it starts with a zero.
  21.       - Increased timeout to avoid a communication issue.
  22.       - Removed maximum number of timeouts for testing.
  23. 2.4   - Again using hl1master.steampowered.com because IPs change often.
  24.       - Endless retries because this server often times out.
  25. 2.5   - Trying following ports on timeout or if the response wasn't correct.
  26. 2.5.3 - Cosmetic changes (defines, variable name).
  27. 2.5.4 - Code optimisation.
  28. 2.6   - Repeat until list isn't empty.
  29. */
  30.  
  31. // Currently uses ports 27011-27013 and 27015.
  32. $master_servers = array("hl2master.steampowered.com");
  33.  
  34. define("MIN_PORT", 27011); // Range of port numbers which the master servers
  35. define("MAX_PORT", 27015); // potentially use.
  36. define("FILTER", '\gamedir\tfc'); // game = Team Fortress Classic
  37. define("REGION", "\xFF"); // region = world
  38. define("TIMEOUT", 2.0); // 2s timeout
  39.  
  40. function query_timeout($socket, $seed)
  41. {
  42.    echo "Sending query to master server.\n";
  43.    stream_set_timeout($socket, TIMEOUT);
  44.    if (!fwrite($socket, "1".REGION."$seed\0".FILTER."\0"))
  45.    {
  46.       fclose($socket);
  47.       exit("fwrite error\n");
  48.    }
  49.  
  50.    echo "Reading response header.\n";
  51.    stream_set_timeout($socket, TIMEOUT);
  52.    $s = bin2hex(fread($socket, 6));
  53.    $info = stream_get_meta_data($socket);
  54.    if ($info['timed_out'])
  55.       echo "Master server timed out.\n";
  56.    else
  57.    {
  58.       if ($s !== "ffffffff660a")
  59.       {
  60.          fclose($socket);
  61.          if ($s == "")
  62.             echo "Expected ff ff ff ff 66 0a (hex) but got nothing.\n";
  63.          else
  64.             echo "Expected ff ff ff ff 66 0a (hex) but got $s.\n";
  65.          return True;
  66.       }
  67.    }
  68.    return $info['timed_out'];
  69. }
  70.  
  71. // Connect to master server, return timeout info.
  72. // The socket is passed as reference and thus returned as well.
  73.  
  74. function master_server_timeout(&$socket, $ip)
  75. {
  76.    $port = MIN_PORT;
  77.    do {
  78.       echo "Connecting to master server \"$ip:$port\".\n";
  79.       $socket = fsockopen("udp://$ip", $port, $errno, $errstr, TIMEOUT);
  80.       if (!$socket) exit("Error $errno : $errstr \n");
  81.       $timeout = query_timeout($socket, "0.0.0.0:0");
  82.       $port = $port + 1;
  83.    } while ($timeout && ($port <= MAX_PORT));
  84.    return $timeout;
  85. }
  86.  
  87. // Read list with server addresses (IP:port).
  88.  
  89. function list_not_empty($socket)
  90.     {
  91.     $count = 0;
  92.     $old_a1 = 0; $old_a2 = 0; $old_a3 = 0; $old_a4 = 0; $old_a5 = 0;
  93.     $max_timeouts = 6;
  94.     do
  95.     {
  96.        stream_set_timeout($socket, TIMEOUT);
  97.        $a1 = ord(fread($socket,1));
  98.        $info = stream_get_meta_data($socket);
  99.        if ($info['timed_out'])
  100.        {
  101.           $seed = "$old_a1.$old_a2.$old_a3.$old_a4:$old_a5";
  102.           echo "Seed: $seed\n";
  103.           while (query_timeout($socket, $seed));
  104.           stream_set_timeout($socket, TIMEOUT);
  105.           $a1 = ord(fread($socket,1));
  106.           $info = stream_get_meta_data($socket);
  107.           if ($info['timed_out'])
  108.           {
  109.              echo "Timeout occured.\n";
  110.              break;
  111.           }
  112.           $check_for_duplicate = 1;
  113.        }
  114.        else
  115.           $check_for_duplicate = 0;
  116.  
  117.        // Let's always read the rest of the address (even if it starts with 0) in
  118.        // order to empty the master server's write buffer. This may avoid subsequent
  119.        // problems, but I'm paranoid here.
  120.        $a2 = ord(fread($socket,1));
  121.        $a3 = ord(fread($socket,1));
  122.        $a4 = ord(fread($socket,1));
  123.        $a5 = ord(fread($socket,1))*256 + ord(fread($socket,1));
  124.  
  125.        if ($a1 != 0)
  126.        {
  127.           if (($check_for_duplicate==0)||($a1!=$old_a1)||($a2!=$old_a2)||
  128.           ($a3!=$old_a3)||($a4!=$old_a4)||($a5!=$old_a5))
  129.           {
  130.              $count++;
  131.              echo "$count $a1.$a2.$a3.$a4:$a5\n";
  132.           }
  133.           $old_a1 = $a1; $old_a2 = $a2; $old_a3 = $a3; $old_a4 = $a4; $old_a5 = $a5;
  134.        }
  135.     } while ($a1 != 0);
  136.     fclose($socket);
  137.  
  138.     if ($count != 0) echo "Retrieved $count server addresses.\n";
  139.     return ($count != 0);
  140. }
  141.  
  142. // Try all master servers until we find one that isn't timing out.
  143.  
  144. foreach ($master_servers as $ip)
  145.     if ($timeout=master_server_timeout($socket, $ip))
  146.         fclose($socket);
  147.     else
  148.         if (list_not_empty($socket)) break;
  149.  
  150. ?>
  151.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement