docs: async def _send_loop(self):
          """
          This loop is responsible for popping items off the send
          queue, encrypting them, and sending them over the network.
  
          Besides `connect`, only this method ever sends data.
          """
          while self._user_connected and not self._reconnecting:
              if self._pending_ack:
                  ack = RequestState(MsgsAck(list(self._pending_ack)), self._loop)
                  self._send_queue.append(ack)
                  self._last_acks.append(ack)
                  self._pending_ack.clear()
  
              self._log.debug('Waiting for messages to send...')
              # TODO Wait for the connection send queue to be empty?
              # This means that while it's not empty we can wait for
              # more messages to be added to the send queue.
              batch, data = await self._send_queue.get()
  
              if not data:
                  continue
  
              self._log.debug('Encrypting %d message(s) in %d bytes for sending',
                            len(batch), len(data))
  
              data = self._state.encrypt_message_data(data)
              try:
                  await self._connection.send(data)
              except IOError as e:
                  self._log.info('Connection closed while sending data')
                  self._start_reconnect(e)
                  return
  
              for state in batch:
                  if not isinstance(state, list):
                      if isinstance(state.request, TLRequest):
                          self._pending_state[state.msg_id] = state
                  else:
                      for s in state:
                          if isinstance(s.request, TLRequest):
                              self._pending_state[s.msg_id] = s
  
              self._log.debug('Encrypted messages put in a queue to be sent')