SHARE
TWEET

pyspy GameSpy4 protocol

a guest Mar 19th, 2012 288 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python
  2. import socket
  3. import time
  4. import struct
  5. import binascii
  6. import string
  7. from twisted.internet.protocol import ConnectedDatagramProtocol, Factory
  8. from twisted.internet import reactor
  9.  
  10. __all__ = ['GamespyProtocol', 'GamespyClient']
  11.  
  12. class GamespyProtocol(ConnectedDatagramProtocol):
  13.     def __init__(self, host, port):
  14.         self.__host = socket.gethostbyname(host)
  15.         self.__port = port
  16.         self.__players = []
  17.         self.__tags = {}
  18.         self.__token = 0
  19.  
  20.     def startProtocol(self):
  21.         self.transport.connect(self.__host, self.__port)
  22.         self.sendHello()
  23.  
  24.     def sendHello(self):
  25.         self._send('!BBBi', 0xfe, 0xfd, 0x09, time.time())
  26.  
  27.     def sendInfoQuery(self):
  28.         self._send('!BBBiiI', 0xFE, 0XFD, 0x00, time.time(), self.__token, 0xFFFFFF01)
  29.  
  30.     def _send(self, fmt, *args):
  31.         msg = struct.pack(fmt, *args)
  32.         self.transport.write(msg)
  33.  
  34.     def datagramReceived(self, data, addr):
  35.         type, = struct.unpack('!B', data[0])
  36.         if type == 0x09:
  37.             # Clamp data size to exactly 16 bytes
  38.             data = data[1:].ljust(15, '\0')[0:15]
  39.             self.__seqnum,token = struct.unpack('!i11s', data)
  40.             validChars = "0123456789-"
  41.             self.__token = int(''.join(c for c in token if c in validChars))
  42.             self.sendInfoQuery()
  43.         elif type == 0:
  44.             tokens, players = data[5:].split('\x01',1)
  45.             tokens = tokens.split('\x00')
  46.             players = players.split('\x00')[:-1]
  47.             ret = {}
  48.             isKey = True
  49.             key = None
  50.             for t in tokens:
  51.                 if isKey:
  52.                     key = t
  53.                     isKey = False
  54.                 else:
  55.                     ret[key] = t
  56.                     isKey = True
  57.             self.__tags = ret
  58.             playerList = []
  59.             isPlayer = False
  60.             for p in players:
  61.                 if (len(p) == 0):
  62.                     continue
  63.                 if isPlayer:
  64.                     playerList.append(p)
  65.                     isPlayer = False
  66.                 else:
  67.                     isPlayer = True
  68.             self.__players = playerList
  69.  
  70.     def tags(self):
  71.         return self.__tags
  72.  
  73.     def players(self):
  74.         return self.__players
  75.  
  76. class GamespyClient(object):
  77.     def __init__(self, host, port):
  78.         self.__proto = GamespyProtocol(host, port)
  79.         self.__listener = reactor.listenUDP(0, self.__proto)
  80.  
  81.     def update(self):
  82.         self.__proto.sendHello()
  83.         reactor.doIteration(100)
  84.         self.__proto.sendInfoQuery()
  85.         reactor.doIteration(100)
  86.  
  87.     def players(self):
  88.         return self.__proto.players()
  89.  
  90.     def tags(self):
  91.         return self.__proto.tags()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top