def unpack_dispatch_and_ack(self, packet: bytes): data = self.unpack(BytesIO(packet)) messages = ( data.body.messages if isinstance(data.body, MsgContainer) else [data] ) log.debug(data) for msg in messages: if msg.seq_no % 2 != 0: if msg.msg_id in self.pending_acks: continue else: self.pending_acks.add(msg.msg_id) if isinstance(msg.body, (types.MsgDetailedInfo, types.MsgNewDetailedInfo)): self.pending_acks.add(msg.body.answer_msg_id) continue if isinstance(msg.body, types.NewSessionCreated): continue msg_id = None if isinstance(msg.body, (types.BadMsgNotification, types.BadServerSalt)): msg_id = msg.body.bad_msg_id elif isinstance(msg.body, (core.FutureSalts, types.RpcResult)): msg_id = msg.body.req_msg_id elif isinstance(msg.body, types.Pong): msg_id = msg.body.msg_id else: if self.client is not None: self.client.updates_queue.put(msg.body) if msg_id in self.results: self.results[msg_id].value = getattr(msg.body, "result", msg.body) self.results[msg_id].event.set() if len(self.pending_acks) >= self.ACKS_THRESHOLD: log.info("Send {} acks".format(len(self.pending_acks))) try: self._send(types.MsgsAck(list(self.pending_acks)), False) except (OSError, TimeoutError): pass else: self.pending_acks.clear()
async def net_worker(self): logging.info("NetWorkerTask started") while True: packet = await self.recv_queue.get() if packet is None: break try: data = MTProto.unpack(BytesIO(packet), self.session_id, self.auth_key, self.auth_key_id) messages = (data.body.messages if isinstance( data.body, MsgContainer) else [data]) log.debug(data) for msg in messages: if msg.seq_no % 2 != 0: if msg.msg_id in self.pending_acks: continue else: self.pending_acks.add(msg.msg_id) if isinstance( msg.body, (types.MsgDetailedInfo, types.MsgNewDetailedInfo)): self.pending_acks.add(msg.body.answer_msg_id) continue if isinstance(msg.body, types.NewSessionCreated): continue msg_id = None if isinstance( msg.body, (types.BadMsgNotification, types.BadServerSalt)): msg_id = msg.body.bad_msg_id elif isinstance(msg.body, (FutureSalts, types.RpcResult)): msg_id = msg.body.req_msg_id elif isinstance(msg.body, types.Pong): msg_id = msg.body.msg_id else: if self.client is not None: self.client.updates_queue.put_nowait(msg.body) if msg_id in self.results: self.results[msg_id].value = getattr( msg.body, "result", msg.body) self.results[msg_id].event.set() if len(self.pending_acks) >= self.ACKS_THRESHOLD: log.info("Send {} acks".format(len(self.pending_acks))) try: await self._send( types.MsgsAck(msg_ids=list(self.pending_acks)), False) except (OSError, TimeoutError): pass else: self.pending_acks.clear() except Exception as e: log.error(e, exc_info=True) log.info("NetWorkerTask stopped")
def unpack_dispatch_and_ack(self, packet: bytes): # TODO: A better dispatcher data = self.unpack(BytesIO(packet)) messages = (data.body.messages if isinstance(data.body, MsgContainer) else [data]) log.debug(data) self.total_bytes += len(packet) self.total_messages += len(messages) for i in messages: if i.seq_no % 2 != 0: if i.msg_id in self.pending_acks: continue else: self.pending_acks.add(i.msg_id) # log.debug("{}".format(type(i.body))) if isinstance(i.body, (types.MsgDetailedInfo, types.MsgNewDetailedInfo)): self.pending_acks.add(i.body.answer_msg_id) continue if isinstance(i.body, types.NewSessionCreated): continue msg_id = None if isinstance(i.body, (types.BadMsgNotification, types.BadServerSalt)): msg_id = i.body.bad_msg_id elif isinstance(i.body, (core.FutureSalts, types.RpcResult)): msg_id = i.body.req_msg_id elif isinstance(i.body, types.Pong): msg_id = i.body.msg_id else: if self.update_handler: self.update_handler(i.body) if msg_id in self.results: self.results[msg_id].value = getattr(i.body, "result", i.body) self.results[msg_id].event.set() # print( # "This packet bytes: ({}) | Total bytes: ({})\n" # "This packet messages: ({}) | Total messages: ({})\n" # "Total connections: ({})".format( # len(packet), self.total_bytes, len(messages), self.total_messages, self.total_connections # ) # ) if len(self.pending_acks) >= self.ACKS_THRESHOLD: log.info("Send {} acks".format(len(self.pending_acks))) try: self._send(types.MsgsAck(list(self.pending_acks)), False) except (OSError, TimeoutError): pass else: self.pending_acks.clear()