def work(pubsub, channel):
    pubsub.subscribe('queue:' + channel)
    while True:
        message = pubsub.get_message()
        if message is not None:
            data = redisConnection.rpop('queue:' + channel + ":list")
            if data is not None:
                packet = packet_pb2.Packet()
                packet.ParseFromString(data)
                aes_key = redisConnection.get(packet.playerID)
                if aes_key is not None:
                    reply = None
                    if channel is "gamemessages":
                        game_packet = client_pb2.ClientGameMessage()
                        game_packet.ParseFromString(
                            AESTool.decrypt(aes_key, packet.message))
                        print("Worker got GAME: ", game_packet)
                        reply_packet = server_pb2.ServerGameMessage()
                        # Here's where you would do the heavy tasks to calculate that data
                        reply_packet.xPos = 12
                        reply_packet.yPos = 1032
                        reply_packet.zPos = 1

                        message = AESTool.encrypt(
                            aes_key, reply_packet.SerializeToString())
                        reply = create_packet(packet_pb2.Packet.GAME, message,
                                              packet.playerID)

                    elif channel is "datamessages":
                        data_packet = client_pb2.ClientDataMessage()
                        data_packet.ParseFromString(
                            AESTool.decrypt(aes_key, packet.message))
                        print("Worker got DATA: ", data_packet)
                        # Here's where you would do the heavy tasks to calculate that data
                        reply_packet = server_pb2.ServerDataMessage()
                        reply_packet.health = 12
                        reply_packet.coins = 1032
                        reply_packet.mana = 1

                        message = AESTool.encrypt(
                            aes_key, reply_packet.SerializeToString())
                        reply = create_packet(packet_pb2.Packet.DATA, message,
                                              packet.playerID)
                    reply.address = packet.address
                    reply.port = packet.port
                    redisConnection.publish('queue:packetreplies',
                                            reply.SerializeToString())
 def start_heartbeat(self):
     """Starts the heartbeat"""
     player_id = "1111"
     while True:
         packet = create_packet(packet_pb2.Packet.HEARTBEAT, b"Ping",
                                player_id)
         self.sock.sendto(packet.SerializeToString(),
                          (self.server_host, self.server_port))
         time.sleep(1)
    def handle_packet(self, data, address):
        """Packer handler thread

        This is where the packet is checked for validity and
        put into the appropriate redis queue

        :param data: the data from the packet
        :address: a tuple with the (ip_address, port_number)
        """
        packet = packet_pb2.Packet()
        packet.ParseFromString(data)

        if packet.type != packet_pb2.Packet.HEARTBEAT:
            print(packet)

        packet_crc = packet.crc
        packet.ClearField('crc')
        crc_data = packet.SerializePartialToString()
        crc = binascii.crc32(crc_data) & 0xFFFFFFFF
        if packet_crc != crc:
            print('Given CRC: {}'.format(packet.crc))
            print('Calculated CRC: {}'.format(
                (binascii.crc32(crc_data) & 0xFFFFFFFF)))
            print("Dropped packet for bad checksum")
            return
        # put the crc back in there!
        packet.crc = packet_crc
        if packet.type == packet_pb2.Packet.HEARTBEAT:
            packet = create_packet(packet_pb2.Packet.HEARTBEAT, b"Pong")
            self.sock.sendto(packet.SerializeToString(), address)
        elif packet.type == packet_pb2.Packet.AUTH:
            decrypted_aes_key = self.rsa_key.decrypt(packet.message)
            print('DECRYPTED AES KEY:', [x for x in decrypted_aes_key])
            print('PLAYER ID AUTH: ', packet.playerID)
            self.redis.set(packet.playerID, decrypted_aes_key)
            packet = create_packet(packet_pb2.Packet.HEARTBEAT, b"Pong")
            self.sock.sendto(packet.SerializeToString(), address)
        elif packet.type in PACKET_TYPE_TO_CHANNEL:
            packet.address = address[0]
            packet.port = address[1]
            self.forward_packet(packet, PACKET_TYPE_TO_CHANNEL[packet.type])
def data_thread(key, player_id):
    """The thread to create dummy data packets
    :param player_id: the player id
    """
    while True:
        data_packet = client_pb2.ClientDataMessage()
        data_packet.lostHealth = 12
        data_packet.usedCoins = 1032
        data_packet.usedMana = 1

        message = AESTool.encrypt(key, data_packet.SerializeToString())
        packet = create_packet(packet_pb2.Packet.DATA, message, player_id)

        client_socket.send_to_server(packet)
        sleep_time = random.randint(300, 1500)
        time.sleep(sleep_time / 1000)
def main():
    """The main client method"""
    # pylint: disable=global-statement
    # pylint: disable=invalid-name
    global client_socket
    # pylint: enable=invalid-name
    # pylint: enable=global-statement
    try:
        key = AESTool.create_key()

        client_socket = Client('127.0.0.1', 1234, key)
        client_socket.start()

        with open('public.key', 'r') as keyfile:
            rsa_key = PKCS1_OAEP.new(RSA.importKey(keyfile.read()),
                                     hashAlgo=Crypto.Hash.SHA256)

        # Apparently the encrypt message has a dummy second param and
        # second item in the return tuple that are to be ignored per the docs
        encrypted_key = rsa_key.encrypt(key)

        player_id = "1111"

        auth_packet = create_packet(packet_pb2.Packet.AUTH, encrypted_key,
                                    player_id)
        client_socket.send_to_server(auth_packet)

        while not client_socket.heartbeat_thread.is_alive():
            time.sleep(0)

        print('starting game threads')
        threading.Thread(target=data_thread, args=(
            key,
            player_id,
        )).start()
        threading.Thread(target=game_thread, args=(
            key,
            player_id,
        )).start()

    except KeyboardInterrupt:
        client_socket.stop()
        client_socket.join(THREAD_TIMEOUT)
def game_thread(key, player_id):
    """The thread to create dummy game packets
    :param player_id: the player id
    """
    count = 0
    while count < 3:
        try:
            game_packet = client_pb2.ClientGameMessage()
            game_packet.xDelta = 2
            game_packet.yDelta = -14
            game_packet.zDelta = 0

            message = AESTool.encrypt(key, game_packet.SerializeToString())
            print('message len', len(message))
            packet = create_packet(packet_pb2.Packet.GAME, message, player_id)
            client_socket.send_to_server(packet)
            sleep_time = random.randint(300, 1500)
            time.sleep(sleep_time / 1000)
            count += 1
            # pylint: disable=broad-except
        except Exception as exception:
            # pylint: enable=broad-except
            print(exception)