Moved all presence functionality into the stack layer from coap layer.
authorJoseph Morrow <joseph.l.morrow@intel.com>
Fri, 12 Dec 2014 23:04:50 +0000 (18:04 -0500)
committerJoseph Morrow <joseph.l.morrow@intel.com>
Fri, 12 Dec 2014 23:04:50 +0000 (18:04 -0500)
This task was initiated so that observe parameters can be polled from
whatever new(er) transport layer we decide to use in the future and then
specific presence parameters can be determined once we have those observe
parameters. This effectively causes all presence related work to be done
in the stack layer, while observe related parameters are transferred OTA
and presence parameters are simply extrapolated after the fact.

This changeset correlates to Rally User Story: US2195 "As an Iotivity
client and server developer, all presence related functionality in the
OCCoap layer is moved to the stack layer."

Change-Id: Ibb784946fe233e17834136ed96ebed3436372742
Signed-off-by: Joseph Morrow <joseph.l.morrow@intel.com>
resource/csdk/occoap/include/occoaphelper.h
resource/csdk/occoap/src/occoap.c
resource/csdk/occoap/src/occoaphelper.c
resource/csdk/stack/include/internal/occlientcb.h
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/src/occlientcb.c
resource/csdk/stack/src/ocstack.c
resource/include/StringConstants.h
resource/src/OCUtilities.cpp

index 7be3e30..7e5b60e 100644 (file)
@@ -82,8 +82,9 @@ OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf,
 void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken);
 
 // Internal function to create OCResponse struct at the client from a received coap pdu
-OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
-        uint8_t TTL, OCClientResponse * clientResponse);
+OCStackResult FormOCResponse(OCResponse * * responseLoc,  ClientCB * cbNode, uint32_t maxAge,
+        unsigned char * fullUri, unsigned char * rcvdUri, OCCoAPToken * rcvdToken,
+        OCClientResponse * clientResponse, unsigned char * bufRes);
 
 // Internal function to create OCClientResponse struct at the client from a received coap pdu
 OCStackResult FormOCClientResponse(OCClientResponse * clientResponse,
index cc9c95a..38f8c0b 100644 (file)
@@ -289,29 +289,19 @@ uint32_t GetTime(float afterSeconds)
 //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) {
+    OCStackResult result = OC_STACK_OK;
+    OCCoAPToken rcvdToken = {{0}};
     OCResponse * response = NULL;
-    OCCoAPToken rcvdToken;
-    OCClientResponse clientResponse = {0};
-    ClientCB * cbNode = NULL;
+    OCClientResponse * clientResponse = 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;
+    uint8_t remoteIpAddr[4] = {0};
+    uint16_t remotePortNu = 0;
+    uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
+    uint32_t maxAge = 0;
     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
+    unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
     coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE};
     coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE};
     uint16_t rcvdSize2 = 0;
@@ -320,53 +310,21 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     VERIFY_NON_NULL(rcvdResponse);
     recvPdu = rcvdResponse->pdu;
 
+    clientResponse = (OCClientResponse *) OCCalloc(1, sizeof(OCClientResponse));
+
     result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge,
-            &clientResponse.numRcvdVendorSpecificHeaderOptions,
-            clientResponse.rcvdVendorSpecificHeaderOptions,
+            &(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)){
-        isPresenceNotification = 1;
-        OC_LOG(INFO, TAG, PCF("Received a presence notification"));
-        tok = strtok((char *)bufRes, "[:]}");
-        bufRes[strlen((char *)bufRes)] = ':';
-        tok = strtok(NULL, "[:]}");
-        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(NULL, "[:]}");
-        VERIFY_NON_NULL(tok);
-        maxAge = (uint32_t )atol(tok);
-        OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
-        tok = strtok(NULL, "[:]}");
-        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
+    // 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, MAX_URI_LENGTH, "coap://%d.%d.%d.%d:%d%s",
+            remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
+            remotePortNu,rcvdUri);
 
     // fill OCCoAPToken structure
     RetrieveOCCoAPToken(recvPdu, &rcvdToken);
@@ -374,224 +332,20 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
 
     // fill OCClientResponse structure
-    result = FormOCClientResponse(&clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code),
-            (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, bufRes);
+    result = FormOCClientResponse(clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code),
+            (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, NULL);
     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);
-        sprintf((char *)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)
-    {
-        sprintf((char *)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);
+    result = FormOCResponse(&response, NULL, maxAge, fullUri, rcvdUri,
+            &rcvdToken, clientResponse, bufRes);
     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)
-            {
-                OC_LOG(INFO, TAG, PCF("Received a presence notification"));
-                if(!cbNode->presence)
-                {
-                    cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
-                    VERIFY_NON_NULL(cbNode->presence);
-                    cbNode->presence->timeOut = NULL;
-                    cbNode->presence->timeOut = (uint32_t *)
-                            OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
-                    if(!(cbNode->presence->timeOut)){
-                        OCFree(cbNode->presence);
-                        goto exit;
-                    }
-                }
-                if(maxAge == 0)
-                {
-                    OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
-                    response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
-                    if(cbNode->presence)
-                    {
-                        OCFree(cbNode->presence->timeOut);
-                        OCFree(cbNode->presence);
-                        cbNode->presence = NULL;
-                    }
-                }
-                else
-                {
-                    OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
-                    cbNode->presence->TTL = maxAge;
-                    for(int index = 0; index < PresenceTimeOutSize; index++)
-                    {
-                        lowerBound = GetTime(((float)(PresenceTimeOut[index])
-                                /(float)100)*(float)cbNode->presence->TTL);
-                        higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
-                                /(float)100)*(float)cbNode->presence->TTL);
-                        cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
-                        OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout  %d", lowerBound);
-                        OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
-                        OC_LOG_V(DEBUG, TAG, "----------------timeOut entry  %d", cbNode->presence->timeOut[index]);
-                    }
-                    cbNode->presence->TTLlevel = 0;
-                    OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
-                    if(cbNode->sequenceNumber == clientResponse.sequenceNumber)
-                    {
-                        OC_LOG(INFO, TAG, PCF("===============No presence change"));
-                        goto exit;
-                    }
-                    OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
-                    cbNode->sequenceNumber = clientResponse.sequenceNumber;;
-                }
-
-                // Ensure that a filter is actually applied.
-                if(resourceTypeName && response->cbNode->filterResourceType)
-                {
-                    if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
-                    {
-                        goto exit;
-                    }
-                }
-            }
-            else if(isMulticastPresence)
-            {
-                // Check if the same nonce for a given host
-                OCMulticastNode* mcNode = NULL;
-                unsigned char senderUri[MAX_URI_LENGTH] = { 0 };
-                sprintf((char *)senderUri, "%d.%d.%d.%d:%d",
-                    remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
-                    remotePortNu);
-                mcNode = GetMCPresenceNode(senderUri);
-
-                if(maxAge == 0)
-                {
-                    OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
-                    response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
-                    if(cbNode->presence)
-                    {
-                        OCFree(cbNode->presence->timeOut);
-                        OCFree(cbNode->presence);
-                        cbNode->presence = NULL;
-                    }
-                }
-                else if(mcNode != NULL)
-                {
-                    if(mcNode->nonce == clientResponse.sequenceNumber)
-                    {
-                        OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
-                        goto exit;
-                    }
-                    mcNode->nonce = clientResponse.sequenceNumber;
-                }
-                else
-                {
-                    uint32_t uriLen = strlen((char*)senderUri);
-                    unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
-                    if(uri)
-                    {
-                        memcpy(uri, senderUri, (uriLen + 1));
-                    }
-                    else
-                    {
-                        OC_LOG(INFO, TAG,
-                            PCF("===============No Memory for URI to store in the presence node"));
-                        goto exit;
-                    }
-                    result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
-                                                clientResponse.sequenceNumber);
-                    if(result == OC_STACK_NO_MEMORY)
-                    {
-                        OC_LOG(INFO, TAG,
-                            PCF("===============No Memory for Multicast Presence Node"));
-                        goto exit;
-                    }
-                }
-
-                // Ensure that a filter is actually applied.
-                if(resourceTypeName && response->cbNode->filterResourceType)
-                {
-                    if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
-                    {
-                        goto exit;
-                    }
-                }
-            }
-            #endif
-        }
-        HandleStackResponses(response);
-    }
-    else if(!cbNode && isObserveNotification)
+    result = HandleStackResponses(response);
+
+    if(result == OC_STACK_ERROR)
     {
-        OC_LOG(INFO, TAG, PCF("Received an observe notification, but I do not have callback \
-                 ------------ sending RESET"));
+        OC_LOG(INFO, TAG, PCF("Received a notification or response that is malformed or incorrect \
+                         ------------ sending RESET"));
         sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
                 recvPdu->hdr->id, NULL, NULL, NULL);
         VERIFY_NON_NULL(sendPdu);
@@ -599,27 +353,26 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                      (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
         VERIFY_SUCCESS(result, OC_STACK_OK);
     }
-    #ifdef WITH_PRESENCE
-    else if(!cbNode && isPresenceNotification)
+    else if(result == OC_STACK_NO_MEMORY)
     {
-        OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
-                     ------------ ignoring"));
+        OC_LOG(ERROR, TAG, PCF("Received a notification or response. While processing, local " \
+                "platform or memory pool ran out memory."));
     }
-    #endif
-    else
+
+    if(recvPdu->hdr->type == COAP_MESSAGE_CON)
     {
-        OC_LOG(INFO, TAG, PCF("Received a response, but I do not have callback. \
-                 ------------ sending RESET"));
-        sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
+        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));
+        result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
+                sendPdu,
+                (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
         VERIFY_SUCCESS(result, OC_STACK_OK);
     }
+
     exit:
-        OCFree(resourceTypeName);
         OCFree(response);
+        OCFree(clientResponse);
 }
 
 //=============================================================================
@@ -754,9 +507,6 @@ OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPTo
     // Decide method type
     switch (method) {
         case OC_REST_GET:
-        #ifdef WITH_PRESENCE
-        case OC_REST_PRESENCE:
-        #endif
             coapMethod = COAP_REQUEST_GET;
             break;
         case OC_REST_PUT:
@@ -876,15 +626,12 @@ OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response)
         OC_LOG(ERROR, TAG, PCF("A problem occurred in sending a pdu"));
         return OC_STACK_ERROR;
     }
-
     return OC_STACK_OK;
-
 exit:
     OC_LOG(ERROR, TAG, PCF("Error formatting server response"));
     return OC_STACK_ERROR;
 }
 
-
 /**
  * Stop the CoAP client or server processing
  *
index f1e9382..a6a7c36 100644 (file)
@@ -105,6 +105,19 @@ uint8_t OCToCoAPQoS(OCQualityOfService qos)
             break;
     }
 }
+
+OCQualityOfService CoAPToOCQoS(uint8_t qos)
+{
+    switch (qos)
+    {
+        case COAP_MESSAGE_CON:
+            return OC_HIGH_QOS;
+        case COAP_MESSAGE_NON:
+            return OC_LOW_QOS;
+        default:
+            return OC_NA_QOS;
+    }
+}
 // Convert CoAP code to OCStack code
 OCStackResult CoAPToOCResponseCode(uint8_t coapCode)
 {
@@ -336,8 +349,9 @@ void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken)
     }
 }
 
-OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
-        uint8_t TTL, OCClientResponse * clientResponse)
+OCStackResult FormOCResponse(OCResponse * * responseLoc,  ClientCB * cbNode, uint32_t maxAge,
+        unsigned char * fullUri, unsigned char * rcvdUri, OCCoAPToken * rcvdToken,
+        OCClientResponse * clientResponse, unsigned char * bufRes)
 {
     OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse));
     if (!response)
@@ -345,8 +359,12 @@ OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
         return OC_STACK_NO_MEMORY;
     }
     response->cbNode = cbNode;
-    response->TTL = TTL;
+    response->maxAge = maxAge;
+    response->fullUri = fullUri;
+    response->rcvdUri = rcvdUri;
+    response->rcvdToken = rcvdToken;
     response->clientResponse = clientResponse;
+    response->bufRes = bufRes;
 
     *responseLoc = response;
     return OC_STACK_OK;
@@ -652,7 +670,7 @@ OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * que
     {
         goto observation;
     }
-    result = FormOCResponse(&response, cbNode, 0, &clientResponse);
+    result = FormOCResponse(&response, cbNode, NULL, NULL, NULL, &token, &clientResponse, NULL);
     if(result != OC_STACK_OK)
     {
         goto observation;
index 67c58a9..5fc14d8 100644 (file)
@@ -126,7 +126,7 @@ void DeleteClientCB(ClientCB *cbNode);
  * @retval address of the node if found, otherwise NULL
  */
 //------------------------------------------------------------------------
-ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri);
+ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, const unsigned char * requestUri);
 
 
 /**
@@ -140,7 +140,9 @@ ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * re
  *      OC_STACK_ERROR with invalid parameters
  *      OC_STACK_NO_MEMORY when out of memory
  */
+#ifdef WITH_PRESENCE
 OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName);
+#endif // WITH_PRESENCE
 
 //-- DeleteClientCBList --------------------------------------------------
 /** @ingroup ocstack
@@ -174,7 +176,7 @@ void FindAndDeleteClientCB(ClientCB * cbNode);
  *              The resulting node from making this call. Null if doesn't exist.
  */
 //------------------------------------------------------------------------
-OCMulticastNode* GetMCPresenceNode(unsigned char * uri);
+OCMulticastNode* GetMCPresenceNode(const unsigned char * uri);
 
 /** @ingroup ocstack
  *
index 385a8fa..c45ee7e 100644 (file)
@@ -134,7 +134,15 @@ typedef struct {
     // handle is retrieved by comparing the token-handle pair in the PDU.
     ClientCB * cbNode;
     // This is how long this response is valid for (in seconds).
-    uint32_t TTL;
+    uint32_t maxAge;
+    // This is the Uri of the resource. (ex. "coap://192.168.1.1/a/led")
+    unsigned char * fullUri;
+    // This is the relative Uri of the resource. (ex. "/a/led")
+    unsigned char * rcvdUri;
+    // This is the received payload.
+    unsigned char * bufRes;
+    // This is the token received OTA.
+    OCCoAPToken * rcvdToken;
     // this structure will be passed to client
     OCClientResponse * clientResponse;
 } OCResponse;
@@ -147,11 +155,11 @@ typedef uint32_t ServerID;
 //-----------------------------------------------------------------------------
 OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status);
 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest);
-void HandleStackResponses(OCResponse * response);
-int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port);
+OCStackResult HandleStackResponses(OCResponse * response);
 #ifdef WITH_PRESENCE
 OCStackResult SendPresenceNotification(OCResourceType *resourceType);
-#endif
+#endif // WITH_PRESENCE
+int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port);
 
 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
                                             const char *resourceInterfaceName);
index 9e0b232..d55a37e 100644 (file)
@@ -129,7 +129,7 @@ void DeleteClientCB(ClientCB * cbNode) {
     }
 }
 
-ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri) {
+ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, const unsigned char * requestUri) {
     ClientCB* out = NULL;
     if(token) {
         LL_FOREACH(cbList, out) {
@@ -160,6 +160,7 @@ ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * re
     return NULL;
 }
 
+#ifdef WITH_PRESENCE
 OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName)
 {
     OCResourceType * newResourceType = NULL;
@@ -180,6 +181,7 @@ OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceT
     }
     return OC_STACK_ERROR;
 }
+#endif // WITH_PRESENCE
 
 void DeleteClientCBList() {
     ClientCB* out;
@@ -222,7 +224,7 @@ OCStackResult AddMCPresenceNode(OCMulticastNode** outnode, unsigned char* uri, u
     return OC_STACK_NO_MEMORY;
 }
 
-OCMulticastNode* GetMCPresenceNode(unsigned char * uri) {
+OCMulticastNode* GetMCPresenceNode(const unsigned char * uri) {
     OCMulticastNode* out = NULL;
 
     if(uri) {
index d9c32d1..d92ad08 100644 (file)
@@ -66,8 +66,12 @@ OCDeviceEntityHandler defaultDeviceHandler;
 // Macros
 //-----------------------------------------------------------------------------
 #define TAG  PCF("OCStack")
+#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
+            {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
              TAG, PCF(#arg " is NULL")); return (retVal); } }
+#define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
+    goto exit;} }
 
 //TODO: we should allow the server to define this
 #define MAX_OBSERVE_AGE (0x2FFFFUL)
@@ -237,23 +241,268 @@ OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
 }
 
 //This function will be called back by occoap layer when a response is received
-void HandleStackResponses(OCResponse * response)
+OCStackResult HandleStackResponses(OCResponse * response)
 {
-    OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
     OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
+    OCStackResult result = OC_STACK_OK;
+    OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
+    uint8_t isObserveNotification = 0;
+    ClientCB * cbNode = NULL;
+    #ifdef WITH_PRESENCE
+    uint8_t isPresenceNotification = 0;
+    uint8_t isMulticastPresence = 0;
+    char * resourceTypeName = NULL;
+    uint32_t lowerBound = 0;
+    uint32_t higherBound = 0;
+    char * tok = NULL;
+    unsigned char * bufRes = response->bufRes;
+    #endif // WITH_PRESENCE
+
+    cbNode = response->cbNode;
+    if(!cbNode)
+    {
+        cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
+    }
+
+    if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
+    {
+        isObserveNotification = 1;
+        OC_LOG(INFO, TAG, PCF("Received an observe notification"));
+    }
+
+    OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
+            response->clientResponse->sequenceNumber);
+    OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
+    OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
+
+#ifdef WITH_PRESENCE
+    if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
+        isPresenceNotification = 1;
+        if(!bufRes)
+        {
+            result = OC_STACK_INVALID_PARAM;
+            goto exit;
+        }
+        tok = strtok((char *)bufRes, "[:]}");
+        bufRes[strlen((char *)bufRes)] = ':';
+        tok = strtok(NULL, "[:]}");
+        bufRes[strlen((char *)bufRes)] = ':';
+        response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
+        OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
+        tok = strtok(NULL, "[:]}");
+        response->maxAge = (uint32_t )atoi(tok);
+        OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
+        tok = strtok(NULL, "[:]}");
+        if(tok)
+        {
+            resourceTypeName = (char *)OCMalloc(strlen(tok));
+            if(!resourceTypeName)
+            {
+                goto exit;
+            }
+            bufRes[strlen((char *)bufRes)] = ':';
+            strcpy(resourceTypeName, tok);
+            OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
+                    resourceTypeName);
+        }
+        bufRes[strlen((char *)bufRes)] = ']';
+    }
+
+    // Check if the application subcribed for presence
+    if(!cbNode)
+    {
+        cbNode = GetClientCB(NULL, NULL, response->fullUri);
+    }
+
+    // Check if application subscribed for multicast presence
+    if(!cbNode)
+    {
+        snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
+                OC_MULTICAST_IP, response->rcvdUri);
+        cbNode = GetClientCB(NULL, NULL, response->fullUri);
+        if(cbNode)
+        {
+            isMulticastPresence = 1;
+            isPresenceNotification = 0;
+        }
+    }
+
+    if(cbNode && isPresenceNotification)
+    {
+        OC_LOG(INFO, TAG, PCF("Received a presence notification"));
+        if(!cbNode->presence)
+        {
+            cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
+            VERIFY_NON_NULL_V(cbNode->presence);
+            cbNode->presence->timeOut = NULL;
+            cbNode->presence->timeOut = (uint32_t *)
+                    OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
+            if(!(cbNode->presence->timeOut)){
+                OCFree(cbNode->presence);
+                result = OC_STACK_NO_MEMORY;
+            }
+        }
+        if(response->maxAge == 0)
+        {
+            OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+            response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+            if(cbNode->presence)
+            {
+                OCFree(cbNode->presence->timeOut);
+                OCFree(cbNode->presence);
+                cbNode->presence = NULL;
+            }
+        }
+        else
+        {
+            OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
+            cbNode->presence->TTL = response->maxAge;
+            for(int index = 0; index < PresenceTimeOutSize; index++)
+            {
+                lowerBound = GetTime(((float)(PresenceTimeOut[index])
+                        /(float)100)*(float)cbNode->presence->TTL);
+                higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
+                        /(float)100)*(float)cbNode->presence->TTL);
+                cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
+                OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout  %d", lowerBound);
+                OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
+                OC_LOG_V(DEBUG, TAG, "----------------timeOut entry  %d",
+                        cbNode->presence->timeOut[index]);
+            }
+            cbNode->presence->TTLlevel = 0;
+            OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
+            if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
+            {
+                OC_LOG(INFO, TAG, PCF("===============No presence change"));
+                goto exit;
+            }
+            OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
+            cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
+        }
+
+        // Ensure that a filter is actually applied.
+        if(resourceTypeName && cbNode->filterResourceType)
+        {
+            if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+            {
+                goto exit;
+            }
+        }
+    }
+    else if(cbNode && isMulticastPresence)
+    {
+        // Check if the same nonce for a given host
+        OCMulticastNode* mcNode = NULL;
+        mcNode = GetMCPresenceNode(response->fullUri);
+
+        if(response->maxAge == 0)
+        {
+            OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+            response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+            if(cbNode->presence)
+            {
+                OCFree(cbNode->presence->timeOut);
+                OCFree(cbNode->presence);
+                cbNode->presence = NULL;
+            }
+        }
+        else if(mcNode != NULL)
+        {
+            if(mcNode->nonce == response->clientResponse->sequenceNumber)
+            {
+                OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+            mcNode->nonce = response->clientResponse->sequenceNumber;
+        }
+        else
+        {
+            uint32_t uriLen = strlen((char*)response->fullUri);
+            unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
+            if(uri)
+            {
+                memcpy(uri, response->fullUri, (uriLen + 1));
+            }
+            else
+            {
+                OC_LOG(INFO, TAG,
+                    PCF("===============No Memory for URI to store in the presence node"));
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+            result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
+                    response->clientResponse->sequenceNumber);
+            if(result == OC_STACK_NO_MEMORY)
+            {
+                OC_LOG(INFO, TAG,
+                    PCF("===============No Memory for Multicast Presence Node"));
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+        }
+
+        // Ensure that a filter is actually applied.
+        if(resourceTypeName && cbNode->filterResourceType)
+        {
+            if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+            {
+                goto exit;
+            }
+        }
+    }
+
+    else if(!cbNode && isPresenceNotification)
+    {
+    OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
+                 ------------ ignoring"));
+    }
+    #endif // WITH_PRESENCE
 
-    if (response->cbNode)
+    if(cbNode)
     {
-        OC_LOG(INFO, TAG, PCF("Calling into application address space"));
-        result = response->cbNode->callBack(response->cbNode->context,
-                response->cbNode->handle, response->clientResponse);
-        if (result == OC_STACK_DELETE_TRANSACTION ||
+        if(isObserveNotification)
+        {
+            OC_LOG(INFO, TAG, PCF("Received an observe notification"));
+            //TODO: check the standard for methods to detect wrap around condition
+            if(cbNode->method == OC_REST_OBSERVE &&
+                    (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
+                            (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
+                                    response->clientResponse->sequenceNumber ==
+                                            MAX_SEQUENCE_NUMBER)))
+            {
+                OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
+                        Ignoring Incoming:%d  Against Current:%d.",
+                        response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
+                goto exit;
+            }
+            if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
+                cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
+            }
+        }
+
+        response->clientResponse->resJSONPayload = bufRes;
+
+        cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
+
+        if (cbResult == OC_STACK_DELETE_TRANSACTION ||
                 response->clientResponse->result == OC_STACK_COMM_ERROR ||
-                response->clientResponse->result == OC_STACK_RESOURCE_DELETED)
+                (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
+                        !isPresenceNotification && !isMulticastPresence))
         {
-            FindAndDeleteClientCB(response->cbNode);
+            FindAndDeleteClientCB(cbNode);
         }
     }
+    else
+    {
+        result = OC_STACK_ERROR;
+    }
+
+    exit:
+    #ifdef WITH_PRESENCE
+    OCFree(resourceTypeName);
+    #endif
+    return result;
 }
 
 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
@@ -591,7 +840,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
         }
         else
         {
-            OC_LOG(DEBUG, TAG, "Got Resource Type is NULL.");
+            OC_LOG(DEBUG, TAG, PCF("Got Resource Type is NULL."));
         }
         if(result != OC_STACK_OK)
         {
@@ -629,6 +878,14 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
         goto exit;
     }
 
+#ifdef WITH_PRESENCE
+    if(method == OC_REST_PRESENCE)
+    {
+        // Replacing method type with GET because "presence" is a stack layer only implementation.
+        method = OC_REST_GET;
+    }
+#endif
+
     // Make call to OCCoAP layer
     result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
 
@@ -760,7 +1017,8 @@ OCStackResult OCProcessPresence()
                         {
                             goto exit;
                         }
-                        result = FormOCResponse(&response, cbNode, 0, &clientResponse);
+                        result = FormOCResponse(&response, cbNode, NULL, NULL, NULL,
+                                &cbNode->token, &clientResponse, NULL);
                         if(result != OC_STACK_OK)
                         {
                             goto exit;
@@ -1693,7 +1951,6 @@ void incrementSequenceNumber(OCResource * resPtr)
     return;
 }
 
-#ifdef WITH_PRESENCE
 /**
  * Notify Presence subscribers that a resource has been modified
  *
@@ -1702,6 +1959,7 @@ void incrementSequenceNumber(OCResource * resPtr)
  * @param qos          - Quality Of Service
  *
  */
+#ifdef WITH_PRESENCE
 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
 {
     OCResource *resPtr = NULL;
@@ -1725,8 +1983,7 @@ OCStackResult SendPresenceNotification(OCResourceType *resourceType)
     result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
     return result;
 }
-#endif
-
+#endif // WITH_PRESENCE
 /**
  * Notify observers that an observed value has changed.
  *
index b29fb0c..6e7a42a 100644 (file)
@@ -85,12 +85,17 @@ namespace OC
         static const std::string OBSV_NO_FOUND              = "Stack observer not found";
         static const std::string OBSV_NOT_ADDED             = "Stack observer not added";
         static const std::string OBSV_NOT_REMOVED           = "Stack observer not removed";
-        static const std::string STACK_RESOURCE_DELETED     = "The specified resource has been deleted";
+        static const std::string STACK_RESOURCE_DELETED     =
+                "The specified resource has been deleted";
         static const std::string PRESENCE_STOPPED           = "Stack presence stopped";
-        static const std::string PRESENCE_NOT_HANDLED       = "Stack presence should not be handled";
+        static const std::string PRESENCE_NOT_HANDLED       =
+                "Stack presence should not be handled";
+        static const std::string REQUEST_NOT_HANDLED        =
+                "Incoming Request should not be handled";
         static const std::string INVALID_OPTION             = "Invalid option";
         static const std::string GENERAL_FAULT              = "General Fault";
-        static const std::string MALFORMED_STACK_RESPONSE   = "Response from OC_STACK is malformed";
+        static const std::string MALFORMED_STACK_RESPONSE   =
+                "Response from OC_STACK is malformed";
         static const std::string VIRTUAL_DO_NOT_HANDLE      = "Virtual Do Not Handle";
         static const std::string PERSISTENT_BUFFER_REQUIRED = "Persistent response buffer required";
         static const std::string STACK_CONTINUE             = "Stack continue";
index c55d8f9..0ed64c2 100644 (file)
@@ -201,10 +201,10 @@ OCStackResult result_guard(const OCStackResult r)
     case OC_STACK_SLOW_RESOURCE:
     case OC_STACK_NO_OBSERVERS:
     case OC_STACK_OBSERVER_NOT_FOUND:
+    case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
 #ifdef WITH_PRESENCE
     case OC_STACK_PRESENCE_STOPPED:
 #endif
-
     break;
  }