PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/SteamCondenser/Servers/MasterServer.php

http://github.com/koraktor/steam-condenser-php
PHP | 204 lines | 71 code | 24 blank | 109 comment | 9 complexity | bd9242733ed73970f72d2e75e8a0a1cb MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * This code is free software; you can redistribute it and/or modify it under
  4. * the terms of the new BSD License.
  5. *
  6. * Copyright (c) 2008-2015, Sebastian Staudt
  7. *
  8. * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  9. */
  10. namespace SteamCondenser\Servers;
  11. use SteamCondenser\Exceptions\TimeoutException;
  12. use SteamCondenser\Servers\Packets\A2MGETSERVERSBATCH2Packet;
  13. use SteamCondenser\Servers\Sockets\MasterServerSocket;
  14. /**
  15. * This class represents a Steam master server and can be used to get game
  16. * servers which are publicly available
  17. *
  18. * An intance of this class can be used much like Steam's server browser to get
  19. * a list of available game servers, including filters to narrow down the
  20. * search results.
  21. *
  22. * @author Sebastian Staudt
  23. * @package steam-condenser
  24. * @subpackage servers
  25. */
  26. class MasterServer extends Server {
  27. /**
  28. * @var string The master server address to query for GoldSrc game servers
  29. */
  30. const GOLDSRC_MASTER_SERVER = 'hl1master.steampowered.com:27011';
  31. /**
  32. * @var string The master server address to query for GoldSrc game servers
  33. */
  34. const SOURCE_MASTER_SERVER = 'hl2master.steampowered.com:27011';
  35. /**
  36. * @var int The region code for the US east coast
  37. */
  38. const REGION_US_EAST_COAST = 0x00;
  39. /**
  40. * @var int The region code for the US west coast
  41. */
  42. const REGION_US_WEST_COAST = 0x01;
  43. /**
  44. * @var int The region code for South America
  45. */
  46. const REGION_SOUTH_AMERICA = 0x02;
  47. /**
  48. * @var int The region code for Europe
  49. */
  50. const REGION_EUROPE = 0x03;
  51. /**
  52. * @var int The region code for Asia
  53. */
  54. const REGION_ASIA = 0x04;
  55. /**
  56. * @var int The region code for Australia
  57. */
  58. const REGION_AUSTRALIA = 0x05;
  59. /**
  60. * @var int The region code for the Middle East
  61. */
  62. const REGION_MIDDLE_EAST = 0x06;
  63. /**
  64. * @var int The region code for Africa
  65. */
  66. const REGION_AFRICA = 0x07;
  67. /**
  68. * @var int The region code for the whole world
  69. */
  70. const REGION_ALL = 0xFF;
  71. /**
  72. * @var int
  73. */
  74. private static $retries = 3;
  75. /**
  76. * @var MasterServerSocket
  77. */
  78. protected $socket;
  79. /**
  80. * Sets the number of consecutive requests that may fail, before getting
  81. * the server list is cancelled (default: 3)
  82. *
  83. * @param int $retries The number of allowed retries
  84. */
  85. public static function setRetries($retries) {
  86. self::$retries = $retries;
  87. }
  88. /**
  89. * Returns a list of game server matching the given region and filters
  90. *
  91. * Filtering:
  92. * Instead of filtering the results sent by the master server locally, you
  93. * should at least use the following filters to narrow down the results
  94. * sent by the master server.
  95. *
  96. * <b>Note:</b> Receiving all servers from the master server is taking
  97. * quite some time.
  98. *
  99. * Available filters:
  100. *
  101. * <ul>
  102. * <li><var>\type\d</var>: Request only dedicated servers
  103. * <li><var>\secure\1</var>: Request only secure servers
  104. * <li><var>\gamedir\[mod]</var>: Request only servers of a specific mod
  105. * <li><var>\map\[mapname]</var>: Request only servers running a specific
  106. * map
  107. * <li><var>\linux\1</var>: Request only linux servers
  108. * <li><var>\emtpy\1</var>: Request only **non**-empty servers
  109. * <li><var>\full\1</var>: Request only servers **not** full
  110. * <li><var>\proxy\1</var>: Request only spectator proxy servers
  111. * </ul>
  112. *
  113. * @param int $regionCode The region code to specify a location of the
  114. * game servers
  115. * @param string $filter The filters that game servers should match
  116. * @param bool $force Return a list of servers even if an error occured
  117. * while fetching them from the master server
  118. * @return array A list of game servers matching the given
  119. * region and filters
  120. * @see setTimeout()
  121. * @see A2M_GET_SERVERS_BATCH2_Packet
  122. * @throws SteamCondenserException if a problem occurs while parsing the
  123. * reply
  124. * @throws TimeoutException if too many timeouts occur while querying the
  125. * master server
  126. */
  127. public function getServers($regionCode = MasterServer::REGION_ALL , $filter = '', $force = false) {
  128. $failCount = 0;
  129. $finished = false;
  130. $portNumber = 0;
  131. $hostName = '0.0.0.0';
  132. $serverArray = [];
  133. while(true) {
  134. $failCount = 0;
  135. try {
  136. do {
  137. $this->socket->send(new A2MGETSERVERSBATCH2Packet($regionCode, "$hostName:$portNumber", $filter));
  138. try {
  139. $serverStringArray = $this->socket->getReply()->getServers();
  140. foreach($serverStringArray as $serverString) {
  141. $serverString = explode(':', $serverString);
  142. $hostName = $serverString[0];
  143. $portNumber = $serverString[1];
  144. if($hostName != '0.0.0.0' && $portNumber != 0) {
  145. $serverArray[] = [$hostName, $portNumber];
  146. } else {
  147. $finished = true;
  148. }
  149. }
  150. $failCount = 0;
  151. } catch(TimeoutException $e) {
  152. $failCount ++;
  153. if($failCount == self::$retries) {
  154. throw $e;
  155. }
  156. $this->logger->info("Request to master server {$this->ipAddress} timed out, retrying...");
  157. }
  158. } while(!$finished);
  159. break;
  160. } catch(TimeoutException $e) {
  161. if ($this->rotateIp()) {
  162. if ($force) {
  163. break;
  164. }
  165. throw $e;
  166. }
  167. $this->logger->info("Request to master server failed, retrying {$this->ipAddress}...");
  168. }
  169. }
  170. return array_unique($serverArray, SORT_REGULAR);
  171. }
  172. /**
  173. * Initializes the socket to communicate with the master server
  174. *
  175. * @see MasterServerSocket
  176. */
  177. public function initSocket() {
  178. $this->socket = new MasterServerSocket($this->ipAddress, $this->port);
  179. }
  180. }