From abd7b5ccdddc0cff76daf67c701eac5e68fa5795 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Mon, 8 Jun 2026 22:17:21 +0500 Subject: [PATCH] engine: masterlist: change parsing static server list from by token to by line --- Documentation/protocol/http-server-list.md | 13 +++++---- engine/common/masterlist.c | 33 +++++++++------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/Documentation/protocol/http-server-list.md b/Documentation/protocol/http-server-list.md index aaac3258..1835d56e 100644 --- a/Documentation/protocol/http-server-list.md +++ b/Documentation/protocol/http-server-list.md @@ -28,17 +28,18 @@ used; servers register out of band. ## Response -UTF-8 text, tokenized with `COM_ParseFileSafe` (whitespace separates, -`//` and `#` start line comments, `"..."` quotes a token). One directive -per record: +UTF-8 text, parsed line by line. Each line is tokenized with +`COM_ParseFileSafe` (whitespace separates, `//` and `#` start line +comments, `"..."` quotes a token). Blank lines and comment-only lines +are ignored. One directive per line: * `ip
` — Xash3D server (protocol 49). * `gs
` — GoldSrc server (protocol 48). `
` is parsed by `NET_StringToAdr` (`1.2.3.4:27015`, -`[2001:db8::1]:27015`, hostnames). Port defaults to `27015`. Unknown -directives are skipped together with one operand so new keywords can be -added without breaking older clients. +`[2001:db8::1]:27015`, hostnames). Port defaults to `27015`. Lines +starting with an unknown directive are skipped entirely, so new keywords +with any number of operands can be added without breaking older clients. `Content-Type` is not inspected, `text/plain; charset=utf-8` expected. diff --git a/engine/common/masterlist.c b/engine/common/masterlist.c index 1121bc79..a68b1595 100644 --- a/engine/common/masterlist.c +++ b/engine/common/masterlist.c @@ -225,33 +225,33 @@ void NET_QueryServerByAddress( netadr_t adr, connprotocol_t proto ) Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO " %i", PROTOCOL_VERSION ); } -static int NET_ParseMasterStaticBody( char *body ) +static int NET_ParseMasterStaticBody( const byte *body, size_t size ) { - char token[MAX_TOKEN]; - char *pfile = body; + char line[1024]; + int offset = 0; int count = 0; - while(( pfile = COM_ParseFileSafe( pfile, token, sizeof( token ), PFILE_HASH_AS_COMMENT, NULL, NULL ))) + while( Q_memfgets( (byte *)body, size, &offset, line, sizeof( line )) != NULL ) { + char token[MAX_TOKEN]; + char *pfile = line; qboolean gs; + netadr_t adr = { 0 }; + + pfile = COM_ParseFileSafe( pfile, token, sizeof( token ), PFILE_HASH_AS_COMMENT, NULL, NULL ); + if( !pfile || token[0] == '\0' ) + continue; if( !Q_strcmp( token, "ip" )) gs = false; else if( !Q_strcmp( token, "gs" )) gs = true; else - { - pfile = COM_ParseFileSafe( pfile, token, sizeof( token ), PFILE_HASH_AS_COMMENT, NULL, NULL ); - if( !pfile ) - break; continue; - } pfile = COM_ParseFileSafe( pfile, token, sizeof( token ), PFILE_HASH_AS_COMMENT, NULL, NULL ); if( !pfile ) - break; - - netadr_t adr = { 0 }; + continue; if( !NET_StringToAdr( token, &adr )) { @@ -288,16 +288,9 @@ static void NET_MasterStaticResponse( const char *url, qboolean success, const b return; } - // HTTP buffer isn't NUL-terminated; COM_ParseFileSafe needs one. - char *body = Mem_Malloc( host.mempool, size + 1 ); - memcpy( body, data, size ); - body[size] = 0; - NET_Config( true, false ); // allow remote sends - int count = NET_ParseMasterStaticBody( body ); - - Mem_Free( body ); + int count = NET_ParseMasterStaticBody( data, size ); Con_Reportf( "masterstatic: %s yielded %d server(s)\n", url, count );