RD Client publish functionality
authorHabib Virji <habib.virji@samsung.com>
Tue, 18 Aug 2015 13:39:09 +0000 (14:39 +0100)
committerMadan Lanka <lanka.madan@samsung.com>
Wed, 19 Aug 2015 11:12:44 +0000 (11:12 +0000)
Includes RD payload changes to support CBOR messages.

Change-Id: I74892b40fe676337e4b0e1c50363d16a88011710
Signed-off-by: Habib Virji <habib.virji@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2190
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Madan Lanka <lanka.madan@samsung.com>
service/resource-directory/include/rd_client.h
service/resource-directory/src/rd_client.c
service/resource-directory/src/rd_payload.c

index e6c1db3..9a1bb9a 100644 (file)
@@ -41,6 +41,18 @@ extern "C" {
  */
 OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor);
 
+/*
+* Publish resource on the RD.
+*
+* @param addr The IP address of the RD, it could be either retrieved via OCRDDiscover().
+* @param port The port of the RD.
+* @param num This denotes the number of registered resource handles being passed
+*            for the remaining arguments.
+*
+* @returns ::OC_STACK_OK when successful and OC_STACK_ERROR when query failed.
+*/
+OCStackResult OCRDPublish(char *addr, uint16_t port, int num, ...);
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index 630d88a..0077a95 100644 (file)
 // limitations under the License.
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <stdarg.h>
+
+#include "rd_client.h"
+
 #include "logger.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 
-#include "rd_client.h"
 #include "rd_payload.h"
 
 #define DEFAULT_CONTEXT_VALUE 0x99
+#define OC_RD_PUBLISH_TTL 86400
 
 #define TAG  PCF("RDClient")
 
-static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB clientCB)
+static OCStackResult sendRequest(OCMethod method, char *uri, OCDevAddr *addr,
+        OCPayload *payload, OCCallbackData cbData)
 {
-    OC_LOG_V(DEBUG, TAG, "\tAddress: %s : %d",  clientResponse->devAddr.addr,
-             clientResponse->devAddr.port);
+    OCDoHandle handle;
+    OCStackResult result;
+
+    result = OCDoResource(handle,
+        method,
+        uri,
+        addr,
+        payload,
+        CT_ADAPTER_IP,
+        OC_LOW_QOS,
+        &cbData,
+        NULL,
+        0);
 
-    OCRDPayload *payload = (OCRDPayload *) clientResponse->payload;
-    if (payload)
+    if (result == OC_STACK_OK)
+    {
+        OC_LOG_V(DEBUG, TAG, "Resource Directory send successful...");
+    }
+    else
     {
-        OC_LOG_V(DEBUG, TAG, "\tType: %d",  payload->base.type);
-        OC_LOG_V(DEBUG, TAG, "\tPayloadType: %d",  payload->payloadType);
-        OC_LOG_V(DEBUG, TAG, "\tBiasFactor: %d",  payload->rdDiscovery->sel);
+        OC_LOG_V(ERROR, TAG, "Resource Directory send failed...");
     }
+
+    return result;
+}
+
+static OCStackApplicationResult handlePublishCB(void *ctx,
+        OCDoHandle handle, OCClientResponse *clientResponse)
+{
+    OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
+    OC_LOG_V(DEBUG, TAG, "Successfully published resources.");
+
+    // TOOO: Stop multicast traffic on the client.
+
+    return ret;
+}
+
+static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB clientCB)
+{
+    OC_LOG_V(DEBUG, TAG, "\tAddress of the RD: %s : %d",  clientResponse->devAddr.addr,
+            clientResponse->devAddr.port);
+
+    OCRDPayload *payload = (OCRDPayload *) clientResponse->payload;
+    OCRDPayloadLog(DEBUG, TAG, payload);
+
     // TODO: Multiple Resource Directory will have different biasFactor,
     // needs to cache here detail
     // and after certain timeout then decide based on the biasFactor.
@@ -47,13 +88,13 @@ static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB
 
 }
 
-static OCStackApplicationResult discoverRDCB(void *ctx,
+static OCStackApplicationResult handleDiscoverCB(void *ctx,
         OCDoHandle handle, OCClientResponse *clientResponse)
 {
     OC_LOG(DEBUG, TAG, "Found Resource Directory");
     OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
 
-    OCRDClientContextCB *cb = (OCRDClientContextCB*) ctx;
+    OCRDClientContextCB *cb = (OCRDClientContextCB *) ctx;
     if (!cb)
     {
         OC_LOG(ERROR, TAG, "RD Context Invalid Parameters.");
@@ -82,10 +123,6 @@ static OCStackApplicationResult discoverRDCB(void *ctx,
 
 OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor)
 {
-    OCStackResult result = OC_STACK_ERROR;
-    OCCallbackData cbData;
-    OCDoHandle handle;
-
     if (!cbBiasFactor)
     {
         OC_LOG(DEBUG, TAG, "No callback function specified.");
@@ -102,29 +139,72 @@ OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor)
     cbContext.context = (void *)DEFAULT_CONTEXT_VALUE;
     cbContext.cbFunc = cbBiasFactor;
 
-    cbData.cb = discoverRDCB;
+    OCCallbackData cbData;
+    cbData.cb = handleDiscoverCB;
     cbData.context = (void *)(&cbContext);
     cbData.cd = NULL;
 
-    result = OCDoResource(&handle,
-                          OC_REST_DISCOVER,
-                          queryUri,
-                          0,
-                          0,
-                          CT_ADAPTER_IP,
-                          OC_LOW_QOS,
-                          &cbData,
-                          NULL,
-                          0);
+    return sendRequest(OC_REST_DISCOVER, queryUri, NULL, NULL, cbData);
+}
 
-    if (result == OC_STACK_OK)
+OCStackResult OCRDPublish(char *addr, uint16_t port, int numArg, ... )
+{
+    if (!addr)
     {
-        OC_LOG_V(DEBUG, TAG, "Resource Directory finding query send successful...");
+        OC_LOG_V(ERROR, TAG, "RD address not specified.");
+        return OC_STACK_INVALID_PARAM;
     }
-    else
+
+    char targetUri[MAX_URI_LENGTH];
+    snprintf(targetUri, MAX_URI_LENGTH, "coap://%s:%d%s?rt=%s", addr, port,
+            OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
+    OC_LOG_V(DEBUG, TAG, "Target URI : %s", targetUri);
+
+    // Gather all resources locally and do publish
+    OCCallbackData cbData = { 0 };
+    cbData.cb = &handlePublishCB;
+    cbData.cd = NULL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+
+    OCRDLinksPayload* linksPayload = NULL;
+
+    va_list arguments;
+    va_start (arguments, numArg);
+
+    for (int j = 0 ; j < numArg; j++)
     {
-        OC_LOG_V(ERROR, TAG, "Resource Directory finding query send failed...");
+        OCResourceHandle handle = va_arg(arguments, OCResourceHandle);
+        if (handle)
+        {
+            const char* uri = OCGetResourceUri(handle);
+            const char* rt  = OCGetResourceTypeName(handle, 0);
+            const char* itf = OCGetResourceInterfaceName(handle, 0);
+            if (uri && rt && itf)
+            {
+                OCRDLinksPayloadCreate(uri, rt, itf, &linksPayload);
+            }
+        }
     }
+    va_end(arguments);
 
-    return result;
+    OCRDPayload *rdPayload = OCRDPayloadCreate(RD_PAYLOAD_TYPE_PUBLISH);
+    if (!rdPayload)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+        return OC_STACK_NO_MEMORY;
+    }
+    rdPayload->rdPublish = OCRDPublishPayloadCreate(OC_RD_PUBLISH_TTL, linksPayload);
+    if (!rdPayload->rdPublish)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OCDevAddr rdAddr = { 0 };
+    OICStrcpy(rdAddr.addr, MAX_ADDR_STR_SIZE, addr);
+    rdAddr.port = port;
+
+    OCRDPayloadLog(DEBUG, TAG, rdPayload);
+
+    return sendRequest(OC_REST_POST, targetUri, &rdAddr, (OCPayload *)rdPayload, cbData);
 }
index 9ec372a..cb05de7 100644 (file)
@@ -29,6 +29,7 @@
 #define TAG PCF("OCRDPayload")
 
 #define CBOR_ROOT_ARRAY_LENGTH 2
+#define CBOR_LINK_ARRAY_LENGTH 3
 
 static void linksPayloadDestroy(OCRDLinksPayload *linkPayload)
 {
@@ -126,12 +127,125 @@ OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPaylo
             }
             OC_LOG_V(DEBUG, TAG, "RD Payload bias factor: %d", rdPayload->rdDiscovery->sel);
         }
+        else
+        {
+            OC_LOG_V(ERROR, TAG, "Missing sel parameter in the discovery payload.");
+            goto exit;
+        }
+    }
+    else if (rdPayload->payloadType == RD_PAYLOAD_TYPE_PUBLISH)
+    {
+        cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_TTL, sizeof(OC_RSRVD_TTL) - 1);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed setting publish ttl type.");
+            goto exit;
+        }
+
+        cborEncoderResult = cbor_encode_uint(&map, rdPayload->rdPublish->ttl);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed setting publish ttl value.");
+            goto exit;
+        }
+
+        CborEncoder linksArray;
+        cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_LINKS, sizeof(OC_RSRVD_LINKS) - 1);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed setting publish links type.");
+            goto exit;
+        }
+
+        cborEncoderResult = cbor_encoder_create_array(&map, &linksArray, CborIndefiniteLength);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed setting publish links array.");
+            goto exit;
+        }
+
+        {
+            OCRDLinksPayload *rtPtr = rdPayload->rdPublish->links;
+            while(rtPtr)
+            {
+                CborEncoder linksMap;
+                cborEncoderResult = cbor_encoder_create_map(&linksArray, &linksMap, CBOR_LINK_ARRAY_LENGTH);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish map.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_HREF,
+                        sizeof(OC_RSRVD_HREF) - 1);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish href type.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->href,
+                        strlen(rtPtr->href));
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish href value.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_INTERFACE,
+                        sizeof(OC_RSRVD_INTERFACE) - 1);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish itf type.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->itf,
+                        strlen(rtPtr->itf));
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish itf value.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_RESOURCE_TYPE,
+                        sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish rt type.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->rt,
+                        strlen(rtPtr->rt));
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish rt value.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encoder_close_container(&linksArray, &linksMap);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed closing linksMap publish map.");
+                    goto exit;
+                }
+
+                rtPtr = rtPtr->next;
+            }
+        }
+        cborEncoderResult = cbor_encoder_close_container(&map, &linksArray);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed closing linksArray container.");
+            goto exit;
+        }
     }
 
     cborEncoderResult = cbor_encoder_close_container(&rootArray, &map);
     if (CborNoError != cborEncoderResult)
     {
-        OC_LOG_V(ERROR, TAG, "Failed closing rootArray container.");
+        OC_LOG_V(ERROR, TAG, "Failed closing map container.");
         goto exit;
     }