Fixes for build errors hit by some versions of Visual Studio
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocpayload.c
old mode 100755 (executable)
new mode 100644 (file)
index 5486e9b..80e9e06
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+// Required for strok_r
+#define _POSIX_C_SOURCE 200112L
 
+#include "iotivity_config.h"
+#include <stdio.h>
 #include "ocpayload.h"
 #include "octypes.h"
 #include <string.h>
@@ -30,6 +34,7 @@
 #include "rdpayload.h"
 
 #define TAG "OIC_RI_PAYLOAD"
+#define CSV_SEPARATOR ','
 
 static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val);
 
@@ -60,9 +65,11 @@ void OCPayloadDestroy(OCPayload* payload)
         case PAYLOAD_TYPE_SECURITY:
             OCSecurityPayloadDestroy((OCSecurityPayload*)payload);
             break;
+#if defined(RD_CLIENT) || defined(RD_SERVER)
         case PAYLOAD_TYPE_RD:
            OCRDPayloadDestroy((OCRDPayload*)payload);
            break;
+#endif
         default:
             OIC_LOG_V(ERROR, TAG, "Unsupported payload type in destroy: %d", payload->type);
             OICFree(payload);
@@ -131,18 +138,22 @@ static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue*
     {
         case OCREP_PROP_INT:
             dest->arr.iArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
+            VERIFY_PARAM_NON_NULL(TAG, dest->arr.iArray, "Failed allocating memory");
             memcpy(dest->arr.iArray, source->arr.iArray, dimTotal * sizeof(int64_t));
             break;
         case OCREP_PROP_DOUBLE:
             dest->arr.dArray = (double*)OICMalloc(dimTotal * sizeof(double));
+            VERIFY_PARAM_NON_NULL(TAG, dest->arr.dArray, "Failed allocating memory");
             memcpy(dest->arr.dArray, source->arr.dArray, dimTotal * sizeof(double));
             break;
         case OCREP_PROP_BOOL:
             dest->arr.bArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
+            VERIFY_PARAM_NON_NULL(TAG, dest->arr.bArray, "Failed allocating memory");
             memcpy(dest->arr.bArray, source->arr.bArray, dimTotal * sizeof(bool));
             break;
         case OCREP_PROP_STRING:
             dest->arr.strArray = (char**)OICMalloc(dimTotal * sizeof(char*));
+            VERIFY_PARAM_NON_NULL(TAG, dest->arr.strArray, "Failed allocating memory");
             for(size_t i = 0; i < dimTotal; ++i)
             {
                 dest->arr.strArray[i] = OICStrdup(source->arr.strArray[i]);
@@ -150,6 +161,7 @@ static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue*
             break;
         case OCREP_PROP_OBJECT:
             dest->arr.objArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
+            VERIFY_PARAM_NON_NULL(TAG, dest->arr.objArray, "Failed allocating memory");
             for(size_t i = 0; i < dimTotal; ++i)
             {
                 dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
@@ -157,6 +169,7 @@ static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue*
             break;
         case OCREP_PROP_ARRAY:
             dest->arr.objArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
+            VERIFY_PARAM_NON_NULL(TAG, dest->arr.objArray, "Failed allocating memory");
             for(size_t i = 0; i < dimTotal; ++i)
             {
                 dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
@@ -166,6 +179,8 @@ static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue*
             OIC_LOG(ERROR, TAG, "CopyPropertyValueArray invalid type");
             break;
     }
+exit:
+    return;
 }
 
 static void OCCopyPropertyValue (OCRepPayloadValue *dest, OCRepPayloadValue *source)
@@ -180,6 +195,12 @@ static void OCCopyPropertyValue (OCRepPayloadValue *dest, OCRepPayloadValue *sou
         case OCREP_PROP_STRING:
             dest->str = OICStrdup(source->str);
             break;
+        case OCREP_PROP_BYTE_STRING:
+            dest->ocByteStr.bytes = (uint8_t*)OICMalloc(source->ocByteStr.len * sizeof(uint8_t));
+            VERIFY_PARAM_NON_NULL(TAG, dest->ocByteStr.bytes, "Failed allocating memory");
+            dest->ocByteStr.len = source->ocByteStr.len;
+            memcpy(dest->ocByteStr.bytes, source->ocByteStr.bytes, dest->ocByteStr.len);
+            break;
         case OCREP_PROP_OBJECT:
             dest->obj = OCRepPayloadClone(source->obj);
             break;
@@ -190,6 +211,8 @@ static void OCCopyPropertyValue (OCRepPayloadValue *dest, OCRepPayloadValue *sou
             // Nothing to do for the trivially copyable types.
             break;
     }
+exit:
+    return;
 }
 
 static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val)
@@ -408,14 +431,14 @@ bool OCRepPayloadAddResourceTypeAsOwner(OCRepPayload* payload, char* resourceTyp
     }
 }
 
-bool OCRepPayloadAddInterface(OCRepPayload* payload, const char* interface)
+bool OCRepPayloadAddInterface(OCRepPayload* payload, const char* iface)
 {
-    return OCRepPayloadAddInterfaceAsOwner(payload, OICStrdup(interface));
+    return OCRepPayloadAddInterfaceAsOwner(payload, OICStrdup(iface));
 }
 
-bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* interface)
+bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* iface)
 {
-    if (!payload || !interface)
+    if (!payload || !iface)
     {
         return false;
     }
@@ -433,7 +456,7 @@ bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* interface)
         {
             return false;
         }
-        cur->next->value = interface;
+        cur->next->value = iface;
         return true;
     }
     else
@@ -443,7 +466,7 @@ bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* interface)
         {
             return false;
         }
-        payload->interfaces->value = interface;
+        payload->interfaces->value = iface;
         return true;
     }
 }
@@ -465,7 +488,7 @@ bool OCRepPayloadIsNull(const OCRepPayload* payload, const char* name)
 
     if (!val)
     {
-        return false;
+        return true;
     }
 
     return val->type == OCREP_PROP_NULL;
@@ -543,13 +566,21 @@ bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, do
 {
     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
 
-    if (!val || val->type != OCREP_PROP_DOUBLE)
+    if (val)
     {
-        return false;
+        if (val->type == OCREP_PROP_DOUBLE)
+        {
+            *value = val->d;
+            return true;
+        }
+        else if (val->type == OCREP_PROP_INT)
+        {
+            *value = val->i;
+            return true;
+        }
     }
 
-    *value = val->d;
-    return true;
+    return false;
 }
 
 bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value)
@@ -725,7 +756,7 @@ bool OCRepPayloadSetByteStringArray(OCRepPayload* payload, const char* name,
 {
     if (!array)
     {
-        return NULL;
+        return false;
     }
 
     size_t dimTotal = calcDimTotal(dimensions);
@@ -937,7 +968,8 @@ bool OCRepPayloadGetDoubleArray(const OCRepPayload* payload, const char* name,
 {
     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
 
-    if (!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_DOUBLE
+    if (!val || val->type != OCREP_PROP_ARRAY ||
+        (val->arr.type != OCREP_PROP_DOUBLE && val->arr.type != OCREP_PROP_INT)
             || !val->arr.dArray)
     {
         return false;
@@ -954,7 +986,19 @@ bool OCRepPayloadGetDoubleArray(const OCRepPayload* payload, const char* name,
         return false;
     }
 
-    memcpy(*array, val->arr.dArray, dimTotal * sizeof(double));
+    if (val->arr.type == OCREP_PROP_DOUBLE)
+    {
+        memcpy(*array, val->arr.dArray, dimTotal * sizeof(double));
+    }
+    else
+    {
+        /* need to convert from integer */
+        size_t n = 0;
+        for ( ; n < dimTotal; ++n)
+        {
+            (*array)[n] = val->arr.iArray[n];
+        }
+    }
     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
     return true;
 }
@@ -1244,6 +1288,99 @@ OCStringLL* CloneOCStringLL (OCStringLL* ll)
     return headOfClone;
 }
 
+OCStringLL* OCCreateOCStringLL(const char* text)
+{
+    char *token = NULL;
+    char *head = NULL;
+    char *tail = NULL;
+    char *backup  = NULL;
+    OCStringLL* result = NULL;
+    OCStringLL* iter = NULL;
+    OCStringLL* prev = NULL;
+    static const char delim[] = { CSV_SEPARATOR, '\0' };
+
+    VERIFY_PARAM_NON_NULL(TAG, text, "Invalid parameter");
+    backup = OICStrdup(text);
+    VERIFY_PARAM_NON_NULL(TAG, backup, "Failed allocating memory");
+
+    for (head = backup; ; head = NULL)
+    {
+        token = (char *) strtok_r(head, delim, &tail);
+        if (!token) break;
+        iter = (OCStringLL *)OICCalloc(1,sizeof(OCStringLL));
+        VERIFY_PARAM_NON_NULL(TAG, iter, "Failed allocating memory");
+        if (!result)
+        {
+             result = iter;
+        }
+        else
+        {
+             prev->next = iter;
+        }
+        iter->value = OICStrdup(token);
+        VERIFY_PARAM_NON_NULL(TAG, iter->value, "Failed allocating memory");
+        prev = iter;
+        iter = iter->next;
+    }
+    OICFree(backup);
+    return result;
+
+exit:
+    OICFree(backup);
+    OCFreeOCStringLL(result);
+    return NULL;
+}
+
+char* OCCreateString(const OCStringLL* ll)
+{
+    if (!ll)
+    {
+        return NULL;
+    }
+
+    char *str = NULL;
+    char *pos = NULL;
+    size_t len = 0;
+    size_t sublen = 0;
+    int count = 0;
+
+    for (const OCStringLL *it = ll; it; it = it->next)
+    {
+        len += strlen(it->value) + 1;
+    }
+    len--; // renove trailing separator (just added above)
+    str = (char*) malloc(len + 1);
+    if (!str)
+    {
+        return NULL;
+    }
+
+    pos = str;
+    const OCStringLL *it = ll;
+    while (it)
+    {
+        sublen = strlen(it->value);
+        count = snprintf(pos, len + 1, "%s", it->value);
+        if ((size_t)count < sublen)
+        {
+            free(str);
+            return NULL;
+        }
+        len -= sublen;
+        pos += count;
+
+        it = it->next;
+        if (it)
+        {
+            *pos = CSV_SEPARATOR;
+            len--;
+            *(++pos) = '\0';
+       }
+    }
+
+    return str;
+}
+
 OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
 {
     if (!payload)
@@ -1296,7 +1433,7 @@ OCDiscoveryPayload* OCDiscoveryPayloadCreate()
     return payload;
 }
 
-OCSecurityPayload* OCSecurityPayloadCreate(const char* securityData)
+OCSecurityPayload* OCSecurityPayloadCreate(const uint8_t* securityData, size_t size)
 {
     OCSecurityPayload* payload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
 
@@ -1306,7 +1443,14 @@ OCSecurityPayload* OCSecurityPayloadCreate(const char* securityData)
     }
 
     payload->base.type = PAYLOAD_TYPE_SECURITY;
-    payload->securityData = OICStrdup(securityData);
+    payload->securityData = (uint8_t *)OICCalloc(1, size);
+    if (!payload->securityData)
+    {
+        OICFree(payload);
+        return NULL;
+    }
+    memcpy(payload->securityData, (uint8_t *)securityData, size);
+    payload->payloadSize = size;
 
     return payload;
 }
@@ -1350,7 +1494,12 @@ OCResourcePayload* OCDiscoveryPayloadGetResource(OCDiscoveryPayload* payload, si
     return NULL;
 }
 
-static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
+#ifndef TCP_ADAPTER
+static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t securePort)
+#else
+static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t securePort,
+                                         uint16_t tcpPort)
+#endif
 {
     OCResourcePayload* pl = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
     if (!pl)
@@ -1443,18 +1592,32 @@ static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
         }
     }
 
-    pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE);
+    pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE
+#ifdef MQ_PUBLISHER
+                                            | OC_MQ_PUBLISHER
+#endif
+                                            );
     pl->secure = (res->resourceProperties & OC_SECURE) != 0;
-    pl->port = port;
-
+    pl->port = securePort;
+#ifdef TCP_ADAPTER
+    pl->tcpPort = tcpPort;
+#endif
     return pl;
 }
 
+#ifndef TCP_ADAPTER
+void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
+                                   uint16_t securePort)
+{
+    OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, securePort));
+}
+#else
 void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
-        uint16_t port)
+                                   uint16_t securePort, uint16_t tcpPort)
 {
-    OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, port));
+    OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, securePort, tcpPort));
 }
+#endif
 
 bool OCResourcePayloadAddStringLL(OCStringLL **stringLL, const char *value)
 {
@@ -1465,7 +1628,7 @@ bool OCResourcePayloadAddStringLL(OCStringLL **stringLL, const char *value)
     if (!*stringLL)
     {
         *stringLL = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
-        VERIFY_PARAM_NON_NULL(TAG, dup, "Failed allocating memory");
+        VERIFY_PARAM_NON_NULL(TAG, *stringLL, "Failed allocating memory");
         (*stringLL)->value = dup;
         return true;
     }
@@ -1531,10 +1694,11 @@ void OCDiscoveryPayloadDestroy(OCDiscoveryPayload* payload)
     OICFree(payload->sid);
     OICFree(payload->baseURI);
     OICFree(payload->uri);
-    OICFree(payload->type);
+    OCFreeOCStringLL(payload->type);
     OICFree(payload->name);
-    OCFreeOCStringLL(payload->interface);
+    OCFreeOCStringLL(payload->iface);
     OCDiscoveryResourceDestroy(payload->resources);
+    OCDiscoveryPayloadDestroy(payload->next);
     OICFree(payload);
 }
 
@@ -1568,8 +1732,8 @@ OCDevicePayload* OCDevicePayloadCreate(const char* sid, const char* dname,
         goto exit;
     }
 
-    payload->dataModelVersion = OICStrdup(dmVer);
-    if (dmVer && !payload->dataModelVersion)
+    payload->dataModelVersions = OCCreateOCStringLL(dmVer);
+    if (!payload->dataModelVersions || (dmVer && !payload->dataModelVersions->value))
     {
         goto exit;
     }
@@ -1600,7 +1764,7 @@ void OCDevicePayloadDestroy(OCDevicePayload* payload)
     OICFree(payload->sid);
     OICFree(payload->deviceName);
     OICFree(payload->specVersion);
-    OICFree(payload->dataModelVersion);
+    OCFreeOCStringLL(payload->dataModelVersions);
     OCFreeOCStringLL(payload->types);
     OCFreeOCStringLL(payload->interfaces);
     OICFree(payload);
@@ -1642,7 +1806,12 @@ OCPlatformPayload* OCPlatformPayloadCreateAsOwner(OCPlatformInfo* platformInfo)
         return NULL;
     }
     payload->interfaces->value = OICStrdup(OC_RSRVD_INTERFACE_READ);
-    payload->rt = OICStrdup(OC_RSRVD_RESOURCE_TYPE_PLATFORM);
+    payload->rt = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+    if (!payload->rt)
+    {
+        return NULL;
+    }
+    payload->rt->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_PLATFORM);
     payload->info = *platformInfo;
 
     return payload;
@@ -1658,7 +1827,7 @@ OCPlatformPayload* OCPlatformPayloadCreate(const OCPlatformInfo* platformInfo)
     }
 
     payload->base.type = PAYLOAD_TYPE_PLATFORM;
-    payload->rt = OICStrdup(OC_RSRVD_RESOURCE_TYPE_PLATFORM);
+    OCResourcePayloadAddStringLL(&payload->rt, OC_RSRVD_RESOURCE_TYPE_PLATFORM);
 
     OCResourcePayloadAddStringLL(&payload->interfaces, OC_RSRVD_INTERFACE_DEFAULT);
     OCResourcePayloadAddStringLL(&payload->interfaces, OC_RSRVD_INTERFACE_READ);
@@ -1691,7 +1860,7 @@ void OCPlatformPayloadDestroy(OCPlatformPayload* payload)
     }
     OICFree(payload->uri);
     OCPlatformInfoDestroy(&payload->info);
-    OICFree(payload->rt);
+    OCFreeOCStringLL(payload->rt);
     OCFreeOCStringLL(payload->interfaces);
     OICFree(payload);
 }