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 handle_connection(self, reader: StreamReader, writer: StreamWriter): self._register_tasks() temp_ref = TempRef() world_packet_manager = WorldPacketManager(temp_ref=temp_ref, reader=reader, writer=writer) Logger.info('[World Server]: trying to process auth session') auth = AuthManager(reader, writer, temp_ref=temp_ref, world_packet_manager=world_packet_manager, session_keys=self.session_keys) is_authenticated = await auth.process(step=AuthStep.SECOND) if is_authenticated: peer_name = writer.get_extra_info('peername') Logger.success( '[World Server]: Accept connection from {}'.format(peer_name)) while True: try: request = await asyncio.wait_for(reader.read(4096), timeout=0.01) if request: response = await asyncio.wait_for( world_packet_manager.process(request), timeout=0.01) if response: for packet in response: writer.write(packet) await writer.drain() except TimeoutError: pass except BrokenPipeError: pass except Exception as e: Logger.error('[World Server]: exception, {}'.format(e)) traceback.print_exc() break finally: await asyncio.sleep(0.01) writer.close()
async def broadcast_packets(self): while True: try: player_name, opcode, data = await wait_for( QueuesRegistry.packets_queue.get(), timeout=Config.Realm.Settings.min_timeout ) except TimeoutError: pass else: connection: Connection = self.connections.get(player_name, None) if connection: writer: StreamWriter = connection.writer response: bytes = WorldPacketManager( connection=connection ).generate_packet( opcode=opcode, data=data, ) writer.write(response) await writer.drain() finally: await sleep(Config.Realm.Settings.min_timeout)
async def send_name_query_packet_to_player(self): while True: try: player_name, name_query_packet = await asyncio.wait_for( QueuesRegistry.name_query_packets_queue.get(), timeout=0.01) # except asyncio.QueueEmpty: # pass except TimeoutError: pass else: try: writer = self.connections[player_name]['writer'] header_crypt = self.connections[player_name][ 'header_crypt'] except KeyError: # on login step player object not registered in self.connections, # just ignore pass else: try: response = WorldPacketManager.generate_packet( opcode=WorldOpCode.SMSG_NAME_QUERY_RESPONSE, data=name_query_packet, header_crypt=header_crypt) writer.write(response) await writer.drain() except BrokenPipeError: del self.connections[player_name] except ConnectionResetError: del self.connections[player_name] finally: await asyncio.sleep(0.01)
async def send_update_packet_to_player(self): while True: try: player_name, update_packets = await asyncio.wait_for( QueuesRegistry.update_packets_queue.get(), timeout=0.01) except TimeoutError: pass else: try: writer = self.connections[player_name]['writer'] header_crypt = self.connections[player_name][ 'header_crypt'] except KeyError: # on login step player object not registered in self.connections, # just ignore pass else: try: for update_packet in update_packets: response = WorldPacketManager.generate_packet( opcode=WorldOpCode.SMSG_UPDATE_OBJECT, data=update_packet, header_crypt=header_crypt) Logger.test( 'Send update packet to {}'.format(player_name)) writer.write(response) await writer.drain() except BrokenPipeError: del self.connections[player_name] except ConnectionResetError: del self.connections[player_name] finally: await asyncio.sleep(0.01)
def send_auth_challenge(self): # auth seed need to generate header_crypt Logger.info('[Auth Manager]: sending auth challenge') self.auth_seed = int.from_bytes(urandom(4), 'little') auth_seed_bytes = pack('<I', self.auth_seed) # TODO: make it like standard request handler response = WorldPacketManager.generate_packet(WorldOpCode.SMSG_AUTH_CHALLENGE, auth_seed_bytes) self.writer.write(response)
def _send_addon_info(self): # TODO parse actual addon list from CMSG_AUTH_SESSION and check response = b'\x02\x01\x00\x00\x00\x00\x00\x00' * 16 response = WorldPacketManager.generate_packet( opcode=WorldOpCode.SMSG_ADDON_INFO, data=response, header_crypt=self.world_packet_manager.header_crypt) # send this packet to show 'addons' button on Characters screen self.writer.write(response)
async def handle_connection(self, reader: StreamReader, writer: StreamWriter): self._register_tasks() connection = Connection(reader=reader, writer=writer, session_keys=self.session_keys) world_packet_mgr = WorldPacketManager(connection=connection) # send auth challenge auth_seed: bytes = urandom(4) writer.write( world_packet_mgr.generate_packet( WorldOpCode.SMSG_AUTH_CHALLENGE, auth_seed ) ) connection.auth_seed = auth_seed while True: try: await WorldServer.process_request(reader, writer, world_packet_mgr) except TimeoutError: continue finally: await sleep(Config.Realm.Settings.min_timeout)
def _send_auth_response(self): # updating session request response = pack( '<BIBIB', ResponseCodes.AUTH_OK.value, 0x00, # BillingTimeRemaining 0x00, # BillingPlanFlags 0x00, # BillingTimeRested 0x01 # Expansion, 0 - normal, 1 - TBC, must be set manually for each account ) response = WorldPacketManager.generate_packet( opcode=WorldOpCode.SMSG_AUTH_RESPONSE, data=response, header_crypt=self.world_packet_manager.header_crypt) self.writer.write(response)
async def process_request(reader: StreamReader, writer: StreamWriter, world_packet_mgr: WorldPacketManager): request = await asyncio.wait_for( reader.read(4096), timeout=Config.Realm.Settings.min_timeout) if request: opcode, data = request[:1], request[1:] if data: response = await asyncio.wait_for( world_packet_mgr.process(opcode=opcode, data=data), timeout=Config.Realm.Settings.min_timeout) if response: for packet in response: writer.write(packet) await writer.drain()
async def send_update_packet_to_player(self): while True: try: player_name, update_packets = await asyncio.wait_for( update_packets_queue.get(), timeout=1.0) except TimeoutError: pass else: try: writer = self.connections[player_name]['writer'] header_crypt = self.connections[player_name][ 'header_crypt'] except KeyError: # do nothing for this because on login step player not saved in self.connections pass else: responses = [] while update_packets: # batches with chained with this packet head_update_packet_builder = update_packets.pop(0) for index in range( 0, WorldServer.MAX_UPDATE_PACKETS_INCLUDED): if not update_packets: break batch = update_packets.pop(0).get_update_packet() head_update_packet_builder.add_batch(batch) update_packet = head_update_packet_builder.get_update_packet( build=True) responses.append(update_packet) for update_packet in responses: response = WorldPacketManager.generate_packet( opcode=WorldOpCode.SMSG_UPDATE_OBJECT, data=update_packet, header_crypt=header_crypt) writer.write(response) await writer.drain() finally: await asyncio.sleep(1)
async def process_request(reader: StreamReader, writer: StreamWriter, world_packet_mgr: WorldPacketManager): request: bytes = await wait_for(reader.read(4096), timeout=Config.Realm.Settings.min_timeout) if request: size, opcode, data = request[:2], request[2:6], request[6:] response: List[bytes] = await wait_for( world_packet_mgr.process( size=size, opcode=opcode, data=data ), timeout=Config.Realm.Settings.min_timeout ) if response: for packet in response: writer.write(packet) await writer.drain()
async def send_update_packet_to_player(self): while True: try: player_name, update_packets = await asyncio.wait_for( QueuesRegistry.update_packets_queue.get(), timeout=1.0 ) except TimeoutError: pass else: try: writer = self.connections[player_name]['writer'] header_crypt = self.connections[player_name]['header_crypt'] except KeyError: # on login step player object not registered in self.connections, # just ignore pass else: responses = [] while update_packets: head_update_packet_builder = update_packets.pop(0) for index in range(0, WorldServer.MAX_UPDATE_PACKETS_INCLUDED): if not update_packets: break batch = update_packets.pop(0).get_update_packet() head_update_packet_builder.add_batch(batch) update_packet = head_update_packet_builder.get_update_packet(build=True) responses.append(update_packet) for update_packet in responses: response = WorldPacketManager.generate_packet( opcode=WorldOpCode.SMSG_UPDATE_OBJECT, data=update_packet, header_crypt=header_crypt ) writer.write(response) await writer.drain()
async def handle_connection(self, reader: StreamReader, writer: StreamWriter): peername = writer.get_extra_info('peername') Logger.info( '[Login Server]: Accepted connection from {}'.format(peername)) connection = Connection(reader=reader, writer=writer, peername=peername) world_packet_mgr = WorldPacketManager(connection=connection) while True: try: await LoginServer.process_request(reader, writer, world_packet_mgr) except TimeoutError: continue finally: await asyncio.sleep(Config.Realm.Settings.min_timeout)