Skip to content

Instantly share code, notes, and snippets.

@bacher09
Last active December 11, 2024 20:23
Show Gist options
  • Save bacher09/e4c2cc38e867ff5d63910365030cfa25 to your computer and use it in GitHub Desktop.
Save bacher09/e4c2cc38e867ff5d63910365030cfa25 to your computer and use it in GitHub Desktop.
Get quake server info
import socket
STATUS_RESPONSE_HEADER = b'\xff\xff\xff\xffstatusResponse\n'
def parse_server_vars(server_vars):
if not server_vars.startswith(b'\\'):
raise ValueError('Invalid server vars')
values = server_vars.split(b'\\')[1:]
return dict(zip(values[::2], values[1::2]))
def parse_status_packet(status_packet, player_factory=lambda x: x):
data = status_packet[len(STATUS_RESPONSE_HEADER):]
parts = data.split(b'\n')[:-1]
if len(parts) < 1:
raise ValueError("Bad packet")
server_vars, players_dat = parts[0], parts[1:]
players = list(player_factory(playerd) for playerd in players_dat)
return parse_server_vars(server_vars), players
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(b"\xff\xff\xff\xffgetstatus", ('168.119.137.110', 26000))
resp, addr = sock.recvfrom(1400)
print(parse_status_packet(resp))
require 'socket'
GET_STATUS = "\xFF\xFF\xFF\xFFgetstatus"
sock = UDPSocket.new
sock.send(GET_STATUS, 0, "168.119.137.110", 26000)
mesg, addr = sock.recvfrom(1400)
puts(mesg.inspect)
#!/bin/bash
exec 13<>/dev/udp/168.119.137.110/26000
printf "\xff\xff\xff\xffgetstatus" >&13
timeout 1 cat <&13
In [1]: import socket
In [2]: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
In [3]: sock.sendto(b"\xff\xff\xff\xffgetstatus", ('168.119.137.110', 26000))
Out[3]: 13
In [4]: resp, addr = sock.recvfrom(1400)
In [5]: resp
Out[5]: b'\xff\xff\xff\xffstatusResponse\n\\gamename\\Xonotic\\modname\\data_extra\\gameversion\\806\\sv_maxclients\\26\\clients\\6\\bots\\0\\mapname\\Vortex.NV\\hostname\\[\xe5\x8a\x9b] TheRegulars \xe2\x98\xa0 Instagib Server [git]\\protocol\\3\\qcstatus\\ctf:git:P49:S20:F7:TINVALID:MInstaGib::score!!:caps!!:5:0:14:0\\d0_blind_id\\1 cfTWCVMoaEXWtSvJyWhWp04abgwA4KVO9NJYhleDZzg=@Xon//KssdlzGkFKdnnN4sgg8H+koTbBn5JTi37BAW1Q= @~XHub/MCjSOklCBU4ADlHX3+EcTjC0xhJ6odguyTvGp0=\n-666 36 0 "? "\n0 33 1 "michiru"\n-666 39 0 "Hagar the Horrible (2k1c)"\n-666 148 0 "\xee\x83\xa4\xee\x83\xb2\xee\x83\xa1\xee\x83\xa3\xee\x83\xaf^x902^7"\n-666 45 0 "mo"\n-666 38 0 "^xFEEGur^x2E1c^xFEEke^7"\n'
In [6]: STATUS_RESPONSE_HEADER = b'\xff\xff\xff\xffstatusResponse\n'
In [7]: def parse_server_vars(server_vars):
...: if not server_vars.startswith(b'\\'):
...: raise ValueError('Invalid server vars')
...:
...: values = server_vars.split(b'\\')[1:]
...: return dict(zip(values[::2], values[1::2]))
...:
...:
...: def parse_status_packet(status_packet, player_factory=lambda x: x):
...: data = status_packet[len(STATUS_RESPONSE_HEADER):]
...: parts = data.split(b'\n')[:-1]
...: if len(parts) < 1:
...: raise ValueError("Bad packet")
...:
...: server_vars, players_dat = parts[0], parts[1:]
...: players = list(player_factory(playerd) for playerd in players_dat)
...: return parse_server_vars(server_vars), players
...:
In [8]: parse_status_packet(resp)
Out[8]:
({b'gamename': b'Xonotic',
b'modname': b'data_extra',
b'gameversion': b'806',
b'sv_maxclients': b'26',
b'clients': b'6',
b'bots': b'0',
b'mapname': b'Vortex.NV',
b'hostname': b'[\xe5\x8a\x9b] TheRegulars \xe2\x98\xa0 Instagib Server [git]',
b'protocol': b'3',
b'qcstatus': b'ctf:git:P49:S20:F7:TINVALID:MInstaGib::score!!:caps!!:5:0:14:0',
b'd0_blind_id': b'1 cfTWCVMoaEXWtSvJyWhWp04abgwA4KVO9NJYhleDZzg=@Xon//KssdlzGkFKdnnN4sgg8H+koTbBn5JTi37BAW1Q= @~XHub/MCjSOklCBU4ADlHX3+EcTjC0xhJ6odguyTvGp0='},
[b'-666 36 0 "? "',
b'0 33 1 "michiru"',
b'-666 39 0 "Hagar the Horrible (2k1c)"',
b'-666 148 0 "\xee\x83\xa4\xee\x83\xb2\xee\x83\xa1\xee\x83\xa3\xee\x83\xaf^x902^7"',
b'-666 45 0 "mo"',
b'-666 38 0 "^xFEEGur^x2E1c^xFEEke^7"'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment