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()
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()
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
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
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
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