def perform_authp(self, data_parsed): authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db) #print authtoken_parsed if "lid" in data_parsed: self.lid = data_parsed['lid'] userid, profileid, gsbrcd, uniquenick = gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed, self.db) if profileid != None: # Successfully logged in or created account, continue creating # session. sesskey = self.db.create_session(profileid, '') self.sessions[profileid] = self self.profileid = int(profileid) msg = gs_query.create_gamespy_message([('__cmd__', "pauthr"), ('__cmd_val__', profileid), ('lid', self.lid),]) else: # login failed self.log(logging.WARNING, "Invalid password") msg = gs_query.create_gamespy_message([('__cmd__', "pauthr"), ('__cmd_val__', -3), ('lid', self.lid), ('errmsg', 'Invalid Validation'),]) self.log(logging.DEBUG, "SENDING: '%s'..." % msg) msg = self.crypt(msg) self.transport.write(bytes(msg))
def perform_authp(self, data_parsed): authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db) #print authtoken_parsed if "lid" in data_parsed: self.lid = data_parsed['lid'] userid, profileid, gsbrcd, uniquenick = gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed, self.db) if profileid != None: # Successfully logged in or created account, continue creating session. sesskey = self.db.create_session(profileid, '') self.sessions[profileid] = self self.profileid = int(profileid) msg = gs_query.create_gamespy_message([ ('__cmd__', "pauthr"), ('__cmd_val__', profileid), ('lid', self.lid), ]) else: # login failed self.log(logging.WARNING, "Invalid password") msg = gs_query.create_gamespy_message([ ('__cmd__', "pauthr"), ('__cmd_val__', -3), ('lid', self.lid), ('errmsg', 'Invalid Validation'), ]) self.log(logging.DEBUG, "SENDING: '%s'..." % msg) msg = self.crypt(msg) self.transport.write(bytes(msg))
def perform_login(self, data_parsed): authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db) if authtoken_parsed == None: self.log(logging.WARNING, "Invalid Authtoken.") msg = gs_query.create_gamespy_message([ ('__cmd__', "error"), ('__cmd_val__', ""), ('err', '266'), ('fatal', ''), ('errmsg', 'There was an error validating the pre-authentication.'), ('id', data_parsed['id']), ]) self.transport.write(bytes(msg)) return if 'sdkrevision' in data_parsed: self.sdkrevision = data_parsed['sdkrevision'] # Verify the client's response valid_response = gs_utils.generate_response(self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken']) if data_parsed['response'] != valid_response: self.log(logging.ERROR, "ERROR: Got invalid response. Got %s, expected %s" % (data_parsed['response'], valid_response)) proof = gs_utils.generate_proof(self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken']) userid, profileid, gsbrcd, uniquenick = gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed, self.db) if profileid != None: # Successfully logged in or created account, continue creating session. loginticket = gs_utils.base64_encode(utils.generate_random_str(16)) self.sesskey = self.db.create_session(profileid, loginticket) self.sessions[profileid] = self self.buddies = self.db.get_buddy_list(self.profileid) self.blocked = self.db.get_blocked_list(self.profileid) if self.sdkrevision == "11": # Used in Tatsunoko vs Capcom def make_list(data): list = [] for d in data: if d['status'] == 1: list.append(str(d['buddyProfileId'])) return list block_list = make_list(self.blocked) msg = gs_query.create_gamespy_message([ ('__cmd__', "blk"), ('__cmd_val__', str(len(block_list))), ('list', ','.join(block_list)), ]) self.log(logging.DEBUG, "SENDING: %s" % msg) self.transport.write(bytes(msg)) buddy_list = make_list(self.buddies) msg = gs_query.create_gamespy_message([ ('__cmd__', "bdy"), ('__cmd_val__', str(len(buddy_list))), ('list', ','.join(buddy_list)), ]) self.log(logging.DEBUG, "SENDING: %s" % msg) self.transport.write(bytes(msg)) msg = gs_query.create_gamespy_message([ ('__cmd__', "lc"), ('__cmd_val__', "2"), ('sesskey', self.sesskey), ('proof', proof), ('userid', userid), ('profileid', profileid), ('uniquenick', uniquenick), # Some kind of token... don't know it gets used or generated, but it doesn't seem to have any negative effects if it's not properly generated. ('lt', loginticket), ('id', data_parsed['id']), ]) # Take the first 4 letters of gsbrcd instead of gamecd because they should be consistent across game # regions. For example, the US version of Metroid Prime Hunters has the gamecd "AMHE" and the first 4 letters # of gsbrcd are "AMHE". However, the Japanese version of Metroid Prime Hunters has the gamecd "AMHJ" with # the first 4 letters of bsbrcd as "AMHE". Tetris DS is the other way, with the first 4 letters as the # Japanese version (ATRJ) while the gamecd is region specific (ATRE for US and ATRJ for JP). # gameid is used to send all people on the player's friends list a status updates, so don't make it region # specific. self.gameid = gsbrcd[:4] self.profileid = int(profileid) self.log(logging.DEBUG, "SENDING: %s" % msg) self.transport.write(bytes(msg)) # Get pending messages. self.get_pending_messages() # Send any friend statuses when the user logs in. # This will allow the user to see if their friends are hosting a game as soon as they log in. self.get_status_from_friends() self.send_status_to_friends() # profile = self.db.get_profile_from_profileid(profileid) # if profile != None: # self.statstring = profile['stat'] # self.locstring = profile['loc'] else: self.log(logging.INFO, "Invalid password or banned user") msg = gs_query.create_gamespy_message([ ('__cmd__', "error"), ('__cmd_val__', ""), ('err', '256'), ('fatal', ''), ('errmsg', 'Login failed.'), ('id', data_parsed['id']), ]) self.log(logging.DEBUG, "SENDING: %s" % msg) self.transport.write(bytes(msg))
def perform_login(self, data_parsed): authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db) #print authtoken_parsed # Track what console is connecting and save it in the database during user creation just in case we can use # the information in the future. console = 0 # 0 = NDS, 1 = Wii # get correct information userid = authtoken_parsed['userid'] # The Wii does not use passwd, so take another uniquely generated string as the password. if "passwd" in authtoken_parsed: password = authtoken_parsed['passwd'] else: password = authtoken_parsed['gsbrcd'] console = 1 gsbrcd = authtoken_parsed['gsbrcd'] gameid = gsbrcd[:4] uniquenick = utils.base32_encode(int(userid)) + gsbrcd email = uniquenick + "@nds" # The Wii also seems to use @nds. # Wii: Serial number if "csnum" in authtoken_parsed: csnum = authtoken_parsed['csnum'] console = 1 else: csnum = "" # Wii: Friend code if "cfc" in authtoken_parsed: cfc = authtoken_parsed['cfc'] console = 1 else: cfc = "" # NDS: Wifi network's BSSID if "bssid" in authtoken_parsed: bssid = authtoken_parsed['bssid'] else: bssid = "" # NDS: Device name if "devname" in authtoken_parsed: devname = authtoken_parsed['devname'] else: devname = "" # NDS: User's birthday if "birth" in authtoken_parsed: birth = authtoken_parsed['birth'] else: birth = "" # Verify the client's response valid_response = gs_utils.generate_response( self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken']) if data_parsed['response'] != valid_response: self.log( logging.ERROR, "ERROR: Got invalid response. Got %s, expected %s" % (data_parsed['response'], valid_response)) proof = gs_utils.generate_proof(self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken']) valid_user = self.db.check_user_exists(userid, gsbrcd) if valid_user == False: profileid = self.db.create_user(userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid) else: profileid = self.db.perform_login(userid, password, gsbrcd) if profileid == None: # Handle case where the user is invalid self.log(logging.ERROR, "Invalid password") if profileid != None: # Successfully logged in or created account, continue creating session. sesskey = self.db.create_session(profileid) self.sessions[profileid] = self msg_d = [] msg_d.append(('__cmd__', "lc")) msg_d.append(('__cmd_val__', "2")) msg_d.append(('sesskey', sesskey)) msg_d.append(('proof', proof)) msg_d.append(('userid', userid)) msg_d.append(('profileid', profileid)) msg_d.append(('uniquenick', uniquenick)) msg_d.append( ('lt', gs_utils.base64_encode(utils.generate_random_str(16))) ) # Some kind of token... don't know it gets used or generated, but it doesn't seem to have any negative effects if it's not properly generated. msg_d.append(('id', data_parsed['id'])) msg = gs_query.create_gamespy_message(msg_d) # Take the first 4 letters of gsbrcd instead of gamecd because they should be consistent across game # regions. For example, the US version of Metroid Prime Hunters has the gamecd "AMHE" and the first 4 letters # of gsbrcd are "AMHE". However, the Japanese version of Metroid Prime Hunters has the gamecd "AMHJ" with # the first 4 letters of bsbrcd as "AMHE". Tetris DS is the other way, with the first 4 letters as the # Japanese version (ATRJ) while the gamecd is region specific (ATRE for US and ATRJ for JP). # gameid is used to send all people on the player's friends list a status updates, so don't make it region # specific. self.gameid = gsbrcd[0:4] self.profileid = int(profileid) self.log(logging.DEBUG, "SENDING: %s" % msg) self.transport.write(bytes(msg)) self.buddies = self.db.get_buddy_list(self.profileid) self.blocked = self.db.get_blocked_list(self.profileid) # Get pending messages. self.get_pending_messages() # Send any friend statuses when the user logs in. # This will allow the user to see if their friends are hosting a game as soon as they log in. self.get_status_from_friends() self.send_status_to_friends()
def perform_login(self, data_parsed): authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db) #print authtoken_parsed # Track what console is connecting and save it in the database during user creation just in case we can use # the information in the future. console = 0 # 0 = NDS, 1 = Wii # get correct information userid = authtoken_parsed['userid'] # The Wii does not use passwd, so take another uniquely generated string as the password. if "passwd" in authtoken_parsed: password = authtoken_parsed['passwd'] else: password = authtoken_parsed['gsbrcd'] console = 1 gsbrcd = authtoken_parsed['gsbrcd'] gameid = gsbrcd[:4] uniquenick = utils.base32_encode(int(userid)) + gsbrcd email = uniquenick + "@nds" # The Wii also seems to use @nds. # Wii: Serial number if "csnum" in authtoken_parsed: csnum = authtoken_parsed['csnum'] console = 1 else: csnum = "" # Wii: Friend code if "cfc" in authtoken_parsed: cfc = authtoken_parsed['cfc'] console = 1 else: cfc = "" # NDS: Wifi network's BSSID if "bssid" in authtoken_parsed: bssid = authtoken_parsed['bssid'] else: bssid = "" # NDS: Device name if "devname" in authtoken_parsed: devname = authtoken_parsed['devname'] else: devname = "" # NDS: User's birthday if "birth" in authtoken_parsed: birth = authtoken_parsed['birth'] else: birth = "" # Verify the client's response valid_response = gs_utils.generate_response(self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken']) if data_parsed['response'] != valid_response: self.log(logging.ERROR, "ERROR: Got invalid response. Got %s, expected %s" % (data_parsed['response'], valid_response)) proof = gs_utils.generate_proof(self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken']) valid_user = self.db.check_user_exists(userid, gsbrcd) if valid_user == False: profileid = self.db.create_user(userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid) else: profileid = self.db.perform_login(userid, password, gsbrcd) if profileid == None: # Handle case where the user is invalid self.log(logging.ERROR, "Invalid password") if profileid != None: # Successfully logged in or created account, continue creating session. loginticket = gs_utils.base64_encode(utils.generate_random_str(16)) self.sesskey = self.db.create_session(profileid, loginticket) self.sessions[profileid] = self msg_d = [] msg_d.append(('__cmd__', "lc")) msg_d.append(('__cmd_val__', "2")) msg_d.append(('sesskey', self.sesskey)) msg_d.append(('proof', proof)) msg_d.append(('userid', userid)) msg_d.append(('profileid', profileid)) msg_d.append(('uniquenick', uniquenick)) msg_d.append(('lt', loginticket)) # Some kind of token... don't know it gets used or generated, but it doesn't seem to have any negative effects if it's not properly generated. msg_d.append(('id', data_parsed['id'])) msg = gs_query.create_gamespy_message(msg_d) # Take the first 4 letters of gsbrcd instead of gamecd because they should be consistent across game # regions. For example, the US version of Metroid Prime Hunters has the gamecd "AMHE" and the first 4 letters # of gsbrcd are "AMHE". However, the Japanese version of Metroid Prime Hunters has the gamecd "AMHJ" with # the first 4 letters of bsbrcd as "AMHE". Tetris DS is the other way, with the first 4 letters as the # Japanese version (ATRJ) while the gamecd is region specific (ATRE for US and ATRJ for JP). # gameid is used to send all people on the player's friends list a status updates, so don't make it region # specific. self.gameid = gsbrcd[0:4] self.profileid = int(profileid) self.log(logging.DEBUG, "SENDING: %s" % msg) self.transport.write(bytes(msg)) self.buddies = self.db.get_buddy_list(self.profileid) self.blocked = self.db.get_blocked_list(self.profileid) # Get pending messages. self.get_pending_messages() # Send any friend statuses when the user logs in. # This will allow the user to see if their friends are hosting a game as soon as they log in. self.get_status_from_friends() self.send_status_to_friends()
def perform_authp(self, data_parsed): authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db) #print authtoken_parsed if "lid" in data_parsed: self.lid = data_parsed['lid'] # Track what console is connecting and save it in the database during user creation just in case we can use # the information in the future. console = 0 # 0 = NDS, 1 = Wii # get correct information userid = authtoken_parsed['userid'] # The Wii does not use passwd, so take another uniquely generated string as the password. if "passwd" in authtoken_parsed: password = authtoken_parsed['passwd'] else: password = authtoken_parsed['gsbrcd'] console = 1 gsbrcd = authtoken_parsed['gsbrcd'] gameid = gsbrcd[:4] uniquenick = utils.base32_encode(int(userid)) + gsbrcd email = uniquenick + "@nds" # The Wii also seems to use @nds. # Wii: Serial number if "csnum" in authtoken_parsed: csnum = authtoken_parsed['csnum'] console = 1 else: csnum = "" # Wii: Friend code if "cfc" in authtoken_parsed: cfc = authtoken_parsed['cfc'] console = 1 else: cfc = "" # NDS: Wifi network's BSSID if "bssid" in authtoken_parsed: bssid = authtoken_parsed['bssid'] else: bssid = "" # NDS: Device name if "devname" in authtoken_parsed: devname = authtoken_parsed['devname'] else: devname = "" # NDS: User's birthday if "birth" in authtoken_parsed: birth = authtoken_parsed['birth'] else: birth = "" valid_user = self.db.check_user_exists(userid, gsbrcd) profileid = None if valid_user: profileid = self.db.perform_login(userid, password, gsbrcd) if profileid == None: # Handle case where the user is invalid self.log(logging.ERROR, "Invalid password") if profileid != None: # Successfully logged in or created account, continue creating session. sesskey = self.db.create_session(profileid) self.sessions[profileid] = self msg_d = [] msg_d.append(('__cmd__', "pauthr")) msg_d.append(('__cmd_val__', profileid)) msg_d.append(('lid', self.lid)) msg = gs_query.create_gamespy_message(msg_d) self.profileid = int(profileid) self.log(logging.DEBUG, "SENDING: '%s'..." % msg) msg = self.crypt(msg) self.transport.write(bytes(msg)) else: # Return error pass
def perform_login(self, data_parsed): authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db) if authtoken_parsed is None: self.log(logging.WARNING, "%s", "Invalid Authtoken.") msg = gs_query.create_gamespy_message([ ('__cmd__', "error"), ('__cmd_val__', ""), ('err', '266'), ('fatal', ''), ('errmsg', 'There was an error validating the' ' pre-authentication.'), ('id', data_parsed['id']), ]) self.transport.write(bytes(msg)) return if 'sdkrevision' in data_parsed: self.sdkrevision = data_parsed['sdkrevision'] # Verify the client's response valid_response = gs_utils.generate_response( self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken']) if data_parsed['response'] != valid_response: self.log(logging.ERROR, "ERROR: Got invalid response." " Got %s, expected %s", data_parsed['response'], valid_response) proof = gs_utils.generate_proof(self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken']) userid, profileid, gsbrcd, uniquenick = \ gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed, self.db) if profileid is not None: # Successfully logged in or created account, continue # creating session. loginticket = gs_utils.base64_encode(utils.generate_random_str(16)) self.sesskey = self.db.create_session(profileid, loginticket) self.sessions[profileid] = self self.buddies = self.db.get_buddy_list(self.profileid) self.blocked = self.db.get_blocked_list(self.profileid) if self.sdkrevision == "11": # Used in Tatsunoko vs Capcom def make_list(data): return [ str(d['buddyProfileId']) for d in data if d['status'] == 1 ] block_list = make_list(self.blocked) msg = gs_query.create_gamespy_message([ ('__cmd__', "blk"), ('__cmd_val__', str(len(block_list))), ('list', ','.join(block_list)), ]) self.log(logging.DEBUG, "SENDING: %s", msg) self.transport.write(bytes(msg)) buddy_list = make_list(self.buddies) msg = gs_query.create_gamespy_message([ ('__cmd__', "bdy"), ('__cmd_val__', str(len(buddy_list))), ('list', ','.join(buddy_list)), ]) self.log(logging.DEBUG, "SENDING: %s", msg) self.transport.write(bytes(msg)) msg = gs_query.create_gamespy_message([ ('__cmd__', "lc"), ('__cmd_val__', "2"), ('sesskey', self.sesskey), ('proof', proof), ('userid', userid), ('profileid', profileid), ('uniquenick', uniquenick), # Some kind of token... don't know it gets used or generated, # but it doesn't seem to have any negative effects if it's # not properly generated. ('lt', loginticket), ('id', data_parsed['id']), ]) # Take the first 4 letters of gsbrcd instead of gamecd because # they should be consistent across game regions. For example, the # US version of Metroid Prime Hunters has the gamecd "AMHE" and # the first 4 letters of gsbrcd are "AMHE". However, the Japanese # version of Metroid Prime Hunters has the gamecd "AMHJ" with the # first 4 letters of bsbrcd as "AMHE". Tetris DS is the other way, # with the first 4 letters as the Japanese version (ATRJ) while # the gamecd is region specific (ATRE for US and ATRJ for JP). # gameid is used to send all people on the player's friends list a # status updates, so don't make it region specific. self.gameid = gsbrcd[:4] self.profileid = int(profileid) self.log(logging.DEBUG, "SENDING: %s", msg) self.transport.write(bytes(msg)) # Get pending messages. self.get_pending_messages() # Send any friend statuses when the user logs in. # This will allow the user to see if their friends are hosting a # game as soon as they log in. self.get_status_from_friends() self.send_status_to_friends() # profile = self.db.get_profile_from_profileid(profileid) # if profile is not None: # self.statstring = profile['stat'] # self.locstring = profile['loc'] else: self.log(logging.INFO, "%s", "Invalid password or banned user") msg = gs_query.create_gamespy_message([ ('__cmd__', "error"), ('__cmd_val__', ""), ('err', '256'), ('fatal', ''), ('errmsg', 'Login failed.'), ('id', data_parsed['id']), ]) self.log(logging.DEBUG, "SENDING: %s", msg) self.transport.write(bytes(msg))
def perform_login(self, data_parsed): authtoken_parsed = gs_utils.parse_authtoken(data_parsed["authtoken"], self.db) if authtoken_parsed is None: self.log(logging.WARNING, "%s", "Invalid Authtoken.") msg = gs_query.create_gamespy_message( [ ("__cmd__", "error"), ("__cmd_val__", ""), ("err", "266"), ("fatal", ""), ("errmsg", "There was an error validating the" " pre-authentication."), ("id", data_parsed["id"]), ] ) self.transport.write(bytes(msg)) return if "sdkrevision" in data_parsed: self.sdkrevision = data_parsed["sdkrevision"] # Verify the client's response valid_response = gs_utils.generate_response( self.challenge, authtoken_parsed["challenge"], data_parsed["challenge"], data_parsed["authtoken"] ) if data_parsed["response"] != valid_response: self.log( logging.ERROR, "ERROR: Got invalid response." " Got %s, expected %s", data_parsed["response"], valid_response, ) proof = gs_utils.generate_proof( self.challenge, authtoken_parsed["challenge"], data_parsed["challenge"], data_parsed["authtoken"] ) userid, profileid, gsbrcd, uniquenick = gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed, self.db) if profileid is not None: # Successfully logged in or created account, continue # creating session. loginticket = gs_utils.base64_encode(utils.generate_random_str(16)) self.sesskey = self.db.create_session(profileid, loginticket) self.sessions[profileid] = self self.buddies = self.db.get_buddy_list(self.profileid) self.blocked = self.db.get_blocked_list(self.profileid) if self.sdkrevision == "11": # Used in Tatsunoko vs Capcom def make_list(data): return [str(d["buddyProfileId"]) for d in data if d["status"] == 1] block_list = make_list(self.blocked) msg = gs_query.create_gamespy_message( [("__cmd__", "blk"), ("__cmd_val__", str(len(block_list))), ("list", ",".join(block_list))] ) self.log(logging.DEBUG, "SENDING: %s", msg) self.transport.write(bytes(msg)) buddy_list = make_list(self.buddies) msg = gs_query.create_gamespy_message( [("__cmd__", "bdy"), ("__cmd_val__", str(len(buddy_list))), ("list", ",".join(buddy_list))] ) self.log(logging.DEBUG, "SENDING: %s", msg) self.transport.write(bytes(msg)) msg = gs_query.create_gamespy_message( [ ("__cmd__", "lc"), ("__cmd_val__", "2"), ("sesskey", self.sesskey), ("proof", proof), ("userid", userid), ("profileid", profileid), ("uniquenick", uniquenick), # Some kind of token... don't know it gets used or generated, # but it doesn't seem to have any negative effects if it's # not properly generated. ("lt", loginticket), ("id", data_parsed["id"]), ] ) # Take the first 4 letters of gsbrcd instead of gamecd because # they should be consistent across game regions. For example, the # US version of Metroid Prime Hunters has the gamecd "AMHE" and # the first 4 letters of gsbrcd are "AMHE". However, the Japanese # version of Metroid Prime Hunters has the gamecd "AMHJ" with the # first 4 letters of bsbrcd as "AMHE". Tetris DS is the other way, # with the first 4 letters as the Japanese version (ATRJ) while # the gamecd is region specific (ATRE for US and ATRJ for JP). # gameid is used to send all people on the player's friends list a # status updates, so don't make it region specific. self.gameid = gsbrcd[:4] self.profileid = int(profileid) self.log(logging.DEBUG, "SENDING: %s", msg) self.transport.write(bytes(msg)) # Get pending messages. self.get_pending_messages() # Send any friend statuses when the user logs in. # This will allow the user to see if their friends are hosting a # game as soon as they log in. self.get_status_from_friends() self.send_status_to_friends() # profile = self.db.get_profile_from_profileid(profileid) # if profile is not None: # self.statstring = profile['stat'] # self.locstring = profile['loc'] else: self.log(logging.INFO, "%s", "Invalid password or banned user") msg = gs_query.create_gamespy_message( [ ("__cmd__", "error"), ("__cmd_val__", ""), ("err", "256"), ("fatal", ""), ("errmsg", "Login failed."), ("id", data_parsed["id"]), ] ) self.log(logging.DEBUG, "SENDING: %s", msg) self.transport.write(bytes(msg))