async def _send(self, data: TLObject, wait_response: bool = True, timeout: float = WAIT_TIMEOUT): message = self.msg_factory(data) msg_id = message.msg_id if wait_response: self.results[msg_id] = Result() log.debug("Sent:\n{}".format(message)) payload = MTProto.pack(message, self.current_salt.salt, self.session_id, self.auth_key, self.auth_key_id) try: await self.connection.send(payload) except OSError as e: self.results.pop(msg_id, None) raise e if wait_response: try: await asyncio.wait_for(self.results[msg_id].event.wait(), timeout) except asyncio.TimeoutError: pass finally: result = self.results.pop(msg_id).value if result is None: raise TimeoutError elif isinstance(result, types.RpcError): if isinstance(data, (functions.InvokeWithoutUpdates, functions.InvokeWithTakeout)): data = data.query RPCError.raise_it(result, type(data)) elif isinstance(result, types.BadMsgNotification): raise Exception( self.BAD_MSG_DESCRIPTION.get( result.error_code, "Error code {}".format(result.error_code))) else: return result
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")