Make server browser communicate through QR

This should hopefully fix a bug with networks that aren't as open, or
behind the same NAT.
This commit is contained in:
polaris 2014-04-14 20:45:59 -04:00
parent 87170787f0
commit 8fcbc22178
3 changed files with 30 additions and 14 deletions

View File

@ -4,11 +4,13 @@
import logging
import socket
import struct
import threading
from multiprocessing.managers import BaseManager
import gamespy.gs_utility as gs_utils
import gamespy.gs_database as gs_database
import other.utils as utils
from multiprocessing.managers import BaseManager
from gamespy_server_browser_server import GameSpyServerBrowserServer
# Logger settings
logger_output_to_console = True
@ -62,6 +64,11 @@ class GameSpyQRServer(object):
logger.log(logging.INFO, "Server is now listening on %s:%s..." % (address[0], address[1]))
# Dependencies! I don't really like this solution but it's easier than trying to manage it another way.
server_browser_server = GameSpyServerBrowserServer(self)
server_browser_server_thread = threading.Thread(target=server_browser_server.start())
server_browser_server_thread.start()
self.wait_loop()
def wait_loop(self):
@ -250,7 +257,8 @@ class GameSpyQRServer(object):
self.log(logging.WARNING, address, "NOT IMPLEMENTED! Received echo from %s:%s... %s" % (address[0], address[1], recv_data[5:]))
elif recv_data[0] == '\x07': # Client Message Ack
self.log(logging.WARNING, address, "NOT IMPLEMENTED! Received client message ack from %s:%s... %s" % (address[0], address[1], recv_data[5:]))
#self.log(logging.WARNING, address, "NOT IMPLEMENTED! Received client message ack from %s:%s... %s" % (address[0], address[1], recv_data[5:]))
self.log(logging.DEBUG, address, "Received client message ack from %s:%s..." % (address[0], address[1]))
elif recv_data[0] == '\x08': # Keep Alive
self.log(logging.DEBUG, address, "Received keep alive from %s:%s..." % (address[0], address[1]))

View File

@ -43,12 +43,12 @@ GameSpyServerDatabase.register("find_server_by_address")
address = ("0.0.0.0", 28910)
class GameSpyServerBrowserServer(object):
def __init__(self):
pass
def __init__(self, qr = None):
self.qr = qr
def start(self):
endpoint = serverFromString(reactor, "tcp:%d:interface=%s" % (address[1], address[0]))
conn = endpoint.listen(SessionFactory())
conn = endpoint.listen(SessionFactory(self.qr))
try:
if reactor.running == False:
@ -59,19 +59,20 @@ class GameSpyServerBrowserServer(object):
class SessionFactory(Factory):
def __init__(self):
def __init__(self, qr):
logger.log(logging.INFO, "Now listening for connections on %s:%d...", address[0], address[1])
self.secret_key_list = gs_utils.generate_secret_keys("gslist.cfg")
# TODO: Prune server cache at some point
self.server_cache = {}
self.qr = qr
def buildProtocol(self, address):
return Session(address, self.secret_key_list, self.server_cache)
return Session(address, self.secret_key_list, self.server_cache, self.qr)
class Session(LineReceiver):
def __init__(self, address, secret_key_list, server_cache):
def __init__(self, address, secret_key_list, server_cache, qr):
self.setRawMode() # We're dealing with binary data so set to raw mode
self.address = address
self.forward_to_client = False
@ -79,6 +80,7 @@ class Session(LineReceiver):
self.secret_key_list = secret_key_list # Don't waste time parsing every session, so just accept it from the parent
self.console = 0
self.server_cache = server_cache
self.qr = qr
manager_address = ("127.0.0.1", 27500)
manager_password = ""
@ -131,9 +133,15 @@ class Session(LineReceiver):
output += bytearray(utils.get_bytes_from_int(natneg_session))
output += bytearray(data)
client_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_s.sendto(output, self.forward_client)
logger.log(logging.DEBUG, "Forwarded data to %s:%s..." % (self.forward_client[0], self.forward_client[1]))
if self.qr != None:
self.qr.socket.sendto(output, self.forward_client)
logger.log(logging.DEBUG, "Forwarded data to %s:%s through QR server..." % (self.forward_client[0], self.forward_client[1]))
else:
# In case we can't contact the QR server, just try sending the packet directly.
# This isn't standard behavior but it can work in some instances.
client_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_s.sendto(output, self.forward_client)
logger.log(logging.DEBUG, "Forwarded data to %s:%s directly (potential error occurred)..." % (self.forward_client[0], self.forward_client[1]))
return
if data[2] == '\x00': # Server list request

View File

@ -44,8 +44,8 @@ if __name__ == "__main__":
player_search_server_thread = threading.Thread(target=start_player_search_server)
player_search_server_thread.start()
server_browser_server_thread = threading.Thread(target=start_server_browser_server)
server_browser_server_thread.start()
#server_browser_server_thread = threading.Thread(target=start_server_browser_server)
#server_browser_server_thread.start()
natneg_server_thread = threading.Thread(target=start_natneg_server)
natneg_server_thread.start()