def perform_getprofile(self, data_parsed):
        #profile = self.db.get_profile_from_session_key(data_parsed['sesskey'])
        profile = self.db.get_profile_from_profileid(data_parsed['profileid'])

        # Wii example: \pi\\profileid\474888031\nick\5pde5vhn1WR9E2g1t533\userid\442778352\email\5pde5vhn1WR9E2g1t533@nds\sig\b126556e5ee62d4da9629dfad0f6b2a8\uniquenick\5pde5vhn1WR9E2g1t533\pid\11\lon\0.000000\lat\0.000000\loc\\id\2\final\
        sig = utils.generate_random_hex_str(32)

        msg_d = []
        msg_d.append(('__cmd__', "pi"))
        msg_d.append(('__cmd_val__', ""))
        msg_d.append(('profileid', profile['profileid']))
        msg_d.append(('nick', profile['uniquenick']))
        msg_d.append(('userid', profile['userid']))
        msg_d.append(('email', profile['email']))
        msg_d.append(('sig', sig))
        msg_d.append(('uniquenick', profile['uniquenick']))
        msg_d.append(('pid', profile['pid']))

        if profile['firstname'] != "":
            msg_d.append(
                ('firstname', profile['firstname']))  # Wii gets a firstname

        if profile['lastname'] != "":
            msg_d.append(('lastname', profile['lastname']))

        msg_d.append(('lon', profile['lon']))
        msg_d.append(('lat', profile['lat']))
        msg_d.append(('loc', profile['loc']))
        msg_d.append(('id', data_parsed['id']))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: %s" % msg)
        self.transport.write(bytes(msg))
    def perform_getprofile(self, data_parsed):
        #profile = self.db.get_profile_from_session_key(data_parsed['sesskey'])
        profile = self.db.get_profile_from_profileid(data_parsed['profileid'])

        # Wii example: \pi\\profileid\474888031\nick\5pde5vhn1WR9E2g1t533\userid\442778352\email\5pde5vhn1WR9E2g1t533@nds\sig\b126556e5ee62d4da9629dfad0f6b2a8\uniquenick\5pde5vhn1WR9E2g1t533\pid\11\lon\0.000000\lat\0.000000\loc\\id\2\final\
        sig = utils.generate_random_hex_str(32)

        msg_d = [
            ('__cmd__', "pi"),
            ('__cmd_val__', ""),
            ('profileid', profile['profileid']),
            ('nick', profile['uniquenick']),
            ('userid', profile['userid']),
            ('email', profile['email']),
            ('sig', sig),
            ('uniquenick', profile['uniquenick']),
            ('pid', profile['pid']),
        ]

        if profile['firstname'] != "":
            msg_d.append(('firstname', profile['firstname'])) # Wii gets a firstname

        if profile['lastname'] != "":
            msg_d.append(('lastname', profile['lastname']))

        msg_d.extend([
            ('lon', profile['lon']),
            ('lat', profile['lat']),
            ('loc', profile['loc']),
            ('id', data_parsed['id']),
        ])
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: %s" % msg)
        self.transport.write(bytes(msg))
Esempio n. 3
0
    def forward_data_to_client(self, data, forward_client):
        # Find session id of server
        # Iterate through the list of servers sent to the client and match by IP and port.
        # Is there a better way to determine this information?
        if self.forward_client == None or len(self.forward_client) != 2:
            return

        server, ip = self.find_server_in_cache(self.forward_client[0],
                                               self.forward_client[1],
                                               self.console)

        if server == None:
            if self.console == 0:
                server, ip = self.find_server_in_cache(self.forward_client[0],
                                                       self.forward_client[1],
                                                       1)  # Try Wii
            elif self.console == 1:
                server, ip = self.find_server_in_cache(self.forward_client[0],
                                                       self.forward_client[1],
                                                       0)  # Try DS

        self.log(logging.DEBUG, "find_server_in_cache returned: %s" % server)
        self.log(
            logging.DEBUG, "Trying to send message to %s:%d..." %
            (self.forward_client[0], self.forward_client[1]))
        self.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))

        if server == None:
            return

        self.log(logging.DEBUG, "%s %s" % (ip, server['publicip']))
        if server['publicip'] == ip and server['publicport'] == str(
                self.forward_client[1]):
            # Send command to server to get it to connect to natneg
            natneg_session = int(
                utils.generate_random_hex_str(8), 16
            )  # Quick and lazy way to get a random 32bit integer. Replace with something else later

            output = bytearray([0xfe, 0xfd, 0x06])
            output += utils.get_bytes_from_int(server['__session__'])
            output += bytearray(utils.get_bytes_from_int(natneg_session))
            output += bytearray(data)

            if self.qr != None:
                self.qr.socket.sendto(output, forward_client)
                self.log(
                    logging.DEBUG,
                    "Forwarded data to %s:%s through QR server..." %
                    (forward_client[0], 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, forward_client)
                self.log(
                    logging.DEBUG,
                    "Forwarded data to %s:%s directly (potential error occurred)..."
                    % (forward_client[0], forward_client[1]))
    def forward_data_to_client(self, data, forward_client):
        # Find session id of server
        # Iterate through the list of servers sent to the client and match by IP and port.
        # Is there a better way to determine this information?
        if self.forward_client == None or len(self.forward_client) != 2:
            return

        server, ip = self.find_server_in_cache(self.forward_client[0], self.forward_client[1], self.console)

        if server == None:
            if self.console == 0:
                server, ip = self.find_server_in_cache(self.forward_client[0], self.forward_client[1], 1) # Try Wii
            elif self.console == 1:
                server, ip = self.find_server_in_cache(self.forward_client[0], self.forward_client[1], 0) # Try DS

        self.log(logging.DEBUG, "find_server_in_cache returned: %s" % server)
        self.log(logging.DEBUG, "Trying to send message to %s:%d..." % (self.forward_client[0], self.forward_client[1]))
        self.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))

        if server == None:
            return

        self.log(logging.DEBUG, "%s %s" % (ip, server['publicip']))
        if server['publicip'] == ip and server['publicport'] == str(self.forward_client[1]):
            if self.forward_client[1] == 0 and 'localport' in server:
                # No public port returned from client, try contacting on the local port.
                self.forward_client = (self.forward_client[0], int(server['localport']))

            # Send command to server to get it to connect to natneg
            cookie = int(utils.generate_random_hex_str(8), 16) # Quick and lazy way to get a random 32bit integer. Replace with something else later

            if len(data) == 10 and bytearray(data)[0:6] == bytearray([0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2]):
                natneg_session = utils.get_int(data,6)
                self.log(logging.DEBUG, "Adding %d to natneg server list: %s" % (natneg_session, server))
                self.server_manager.add_natneg_server(natneg_session, server) # Store info in backend so we can get it later in natneg

                # if self.qr != None:
                #     own_server = self.qr.get_own_server()
                #
                #     self.log(logging.DEBUG, "Adding %d to natneg server list: %s" % (natneg_session, own_server))
                #     self.server_manager.add_natneg_server(natneg_session, own_server) # Store info in backend so we can get it later in natneg

            output = bytearray([0xfe, 0xfd, 0x06])
            output += utils.get_bytes_from_int(server['__session__'])
            output += bytearray(utils.get_bytes_from_int(cookie))
            output += bytearray(data)

            if self.qr != None:
                self.log(logging.DEBUG, "Forwarded data to %s:%s through QR server..." % (forward_client[0], forward_client[1]))
                self.qr.socket.sendto(output, forward_client)
            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.
                self.log(logging.DEBUG, "Forwarded data to %s:%s directly (potential error occurred)..." % (forward_client[0], forward_client[1]))
                client_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                client_s.sendto(output, forward_client)
    def send_buddy_request(self, session, profileid, senttime=None):
        sig = utils.generate_random_hex_str(32)
        msg = "\r\n\r\n"
        msg += "|signed|" + sig

        if senttime is None:
            senttime = int(time.time())

        msg = gs_query.create_gamespy_message(
            [("__cmd__", "bm"), ("__cmd_val__", "2"), ("f", profileid), ("date", senttime), ("msg", msg)]
        )

        session.transport.write(bytes(msg))
    def send_buddy_request(self, session, profileid, senttime=None):
        sig = utils.generate_random_hex_str(32)
        msg = "\r\n\r\n"
        msg += "|signed|" + sig

        if senttime == None:
            senttime = int(time.time())

        msg_d = []
        msg_d.append(('__cmd__', "bm"))
        msg_d.append(('__cmd_val__', "2"))
        msg_d.append(('f', profileid))
        msg_d.append(('date', senttime))
        msg_d.append(('msg', msg))
        msg = gs_query.create_gamespy_message(msg_d)

        session.transport.write(bytes(msg))
    def send_buddy_request(self, session, profileid, senttime = None):
        sig = utils.generate_random_hex_str(32)
        msg = "\r\n\r\n"
        msg += "|signed|" + sig

        if senttime == None:
            senttime = int(time.time())

        msg_d = []
        msg_d.append(('__cmd__', "bm"))
        msg_d.append(('__cmd_val__', "2"))
        msg_d.append(('f', profileid))
        msg_d.append(('date', senttime))
        msg_d.append(('msg', msg))
        msg = gs_query.create_gamespy_message(msg_d)

        session.transport.write(bytes(msg))
    def get_buddy_requests(self):
        # Get list people who have added the user but haven't been accepted yet.
        buddies = self.db.get_pending_buddy_requests(self.profileid)

        profile = self.db.get_profile_from_profileid(self.profileid)
        sig = utils.generate_random_hex_str(32)
        msg = "\r\n\r\n"
        msg += "|signed|" + sig

        for buddy in buddies:
            msg_d = []
            msg_d.append(('__cmd__', "bm"))
            msg_d.append(('__cmd_val__', "2"))
            msg_d.append(('f', buddy['userProfileId']))
            msg_d.append(('date', buddy['time']))
            msg_d.append(('msg', msg))
            msg = gs_query.create_gamespy_message(msg_d)

            self.transport.write(bytes(msg))
    def forward_data_to_client(self, data, forward_client):
        # Find session id of server
        # Iterate through the list of servers sent to the client and match by IP and port.
        # Is there a better way to determine this information?
        if self.forward_client == None or len(self.forward_client) != 2:
            return

        server, ip = self.find_server_in_cache(self.forward_client[0], self.forward_client[1], self.console)

        if server == None:
            if self.console == 0:
                server, ip = self.find_server_in_cache(self.forward_client[0], self.forward_client[1], 1) # Try Wii
            elif self.console == 1:
                server, ip = self.find_server_in_cache(self.forward_client[0], self.forward_client[1], 0) # Try DS

        self.log(logging.DEBUG, "find_server_in_cache returned: %s" % server)
        self.log(logging.DEBUG, "Trying to send message to %s:%d..." % (self.forward_client[0], self.forward_client[1]))
        self.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))

        if server == None:
            return

        self.log(logging.DEBUG, "%s %s" % (ip, server['publicip']))
        if server['publicip'] == ip and server['publicport'] == str(self.forward_client[1]):
            # Send command to server to get it to connect to natneg
            natneg_session = int(utils.generate_random_hex_str(8), 16) # Quick and lazy way to get a random 32bit integer. Replace with something else later

            output = bytearray([0xfe, 0xfd, 0x06])
            output += utils.get_bytes_from_int(server['__session__'])
            output += bytearray(utils.get_bytes_from_int(natneg_session))
            output += bytearray(data)

            if self.qr != None:
                self.qr.socket.sendto(output, forward_client)
                self.log(logging.DEBUG, "Forwarded data to %s:%s through QR server..." % (forward_client[0], 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, forward_client)
                self.log(logging.DEBUG, "Forwarded data to %s:%s directly (potential error occurred)..." % (forward_client[0], forward_client[1]))
    def perform_getprofile(self, data_parsed):
        # profile = self.db.get_profile_from_session_key(
        #     data_parsed['sesskey']
        # )
        profile = self.db.get_profile_from_profileid(data_parsed["profileid"])

        # Wii example:
        # \pi\\profileid\474888031\nick\5pde5vhn1WR9E2g1t533\userid\442778352
        # \email\5pde5vhn1WR9E2g1t533@nds\sig\b126556e5ee62d4da9629dfad0f6b2a8
        # \uniquenick\5pde5vhn1WR9E2g1t533\pid\11\lon\0.000000\lat\0.000000
        # \loc\\id\2\final\
        sig = utils.generate_random_hex_str(32)

        msg_d = [
            ("__cmd__", "pi"),
            ("__cmd_val__", ""),
            ("profileid", profile["profileid"]),
            ("nick", profile["uniquenick"]),
            ("userid", profile["userid"]),
            ("email", profile["email"]),
            ("sig", sig),
            ("uniquenick", profile["uniquenick"]),
            ("pid", profile["pid"]),
        ]

        if profile["firstname"]:
            # Wii gets a firstname
            msg_d.append(("firstname", profile["firstname"]))

        if profile["lastname"]:
            msg_d.append(("lastname", profile["lastname"]))

        msg_d.extend(
            [("lon", profile["lon"]), ("lat", profile["lat"]), ("loc", profile["loc"]), ("id", data_parsed["id"])]
        )
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: %s", msg)
        self.transport.write(bytes(msg))
Esempio n. 11
0
    def forward_data_to_client(self, data, forward_client):
        # Find session id of server
        # Iterate through the list of servers sent to the client and match by
        # IP and port. Is there a better way to determine this information?
        if forward_client is None or len(forward_client) != 2:
            return

        server, ip = self.find_server_in_cache(forward_client[0],
                                               forward_client[1], self.console)

        if server is None:
            if self.console == 0:
                server, ip = self.find_server_in_cache(forward_client[0],
                                                       forward_client[1],
                                                       1)  # Try Wii
            elif self.console == 1:
                server, ip = self.find_server_in_cache(forward_client[0],
                                                       forward_client[1],
                                                       0)  # Try DS

        self.log(logging.DEBUG, "find_server_in_cache returned: %s", server)
        self.log(logging.DEBUG, "Trying to send message to %s:%d...",
                 forward_client[0], forward_client[1])
        self.log(logging.DEBUG, "%s", utils.pretty_print_hex(bytearray(data)))

        if server is None:
            return

        self.log(logging.DEBUG, "%s %s", ip, server['publicip'])
        if server['publicip'] == ip and \
           server['publicport'] == str(forward_client[1]):
            if forward_client[1] == 0 and 'localport' in server:
                # No public port returned from client, try contacting on
                # the local port.
                forward_client = (forward_client[0], int(server['localport']))

            # Send command to server to get it to connect to natneg
            # Quick and lazy way to get a random 32bit integer. Replace with
            # something else later
            cookie = int(utils.generate_random_hex_str(8), 16)

            # if (len(data) == 24 and bytearray(data)[0:10] == \
            #     bytearray([0x53, 0x42, 0x43, 0x4d, 0x03,
            #                0x00, 0x00, 0x00, 0x01, 0x04])) or \
            #     (len(data) == 40 and bytearray(data)[0:10] == \
            #                          bytearray([0x53, 0x42, 0x43, 0x4d,
            #                                     0x0b, 0x00, 0x00, 0x00,
            #                                     0x01, 0x04])):
            if self.own_server is None and len(data) >= 16 and \
               bytearray(data)[0:4] in (bytearray([0xbb, 0x49, 0xcc, 0x4d]),
                                        bytearray([0x53, 0x42, 0x43, 0x4d])):
                # Is the endianness the same between the DS and Wii here?
                # It seems so but I'm not positive.
                # Note to self: Port is little endian here.
                self_port = utils.get_short(bytearray(data[10:12]), 0, False)
                self_ip = '.'.join(["%d" % x for x in bytearray(data[12:16])])

                self.own_server, _ = self.find_server_in_cache(
                    self_ip, self_port, self.console)

                if self.own_server is None:
                    if self.console == 0:
                        # Try Wii
                        self.own_server, _ = self.find_server_in_cache(
                            self_ip, self_port, 1)
                    elif self.console == 1:
                        # Try DS
                        self.own_server, _ = self.find_server_in_cache(
                            self_ip, self_port, 0)

                if self.own_server is None:
                    self.log(logging.DEBUG, "Could not find own server: %s:%d",
                             self_ip, self_port)
                else:
                    self.log(logging.DEBUG, "Found own server: %s",
                             self.own_server)

            elif len(data) == 10 and \
                    bytearray(data)[0:6] == \
                    bytearray([0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2]):
                natneg_session = utils.get_int_signed(data, 6)
                self.log(logging.DEBUG, "Adding %d to natneg server list: %s",
                         natneg_session, server)
                # Store info in backend so we can get it later in natneg
                self.server_manager.add_natneg_server(natneg_session, server)

                if self.own_server is not None:
                    self.log(logging.DEBUG,
                             "Adding %d to natneg server list: %s (self)",
                             natneg_session, self.own_server)
                    # Store info in backend so we can get it later in natneg
                    self.server_manager.add_natneg_server(
                        natneg_session, self.own_server)

                # if self.qr is not None:
                #     own_server = self.qr.get_own_server()
                #
                #     self.log(logging.DEBUG,
                #              "Adding %d to natneg server list: %s",
                #              natneg_session, own_server)
                #     self.server_manager.add_natneg_server(natneg_session,
                #                                           own_server)

            output = bytearray([0xfe, 0xfd, 0x06])
            output += utils.get_bytes_from_int(server['__session__'])
            output += bytearray(utils.get_bytes_from_int(cookie))
            output += bytearray(data)

            if self.qr is not None:
                self.log(logging.DEBUG,
                         "Forwarded data to %s:%s through QR server...",
                         forward_client[0], forward_client[1])
                self.qr.socket.sendto(output, forward_client)
            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.
                self.log(
                    logging.DEBUG, "Forwarded data to %s:%s directly"
                    " (potential error occurred)...", forward_client[0],
                    forward_client[1])
                client_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                client_s.sendto(output, forward_client)
    def rawDataReceived(self, data):
        # First 2 bytes are the packet size.
        #
        # Third byte is the command byte.
        # According to Openspy-Core:
        #   0x00 - Server list request
        #   0x01 - Server info request
        #   0x02 - Send message request
        #   0x03 - Keep alive reply
        #   0x04 - Map loop request (?)
        #   0x05 - Player search request
        #
        # For Tetris DS, at the very least 0x00 and 0x02 need to be implemented.

        if self.forward_to_client:
            self.forward_to_client = False

            # Find session id of server
            # Iterate through the list of servers sent to the client and match by IP and port.
            # Is there a better way to determine this information?
            if self.console != 0:
                ip = str(ctypes.c_int32(utils.get_int_be(bytearray([int(x) for x in self.forward_client[0].split('.')]), 0)).value) # Wii
            else:
                ip = str(ctypes.c_int32(utils.get_int(bytearray([int(x) for x in self.forward_client[0].split('.')]), 0)).value) # DS

            logger.log(logging.DEBUG, "Trying to send message to %s:%d..." % (self.forward_client[0], self.forward_client[1]))
            logger.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))

            # Get server based on ip/port
            server = self.server_manager.find_server_by_address(ip, self.forward_client[1])._getvalue()
            logger.log(logging.DEBUG, "find_server_by_address returned: %s" % server)

            if server == None:
                pass

            logger.log(logging.DEBUG, "%s %s" % (ip, server['publicip']))
            if server['publicip'] == ip and server['publicport'] == str(self.forward_client[1]):
                # Send command to server to get it to connect to natneg
                natneg_session = int(utils.generate_random_hex_str(8), 16) # Quick and lazy way to get a random 32bit integer. Replace with something else late.r

                output = bytearray([0xfe, 0xfd, 0x06])
                output += utils.get_bytes_from_int(server['__session__'])
                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]))
            return

        if data[2] == '\x00': # Server list request
            logger.log(logging.DEBUG, "Received server list request from %s:%s..." % (self.address.host, self.address.port))

            # This code is so... not python. The C programmer in me is coming out strong.
            # TODO: Rewrite this section later?
            idx = 3
            list_version = ord(data[idx])
            idx += 1
            encoding_version = ord(data[idx])
            idx += 1
            game_version = utils.get_int(data, idx)
            idx += 4

            query_game = utils.get_string(data, idx)
            idx += len(query_game) + 1
            game_name = utils.get_string(data, idx)
            idx += len(game_name) + 1

            challenge = data[idx:idx+8]
            idx += 8

            filter = utils.get_string(data, idx)
            idx += len(filter) + 1
            fields = utils.get_string(data, idx)
            idx += len(fields) + 1

            options = utils.get_int_be(data, idx)
            idx += 4

            source_ip = 0
            max_servers = 0

            ALTERNATE_SOURCE_IP = 0x08
            LIMIT_RESULT_COUNT = 0x80
            if (options & LIMIT_RESULT_COUNT):
                max_servers = utils.get_int(data, idx)
            elif (options & ALTERNATE_SOURCE_IP):
                source_ip = utils.get_int(data, idx)

            if '\\' in fields:
                fields = [x for x in fields.split('\\') if x and not x.isspace()]

            #print "%02x %02x %08x" % (list_version, encoding_version, game_version)
            #print "%s" % query_game
            #print "%s" % game_name
            #print "%s" % challenge
            #print "%s" % filter
            #print "%s" % fields

            #print "%08x" % options
            #print "%d %08x" % (max_servers, source_ip)

            logger.log(logging.DEBUG, "list version: %02x / encoding version: %02x / game version: %08x / query game: %s / game name: %s / challenge: %s / filter: %s / fields: %s / options: %08x / max servers: %d / source ip: %08x" % (list_version, encoding_version, game_version, query_game, game_name, challenge, filter, fields, options, max_servers, source_ip))

            # Requesting ip and port of client, not server
            if filter == "" or fields == "":
                output = bytearray([int(x) for x in self.address.host.split('.')])
                output += utils.get_bytes_from_short_be(self.address.port)
                self.transport.write(bytes(output))
                logger.log(logging.DEBUG, "Responding with own IP and port...")
                logger.log(logging.DEBUG, utils.pretty_print_hex(output))
            else:
                self.find_server(query_game, filter, fields, max_servers, game_name, challenge)



        elif data[2] == '\x02': # Send message request
            dest_addr = '.'.join(["%d" % ord(x) for x in data[3:7]])
            dest_port = utils.get_short_be(data, 7) # What's the pythonic way to do this? unpack?
            dest = (dest_addr, dest_port)

            logger.log(logging.DEBUG, "Received send message request from %s:%s to %s:%d..." % (self.address.host, self.address.port, dest_addr, dest_port))
            logger.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))

            self.forward_to_client = True
            self.forward_client = dest

        elif data[2] == '\x03': # Keep alive reply
            logger.log(logging.DEBUG, "Received keep alive from %s:%s..." % (self.address.host, self.address.port))

        else:
            logger.log(logging.DEBUG, "Received unknown command (%02x) from %s:%s..." % (ord(data[2]), self.address.host, self.address.port))
            logger.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))
            logger.log(logging.DEBUG, utils.pretty_print_hex(data))
    def forward_data_to_client(self, data, forward_client):
        # Find session id of server
        # Iterate through the list of servers sent to the client and match by
        # IP and port. Is there a better way to determine this information?
        if forward_client is None or len(forward_client) != 2:
            return

        server, ip = self.find_server_in_cache(forward_client[0],
                                               forward_client[1], self.console)

        if server is None:
            if self.console == 0:
                server, ip = self.find_server_in_cache(forward_client[0],
                                                       forward_client[1],
                                                       1)  # Try Wii
            elif self.console == 1:
                server, ip = self.find_server_in_cache(forward_client[0],
                                                       forward_client[1],
                                                       0)  # Try DS

        self.log(logging.DEBUG,
                 "find_server_in_cache returned: %s",
                 server)
        self.log(logging.DEBUG,
                 "Trying to send message to %s:%d...",
                 forward_client[0], forward_client[1])
        self.log(logging.DEBUG, "%s", utils.pretty_print_hex(bytearray(data)))

        if server is None:
            return

        self.log(logging.DEBUG, "%s %s", ip, server['publicip'])
        if server['publicip'] == ip and \
           server['publicport'] == str(forward_client[1]):
            if forward_client[1] == 0 and 'localport' in server:
                # No public port returned from client, try contacting on
                # the local port.
                forward_client = (forward_client[0], int(server['localport']))

            # Send command to server to get it to connect to natneg
            # Quick and lazy way to get a random 32bit integer. Replace with
            # something else later
            cookie = int(utils.generate_random_hex_str(8), 16)

            # if (len(data) == 24 and bytearray(data)[0:10] == \
            #     bytearray([0x53, 0x42, 0x43, 0x4d, 0x03,
            #                0x00, 0x00, 0x00, 0x01, 0x04])) or \
            #     (len(data) == 40 and bytearray(data)[0:10] == \
            #                          bytearray([0x53, 0x42, 0x43, 0x4d,
            #                                     0x0b, 0x00, 0x00, 0x00,
            #                                     0x01, 0x04])):
            if self.own_server is None and len(data) >= 16 and \
               bytearray(data)[0:4] in (bytearray([0xbb, 0x49, 0xcc, 0x4d]),
                                        bytearray([0x53, 0x42, 0x43, 0x4d])):
                # Is the endianness the same between the DS and Wii here?
                # It seems so but I'm not positive.
                # Note to self: Port is little endian here.
                self_port = utils.get_short(bytearray(data[10:12]), 0, False)
                self_ip = '.'.join(["%d" % x for x in bytearray(data[12:16])])

                self.own_server, _ = self.find_server_in_cache(self_ip,
                                                               self_port,
                                                               self.console)

                if self.own_server is None:
                    if self.console == 0:
                        # Try Wii
                        self.own_server, _ = self.find_server_in_cache(
                            self_ip, self_port, 1
                        )
                    elif self.console == 1:
                        # Try DS
                        self.own_server, _ = self.find_server_in_cache(
                            self_ip, self_port, 0
                        )

                if self.own_server is None:
                    self.log(logging.DEBUG,
                             "Could not find own server: %s:%d",
                             self_ip, self_port)
                else:
                    self.log(logging.DEBUG,
                             "Found own server: %s",
                             self.own_server)

            elif len(data) == 10 and \
                    bytearray(data)[0:6] == \
                    bytearray([0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2]):
                natneg_session = utils.get_int_signed(data, 6)
                self.log(logging.DEBUG,
                         "Adding %d to natneg server list: %s",
                         natneg_session, server)
                # Store info in backend so we can get it later in natneg
                self.server_manager.add_natneg_server(natneg_session, server)

                if self.own_server is not None:
                    self.log(logging.DEBUG,
                             "Adding %d to natneg server list: %s (self)",
                             natneg_session, self.own_server)
                    # Store info in backend so we can get it later in natneg
                    self.server_manager.add_natneg_server(natneg_session,
                                                          self.own_server)

                # if self.qr is not None:
                #     own_server = self.qr.get_own_server()
                #
                #     self.log(logging.DEBUG,
                #              "Adding %d to natneg server list: %s",
                #              natneg_session, own_server)
                #     self.server_manager.add_natneg_server(natneg_session,
                #                                           own_server)

            output = bytearray([0xfe, 0xfd, 0x06])
            output += utils.get_bytes_from_int(server['__session__'])
            output += bytearray(utils.get_bytes_from_int(cookie))
            output += bytearray(data)

            if self.qr is not None:
                self.log(logging.DEBUG,
                         "Forwarded data to %s:%s through QR server...",
                         forward_client[0], forward_client[1])
                self.qr.socket.sendto(output, forward_client)
            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.
                self.log(logging.DEBUG,
                         "Forwarded data to %s:%s directly"
                         " (potential error occurred)...",
                         forward_client[0], forward_client[1])
                client_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                client_s.sendto(output, forward_client)