Ejemplo n.º 1
0
OCStackResult
AddClientCB (ClientCB** clientCB, OCCallbackData* cbData,
             CAToken_t token, uint8_t tokenLength,
             OCDoHandle *handle, OCMethod method,
             OCDevAddr *devAddr, char * requestUri,
             char * resourceTypeName, uint32_t ttl)
{
    if(!clientCB || !cbData || !handle || !requestUri || tokenLength > CA_MAX_TOKEN_LEN)
    {
        return OC_STACK_INVALID_PARAM;
    }

    ClientCB *cbNode = NULL;

    #ifdef WITH_PRESENCE
    if(method == OC_REST_PRESENCE)
    {   // Retrieve the presence callback structure for this specific requestUri.
        cbNode = GetClientCB(NULL, 0, NULL, requestUri);
    }
    #endif // WITH_PRESENCE

    if(!cbNode)// If it does not already exist, create new node.
    {
        cbNode = (ClientCB*) OICMalloc(sizeof(ClientCB));
        if(!cbNode)
        {
            *clientCB = NULL;
            goto exit;
        }
        else
        {
            OC_LOG(INFO, TAG, "Adding client callback with token");
            OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
            cbNode->callBack = cbData->cb;
            cbNode->context = cbData->context;
            cbNode->deleteCallback = cbData->cd;
            //Note: token memory is allocated in the caller OCDoResource
            //but freed in DeleteClientCB
            cbNode->token = token;
            cbNode->tokenLength = tokenLength;
            cbNode->handle = *handle;
            cbNode->method = method;
            cbNode->sequenceNumber = 0;
            #ifdef WITH_PRESENCE
            cbNode->presence = NULL;
            cbNode->filterResourceType = NULL;
            #endif // WITH_PRESENCE

            if (method == OC_REST_PRESENCE ||
                method == OC_REST_OBSERVE  ||
                method == OC_REST_OBSERVE_ALL)
            {
                cbNode->TTL = 0;
            }
            else
            {
                cbNode->TTL = ttl;
            }
            cbNode->requestUri = requestUri;    // I own it now
            cbNode->devAddr = devAddr;          // I own it now
            OC_LOG_V(INFO, TAG, "Added Callback for uri : %s", requestUri);
            LL_APPEND(cbList, cbNode);
            *clientCB = cbNode;
        }
    }
    else
    {
        // Ensure that the handle the SDK hands back up to the application layer for the
        // OCDoResource call matches the found ClientCB Node.
        *clientCB = cbNode;

        if (cbData->cd)
        {
            cbData->cd(cbData->context);
        }

        OICFree(token);
        OICFree(*handle);
        OICFree(requestUri);
        OICFree(devAddr);
        *handle = cbNode->handle;
    }

    #ifdef WITH_PRESENCE
    if(method == OC_REST_PRESENCE && resourceTypeName)
    {
        // Amend the found or created node by adding a new resourceType to it.
        return InsertResourceTypeFilter(cbNode,(char *)resourceTypeName);
        // I own resourceTypName now.
    }
    else
    {
        OICFree(resourceTypeName);
    }
    #else
    OICFree(resourceTypeName);
    #endif

    return OC_STACK_OK;

    exit:
        return OC_STACK_NO_MEMORY;
}
Ejemplo n.º 2
0
//This function is called back by libcoap when a response is received
static void HandleCoAPResponses(struct coap_context_t *ctx,
        const coap_queue_t * rcvdResponse) {
    OCResponse * response = NULL;
    OCCoAPToken rcvdToken;
    OCClientResponse clientResponse = {0};
    ClientCB * cbNode = NULL;
    unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
    uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
    uint32_t maxAge = 0;
    OCStackResult result = OC_STACK_ERROR;
    coap_pdu_t * sendPdu = NULL;
    coap_pdu_t * recvPdu = NULL;
    unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
    uint8_t isObserveNotification = 0;
    #ifdef WITH_PRESENCE
    char * resourceTypeName = NULL;
    uint8_t remoteIpAddr[4];
    uint16_t remotePortNu;
    unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
    uint8_t isPresenceNotification = 0;
    uint8_t isMulticastPresence = 0;
    uint32_t lowerBound;
    uint32_t higherBound;
    char * tok = NULL;
    #endif
    coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE};
    coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE};
    uint16_t rcvdSize2 = 0;

    VERIFY_NON_NULL(ctx);
    VERIFY_NON_NULL(rcvdResponse);
    recvPdu = rcvdResponse->pdu;

    result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge,
            &clientResponse.numRcvdVendorSpecificHeaderOptions,
            clientResponse.rcvdVendorSpecificHeaderOptions,
            &rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes);

    VERIFY_SUCCESS(result, OC_STACK_OK);

    OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u", sequenceNumber);
    OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", maxAge);
    OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);

    if(sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
    {
        isObserveNotification = 1;
        OC_LOG(INFO, TAG, PCF("Received an observe notification"));
    }

    #ifdef WITH_PRESENCE
    if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
        char* tokSavePtr;

        isPresenceNotification = 1;
        OC_LOG(INFO, TAG, PCF("Received a presence notification"));
        tok = strtok_r((char *)bufRes, "[:]}", &tokSavePtr);
        bufRes[strlen((char *)bufRes)] = ':';
        tok = strtok_r(NULL, "[:]}", &tokSavePtr);
        bufRes[strlen((char *)bufRes)] = ':';
        VERIFY_NON_NULL(tok);
        sequenceNumber = (uint32_t )atol(tok);
        OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
        tok = strtok_r(NULL, "[:]}", &tokSavePtr);
        VERIFY_NON_NULL(tok);
        maxAge = (uint32_t )atol(tok);
        OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
        tok = strtok_r(NULL, "[:]}", &tokSavePtr);
        if(tok) {
            bufRes[strlen((char *)bufRes)] = ':';
            resourceTypeName = (char *)OCMalloc(strlen(tok));
            if(!resourceTypeName)
            {
                goto exit;
            }
            strcpy(resourceTypeName, tok);
            OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
                    resourceTypeName);
        }
        bufRes[strlen((char *)bufRes)] = ']';
    }
    #endif

    // fill OCCoAPToken structure
    RetrieveOCCoAPToken(recvPdu, &rcvdToken);
    OC_LOG_V(INFO, TAG,"Received a pdu with Token", rcvdToken.tokenLength);
    OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);

    // fill OCClientResponse structure
    result = FormOCClientResponse(&clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code),
            (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, bufRes);
    VERIFY_SUCCESS(result, OC_STACK_OK);

    cbNode = GetClientCB(&rcvdToken, NULL, NULL);

    #ifdef WITH_PRESENCE
    // Check if the application subscribed for presence
    if(!cbNode)
    {
        // get the address of the remote
        OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr,
                remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
        OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu);
        snprintf((char *)fullUri, sizeof(fullUri), "coap://%d.%d.%d.%d:%d%s",
                remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
                remotePortNu,rcvdUri);
        cbNode = GetClientCB(NULL, NULL, fullUri);
    }

    // Check if application subscribed for multicast presence
    if(!cbNode)
    {
        snprintf((char *)fullUri, sizeof(fullUri), "%s%s", OC_MULTICAST_IP, rcvdUri);
        cbNode = GetClientCB(NULL, NULL, fullUri);
        isMulticastPresence = 1;
        isPresenceNotification = 0;
    }
    #endif

    // fill OCResponse structure
    result = FormOCResponse(&response, cbNode, maxAge, &clientResponse);
    VERIFY_SUCCESS(result, OC_STACK_OK);

    if(cbNode)
    {
        if(!isObserveNotification)
        {
            #ifdef WITH_PRESENCE
            if(!isPresenceNotification)
            {
            #endif
                OC_LOG(INFO, TAG, PCF("Received a regular response"));
                if(recvPdu->hdr->type == COAP_MESSAGE_CON)
                {
                    sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
                            recvPdu->hdr->id, NULL, NULL, NULL);
                    VERIFY_NON_NULL(sendPdu);
                    result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
                            sendPdu,
                            (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
                }
            #ifdef WITH_PRESENCE
            }
            #endif
        }
        if(isObserveNotification)
        {
            OC_LOG(INFO, TAG, PCF("Received an observe notification"));
            if(recvPdu->hdr->type == COAP_MESSAGE_CON)
            {
                sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
                        recvPdu->hdr->id, NULL, NULL, NULL);
                VERIFY_NON_NULL(sendPdu);
                result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
                        sendPdu,
                        (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
            }
            //TODO: check the standard for methods to detect wrap around condition
            if(cbNode->method == OC_REST_OBSERVE &&
                    (clientResponse.sequenceNumber <= cbNode->sequenceNumber ||
                            (clientResponse.sequenceNumber > cbNode->sequenceNumber &&
                                    clientResponse.sequenceNumber == (MAX_SEQUENCE_NUMBER))))
            {
                OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
                        Ignoring Incoming:%d  Against Current:%d.",
                        clientResponse.sequenceNumber, cbNode->sequenceNumber);
                goto exit;
            }
            if(clientResponse.sequenceNumber > cbNode->sequenceNumber){
                cbNode->sequenceNumber = clientResponse.sequenceNumber;
            }
        }
        else
        {
            #ifdef WITH_PRESENCE
            if(isPresenceNotification)