Game servers will answer the following messages: Messages are sent to the server by sending 4 consecutive bytes of 255 (32-bit integer -1) and then the string command followed by a zero byte to terminate it "ping" Server responds with a single byte code ASCII 'j' "info" Server responds with the following packet: (int32) -1 (byte) ASCII 'C' (info response, S2A_INFO) (string) net address of server (string) name of the host / server (string) name of the map (string) game directory (i.e. valve/) (string) Game description (e.g. "half-life multiplay") (byte) active client count (byte) maximum clients allowed (byte) protocol version (currently 7) "players" Server responds with the following packet: (int32) -1 (byte) ASCII 'D' (players response, S2A_PLAYER) (byte) active client count for each active client (byte) client number / index (string) player name (int32) client's frag total (float32) client's total time in-game "rules" Server responds with the following packet: (int32) -1 (byte) ASCII 'E' (rules response, S2A_RULES) (int16) number of rules for each rule (string) rule name (string) rule value ------------------- Master server query protocol: Sent to master: (byte) ASCII 'c' ( A2M_GET_SERVERS ) Response from master: (int32) -1 (byte) ASCII 'd' ( M2A_SERVERS ) (byte) unused // This is followed by as many 6 byte ip addresses as will fit in the message. The master currently feeds about 2K worth of IP address ( 300+ or so ), but we may up that # significantly in the near future. (4 x byte) ip address (int16) port # The old protocol is still valid, but there is a new, extended protocol: Here are both the old and new protocols ( the new one is the "details" message ): "info" Server responds with the following packet: (int32) -1 (byte) ASCII 'C' (info response, S2A_INFO) (string) net address of server (string) name of the host / server (string) name of the map (string) game directory (i.e. valve/) (string) Game description (e.g. "half-life multiplay") (byte) active client count (byte) maximum clients allowed (byte) protocol version (currently 37) "details" (int32) -1 (byte) ASCII 'm' ( S2A_INFO_DETAILED ) (string) net address of server (string) name of the host / server (string) name of the map (string) game directory (i.e. valve/) (string) Game description (e.g. "half-life multiplay") (byte) active client count (byte) maximum clients allowed (byte) protocol version (currently 37) (byte) type of server == 'l' for listen or 'd' for dedicated (byte) os of server == 'w' for win32 or 'l' for linux (byte) password on server == 1 or yes, 0, for no (byte) is server running a mod? == 1 for yes, 0 for no IFF the server is running mod byte was 1: (string) URL for mod's "info" website (string) URL for mod's download ftp server (int32) mod version # (int32) mod download size ( in bytes, approx. ) (byte) is the mod a server side only mod? 1 == yes, 0 == no (byte) does this server require you to have a custom client side .dll ( client.dll )? 1 == yes, 0 == no. Here is some code that uses the new protocol. The first function starts the protocol and the second services the message and requests more ip addresses: /* ================== Host_GetBatchServerList_f Request full server list from HL master server. ================== */ void Host_GetBatchServerList_f( void ) { unsigned char c[10]; adrlist_t *p; int i = 0; // Request a server list from the master servers. NET_Config( true ); // Initialize networking if ( gfNoMasterServer ) return; if ( !valvemaster_adr ) return; c[0] = A2M_GET_SERVERS_BATCH; // ascii 'e' i++; *(int *)&c[1] = 0; // Request first batch. i += sizeof( int ); p = valvemaster_adr; while ( p ) { // send to valve master Con_Printf ("Requesting batch server list from %s\n", NET_AdrToString ( p->adr) ); NET_SendPacket (NS_CLIENT, i, c, p->adr ); p = p->next; } } // Upon receiving ( 5 bytes, 4 for the -1 and 1 byte for the 'f' character ): int32 -1 M2A_SERVER_BATCH // Ascii 'f', the response to the above void CL_ParseBatchServerList( void ) { char szAddress[128] = ""; unsigned char cIP[4]; int i; unsigned short iIPPort; int nNumAddresses; int count = 1; int unique = 0; MSG_ReadByte(); // Skip \r unique = MSG_ReadLong(); // So far we have read 6 chars. Remainder of message length is iBytesRead - 6 nNumAddresses = net_message.cursize - sizeof(int) - sizeof(unsigned char) - sizeof(byte); // Each address is 6 bytes long // nNumAddresses /= 6; while (nNumAddresses-- > 0) { memset(szAddress, 0, 128); for (i = 0; i < 4; i++) cIP[i] = MSG_ReadByte(); sprintf( szAddress, "%i.%i.%i.%i" , (int)cIP[0] , (int)cIP[1] , (int)cIP[2] , (int)cIP[3] ); iIPPort = BigShort((unsigned short)MSG_ReadShort()); //if ( count <= 100 ) // Con_Printf( "%4i: %s:%i\n", count, szAddress, iIPPort ); count++; } Con_Printf( "%i servers\n", count ); if ( unique != 0 ) // More servers left, send another request to master { unsigned char c[10]; int i = 0; // Request a server list from the master servers. NET_Config( true ); // Initialize networking c[0] = A2M_GET_SERVERS_BATCH; i++; *(int *)&c[1] = unique; // Request servers starting after this unique id. i += sizeof( int ); // send to valve master Con_DPrintf ("Requesting next batch ( %i ) server list from %s\n", unique, NET_AdrToString ( net_from ) ); NET_SendPacket (NS_CLIENT, i, c, net_from ); } else Con_Printf( "Done.\n" ); }