#!/usr/bin/env python3 """Asks a CS 1.6 / GoldSrc server for its info (A2S_INFO), like the in-game server browser does. python3 tools/hlq.py info Prints: name | map | players x/y (bots n) | password yes/no. Exit code 1 when there's no answer. Works against any address (LAN, VPN, a playit tunnel), so it also tests the way in from outside.""" import socket, sys H = b"\xff\xff\xff\xff" def info(host, port, timeout=4): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(timeout) q = H + b"TSource Engine Query\x00" s.sendto(q, (host, port)) d = s.recvfrom(65535)[0] if d[4:5] == b"A": # newer servers answer with a challenge first: ask again with it s.sendto(q + d[5:9], (host, port)) d = s.recvfrom(65535)[0] if d[4:5] != b"I": raise ValueError("unexpected reply type %r" % d[4:5]) name, mp, folder, game, rest = d[6:].split(b"\x00", 4) players, maxp, bots, pw = rest[2], rest[3], rest[4], rest[7] return (f"{name.decode(errors='replace')} | map {mp.decode()} | players {players}/{maxp} (bots {bots})" f" | password {'yes' if pw else 'no'}") if __name__ == "__main__": if len(sys.argv) != 4 or sys.argv[1] != "info": sys.exit(__doc__) try: print("A2S_INFO ok:", info(sys.argv[2], int(sys.argv[3]))) except (OSError, ValueError) as e: print("no answer:", e) sys.exit(1)