MasterServer: How it works
Detailed explanation of the processes within a masterserver.
What is a MasterServer?
The masterserver receives digital heartbeats from online gameservers, maintains the list of gameservers and provides the serverlist to your game client. To be able to play multiplayer games, you need a list of available gameservers. If you have no (working) masterservers in your game settings, no online servers will appear.
We refer to gameservers and masterservers instead of game servers and master servers. The latter is correct English, but the former improves readability and avoids confusion about what type of server we explicitly try to describe.
There are three important elements in an online game. There are numerous gameservers that hosts multiplayer game sessions, numerous game clients that let you play the online games on your computer and a masterserver that facilitates the interactions between them to make it work. Generally, there are hundreds of gameservers, hundreds of clients, but only a single masterserver for that particular game.
When somebody starts a gameserver, the gameserver starts sending a heartbeat to the masterserver every few minutes. This heartbeat is a small text message that contains information about the gameserver (1). The masterserver maintains a list of all the gameservers that have sent heartbeats to it. Gameservers that stop sending heartbeats are removed from the list after some time.
When you open your game and click on the online game browser to get a list of available online gameservers, the game client sends a list request to the masterserver. The game client asks the masterserver for a list of all servers for this specific game. The masterserver first verifies that this game is actually permitted to see the server list and then sends the list to the game client (2).
The serverlist only contains IP-addresses and query ports of gameservers, but does not describe any of the server properties like the gametype, server name or number of players. In order to obtain all descriptive information, the game client sends a status request to the game server to obtain all the data that you see while browsing your game list (3).
There are multiple methods of sending information over the internet between computers. The two most important methods are UDP and TCP communication. Imagine that there is a speaker in front of a large audience. In order to get to know the audience, the speaker could ask everyone to shout their names. Everyone would shout their names one by one to the speaker and hope that the speaker would hear them properly. The User Datagram Protocol (UDP) is similar to this situation: a gameserver sends a heartbeat to the masterserver, but there is no guarantee that information is correctly received or in the correct order.
The other method would be for the speaker to ask the audience to walk up to him one by one, shake hands and introduce themselves before sitting down again. The Transfer Control Protocol (TCP) handles information in the same way: a client connects with the masterserver, identifies itself and retrieves the serverlist. As one could imagine, the information is conveyed correctly, but at the expense of a much larger duration of the interaction. The choice for either of these protocols in the game interactions is defined by the circumstances: some interactions require speed rather than precision, some interactions require precision over speed.
Information is sent in a standardised fashion for both gameserver, masterserver and client. The particular protocol for this masterserver is the GameSpy v0 protocol. In the example communication below, we see that information is sent using a keyword and a value, separated by a backslash ('\'). The keyword and value can contain any text, as long as the receiving server or client knows how to interpret both the keyword and its value. The value may also be empty. Multiple keywords and values can be concated in series.
The heartbeat that the gameserver sends to the masterserver is a small text message that contains the IP-address, network port and the game title. With this heartbeat, the gameserver informs the masterserver that the gameserver is active, ready to receive incoming connections and on which IP-address and port the gameserver can be contacted.
When a heartbeat is received, the masterserver responds with the secure/validate challenge that determines whether the gameserver is authentic and conforms to the defined protocol. The masterserver challenges with a 6-byte secure text string and the gameserver responds with an 8-byte validate text string. The masterserver decides whether the response is correctly calculated and adds the gameserver to its (internal) serverlist.
List request (2)
When the user/player starts browsing the online multiplayer game list, a TCP connection is established with the masterserver. The masterserver requests minimal ("basic") game information and sends a secure keyword for the secure/validate challenge. The client responds in kind and is authenticated by the masterserver. After this, the client requests the serverlist, which can be sent to the client in two ways: as plaintext and in a compressed format.
Gameserver addresses are usually expressed as an IP-address and port with a colon (':') as separator in a plaintext string. The length of this string is up to 21 characters, with a 4- or 5-digit port (example below). To separate multiple addresses, the \ip\ keyword is added for every new address in the list, adding another 4 characters to the plaintext address. Every character requires a single byte to transfer.
In the time that the GameSpy protocol was drafted, bandwidth was scarce. With more than two thousand servers during its popular period, a serverlist for Unreal Tournament could easily be 50,000 characters large and take several seconds to transmit on a dial-up connection. To reduce the size of the data stream, the compressed serverlist was introduced. By specifying the cmp value for the list keyword, the masterserver would send a compressed serverlist where the gameserver addresses were not sent as plaintext, but as byte values.
A single byte can hold 2^8 or 256 values. With the inclusion of the zero, that leads to a value range between 0 and 255, including both values. An IP-address consists of four octets (groups of numbers) with the values 0 to 255, joined by periods. Conveniently, every individual octet can fit inside a single fixed-length byte, despite the lexical length being two (e.g. 99) or three (e.g. 101) digits. As we know that every new byte is a new octet, it is no longer necessary to join the octets by periods in their text representation.
The port value 12556 can be represented as hexadecimal number 0x310C, which occupies two bytes where the first byte holds the value 0x31 and the second byte 0x0C. In the table above, we represented the same IP-address as plaintext (top) and hexadecimal values (bottom), where every occupied table cell is a byte. As seen, the bottom row requires significantly fewer bytes to store the same data.
Earlier we derived that a plaintext gameserver address with ip key prefix can occupy up to 25 characters/bytes. With the hexadecimal representation, we compressed the same address to a fixed length of 6 bytes, which means that the same Unreal Tournament serverlist could now be compressed into a 12,000-byte data string, a reduction of more than two-thirds of the original plaintext data transfer. It depends on the game whether the plaintext- or compressed serverlist is requested.
Status request (3)
The serverlist only contains the addresses of gameservers, but not descriptive information such as the servername, current map or number of present players. In order to get this information, the game client queries every individual gameserver with a status request. The gameserver then sends detailed information about its game rules, active state and current players.
The status query consists of four components: basic identifier and location information, info segments about the version, compatibility, active map and administrator information, rules such as the time limit, frag limit and number of teams, and players that are active on the server, as well as their skins and scores. The information can be requested all at once, or with the individual (highlighted) keywords.
Though 333networks utilises the status query to obtain detailed server information for the website, the status query is not an integral component of the traditional masterserver. More information about the status query can be found at Old Unreal where the exact contents and formatting of the status query is discussed.
We hope that this overview helps you with understanding the masterserver and how it is necessary to support legacy games. If you have questions or suggestions about this lectorial, do not hesitate to ask us on our discord server.
If you are interested in further reading, also see the following articles or look directly at our source code: