Added support for multicast presence
authorSashi Penta <sashi.kumar.penta@intel.com>
Mon, 10 Nov 2014 15:49:55 +0000 (07:49 -0800)
committerSashi Penta <sashi.kumar.penta@intel.com>
Wed, 12 Nov 2014 21:43:11 +0000 (13:43 -0800)
Added OCMulticastNode data structure to store the nonce information of the server send
presence notifications. When a new notification comes to the client, client checks if there
is a multicast node, and then checks to see if the nonce is same or not. If same nonce, no call
back to client application is made. If nonce is different a call to client application is made.

Signed-off-by: Sashi Penta <sashi.kumar.penta@intel.com>
Change-Id: Ia3fe163e7a304f499272f9ffa8a22a359f123d98

resource/csdk/occoap/src/occoap.c
resource/csdk/stack/include/internal/occlientcb.h
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/src/occlientcb.c
resource/examples/presenceclient.cpp

index 4081675..847e528 100644 (file)
@@ -323,6 +323,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     uint8_t isObserveNotification = 0;
     #ifdef WITH_PRESENCE
     uint8_t isPresenceNotification = 0;
+    uint8_t isMulticastPresence = 0;
     uint32_t lowerBound;
     uint32_t higherBound;
     char * tok = NULL;
@@ -381,10 +382,12 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     cbNode = GetClientCB(&rcvdToken, NULL, NULL);
+
+    #ifdef WITH_PRESENCE
+    // Check if the application subcribed for presence
     if(!cbNode)
     {
-        // we should check if we are monitoring the presence of this resource
-        //get the address of the remote
+        // get the address of the remote
         OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr,
                 remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
         OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu);
@@ -394,6 +397,15 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         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;
+    }
+    #endif
+
     // fill OCResponse structure
     result = FormOCResponse(&response, cbNode, maxAge, &clientResponse);
     VERIFY_SUCCESS(result, OC_STACK_OK);
@@ -476,6 +488,49 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     cbNode->sequenceNumber = clientResponse.sequenceNumber;;
                 }
             }
+            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(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;
+                    }
+                }
+            }
             #endif
         }
         HandleStackResponses(response);
@@ -495,7 +550,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     else if(!cbNode && isPresenceNotification)
     {
         OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
-                         ------------ ignoring"));
+                     ------------ ignoring"));
     }
     #endif
     else
index a202db8..0d47ead 100644 (file)
@@ -32,6 +32,14 @@ typedef struct OCPresence {
     uint32_t TTLlevel;
 }OCPresence;
 
+typedef struct OCMulticastNode {
+    unsigned char * uri;
+    uint32_t nonce;
+    struct OCMulticastNode * next;
+} OCMulticastNode;
+
+extern OCMulticastNode * mcPresenceNodes;
+
 typedef struct ClientCB {
     // callback method defined in application address space
     OCClientResponseHandler callBack;
@@ -137,4 +145,33 @@ void DeleteClientCBList();
 //------------------------------------------------------------------------
 void FindAndDeleteClientCB(ClientCB * cbNode);
 
+/** @ingroup ocstack
+ *
+ * This method is used to search a multicast presence node from list.
+ *
+ * @param[in]  uri
+ *              the uri of the request.
+ *
+ * @return OCMulticastNode
+ *              The resulting node from making this call. Null if doesn't exist.
+ */
+//------------------------------------------------------------------------
+OCMulticastNode* GetMCPresenceNode(unsigned char * uri);
+
+/** @ingroup ocstack
+ *
+ * This method is used to add a multicast presence node to the list.
+ *
+ * @param[out] outnode
+ *              The resulting node from making this call. Null if out of memory.
+ * @param[in] uri
+ *              the uri of the server.
+ * @param[in] nonce
+ *              current nonce for the server
+ *
+ * @return OC_STACK_OK for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+OCStackResult AddMCPresenceNode(OCMulticastNode** outnode, unsigned char* uri, uint32_t nonce);
+
 #endif //OC_CLIENT_CB
index f1a04fd..5fb0cc0 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
 #define OC_WELL_KNOWN_QUERY                  "coap://224.0.1.187:5683/oc/core"
 #define OC_EXPLICIT_DEVICE_DISCOVERY_URI     "coap://224.0.1.187:5683/oc/core?rt=core.led"
 #define OC_MULTICAST_PREFIX                  "coap://224.0.1.187:5683"
+#define OC_MULTICAST_IP                      "coap://224.0.1.187"
 
 #define USE_RANDOM_PORT (0)
 #ifdef WITH_PRESENCE
index 1475e12..6f97025 100644 (file)
@@ -30,6 +30,7 @@
 #define TAG PCF("occlientcb")
 
 struct ClientCB *cbList = NULL;
+OCMulticastNode * mcPresenceNodes = NULL;
 
 OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
         OCCoAPToken * token, OCDoHandle handle, OCMethod method,
@@ -135,3 +136,33 @@ void FindAndDeleteClientCB(ClientCB * cbNode) {
     }
 }
 
+OCStackResult AddMCPresenceNode(OCMulticastNode** outnode, unsigned char* uri, uint32_t nonce)
+{
+    OCMulticastNode *node;
+
+    node = (OCMulticastNode*) OCMalloc(sizeof(OCMulticastNode));
+
+    if (node) {
+        node->nonce = nonce;
+        node->uri = uri;
+        LL_APPEND(mcPresenceNodes, node);
+        *outnode = node;
+        return OC_STACK_OK;
+    }
+    *outnode = NULL;
+    return OC_STACK_NO_MEMORY;
+}
+
+OCMulticastNode* GetMCPresenceNode(unsigned char * uri) {
+    OCMulticastNode* out = NULL;
+
+    if(uri) {
+        LL_FOREACH(mcPresenceNodes, out) {
+            if(out->uri && strcmp((char *)out->uri, (char *)uri) == 0) {
+                return out;
+            }
+        }
+    }
+    OC_LOG(INFO, TAG, PCF("MulticastNode Not found !!"));
+    return NULL;
+}
index 8dfda11..9c6204f 100644 (file)
@@ -93,6 +93,7 @@ void foundResource(std::shared_ptr<OCResource> resource)
                 curResource = resource;
                 OCPlatform::OCPresenceHandle presenceHandle;
                 OCPlatform::subscribePresence(presenceHandle, hostAddress, &presenceHandler);
+                std::cout<< "subscribing for unicast presence... " <<std::endl;
             }
         }
         else
@@ -108,7 +109,38 @@ void foundResource(std::shared_ptr<OCResource> resource)
     }
 }
 
-int main(int argc, char* argv[]) {
+void PrintUsage()
+{
+    std::cout << std::endl;
+    std::cout << "Usage : presenceclient <isMulticastAddress>\n";
+    std::cout << "   0 - unicast subcribe presence\n";
+    std::cout << "   1 - multicast subscribe presence\n\n";
+}
+
+// 0 - unicast subcribe presence
+// 1 - multicast subscribe presence
+int isMulticastAddress = 0;
+
+int main(int argc, char* argv[1])
+{
+    PrintUsage();
+
+    if (argc == 1)
+    {
+        isMulticastAddress = 0;
+    }
+    else if (argc == 2)
+    {
+        int value = atoi(argv[1]);
+        if (value == 1)
+            isMulticastAddress = 1;
+        else
+            isMulticastAddress = 0;
+    }
+    else
+    {
+        return -1;
+    }
 
     // Create PlatformConfig object
     PlatformConfig cfg {
@@ -119,14 +151,23 @@ int main(int argc, char* argv[]) {
         OC::QualityOfService::LowQos
     };
 
-    OCPlatform::Configure(cfg);
-
     try
     {
-        std::cout << "Created Platform..."<<std::endl;
-        // Find all resources
-        OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
-        std::cout<< "Finding Resource... " <<std::endl;
+        OCPlatform::Configure(cfg);
+
+        if(isMulticastAddress)
+        {
+            OCPlatform::OCPresenceHandle presenceHandle;
+            OCPlatform::subscribePresence(presenceHandle, OC_MULTICAST_IP, presenceHandler);
+            std::cout<< "subscribing for multicast presence... " <<std::endl;
+        }
+        else
+        {
+            // Find all resources
+            OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
+            std::cout<< "Finding Resource... " <<std::endl;
+        }
+
         while(true)
         {
             // some operations