Ejemplo n.º 1
0
	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()
Ejemplo n.º 6
0
    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_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
Ejemplo n.º 8
0
    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))