/**
 * This code makes a connection unique, we have tried to make
 * connections through several channels. But when we receives the
 * first real data message on one channel we know that the client
 * ended up using this specific channel.
 */
void nabto_connection_end_connecting(nabto_connect* con, message_event* event) {
    if (event->type == MT_UDP) {
#if NABTO_ENABLE_TCP_FALLBACK
        unabto_tcp_fallback_close(con);
#endif
        con->state = CS_CONNECTED;
        con->type = NCT_REMOTE_P2P;
        con->conAttr = CON_ATTR_DEFAULT;

        con->socket = event->udpMessage.socket;
        NABTO_LOG_TRACE(("Received data on socket %i", con->socket));

        con->peer = event->udpMessage.peer;
        if (EP_EQUAL(event->udpMessage.peer, nmc.context.gsp)) {
            NABTO_LOG_INFO((PRInsi " UDP Fallback through the GSP ", MAKE_NSI_PRINTABLE(0, con->spnsi, 0)));
        } else {
            NABTO_LOG_INFO((PRInsi " Direct UDP connection", MAKE_NSI_PRINTABLE(0, con->spnsi, 0)));
        }
    }

#if NABTO_ENABLE_TCP_FALLBACK    
    if (event->type == MT_TCP_FALLBACK) {
        con->state = CS_CONNECTED;
        con->type = NCT_REMOTE_RELAY_MICRO;
        con->conAttr |= con->fbConAttr;
        NABTO_LOG_INFO((PRInsi " TCP FAllback connection ", MAKE_NSI_PRINTABLE(0, con->spnsi, 0)));
    }
#endif

    nabto_rendezvous_end(con);

    con->sendConnectStatistics = true;
} 
void nabto_release_connection(nabto_connect* con)
{
    if (con->state != CS_IDLE) {
        NABTO_LOG_INFO((PRInsi " Release connection (record %i)", MAKE_NSI_PRINTABLE(0, con->spnsi, 0), nabto_connection_index(con)));
        if (con->state != CS_CLOSE_REQUESTED) {
            con->state = CS_CLOSE_REQUESTED;
#if NABTO_ENABLE_STREAM
            nabto_stream_connection_released(con);
#endif
        }

        if (con->socket != NABTO_INVALID_SOCKET) {
            if (con->socket != nmc.socketGSP &&
                con->socket != nmc.socketLocal) 
            {
                nabto_close_socket(&con->socket);
            }
        }

        // in case the rendezvous state is still active.
        nabto_rendezvous_end(con);
        
#if NABTO_ENABLE_TCP_FALLBACK
        unabto_tcp_fallback_close(con);
#endif
        con->state = CS_IDLE;
        nabto_crypto_release(&con->cryptoctx);

    } else {
        NABTO_LOG_TRACE(("nabto_release_connection called on non used connection"));
    }
}
Ejemplo n.º 3
0
bool nabto_fallback_connect_u_event(uint16_t packetLength, nabto_packet_header* hdr) {
    nabto_connect* con;
    uint8_t* startOfPayloads;
    uint8_t* endOfPayloads;
    uint8_t* noncePayloadStart;
    uint16_t noncePayloadLength;
    uint8_t type;
    uint8_t flags;
    uint8_t* ptr;
    bool isReliable;
    bool hasKeepAlive;

    con = nabto_find_connection(hdr->nsi_sp);
    if (con == 0) {
        NABTO_LOG_TRACE((PRInsi " No connection found.", MAKE_NSI_PRINTABLE(hdr->nsi_cp, hdr->nsi_sp, 0)));
        return false;
    }

    startOfPayloads = nabtoCommunicationBuffer + hdr->hlen;
    endOfPayloads = nabtoCommunicationBuffer + packetLength;

    if (!find_payload(startOfPayloads, endOfPayloads, NP_PAYLOAD_TYPE_NONCE, &noncePayloadStart, &noncePayloadLength)) {
        NABTO_LOG_ERROR((PRI_tcp_fb "No nonce payload in GW_CONN_U packet.", TCP_FB_ARGS(con)));
        return false;
    }

    if (noncePayloadLength < 2) {
        NABTO_LOG_ERROR((PRI_tcp_fb "The payload received is too small to contain both flags and type.", TCP_FB_ARGS(con)));
        return false;
    }

    ptr = noncePayloadStart + NP_PAYLOAD_HDR_BYTELENGTH;

    READ_U8(type, ptr);  ptr++;
    READ_U8(flags, ptr); ptr++;

    isReliable   = (flags & NP_GW_CONN_U_FLAG_RELIABLE) != 0;
    hasKeepAlive = (flags & NP_GW_CONN_U_FLAG_KEEP_ALIVE) != 0;

    con->tcpFallbackConnectionState = UTFS_READY_FOR_DATA;

    // If the connection is still resolving upgrade it to a fallback connection.
    if (isReliable) {
        con->fbConAttr |= CON_ATTR_NO_RETRANSMIT;
        NABTO_LOG_DEBUG((PRI_tcp_fb "connection needs no retransmition", TCP_FB_ARGS(con)));
    }

    if (!hasKeepAlive) {
        con->fbConAttr |= CON_ATTR_NO_KEEP_ALIVE;
        NABTO_LOG_DEBUG((PRI_tcp_fb "connection needs no keep alive", TCP_FB_ARGS(con)));
    } else {
        NABTO_LOG_DEBUG((PRI_tcp_fb "connection needs keep alive", TCP_FB_ARGS(con)));
    }
    
    return true;
}
/** initialise a connection */
static void nabto_reset_connection(nabto_connect* con)
{
    nabto_stamp_t tmp = nabtoGetStamp();
    NABTO_LOG_TRACE((PRInsi " Reset connection", MAKE_NSI_PRINTABLE(0, con->spnsi, 0)));
    memset(con, 0, offsetof(nabto_connect, cryptoctx));
    con->stamp = tmp;
    con->socket = NABTO_INVALID_SOCKET;
    con->stats.connectionStart = tmp;
#if NABTO_ENABLE_TCP_FALLBACK
    unabto_tcp_fallback_init(con);
#endif                

    nabto_crypto_reset(&con->cryptoctx);
}
bool connect_event(message_event* event, nabto_packet_header* hdr)
{
    nabto_endpoint* peer = &event->udpMessage.peer;
    bool isLocal = (event->udpMessage.socket == nmc.socketLocal);
    

    NABTO_LOG_TRACE(("U_CONNECT: Searching for hdr->nsi_cp=%" PRIu32 " (should not be found)", hdr->nsi_cp));
    if (nabto_find_connection(hdr->nsi_cp) == NULL) {
        uint32_t nsi;
        uint32_t ec = 0;
        nabto_connect* con = nabto_init_connection(hdr, &nsi, &ec, isLocal);
        if (con) {
            size_t olen;
            NABTO_LOG_TRACE(("Couldn't find connection (good!). Created a new connection (nsi=%" PRIu32 ") con->spnsi=%" PRIu32, nsi, con->spnsi));
            olen = mk_gsp_connect_rsp(nabtoCommunicationBuffer, hdr->seq, NOTIFY_CONNECT_OK, con->spnsi, hdr->nsi_cp, hdr->nsi_sp, isLocal);
            
            if (olen == 0) {
                NABTO_LOG_ERROR(("U_CONNECT out of resources in connect event."));
                nabto_release_connection(con); // no resources available
            } else {
                if (EP_EQUAL(*peer, nmc.context.gsp)) {
                    send_to_basestation(nabtoCommunicationBuffer, olen, peer);
                } else {
                    nabto_write(event->udpMessage.socket, nabtoCommunicationBuffer, olen, peer->addr, peer->port);
                }
                
                con->state = CS_CONNECTING;

                if (!con->noRendezvous) {
                    nabto_rendezvous_start(con);
                }
#if NABTO_ENABLE_TCP_FALLBACK
                if (con->hasTcpFallbackCapabilities) {
                    unabto_tcp_fallback_connect(con);
                }
#endif
                return true;
            }
        } else if (nsi && ec) {
            // build negative answer
            size_t olen = mk_gsp_connect_rsp(nabtoCommunicationBuffer, hdr->seq, ec, nsi, hdr->nsi_cp, hdr->nsi_sp, isLocal);
            NABTO_LOG_TRACE((PRInsi " Deny connection, result: %" PRIu32, MAKE_NSI_PRINTABLE(0, nsi, 0), ec));
            nabto_write(event->udpMessage.socket, nabtoCommunicationBuffer, olen, peer->addr, peer->port);
            return true;
        } else {
            NABTO_LOG_ERROR(("U_CONNECT was a malformed connect event."));
        }
    }
    return false;
}
void nabto_release_connection_req(nabto_connect* con)
{
    NABTO_LOG_DEBUG((PRInsi " Release connection req", MAKE_NSI_PRINTABLE(0, con->spnsi, 0)));
    if (con->state != CS_CLOSE_REQUESTED) {
        uint32_t timeout = con->timeOut;
        if (timeout > MAX_TIMEOUT) {
            timeout = MAX_TIMEOUT;
        }
        con->state = CS_CLOSE_REQUESTED;
        nabtoSetFutureStamp(&con->stamp, timeout);
#if NABTO_ENABLE_STREAM
        nabto_stream_connection_closed(con);
#endif
        con->sendConnectionEndedStatistics = true;
    } else {
        NABTO_LOG_TRACE(("nabto_release_connection_req on closed connection"));
    }
}
Ejemplo n.º 7
0
void nabto_release_connection_req(nabto_connect* con)
{
    NABTO_LOG_DEBUG((PRInsi " Release connection req", MAKE_NSI_PRINTABLE(0, con->spnsi, 0)));
    if (con->state != CS_CLOSE_REQUESTED) {
        uint32_t timeout = con->timeOut;
        if (timeout > MAX_TIMEOUT) {
            timeout = MAX_TIMEOUT;
        }
        con->state = CS_CLOSE_REQUESTED;
        unabto_connection_set_future_stamp(&con->stamp, timeout);
#if NABTO_ENABLE_STREAM
        nabto_stream_connection_closed(con);
#endif
        con->sendConnectionEndedStatistics = true;
        // trigger recalculation of timeout such that statistics can be sent.
        connection_timeout_cache_cached = false;
    
    } else {
        NABTO_LOG_TRACE(("nabto_release_connection_req on closed connection"));
    }
}
void nabto_time_event_connection(void)
{
    nabto_connect* con;

    for (con = connections; con < connections + NABTO_CONNECTIONS_SIZE; ++con) {
        if (con->state != CS_IDLE) {
            rendezvous_time_event(con);
            statistics_time_event(con);
#if NABTO_ENABLE_TCP_FALLBACK
            unabto_tcp_fallback_event(con);
#endif

            if (nabto_connection_has_keep_alive(con) && nabtoIsStampPassed(&con->stamp)) {
                NABTO_LOG_DEBUG((PRInsi " Connection timeout", MAKE_NSI_PRINTABLE(0, con->spnsi, 0))); //, Stamp value is: %ul", con->spnsi, con->stamp));
                nabto_release_connection(con);
            }
        }
    }
#if NABTO_ENABLE_STREAM
    unabto_time_event_stream();
#endif
}
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"));
        }
    }
}
bool rendezvous_event(message_event* event, nabto_packet_header* hdr)
{
    uint8_t*          end = nabtoCommunicationBuffer + hdr->len;
    uint16_t          res = hdr->hlen;

    uint8_t*          ptr;
    uint8_t           type;
    nabto_endpoint  epUD;
    nabto_connect*  con   = 0;
    nabto_endpoint  src;
    uint32_t        interval = 5000;

    src = event->udpMessage.peer;
    NABTO_LOG_TRACE((PRInsi " Received from " PRIep " seq=%" PRIu16, MAKE_NSI_PRINTABLE(0, hdr->nsi_sp, 0), MAKE_EP_PRINTABLE(src), hdr->seq));

    ptr = nabtoCommunicationBuffer + res;
    res = nabto_rd_payload(ptr, end, &type); ptr += SIZE_PAYLOAD_HEADER;
    if (res != 6 || type != NP_PAYLOAD_TYPE_EP) {
        NABTO_LOG_TRACE(("Can't read first EP"));
        return false;
    }
    READ_U32(epUD.addr, ptr); ptr += 4;
    READ_U16(epUD.port, ptr); ptr += 2;
    res = nabto_rd_payload(ptr, end, &type); ptr += SIZE_PAYLOAD_HEADER;
    if (res == 6 && type == NP_PAYLOAD_TYPE_EP) {
        // The second EP is not neccessary since we read the destination ep from the udp packet.
        
        ptr += 6;
        res = nabto_rd_payload(ptr, end, &type); ptr += SIZE_PAYLOAD_HEADER;
        if (res == 4 && type == NP_PAYLOAD_TYPE_NONCE) {
            READ_U32(interval, ptr);
            NABTO_LOG_TRACE((PRInsi " Read interval from packet: %" PRIu32, MAKE_NSI_PRINTABLE(0, hdr->nsi_sp, 0), interval));
            if (interval == 0) {
                NABTO_LOG_WARN(("Interval was 0, setting to 5000"));
                interval = 5000;
            }
        }
    }

    con  = nabto_find_connection(hdr->nsi_sp);

    if (!con) {
        NABTO_LOG_ERROR(("Connection was not found, nsi: %i", hdr->nsi_sp));
    } else {
        if (hdr->seq == 0) {
            send_rendezvous_socket(event->udpMessage.socket, con, 1, &src, &epUD);
        } else if (hdr->seq == 1) {
            send_rendezvous_socket(event->udpMessage.socket, con, 2, &src, &epUD);
            if (!conclude_connection(con, &src, interval)) {
                return false;
            }
        } else if (hdr->seq == 2) {
            if (!conclude_connection(con, &src, interval)) {
                return false;
            }
        } else {
            NABTO_LOG_ERROR(("Invalid Sequence Number"));
        }
    }
    return false;
}
nabto_connect* nabto_init_connection(nabto_packet_header* hdr, uint32_t* nsi, uint32_t* ec, bool isLocal)
{
    uint8_t  type;
    uint8_t  flags;   /* NP_PAYLOAD_IPX_FLAG_* */
    nabto_connect* con;

    const uint8_t* end = nabtoCommunicationBuffer + hdr->len;
    uint8_t* ptr = nabtoCommunicationBuffer + hdr->hlen;
    uint16_t res;
    uint16_t ipxPayloadLength;
    
    ipxPayloadLength = nabto_rd_payload(ptr, end, &type); ptr += SIZE_PAYLOAD_HEADER;
    
    *nsi = 0;
    *ec  = 0;

    if ((ipxPayloadLength != IPX_PAYLOAD_LENGTH_WITHOUT_NSI) && 
        (ipxPayloadLength != IPX_PAYLOAD_LENGTH_WITH_NSI) && 
        (ipxPayloadLength != IPX_PAYLOAD_LENGTH_FULL_NSI)) {
        NABTO_LOG_TRACE(("Illegal payload size in U_CONNECT request from GSP: %" PRIu16 " %" PRIu8, ipxPayloadLength, type));
        return 0;
    }
    if (type != NP_PAYLOAD_TYPE_IPX) {
        NABTO_LOG_TRACE(("Illegal payload type in U_CONNECT request from GSP: %" PRIu16 " %" PRIu8, ipxPayloadLength, type));
        return 0;
    }
    
    if (ipxPayloadLength == IPX_PAYLOAD_LENGTH_WITH_NSI || 
        ipxPayloadLength == IPX_PAYLOAD_LENGTH_FULL_NSI) {
        READ_U32(*nsi, ptr + 13);
        NABTO_LOG_TRACE(("IPX payload with NSI (SPNSI=%" PRIu32 ")", *nsi));
    } else {
        *nsi = fresh_nsi();
        NABTO_LOG_TRACE(("IPX payload without NSI (fresh NSI=%" PRIu32 ")", *nsi));
    }

    if (*nsi == 0) {
        NABTO_LOG_ERROR(("Trying to create connection with spnsi == 0"));
        return 0;
    }

    if (nabto_find_connection(*nsi)) {
        NABTO_LOG_DEBUG((PRInsi " A connection already exists this is probably a retransmission", MAKE_NSI_PRINTABLE(0, *nsi, 0)));
        *ec = NOTIFY_CONNECT_OK;
        return 0;
    }

    con = nabto_init_connection_real(*nsi);

    if (con == 0) {
        if (nabto_find_connection(*nsi)) {
            NABTO_LOG_DEBUG((PRInsi " U_CONNECT: A connection resource is already pending new connection", MAKE_NSI_PRINTABLE(0, *nsi, 0)));
        } else {
            NABTO_LOG_INFO((PRInsi " U_CONNECT: No connection resources free for new connection", MAKE_NSI_PRINTABLE(0, *nsi, 0)));
#if NABTO_ENABLE_DEVICE_BUSY_AS_FATAL
            NABTO_LOG_FATAL((PRInsi " U_CONNECT: No free connections configured to be considered fatal", MAKE_NSI_PRINTABLE(0, *nsi, 0)));
#endif
        }
        *ec = NOTIFY_ERROR_BUSY_MICRO;
        return 0;
    }

    NABTO_LOG_DEBUG((PRInsi " U_CONNECT: Connecting using record %i", MAKE_NSI_PRINTABLE(0, *nsi, 0), nabto_connection_index(con)));
    READ_U32(con->cp.privateEndpoint.addr, ptr +  0);
    READ_U16(con->cp.privateEndpoint.port, ptr +  4);
    READ_U32(con->cp.globalEndpoint.addr, ptr +  6);
    READ_U16(con->cp.globalEndpoint.port, ptr + 10);
    READ_U8(flags,                ptr + 12); /* the final word (4 bytes) has been read already (nsi) */
    con->noRendezvous = (flags & NP_PAYLOAD_IPX_FLAG_NO_RENDEZVOUS) ? 1 : 0;
    con->cpEqual      = EP_EQUAL(con->cp.privateEndpoint, con->cp.globalEndpoint);
    con->cpAsync      = (flags & NP_PAYLOAD_IPX_FLAG_CP_ASYNC) ? 1 : 0;
    con->clientNatType      = (flags & NP_PAYLOAD_IPX_NAT_MASK);
    con->isLocal      = isLocal;
    NABTO_LOG_INFO((PRInsi " U_CONNECT: cp.private: " PRIep " cp.global: " PRIep ", noRdv=%" PRIu8 ", cpeq=%" PRIu8 ", asy=%" PRIu8 ", NATType: %" PRIu8 , MAKE_NSI_PRINTABLE(0, *nsi, 0), MAKE_EP_PRINTABLE(con->cp.privateEndpoint), MAKE_EP_PRINTABLE(con->cp.globalEndpoint), con->noRendezvous, con->cpEqual, con->cpAsync, con->clientNatType));

#if NABTO_ENABLE_TCP_FALLBACK
    if (ipxPayloadLength == IPX_PAYLOAD_LENGTH_FULL_NSI) {
        memcpy(con->consi, ptr+17, 8);
        con->nsico = con->consi;
        READ_U32(con->cpnsi, ptr+25);
    }
#endif

    ptr += ipxPayloadLength;  //IPX_PAYLOAD_LENGTH_WITHOUT_NSI or IPX_PAYLOAD_LENGTH_WITH_NSI
        
    con->clientId[0]  = 0;
    res = nabto_rd_payload(ptr, end, &type);
    if (type == NP_PAYLOAD_TYPE_CP_ID) {
        uint8_t idType;
        ptr += SIZE_PAYLOAD_HEADER;
        if (res > 0) {
            READ_U8(idType, ptr); ++ptr; --res;
            if (idType == 1) { // 1 == EMAIL
                size_t sz = res;
                if (sz >= sizeof(con->clientId)) {
                    if (sizeof(con->clientId) > 1) {
                        NABTO_LOG_WARN(("Client ID truncated"));
                    }
                    sz = sizeof(con->clientId) - 1;
                }
                if (sz) {
                    memcpy(con->clientId, (const void*) ptr, sz);
                }
                con->clientId[sz] = 0;
            }
        }
        NABTO_LOG_TRACE(("Connection opened from '%s' (to %s)", con->clientId, nmc.nabtoMainSetup.id));
        ptr += res;
    }
#if NABTO_ENABLE_CONNECTION_ESTABLISHMENT_ACL_CHECK
    if (!allow_client_access(con)) {
        *ec = NOTIFY_ERROR_CP_ACCESS;
        goto init_error;
    }
#endif

#if NABTO_ENABLE_TCP_FALLBACK
    {
        uint8_t* gatewayPtr = ptr;
        res = nabto_rd_payload(ptr, end, &type);
        if (type == NP_PAYLOAD_TYPE_GW && ipxPayloadLength == IPX_PAYLOAD_LENGTH_FULL_NSI) {
            uint8_t* gatewayEndPtr;
            size_t idLength;
            NABTO_LOG_TRACE(("The connect contains a gateway payload."));
            ptr += res + SIZE_PAYLOAD_HEADER;
            gatewayPtr += SIZE_PAYLOAD_HEADER;
            gatewayEndPtr = ptr;

            READ_U32(con->fallbackHost.addr, gatewayPtr); gatewayPtr+=4;
            READ_U16(con->fallbackHost.port, gatewayPtr); gatewayPtr+=2;
            // skip the nsi
            gatewayPtr+=4;
        
            idLength = gatewayEndPtr-gatewayPtr;
            if (idLength != 20) {
                NABTO_LOG_FATAL(("The id length should be 20 bytes. bytes=%" PRIsize, idLength));
                // todo
            } 
            memcpy(con->gatewayId, gatewayPtr, 20);
            con->hasTcpFallbackCapabilities = true;
        }
    }
#endif


#if NABTO_ENABLE_UCRYPTO
    if (nmc.context.nonceSize == NONCE_SIZE) {
        uint8_t* decryptedDataStart;
        uint16_t decryptedDataLength;
        if (!unabto_connection_verify_and_decrypt_connect_packet(hdr, &decryptedDataStart, &decryptedDataLength)) {
            NABTO_LOG_TRACE(("Failed to read crypto payload in U_CONNECT"));
        } else {
            unabto_crypto_reinit_d(&con->cryptoctx, nmc.nabtoMainSetup.cryptoSuite, decryptedDataStart, decryptedDataLength);
        }
    } else
#endif
    {
        NABTO_LOG_TRACE(("########    U_CONNECT without crypto payload"));
        unabto_crypto_reinit_d(&con->cryptoctx, CRYPT_W_NULL_DATA, 0, 0);
    }


    con->timeOut = CONNECTION_TIMEOUT;
    nabtoSetFutureStamp(&con->stamp, 20000); /* give much extra time during initialisation */

    if (!verify_connection_encryption(con)) {
        goto init_crypto_error;
    }

    if (con->cpEqual) {
        NABTO_LOG_DEBUG((PRInsi " U_CONNECT: addr:" PRIep " rendezvous:%" PRIu8, MAKE_NSI_PRINTABLE(0, *nsi, 0), MAKE_EP_PRINTABLE(con->cp.privateEndpoint), !con->noRendezvous));
    } else {
        NABTO_LOG_DEBUG((PRInsi " U_CONNECT: private:" PRIep ", global:" PRIep " rendezvous:%" PRIu8, MAKE_NSI_PRINTABLE(0, *nsi, 0), MAKE_EP_PRINTABLE(con->cp.privateEndpoint), MAKE_EP_PRINTABLE(con->cp.globalEndpoint), !con->noRendezvous));
    }

    NABTO_LOG_INFO(("Connection opened from '%s' (to %s). Encryption code %i", con->clientId, nmc.nabtoMainSetup.id, con->cryptoctx.code));

    return con;

init_crypto_error:
    *ec = NOTIFY_ERROR_ENCR_MISMATCH;

#if NABTO_ENABLE_CONNECTION_ESTABLISHMENT_ACL_CHECK
init_error:
    nabto_release_connection(con);
#endif

    return 0;
}
Ejemplo n.º 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;
}