docs: def send(self, body, req_type, seq_no=1):
          """
          Send a TACACS+ message body
  
          :param body:     packed bytes, i.e., `struct.pack(...)`
          :param req_type: TAC_PLUS_AUTHEN,
                           TAC_PLUS_AUTHOR,
                           TAC_PLUS_ACCT
          :param seq_no:   The sequence number of the current packet.  The
                           first packet in a session MUST have the sequence
                           number 1 and each subsequent packet will increment
                           the sequence number by one.  Thus clients only send
                           packets containing odd sequence numbers, and TACACS+
                           servers only send packets containing even sequence
                           numbers.
          :return:         TACACSPacket
          :raises:         socket.timeout, socket.error
          """
          # construct a packet
          header = TACACSHeader(
              self.version,
              req_type,
              self.session_id,
              len(body.packed),
              seq_no=seq_no
          )
          packet = TACACSPacket(header, body.packed, self.secret)
  
          logger.debug('\n'.join([
              body.__class__.__name__,
              'sent header <%s>' % header,
              'sent body <%s>' % body,
          ]))
          self.sock.send(bytes(packet))
  
          readable, _, _ = select.select([self.sock], [], [], self.timeout)
          if readable:
              # TACACS+ header packets are always 12 bytes
              header_bytes = self.sock.recv(12)
              resp_header = TACACSHeader.unpacked(header_bytes)
              # If the reply header doesn't match, it's likely a non-TACACS+ TCP
              # service answering with data we don't antipicate.  Bail out.
              if any([
                  resp_header.version_max != header.version_max,
                  resp_header.type != header.type,
                  resp_header.session_id != header.session_id
              ]):
                  logger.error('\n'.join([
                      resp_header.__class__.__name__,
                      'recv header <%s>' % resp_header,
                      str(resp_header.packed)
                  ]))
                  raise socket.error
  
              # read the number of bytes specified in the response header
              body_bytes = six.b('')
              remaining = resp_header.length
              while remaining > 0:
                  body_bytes += self.sock.recv(remaining)
                  remaining = resp_header.length - len(body_bytes)
              return TACACSPacket(
                  resp_header,
                  body_bytes,
                  self.secret
              )
          raise socket.timeout