Example #1
0
bool
possible_inverse (modification m1, modification m2) {
  if (root (m1) != root (m2)) return false;
  switch (m1->k) {
  case MOD_ASSIGN:
    return m2->k == MOD_ASSIGN;
  case MOD_INSERT:
    return m2->k == MOD_REMOVE && 
           argument (m2) == insert_length (m1->t);
  case MOD_REMOVE:
    return m2->k == MOD_INSERT && 
           insert_length (m2->t) == argument (m1);
  case MOD_SPLIT:
    return m2->k == MOD_JOIN && 
           index (m2) == index (m1);
  case MOD_JOIN:
    return m2->k == MOD_SPLIT && 
           index (m2) == index (m1);
  case MOD_ASSIGN_NODE:
    return m2->k == MOD_ASSIGN_NODE;
  case MOD_INSERT_NODE:
    return m2->k == MOD_REMOVE_NODE && 
           index (m2) == argument (m1);
  case MOD_REMOVE_NODE:
    return m2->k == MOD_INSERT_NODE && 
           argument (m2) == index (m1);
  case MOD_SET_CURSOR:
    return m1 == m2;
  default:
    FAILED ("invalid situation");
    return false;
  }
}
Example #2
0
bool build_handshake_packet(nabto_connect* con, uint8_t* buffer, size_t bufferLength, size_t* packetLength) {
    uint8_t* packetPtr;
    
    /*
     * type,   1 bytes
     * flags,  1 bytes
     * nsi cp, 4 bytes
     * nsi sp, 4 bytes
     * nsi co, 4 bytes
     * id, 20 bytes
     */
    size_t nonceLength = 38;
    uint8_t nonce[38];
    uint8_t* noncePtr = nonce;
    
    packetPtr = insert_header(buffer, con->cpnsi, con->spnsi, NP_PACKET_HDR_TYPE_GW_CONN_U, false, 0, 0, con->consi);

    //NOTE: These type and flags must match the connection attributes set
    //in the unabto_tcp_fallback_connect_thread when a connection is
    //established.
    WRITE_U8(noncePtr, NP_GW_CONN_U_TYPE_TCP); noncePtr+=1;
    WRITE_U8(noncePtr, NP_GW_CONN_U_FLAG_RELIABLE); noncePtr+=1;
    WRITE_U32(noncePtr, con->cpnsi); noncePtr+=4;
    WRITE_U32(noncePtr, con->spnsi); noncePtr+=4;
    memcpy(noncePtr, con->consi, 8); noncePtr+=8;
    memcpy(noncePtr, con->gatewayId, 20);

    packetPtr = insert_payload(packetPtr, NP_PAYLOAD_TYPE_NONCE, nonce, nonceLength);
    
    *packetLength = packetPtr - buffer;

    insert_length(buffer, *packetLength);
    return true;
}
Example #3
0
void send_debug_packet_response(nabto_packet_header* header, uint32_t notification) 
{
    uint8_t* buf = nabtoCommunicationBuffer;
    uint8_t* ptr = nabtoCommunicationBuffer;
    uint8_t* end = nabtoCommunicationBuffer+nabtoCommunicationBufferSize;
    
    ptr = insert_header(ptr, header->nsi_cp, header->nsi_sp, U_DEBUG, true, header->seq, 0, NULL);
    
    if (ptr == NULL) {
        NABTO_LOG_ERROR(("Could not insert debug packet header"));
        return;
    }

    ptr = insert_notify_payload(ptr, end, NP_PAYLOAD_NOTIFY_DEBUG_OK);
    if (ptr == NULL) {
        NABTO_LOG_ERROR(("Could not insert notify payload"));
        return;
    }

    {
        uint16_t length = ptr - buf;
        insert_length(buf, length);
        send_to_basestation(buf, length, &nmc.context.gsp);
    }

}
void send_connection_statistics(nabto_connect* con, uint8_t event) {
    size_t length;
    uint8_t* ptr = insert_header(nabtoCommunicationBuffer, 0, con->spnsi, NP_PACKET_HDR_TYPE_STATS, false, 0, 0, 0);
    uint8_t* end = nabtoCommunicationBuffer + nabtoCommunicationBufferSize;
    
    ptr = insert_stats_payload(ptr, end, event);
    if (ptr == NULL) {
        return;
    }
    ptr = insert_version_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }

#if NABTO_ENABLE_CLIENT_ID
    ptr = insert_cp_id_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }
#endif

    ptr = insert_sp_id_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }

    ptr = insert_ipx_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }
    ptr = insert_connect_stats_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }

    if (!con->noRendezvous) {
        ptr = insert_rendezvous_stats_payload(ptr, end, con);
        if (ptr == NULL) {
            return;
        }
    }

    ptr = insert_connection_stats_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }

    length = ptr - nabtoCommunicationBuffer;
    insert_length(nabtoCommunicationBuffer, length);
    send_to_basestation(nabtoCommunicationBuffer, length, &nmc.context.gsp);
}
Example #5
0
modification
invert (modification m, tree t) {
  ASSERT (is_applicable (t, m), "modification not applicable");
  path rp= root (m);
  switch (m->k) {
  case MOD_ASSIGN:
    return mod_assign (rp, copy (subtree (t, rp)));
  case MOD_INSERT:
    return mod_remove (rp, index (m), insert_length (m->t));
  case MOD_REMOVE:
    {
      int i= index (m);
      int n= argument (m);
      return mod_insert (rp, i, copy (insert_range (subtree (t, rp), i, n)));
    }
  case MOD_SPLIT:
    return mod_join (rp, index (m));
  case MOD_JOIN:
    {
      int  i= index (m);
      return mod_split (rp, i, insert_length (subtree (t, rp * i)));
    }
  case MOD_ASSIGN_NODE:
    return mod_assign_node (rp, L (subtree (t, rp)));
  case MOD_INSERT_NODE:
    return mod_remove_node (rp, argument (m));
  case MOD_REMOVE_NODE:
    {
      tree u= subtree (t, rp);
      int  i= index (m);
      return mod_insert_node (rp, i, copy (u (0, i) * u (i+1, N(u))));
    }
  case MOD_SET_CURSOR:
    return m;
  default:
    FAILED ("unexpected situation");
  }
}
/**
 * Build U_CONNECT response to GSP
 * @param buf                the destination buffer
 * @param seq                the sequence number
 * @param notif              the result notification
 * @param nsi                the nsi value of the connection
 * @param cpnsi              the nsi of the clientpeer to put into the packet.
 * @param spnsi              the nsi of the serverpeer to put into the packet.
 * @param isLocalConnectRsp  true if a capabilities packet 
 * @return                   the size of the response
 */
static size_t mk_gsp_connect_rsp(uint8_t* buf, uint16_t seq, uint32_t notif, uint32_t nsi, uint32_t cpnsi, uint32_t spnsi, bool isLocalConnectRsp)
{
    uint8_t* ptr = insert_header(buf, cpnsi, spnsi, U_CONNECT, true, seq, 0, 0);
    ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_NOTIFY, 0, 8);
    WRITE_U32(ptr, notif); ptr += 4;
    WRITE_U32(ptr, nsi);   ptr += 4;
    
    if (isLocalConnectRsp) {
        ptr = insert_capabilities(ptr, 1 /*unenc*/);
    }

    insert_length(buf, ptr - buf);
    return ptr - buf;
}
Example #7
0
static bool
swap1 (modification& m1, modification& m2, int i, int d) {
  modification r1= dup (m2);
  modification r2= dup (m1);
  if (m2->p->item >= i)
    if (m2->p->item != i || !is_nil (root (m2)) || m2->k != MOD_INSERT)
      r1->p->item -= d;
  if (is_nil (root (m2)))
    switch (m2->k) {
    case MOD_INSERT:
      {
	int b2= m2->p->item;
	int e2= b2 + insert_length (m2->t);
	if (b2 <= i) r2->p->item += (e2-b2);
	break;
      }
    case MOD_REMOVE:
      {
	int b2= m2->p->item;
	int e2= b2 + m2->p->next->item;
	if (b2 <= i && i < e2)
	  if (b2 != i || m1->k != MOD_REMOVE)
	    return false;
	if (b2 < i) r2->p->item -= (e2-b2);
	break;
      }
    case MOD_SPLIT:
      if (m2->p->item < i) r2->p->item++;
      break;
    case MOD_JOIN:
      if (m2->p->item == i-1) return false;
      if (m2->p->item < i) r2->p->item--;
      break;
    case MOD_INSERT_NODE:
      {
	modification aux= m2;
	m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
	m1= aux;
	return true;
      }
    case MOD_REMOVE_NODE:
      return false;
    case MOD_SET_CURSOR:
      return false;
    }
  m1= r1;
  m2= r2;
  return true;
}
static void send_rendezvous_socket(nabto_socket_t socket, nabto_connect* con, uint16_t seq, nabto_endpoint* dest, nabto_endpoint *myAddress)
{
    uint8_t* ptr;
    uint8_t* buf = nabtoCommunicationBuffer;

    ptr = insert_header(buf, 0, con->spnsi, U_CONNECT, false, seq, 0, 0);
    ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6);
    WRITE_U32(ptr, dest->addr); ptr += 4;
    WRITE_U16(ptr, dest->port); ptr += 2;
    if (seq > 0) {
        if (!myAddress) {
            NABTO_LOG_ERROR(("Send rendezvous called with an invalid address"));
            return;
        } else {
            ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6);
            WRITE_U32(ptr, myAddress->addr); ptr += 4;
            WRITE_U16(ptr, myAddress->port); ptr += 2;
        }
    }
    {
        size_t len = ptr - buf;

        insert_length(buf, len);

        if (seq) {
            NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=%" PRIu16 "  " PRIep, MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest), seq, MAKE_EP_PRINTABLE(*myAddress)));
        } else {
            NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=0", MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest)));
        }
        if (dest->addr != 0 && dest->port != 0) {
            nabto_write(socket, buf, len, dest->addr, dest->port);
        } else {
            NABTO_LOG_TRACE(("invalid rendezvous packet thrown away"));
        }
    }
}
void send_connection_ended_statistics(nabto_connect* con) {
    size_t length;
    uint8_t* ptr = insert_header(nabtoCommunicationBuffer, 0, con->spnsi, NP_PACKET_HDR_TYPE_STATS, false, 0, 0, 0);
    uint8_t* end = nabtoCommunicationBuffer + nabtoCommunicationBufferSize;

    ptr = insert_stats_payload(ptr, end, NP_PAYLOAD_STATS_TYPE_UNABTO_CONNECTION_ENDED);
    if (ptr == NULL) {
        return;
    }

    ptr = insert_version_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }

#if NABTO_ENABLE_CLIENT_ID
    ptr = insert_cp_id_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }
#endif

    ptr = insert_sp_id_payload(ptr, end);
    if (ptr == NULL) {
        return;
    }
    ptr = insert_connection_stats_payload(ptr, end, con);
    if (ptr == NULL) {
        return;
    }

    length = ptr - nabtoCommunicationBuffer;
    insert_length(nabtoCommunicationBuffer, length);
    
    send_to_basestation(nabtoCommunicationBuffer, length, &nmc.context.gsp);
}
Example #10
0
bool
swap (modification& m1, modification& m2) {
  path rp1= root (m1);
  path rp2= root (m2);
  if (is_nil (rp1))
    switch (m1->k) {
    case MOD_ASSIGN:
      {
	if (m1 == m2) return true;
	if (!is_nil (rp2) || m2->k != MOD_INSERT_NODE) return false;
	modification aux= m2;
	m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
	m1= aux;
	return true;
      }
    case MOD_INSERT:
      {
	if (is_nil (m2->p)) return false;
	int b= m1->p->item;
	int e= b + insert_length (m1->t);
	if (m2->p->item >= b && m2->p->item < e)
	  if (!is_nil (root (m2)) || m2->p->item != b || m2->k != MOD_INSERT)
	    if (!is_nil (root (m2)) || m2->k != MOD_INSERT_NODE)
	      return false;
	return swap1 (m1, m2, b, e-b);
      }
    case MOD_REMOVE:
      {
	if (is_nil (m2->p)) return false;
	int i= m1->p->item;
	int d= m1->p->next->item;
	return swap1 (m1, m2, i, -d);
      }
    case MOD_SPLIT:
      {
	if (is_nil (m2->p)) return false;
	int i= m1->p->item;
	if (m2->p->item == i || m2->p->item == i+1)
	  if (!is_nil (root (m2)) || m2->p->item != i || m2->k != MOD_INSERT)
	    if (!is_nil (root (m2)) || m2->k != MOD_INSERT_NODE)
	      return false;
	return swap1 (m1, m2, i, 1);
      }
    case MOD_JOIN:
      {
	if (is_nil (m2->p)) return false;
	int i= m1->p->item;
	if (m2->p->item == i)
	  if (!is_nil (root (m2)) || m2->k != MOD_INSERT)
	    return false;
	return swap1 (m1, m2, i, -1);
      }
    case MOD_ASSIGN_NODE:
      {
	if (!is_nil (root (m2))) return swap_basic (m1, m2);
	if (m1 == m2) return true;
	if (!is_nil (rp2) || m2->k != MOD_INSERT_NODE) return false;
	modification aux= m2;
	m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
	m1= aux;
	return true;
      }
    case MOD_INSERT_NODE:
      {
	if (is_nil (root (m2))) return false;
	if (m2->p->item != m1->p->item) return false;
	modification aux= m1;
	m1= modification (m2->k, m2->p->next, m2->t);
	if (m2->k != MOD_INSERT_NODE || !is_nil (root (m1))) m2= aux;
	else m2= modification (aux->k, path (m1->p->item, aux->p), aux->t);
	return true;
      }
    case MOD_REMOVE_NODE:
      {
	modification aux= m1;
	m1= modification (m2->k, path (m1->p->item, m2->p), m2->t);
	m2= aux;
	return true;
      }
    case MOD_SET_CURSOR:
      {
        if (!is_nil (rp2) ||
            m2->k == MOD_JOIN ||
            m2->k == MOD_SPLIT ||
            m2->k == MOD_ASSIGN_NODE)
          return swap_basic (m1, m2);
        return false;
      }
    }
  else if (is_nil (rp2))
    switch (m2->k) {
    case MOD_ASSIGN:
      return false;
    case MOD_INSERT:
      {
	int b= m2->p->item;
	int e= b + insert_length (m2->t);
	return swap2 (m1, m2, b, e-b);
      }
    case MOD_REMOVE:
      {
	int b= m2->p->item;
	int e= b + m2->p->next->item;
	if (m1->p->item >= b && m1->p->item < e) return false;
	return swap2 (m1, m2, b, b-e);
      }
    case MOD_SPLIT:
      {
	int i= m2->p->item;
	if (m1->p->item == i) return false;
	return swap2 (m1, m2, i, 1);
      }
    case MOD_JOIN:
      {
	int i= m2->p->item;
	if (m1->p->item == i || m1->p->item == i+1) return false;
	return swap2 (m1, m2, i, -1);
      }
    case MOD_ASSIGN_NODE:
      return swap_basic (m1, m2);
    case MOD_INSERT_NODE:
      {
	modification aux= m2;
	m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
	m1= aux;
	return true;
      }
    case MOD_REMOVE_NODE:
      {
	if (m1->p->item != m2->p->item) return false;
	modification aux= m2;
	m2= modification (m1->k, m1->p->next, m1->t);
	m1= aux;
	return true;
      }
    case MOD_SET_CURSOR:
      {
        if (!is_nil (rp1) ||
            m1->k == MOD_JOIN ||
            m1->k == MOD_SPLIT ||
            m1->k == MOD_ASSIGN_NODE)
          return swap_basic (m1, m2);
        return false;
      }
    }
  else if (rp1->item == rp2->item) {
    path h (rp1->item);
    modification s1= m1 / h;
    modification s2= m2 / h;
    bool r= swap (s1, s2);
    m1= h * s1;
    m2= h * s2;
    return r;
  }
  else return swap_basic (m1, m2);
  FAILED ("unexpected situation");
}
Example #11
0
bool
swap (modification& m1, modification& m2) {
  // Assuming that m1;m2 (the patch m1 followed by m2) is well-defined,
  // determine modifications m1* and m2* such that m2*;m1* is equivalent
  // to m1;m2.  If such modifications exist, then set m1 := m2* and
  // m2 := m1* and return true.  Otherwise, return false
  path rp1= root (m1);
  path rp2= root (m2);
  if (is_nil (rp1))
    switch (m1->k) {
    case MOD_ASSIGN:
      {
	if (m1 == m2) return true;
	if (!is_nil (rp2) || m2->k != MOD_INSERT_NODE) return false;
	modification aux= m2;
	m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
	m1= aux;
	return true;
      }
    case MOD_INSERT:
      {
	if (is_nil (m2->p)) return false;
	int b= m1->p->item;
	int e= b + insert_length (m1->t);
	if (m2->p->item >= b && m2->p->item < e)
	  if (!is_nil (root (m2)) || m2->p->item != b || m2->k != MOD_INSERT)
	    if (!is_nil (root (m2)) || m2->k != MOD_INSERT_NODE)
	      return false;
	return swap1 (m1, m2, b, e-b);
      }
    case MOD_REMOVE:
      {
	if (is_nil (m2->p)) return false;
	int i= m1->p->item;
	int d= m1->p->next->item;
	return swap1 (m1, m2, i, -d);
      }
    case MOD_SPLIT:
      {
	if (is_nil (m2->p)) return false;
	int i= m1->p->item;
	if (m2->p->item == i || m2->p->item == i+1)
	  if (!is_nil (root (m2)) || m2->p->item != i || m2->k != MOD_INSERT)
	    if (!is_nil (root (m2)) || m2->k != MOD_INSERT_NODE)
	      return false;
	return swap1 (m1, m2, i, 1);
      }
    case MOD_JOIN:
      {
	if (is_nil (m2->p)) return false;
	int i= m1->p->item;
	if (m2->p->item == i)
	  if (!is_nil (root (m2)) || m2->k != MOD_INSERT)
	    return false;
	return swap1 (m1, m2, i, -1);
      }
    case MOD_ASSIGN_NODE:
      {
	if (!is_nil (root (m2))) return swap_basic (m1, m2);
	if (m1 == m2) return true;
	if (!is_nil (rp2) || m2->k != MOD_INSERT_NODE) return false;
	modification aux= m2;
	m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
	m1= aux;
	return true;
      }
    case MOD_INSERT_NODE:
      {
	if (is_nil (root (m2))) return false;
	if (m2->p->item != m1->p->item) return false;
	modification aux= m1;
	m1= modification (m2->k, m2->p->next, m2->t);
	if (m2->k != MOD_INSERT_NODE || !is_nil (root (m1))) m2= aux;
	else m2= modification (aux->k, path (m1->p->item, aux->p), aux->t);
	return true;
      }
    case MOD_REMOVE_NODE:
      {
	modification aux= m1;
	m1= modification (m2->k, path (m1->p->item, m2->p), m2->t);
	m2= aux;
	return true;
      }
    case MOD_SET_CURSOR:
      {
        if (!is_nil (rp2) ||
            m2->k == MOD_JOIN ||
            m2->k == MOD_SPLIT ||
            m2->k == MOD_ASSIGN_NODE)
          return swap_basic (m1, m2);
        return false;
      }
    }
  else if (is_nil (rp2))
    switch (m2->k) {
    case MOD_ASSIGN:
      return false;
    case MOD_INSERT:
      {
	int b= m2->p->item;
	int e= b + insert_length (m2->t);
	return swap2 (m1, m2, b, e-b);
      }
    case MOD_REMOVE:
      {
	int b= m2->p->item;
	int e= b + m2->p->next->item;
	if (m1->p->item >= b && m1->p->item < e) return false;
	return swap2 (m1, m2, b, b-e);
      }
    case MOD_SPLIT:
      {
	int i= m2->p->item;
	if (m1->p->item == i) return false;
	return swap2 (m1, m2, i, 1);
      }
    case MOD_JOIN:
      {
	int i= m2->p->item;
	if (m1->p->item == i || m1->p->item == i+1) return false;
	return swap2 (m1, m2, i, -1);
      }
    case MOD_ASSIGN_NODE:
      return swap_basic (m1, m2);
    case MOD_INSERT_NODE:
      {
	modification aux= m2;
	m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
	m1= aux;
	return true;
      }
    case MOD_REMOVE_NODE:
      {
	if (m1->p->item != m2->p->item) return false;
	modification aux= m2;
	m2= modification (m1->k, m1->p->next, m1->t);
	m1= aux;
	return true;
      }
    case MOD_SET_CURSOR:
      {
        if (!is_nil (rp1) ||
            m1->k == MOD_JOIN ||
            m1->k == MOD_SPLIT ||
            m1->k == MOD_ASSIGN_NODE)
          return swap_basic (m1, m2);
        return false;
      }
    }
  else if (rp1->item == rp2->item) {
    path h (rp1->item);
    modification s1= m1 / h;
    modification s2= m2 / h;
    bool r= swap (s1, s2);
    m1= h * s1;
    m2= h * s2;
    return r;
  }
  else return swap_basic (m1, m2);
  FAILED ("unexpected situation");
}
Example #12
0
/* Handle event by polling application - use data from header stored in data */
application_event_result framework_poll_event(struct naf_handle_s *handle,
                                              uint8_t             *buf,
                                              uint16_t             size,
                                              uint16_t            *olen)
{
    unabto_buffer              w_buf;
    unabto_query_response      w_b;
    uint16_t                   expected_len;
    uint8_t                   *ptr;
    uint32_t                   query_id;
    application_event_result   res;
    uint16_t                   dlen;

    expected_len = handle->header.hlen + OFS_DATA;
    if (size <= expected_len) {
        NABTO_LOG_ERROR(("buffer too small to contain reconstructed header. size=%" PRIu16 " needed=%" PRIu16, size, expected_len));
        return AER_REQ_SYSTEM_ERROR;
    }

    /* Write packet header and crypto payload header into buf. */
    ptr = reconstruct_header(buf, &handle->header);
    if (!ptr) {
        //log message already given (header length mismatch)
        return AER_REQ_SYSTEM_ERROR;
    }
    {
        ptrdiff_t diff = ptr - buf;
        if (expected_len != (uint16_t)(diff)) {
            NABTO_LOG_ERROR(("header (with crypto) length mismatch: %" PRIu16 " != %" PRIptrdiff " !!!!!!!!!!!!!!!!!!!", expected_len, diff));
            return AER_REQ_SYSTEM_ERROR;
        }
    }

    /* Set up a write buffer to write into buf (after crypto payload header). */
    unabto_buffer_init(&w_buf, buf + expected_len, (int)(size - expected_len));
    unabto_query_response_init(&w_b, &w_buf);

    /* Start reading input buffer from start again. */
    unabto_query_request_reset(&handle->readBuffer);
    /* Skip query id. */
    if (!unabto_query_read_uint32(&handle->readBuffer, &query_id)) {
        return AER_REQ_NO_QUERY_ID;
    }

  /* Call application */
    NABTO_LOG_TRACE(("APPREQ application_poll: client=" PRI_client_id_q, CLIENT_ID_Q_ARGH(*handle)));

    res = application_poll(&handle->applicationRequest, NULL, &w_b);
    NABTO_LOG_TRACE(("APPREQ application_poll: result=%i %" PRItext, res, result_s(res)));

    if (res != AER_REQ_RESPONSE_READY)
    {
        return res;
    }

    dlen = unabto_crypto_max_data(&handle->connection->cryptoctx, (uint16_t)(size - expected_len));

    if (!unabto_encrypt(&handle->connection->cryptoctx, ptr, unabto_query_response_used(&w_b), ptr, dlen, &dlen)) {
        NABTO_LOG_TRACE((PRInsi" Encryption failure", MAKE_NSI_PRINTABLE(0, handle->header.nsi_sp, 0)));
        return AER_REQ_SYSTEM_ERROR;
    }

    /* Update packet length and flag fields */
    dlen += expected_len;
    insert_length(buf, dlen);
    if (!unabto_insert_integrity(&handle->connection->cryptoctx, buf, dlen)) {
        NABTO_LOG_TRACE((PRInsi" Signing failure", MAKE_NSI_PRINTABLE(0, handle->header.nsi_sp, 0)));
        return AER_REQ_SYSTEM_ERROR;
    }

    *olen = dlen;
    return AER_REQ_RESPONSE_READY;
}