Пример #1
0
    async def process(self):
        Logger.debug('[Login Challenge]: processing')
        self._parse_data()

        try:
            with AccountManager() as account_mgr:
                account = account_mgr.get(name=self.account_name).account

                if account is None:
                    raise Exception('Account \'{}\' is not found'.format(self.account_name))

                account.os = self.os
                account.ip = '.'.join([str(i) for i in self.ip_addr])
                account.platform = self.platform
                account.timezone = self.timezone
                account.locale = self.locale

                account_mgr.update()

                self.account = account
                self.temp_ref.account = account

        # TODO: define account exceptions
        except Exception as e:
            Logger.error('[Login Challenge]: error = {}'.format(e))
            return None
        finally:
            return self._get_response()
Пример #2
0
    async def handle_connection(self, reader: StreamReader, writer: StreamWriter):
        temp_ref = TempRef()
        world_packet_manager = WorldPacketManager(temp_ref=temp_ref, reader=reader, writer=writer)

        peername = writer.get_extra_info('peername')
        Logger.debug('[World Server]: Accept connection from {}'.format(peername))

        Logger.info('[World Server]: trying to process auth session')
        auth = AuthManager(reader, writer, temp_ref=temp_ref, world_packet_manager=world_packet_manager)
        await auth.process(step=AuthStep.SECOND)

        self._register_tasks()

        while True:
            try:
                request = await asyncio.wait_for(reader.read(4096), timeout=1.0)
                if request:
                    response = await asyncio.wait_for(world_packet_manager.process(request), timeout=1.0)

                    if response:
                        for packet in response:
                            writer.write(packet)
                            await writer.drain()

            except TimeoutError:
                continue

            except Exception as e:
                Logger.error('[World Server]: exception, {}'.format(e))
                traceback.print_exc()
                break

        writer.close()
Пример #3
0
    async def process(self, packet: bytes):
        if not self.header_crypt:
            raise Exception('Cannot decrypt packet')

        # this is workaround cause one-time decryption do not works correctly for some opcodes
        # so I need decrypt some packets for multiple times
        def decrypt(packet: bytes):
            result = packet
            for index in range(20):
                enc = self.header_crypt.decrypt(packet)
                try:
                    # TODO: add has_key for Enum
                    WorldOpCode(int.from_bytes(enc[2:6], 'little')).value
                except ValueError:
                    continue
                else:
                    result = enc
                    break

            return result

        packet = decrypt(packet)

        size = unpack('>H', packet[:2])[0]
        opcode = WorldOpCode(unpack('<I', packet[2:6])[0])

        if opcode in HANDLERS:
            Logger.debug(
                '[World Packet]: processing {} opcode ({} bytes)'.format(
                    WorldOpCode(opcode).name, size))
            handlers = HANDLERS[opcode]
            packets = list()

            for handler in handlers:
                opcode, response = await handler(
                    packet,
                    temp_ref=self.temp_ref,
                    reader=self.reader,
                    writer=self.writer,
                    header_crypt=self.header_crypt).process()
                if opcode and response:
                    packets.append(
                        WorldPacketManager.generate_packet(
                            opcode, response, self.header_crypt))

            return packets
        else:
            try:
                Logger.warning(
                    '[World Packet]: no handler for opcode = {} ({} bytes)'.
                    format(WorldOpCode(opcode).name, size))
            except ValueError:
                Logger.error(
                    '[World Packet]: no handler for unknown opcode = {} ({} bytes)'
                    .format(opcode, size))
            finally:
                return None
Пример #4
0
    async def process(self):
        Logger.debug('[Login Proof]: processing...')
        self._parse_data()

        # generated for server-side authentication (next step, after realmlist recv)
        self.srp.generate_session_key(self.client_ephemeral,
                                      self.account.verifier)
        self.srp.generate_client_proof(self.client_ephemeral, self.account)

        if self.srp.client_proof == self.client_proof:
            Logger.debug('[Login Proof]: OK')
            self.srp.generate_server_proof(self.client_ephemeral)

            await QueuesRegistry.session_keys_queue.put(
                ('#{}-session-key'.format(self.account.name),
                 b64encode(self.srp.session_key).decode('utf-8')))

            return self._get_response()

        return None
Пример #5
0
    def _get_response(self):
        Logger.debug('[Realmlist]: processing')

        realm_packet = realm.get_state_packet(RealmFlags.NORMAL.value,
                                              RealmPopulation.LOW.value)
        realm_packet_as_bytes = b''.join([realm_packet])

        # TODO: should be moved to constants since more than one realm will exists
        num_realms = 1

        header = pack(Realmlist.REALMLIST_RESPONSE_HEADER_FORMAT,
                      LoginOpCode.REALMLIST.value,
                      Realmlist.MIN_RESPONSE_SIZE + len(realm_packet_as_bytes),
                      0x00, num_realms)

        footer = pack(Realmlist.REALMLIST_RESPONSE_FOOTER_FORMAT, 0)

        response = header + realm_packet_as_bytes + footer

        return response
Пример #6
0
    def load_all(self) -> Dict[int, Region]:
        Logger.debug('[RegionMgr]: Loading regions')
        regions = self.session.query(Region).all()
        t0 = time()

        result: Dict[int, Region] = {}

        for region in regions:
            objects = RegionManager.load_region_objects(region)
            octree = OctreeManager.create_octree(x0=region.x2,
                                                 x1=region.x1,
                                                 y0=region.y2,
                                                 y1=region.y1,
                                                 objects=objects)
            region.set_octree(octree)
            result[region.id] = region

        t1 = time()
        Logger.debug('[RegionMgr]: regions loaded in {}s'.format(t1 - t0))

        return result