RDServer publish parsing and managing resource
authorHabib Virji <habib.virji@samsung.com>
Tue, 11 Aug 2015 13:11:10 +0000 (14:11 +0100)
committerMadan Lanka <lanka.madan@samsung.com>
Tue, 18 Aug 2015 12:42:42 +0000 (12:42 +0000)
Payload sent by the RD Client parsing from cbor to the structure.

This also defines the structure used for handling publish resources.

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

index da219fe..df2b823 100644 (file)
 #ifndef _RESOURCE_DIRECTORY_PAYLOAD_H_
 #define _RESOURCE_DIRECTORY_PAYLOAD_H_
 
-#include "rd_types.h"
-
 #include <cbor.h>
 
-#include "octypes.h"
-#include "ocstack.h"
-#include "logger.h"
+#include "rd_types.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -82,6 +78,30 @@ OCRDPayload *OCRDPayloadCreate(OCRDPayloadType payloadType);
 OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor);
 
 /**
+ * Creates the links payload, which is then embedded inside OCRDPublishPayload.
+ *
+ * @param uri  The Web Link Address of the resource.
+ * @param rt   The resource type of the published resource.
+ * @param itf  The interface type of the published resource.
+ * @param linkPayload The address of the allocated memory or NULL in case if failed
+ *                    to allocate memory.
+ */
+void OCRDLinksPayloadCreate(const char *uri, const char *rt, const char *itf,
+        OCRDLinksPayload **linkPayload);
+
+/**
+ * Creates the links payload, which is then embedded inside OCRDPublishPayload.
+ *
+ * @param ttl  Time to live of the published resource..
+ * @param linkPayload  The link payload with uri, rt and itf.
+ *
+ * @return  Allocated memory of OCRDPublishPayload or NULL in case if failed
+ *          to allocate memory.
+ */
+OCRDPublishPayload *OCRDPublishPayloadCreate(const int ttl,
+        OCRDLinksPayload *linkPayload);
+
+/**
  * Free memory allocation of the RDPayload and its internal structure.
  *
  * @param payload Pointer to already allocated memory for OCRDPayload.
index 1c03479..31dfd14 100644 (file)
@@ -35,6 +35,9 @@ extern "C" {
 /** RD Discovery bias factor type. */
 #define OC_RSRVD_RD_DISCOVERY_SEL        "sel"
 
+/** To represent resource type with Publish RD.*/
+#define OC_RSRVD_RESOURCE_TYPE_RDPUBLISH "oic.wk.rdPub"
+
 /** Max ADDR SIZE */
 #define MAX_ADDR_STR_SIZE (40)
 
@@ -60,12 +63,45 @@ typedef struct
 } OCRDDiscoveryPayload;
 
 /**
+ * Structure holding RD Links Payload. It is a sub-structure used in
+ * OCRDPublishPayload.
+ */
+typedef struct OCRDLinksPayload
+{
+    /** Web Link Address of the resource. */
+    char *href;
+    /** Resource type of the resource. */
+    char *rt;
+    /** Interace type of the resource. */
+    char *itf;
+    /** Holding address of the next resource. */
+    struct OCRDLinksPayload *next;
+} OCRDLinksPayload;
+
+/**
+ * Structure holding RD Publish payload.
+ */
+typedef struct
+{
+    /** Device Name. */
+    OCDeviceInfo deviceName;
+    /** Device id. */
+    OCIdentity deviceId;
+    /** Time to keep holding resource.*/
+    uint32_t ttl;
+    /** List of resource information that will be stored at RD.*/
+    OCRDLinksPayload *links;
+} OCRDPublishPayload;
+
+/**
  * Enum values of multiple RD type payload.
  */
 typedef enum
 {
     /** Value pf the RD discovery payload. */
-    RD_PAYLOAD_TYPE_DISCOVERY
+    RD_PAYLOAD_TYPE_DISCOVERY,
+    /** Value of the RD publish payload. */
+    RD_PAYLOAD_TYPE_PUBLISH
 } OCRDPayloadType;
 
 /**
@@ -79,6 +115,8 @@ typedef struct
     OCRDPayloadType payloadType;
     /** Pointer to the discovery response payload.*/
     OCRDDiscoveryPayload *rdDiscovery;
+    /** Pointer to the publish payload.*/
+    OCRDPublishPayload *rdPublish;
 } OCRDPayload;
 
 #ifdef __cplusplus
index 441b192..23a5f81 100644 (file)
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 #include "rd_payload.h"
 
-#include <cbor.h>
-
 #include "oic_malloc.h"
 #include "oic_string.h"
 
-#ifdef WITH_RD
-#include "rd_payload.h"
-#endif
+#include "octypes.h"
+#include "ocstack.h"
+#include "logger.h"
 
 #define TAG PCF("OCRDPayload")
 
+#define CBOR_ROOT_ARRAY_LENGTH 2
+
+static void linksPayloadDestroy(OCRDLinksPayload *linkPayload)
+{
+    OCRDLinksPayload *links = linkPayload;
+
+    while (links)
+    {
+        OICFree(links->href);
+        OICFree(links->rt);
+        OICFree(links->itf);
+        OCRDLinksPayload *tmp = links;
+        links = links->next;
+        OICFree(tmp);
+    }
+
+}
+
 OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPayload, size_t *size)
 {
     if (!outPayload || !size)
@@ -47,14 +63,15 @@ OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPaylo
     *size = MAX_REQUEST_LENGTH;
 
     CborEncoder encoder;
-    cbor_encoder_init(&encoder, *outPayload, *size, 0);
+    int flags = 0;
+    cbor_encoder_init(&encoder, *outPayload, *size, flags);
 
     OC_LOG_V(DEBUG, TAG, "RD Payload : %d", rdPayload->base.type);
     OC_LOG_V(DEBUG, TAG, "RD Payload Type: %d", rdPayload->payloadType);
 
     CborEncoder rootArray;
     CborError cborEncoderResult;
-    cborEncoderResult = cbor_encoder_create_array(&encoder, &rootArray, 2);
+    cborEncoderResult = cbor_encoder_create_array(&encoder, &rootArray, CBOR_ROOT_ARRAY_LENGTH);
     if (CborNoError != cborEncoderResult)
     {
         OC_LOG_V(ERROR, TAG, "Failed creating cbor array.");
@@ -97,7 +114,7 @@ OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPaylo
         {
             cborEncoderResult = cbor_encode_text_string(&map,
                 OC_RSRVD_RD_DISCOVERY_SEL, sizeof(OC_RSRVD_RD_DISCOVERY_SEL) -1);
-            if (CborNoError !=  cborEncoderResult)
+            if (CborNoError != cborEncoderResult)
             {
                 OC_LOG_V(ERROR, TAG, "Failed setting discovery sel type.");
                 goto exit;
@@ -151,7 +168,12 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay
     CborValue *rdCBORPayload = (CborValue *)cborPayload;
     OCRDPayload *rdPayload = NULL;
 
-    if (cbor_value_is_map(rdCBORPayload))
+    if (!cbor_value_is_map(rdCBORPayload))
+    {
+        OC_LOG_V(ERROR, TAG, "RD CBOR Payload is not in map format.");
+        return OC_STACK_ERROR;
+    }
+    else
     {
         CborValue curVal;
         CborError cborFindResult;
@@ -172,7 +194,6 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay
                 OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_CONTENT_TYPE value in the payload.");
                 goto exit;
             }
-            OC_LOG_V(DEBUG, TAG, "RD Payload Type : %d ", payloadType);
         }
 
         rdPayload = OCRDPayloadCreate(payloadType);
@@ -201,7 +222,6 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay
                     goto exit;
                 }
             }
-            OC_LOG_V(DEBUG, TAG, "Bias Factor : %d ", biasFactor);
 
             rdPayload->rdDiscovery = OCRDDiscoveryPayloadCreate(biasFactor);
             if (!rdPayload->rdDiscovery)
@@ -209,19 +229,126 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay
                 goto no_memory;
             }
         }
+        else
+        {    // TTL
+            int ttl = 0;
+            cborFindResult = cbor_value_map_find_value(rdCBORPayload, OC_RSRVD_TTL, &curVal);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_TTL type in the payload.");
+                goto exit;
+            }
 
-        cborFindResult = cbor_value_advance(rdCBORPayload);
-        if (CborNoError != cborFindResult)
-        {
-            OC_LOG_V(ERROR, TAG, "Failed advancing the payload.");
-            goto exit;
-        }
+            cborFindResult = cbor_value_get_int(&curVal, &ttl);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_TTL value in the payload.");
+                goto exit;
+            }
+
+            // Link Array
+            CborValue linkArray;
+            cborFindResult = cbor_value_map_find_value(rdCBORPayload, OC_RSRVD_LINKS, &linkArray);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_LINKS type in the payload.");
+                goto exit;
+            }
+
+            CborValue linkVal;
+            cborFindResult = cbor_value_enter_container(&linkArray, &linkVal);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed entering linkArray container in the payload.");
+                goto exit;
+            }
+
+            OCRDLinksPayload *links = NULL;
+            while(cbor_value_is_map(&linkVal))
+            {
+                char *href = NULL;
+                char *itf = NULL;
+                char *rt = NULL;
+                size_t len;
+
+                cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_HREF, &curVal);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_HREF type in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_dup_text_string(&curVal, &href, &len, NULL);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_HREF value in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_INTERFACE, &curVal);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_INTERFACE type in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_dup_text_string(&curVal, &itf, &len, NULL);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_INTERFACE value in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_RESOURCE_TYPE type in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_dup_text_string(&curVal, &rt, &len, NULL);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_RESOURCE_TYPE value in the payload.");
+                    goto exit;
+                }
+
+                OCRDLinksPayloadCreate(href, itf, rt, &links);
+                if (!links)
+                {
+                    goto no_memory;
+                }
+
+                cborFindResult = cbor_value_advance(&linkVal);
+                if (CborNoError != cborFindResult)
+                {
+                        OC_LOG_V(ERROR, TAG, "Failed advancing the linkVal payload.");
+                        goto exit;
+                }
+            }
+            cborFindResult = cbor_value_advance(&linkArray);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed advancing the linkArray payload.");
+                goto exit;
+            }
+            rdPayload->rdPublish = OCRDPublishPayloadCreate(ttl, links);
+            if (!rdPayload->rdPublish)
+            {
+                goto no_memory;
+            }
 
+            OCRDPayloadLog(DEBUG, TAG, rdPayload);
+            cborFindResult = cbor_value_advance(rdCBORPayload);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed advancing the payload.");
+                goto exit;
+            }
+        }
         *outPayload = (OCPayload *)rdPayload;
     }
-
     return OC_STACK_OK;
-
 no_memory:
     OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
     OCRDPayloadDestroy(rdPayload);
@@ -247,10 +374,59 @@ OCRDPayload *OCRDPayloadCreate(OCRDPayloadType payloadType)
     return rdPayload;
 }
 
+void OCRDLinksPayloadCreate(const char *uri, const char *rt, const char *itf,
+        OCRDLinksPayload **linksPayload)
+{
+    OCRDLinksPayload *payload = OICCalloc(1, sizeof(OCRDLinksPayload));
+
+    if (!payload)
+    {
+        goto no_memory;
+    }
+
+    payload->href = OICStrdup(uri);
+    if (!payload->href)
+    {
+        goto no_memory;
+    }
+
+    payload->rt = OICStrdup(rt);
+    if (!payload->rt)
+    {
+        goto no_memory;
+    }
+
+    payload->itf = OICStrdup(itf);
+    if (!payload->itf)
+    {
+        goto no_memory;
+    }
+
+    payload->next = NULL;
+
+    if (*linksPayload == NULL)
+    {
+        *linksPayload = payload;
+    }
+    else
+    {
+        OCRDLinksPayload *temp = *linksPayload;
+        while (temp->next)
+        {
+            temp = temp->next;
+        }
+        temp->next = payload;
+    }
+    return;
+
+no_memory:
+    OC_LOG_V(ERROR, TAG, "Memory allocation failed.");
+    linksPayloadDestroy(payload);
+}
+
 OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor)
 {
-    OCRDDiscoveryPayload *discoveryPayload = (OCRDDiscoveryPayload *)
-        OICCalloc(1, sizeof(OCRDDiscoveryPayload));
+    OCRDDiscoveryPayload *discoveryPayload = OICCalloc(1, sizeof(OCRDDiscoveryPayload));
 
     if (!discoveryPayload)
     {
@@ -261,6 +437,29 @@ OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor)
     return discoveryPayload;
 }
 
+
+OCRDPublishPayload* OCRDPublishPayloadCreate(int ttl,
+        OCRDLinksPayload *linksPayload)
+{
+    OCRDPublishPayload *rdPublish = OICCalloc(1, sizeof(OCRDPublishPayload));
+
+    if (!rdPublish)
+    {
+        return NULL;
+    }
+
+    //TODO: Find way of device device id.
+    // rdPayload->rdPublish->id = (uint8_t *)OICCalloc(1, UUID_SIZE);
+    // memcpy(rdPayload->rdPublish->id, , UUID_SIZE);
+    //TODO: Find way of device device name.
+    // rdPayload->rdPublish->n = (char*)OICCalloc(1, strlen(name));
+    // memcpy(rdPayload->rdPublish->n, , strlen(name));
+    rdPublish->ttl = ttl; // TODO Expose API to allow user to set this value.
+    rdPublish->links = linksPayload;
+
+    return rdPublish;
+}
+
 void OCRDPayloadDestroy(OCRDPayload *payload)
 {
     if (!payload)
@@ -273,6 +472,21 @@ void OCRDPayloadDestroy(OCRDPayload *payload)
         OICFree(payload->rdDiscovery);
     }
 
+    if (payload->rdPublish)
+    {
+        if (payload->rdPublish->links)
+        {
+            linksPayloadDestroy(payload->rdPublish->links);
+        }
+
+        if (payload->rdPublish->deviceName.deviceName)
+        {
+            OICFree(payload->rdPublish->deviceName.deviceName);
+        }
+
+        OICFree(payload->rdPublish);
+    }
+
     OICFree(payload);
 }
 
@@ -290,4 +504,29 @@ void OCRDPayloadLog(LogLevel level, const char *tag, const OCRDPayload *payload)
     {
         OC_LOG_V(level, tag, "RD Payload Discovery BIAS : %d", payload->rdDiscovery->sel);
     }
+
+    if (payload->rdPublish)
+    {
+        if (payload->rdPublish->deviceName.deviceName)
+        {
+            OC_LOG_V(level, tag, "RD Payload Pulish Name : %s", payload->rdPublish->deviceName.deviceName);
+        }
+
+        if (payload->rdPublish->deviceId.id)
+        {
+            OC_LOG_V(level, tag, "RD Payload Publish ID : %s",  payload->rdPublish->deviceId.id);
+        }
+
+        OC_LOG_V(level, tag, "RD Payload Publish TTL : %d", payload->rdPublish->ttl);
+
+        if (payload->rdPublish->links)
+        {
+            for (OCRDLinksPayload *temp = payload->rdPublish->links; temp; temp = temp->next)
+            {
+                OC_LOG_V(level, tag, "RD Payload Publish Link RT : %s", temp->rt);
+                OC_LOG_V(level, tag, "RD Payload Publish Link ITF : %s", temp->itf);
+                OC_LOG_V(level, tag, "RD Payload Publish Link HREF : %s", temp->href);
+            }
+        }
+    }
 }
index c605bb8..72446f3 100644 (file)
 // This is temporary hardcoded value for bias factor.
 #define OC_RD_DISC_SEL 100
 
-static OCResourceHandle gRDHandle = NULL;
+static OCStackResult sendResponse(const OCEntityHandlerRequest *ehRequest, OCRDPayload *rdPayload)
+{
+    OCEntityHandlerResponse response = { 0 };
+    response.requestHandle = ehRequest->requestHandle;
+    response.resourceHandle = ehRequest->resource;
+    response.ehResult = OC_EH_OK;
+    response.payload = (OCPayload*)(&rdPayload);
+    response.payload->type = PAYLOAD_TYPE_RD;
+
+    return OCDoResponse(&response);
+}
 
 /**
  * This internal method handles RD discovery request.
  * Responds with the RD discovery payload message.
  */
-static OCEntityHandlerResult HandleRDGetRequest(const OCEntityHandlerRequest *ehRequest)
+static OCEntityHandlerResult handleGetRequest(const OCEntityHandlerRequest *ehRequest)
 {
     if (!ehRequest)
     {
@@ -60,13 +70,7 @@ static OCEntityHandlerResult HandleRDGetRequest(const OCEntityHandlerRequest *eh
 
     OCRDPayloadLog(DEBUG, TAG, rdPayload);
 
-    OCEntityHandlerResponse ehResponse = {};
-    ehResponse.requestHandle = ehRequest->requestHandle;
-    ehResponse.resourceHandle = ehRequest->resource;
-    ehResponse.payload = (OCPayload *)rdPayload;
-    ehResponse.ehResult = ehResult;
-
-    if (OCDoResponse(&ehResponse) != OC_STACK_OK)
+    if (sendResponse(ehRequest, rdPayload) != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "Sending response failed.");
         ehResult = OC_EH_ERROR;
@@ -77,6 +81,40 @@ static OCEntityHandlerResult HandleRDGetRequest(const OCEntityHandlerRequest *eh
     return ehResult;
 }
 
+/**
+ * This internal method handles RD publish request.
+ * Responds with the RD success message.
+ */
+static OCEntityHandlerResult handlePublishRequest(const OCEntityHandlerRequest *ehRequest)
+{
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+
+    OC_LOG_V(DEBUG, TAG, "Received OC_REST_PUT from client with query: %s.", ehRequest->query);
+
+    if (!ehRequest)
+    {
+        OC_LOG_V(DEBUG, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRDPayload *payload = (OCRDPayload*)ehRequest->payload;
+    if (payload->payloadType == RD_PAYLOAD_TYPE_PUBLISH)
+    {
+        // TODO STORE RESOURCE...
+    }
+
+    OC_LOG_V(DEBUG, TAG, "Sending success response");
+    OCRDPayload *rdPayload = OCRDPayloadCreate(RD_PAYLOAD_TYPE_PUBLISH);
+    if (sendResponse(ehRequest, rdPayload) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "Sending response failed.");
+        ehResult = OC_EH_ERROR;
+    }
+
+    OCRDPayloadDestroy(rdPayload);
+
+    return ehResult;
+}
 /*
  * This internal method is the entity handler for RD resources and
  * will handle REST request (GET/PUT/POST/DEL) for them.
@@ -98,9 +136,11 @@ static OCEntityHandlerResult RDEntityHandler(OCEntityHandlerFlag flag,
         {
             case OC_REST_GET:
             case OC_REST_DISCOVER:
-                HandleRDGetRequest(ehRequest);
+                handleGetRequest(ehRequest);
                 break;
             case OC_REST_POST:
+                handlePublishRequest(ehRequest);
+                break;
             case OC_REST_PUT:
             case OC_REST_DELETE:
             case OC_REST_OBSERVE:
@@ -121,10 +161,11 @@ static OCEntityHandlerResult RDEntityHandler(OCEntityHandlerFlag flag,
 OCStackResult OCRDStart()
 {
     OCStackResult result = OCInit(NULL, 0, OC_CLIENT_SERVER);
+    OCResourceHandle rdHandle = NULL;
 
     if (result == OC_STACK_OK)
     {
-        result = OCCreateResource(&gRDHandle,
+        result = OCCreateResource(&rdHandle,
                                   OC_RSRVD_RESOURCE_TYPE_RD,
                                   OC_RSRVD_INTERFACE_DEFAULT,
                                   OC_RSRVD_RD_URI,