Imported Upstream version 1.1.1
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocpayload.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 // Required for strok_r
22 #define _POSIX_C_SOURCE 200112L
23
24 #include <stdio.h>
25 #include "ocpayload.h"
26 #include "octypes.h"
27 #include <string.h>
28 #include "oic_malloc.h"
29 #include "oic_string.h"
30 #include "ocstackinternal.h"
31 #include "ocresource.h"
32 #include "logger.h"
33 #include "rdpayload.h"
34
35 #define TAG "OIC_RI_PAYLOAD"
36 #define CSV_SEPARATOR ','
37
38 static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val);
39
40 void OCPayloadDestroy(OCPayload* payload)
41 {
42     if (!payload)
43     {
44         return;
45     }
46
47     switch(payload->type)
48     {
49         case PAYLOAD_TYPE_REPRESENTATION:
50             OCRepPayloadDestroy((OCRepPayload*)payload);
51             break;
52         case PAYLOAD_TYPE_DISCOVERY:
53             OCDiscoveryPayloadDestroy((OCDiscoveryPayload*)payload);
54             break;
55         case PAYLOAD_TYPE_DEVICE:
56             OCDevicePayloadDestroy((OCDevicePayload*)payload);
57             break;
58         case PAYLOAD_TYPE_PLATFORM:
59             OCPlatformPayloadDestroy((OCPlatformPayload*)payload);
60             break;
61         case PAYLOAD_TYPE_PRESENCE:
62             OCPresencePayloadDestroy((OCPresencePayload*)payload);
63             break;
64         case PAYLOAD_TYPE_SECURITY:
65             OCSecurityPayloadDestroy((OCSecurityPayload*)payload);
66             break;
67         case PAYLOAD_TYPE_RD:
68            OCRDPayloadDestroy((OCRDPayload*)payload);
69            break;
70         default:
71             OIC_LOG_V(ERROR, TAG, "Unsupported payload type in destroy: %d", payload->type);
72             OICFree(payload);
73             break;
74     }
75 }
76 OCRepPayload* OCRepPayloadCreate()
77 {
78     OCRepPayload* payload = (OCRepPayload*)OICCalloc(1, sizeof(OCRepPayload));
79
80     if (!payload)
81     {
82         return NULL;
83     }
84
85     payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
86
87     return payload;
88 }
89
90 void OCRepPayloadAppend(OCRepPayload* parent, OCRepPayload* child)
91 {
92     if (!parent)
93     {
94         return;
95     }
96
97     while(parent->next)
98     {
99         parent = parent->next;
100     }
101
102     parent->next= child;
103     child->next = NULL;
104 }
105
106 static OCRepPayloadValue* OCRepPayloadFindValue(const OCRepPayload* payload, const char* name)
107 {
108     if (!payload || !name)
109     {
110         return NULL;
111     }
112
113     OCRepPayloadValue* val = payload->values;
114     while(val)
115     {
116         if (0 == strcmp(val->name, name))
117         {
118             return val;
119         }
120         val = val->next;
121     }
122
123     return NULL;
124 }
125
126 static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue* source)
127 {
128     if (!dest || !source)
129     {
130         return;
131     }
132
133     size_t dimTotal = calcDimTotal(source->arr.dimensions);
134     switch(source->arr.type)
135     {
136         case OCREP_PROP_INT:
137             dest->arr.iArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
138             VERIFY_PARAM_NON_NULL(TAG, dest->arr.iArray, "Failed allocating memory");
139             memcpy(dest->arr.iArray, source->arr.iArray, dimTotal * sizeof(int64_t));
140             break;
141         case OCREP_PROP_DOUBLE:
142             dest->arr.dArray = (double*)OICMalloc(dimTotal * sizeof(double));
143             VERIFY_PARAM_NON_NULL(TAG, dest->arr.dArray, "Failed allocating memory");
144             memcpy(dest->arr.dArray, source->arr.dArray, dimTotal * sizeof(double));
145             break;
146         case OCREP_PROP_BOOL:
147             dest->arr.bArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
148             VERIFY_PARAM_NON_NULL(TAG, dest->arr.bArray, "Failed allocating memory");
149             memcpy(dest->arr.bArray, source->arr.bArray, dimTotal * sizeof(bool));
150             break;
151         case OCREP_PROP_STRING:
152             dest->arr.strArray = (char**)OICMalloc(dimTotal * sizeof(char*));
153             VERIFY_PARAM_NON_NULL(TAG, dest->arr.strArray, "Failed allocating memory");
154             for(size_t i = 0; i < dimTotal; ++i)
155             {
156                 dest->arr.strArray[i] = OICStrdup(source->arr.strArray[i]);
157             }
158             break;
159         case OCREP_PROP_OBJECT:
160             dest->arr.objArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
161             VERIFY_PARAM_NON_NULL(TAG, dest->arr.objArray, "Failed allocating memory");
162             for(size_t i = 0; i < dimTotal; ++i)
163             {
164                 dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
165             }
166             break;
167         case OCREP_PROP_ARRAY:
168             dest->arr.objArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
169             VERIFY_PARAM_NON_NULL(TAG, dest->arr.objArray, "Failed allocating memory");
170             for(size_t i = 0; i < dimTotal; ++i)
171             {
172                 dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
173             }
174             break;
175         default:
176             OIC_LOG(ERROR, TAG, "CopyPropertyValueArray invalid type");
177             break;
178     }
179 exit:
180     return;
181 }
182
183 static void OCCopyPropertyValue (OCRepPayloadValue *dest, OCRepPayloadValue *source)
184 {
185     if (!source || !dest)
186     {
187         return;
188     }
189
190     switch(source->type)
191     {
192         case OCREP_PROP_STRING:
193             dest->str = OICStrdup(source->str);
194             break;
195         case OCREP_PROP_OBJECT:
196             dest->obj = OCRepPayloadClone(source->obj);
197             break;
198         case OCREP_PROP_ARRAY:
199             OCCopyPropertyValueArray(dest, source);
200             break;
201         default:
202             // Nothing to do for the trivially copyable types.
203             break;
204     }
205 }
206
207 static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val)
208 {
209     if (!val)
210     {
211         return;
212     }
213
214     if (val->type == OCREP_PROP_STRING)
215     {
216         OICFree(val->str);
217     }
218     else if (val->type == OCREP_PROP_BYTE_STRING)
219     {
220         OICFree(val->ocByteStr.bytes);
221     }
222     else if (val->type == OCREP_PROP_OBJECT)
223     {
224         OCRepPayloadDestroy(val->obj);
225     }
226     else if (val->type == OCREP_PROP_ARRAY)
227     {
228         size_t dimTotal = calcDimTotal(val->arr.dimensions);
229         switch(val->arr.type)
230         {
231             case OCREP_PROP_INT:
232             case OCREP_PROP_DOUBLE:
233             case OCREP_PROP_BOOL:
234                 // Since this is a union, iArray will
235                 // point to all of the above
236                 OICFree(val->arr.iArray);
237                 break;
238             case OCREP_PROP_STRING:
239                 for(size_t i = 0; i< dimTotal; ++i)
240                 {
241                     OICFree(val->arr.strArray[i]);
242                 }
243                 OICFree(val->arr.strArray);
244                 break;
245             case OCREP_PROP_BYTE_STRING:
246                 for (size_t i = 0; i< dimTotal; ++i)
247                 {
248                     OICFree(val->arr.ocByteStrArray[i].bytes);
249                 }
250                 OICFree(val->arr.ocByteStrArray);
251                 break;
252             case OCREP_PROP_OBJECT: // This case is the temporary fix for string input
253                 for(size_t i = 0; i< dimTotal; ++i)
254                 {
255                     OCRepPayloadDestroy(val->arr.objArray[i]);
256                 }
257                 OICFree(val->arr.objArray);
258                 break;
259             case OCREP_PROP_NULL:
260             case OCREP_PROP_ARRAY:
261                 OIC_LOG_V(ERROR, TAG, "FreeRepPayloadValueContents: Illegal type\
262                         inside an array: %d", val->arr.type);
263                 break;
264         }
265     }
266 }
267
268 static void OCFreeRepPayloadValue(OCRepPayloadValue* val)
269 {
270     if (!val)
271     {
272         return;
273     }
274
275     OICFree(val->name);
276     OCFreeRepPayloadValueContents(val);
277     OCFreeRepPayloadValue(val->next);
278     OICFree(val);
279 }
280 static OCRepPayloadValue* OCRepPayloadValueClone (OCRepPayloadValue* source)
281 {
282     if (!source)
283     {
284         return NULL;
285     }
286
287     OCRepPayloadValue *sourceIter = source;
288     OCRepPayloadValue *destIter = (OCRepPayloadValue*) OICCalloc(1, sizeof(OCRepPayloadValue));
289     if (!destIter)
290     {
291         return NULL;
292     }
293
294     OCRepPayloadValue *headOfClone = destIter;
295
296     // Copy payload type and non pointer types in union.
297     *destIter = *sourceIter;
298     destIter->name = OICStrdup (sourceIter->name);
299     OCCopyPropertyValue (destIter, sourceIter);
300
301     sourceIter = sourceIter->next;
302
303     while (sourceIter)
304     {
305         destIter->next = (OCRepPayloadValue*) OICCalloc(1, sizeof(OCRepPayloadValue));
306         if (!destIter->next)
307         {
308             OCFreeRepPayloadValue (headOfClone);
309             return NULL;
310         }
311
312         *(destIter->next) = *sourceIter;
313         destIter->next->name = OICStrdup (sourceIter->name);
314         OCCopyPropertyValue (destIter->next, sourceIter);
315
316         sourceIter = sourceIter->next;
317         destIter = destIter->next;
318     }
319     return headOfClone;
320 }
321
322 static OCRepPayloadValue* OCRepPayloadFindAndSetValue(OCRepPayload* payload, const char* name,
323         OCRepPayloadPropType type)
324 {
325     if (!payload || !name)
326     {
327         return NULL;
328     }
329
330     OCRepPayloadValue* val = payload->values;
331     if (val == NULL)
332     {
333         payload->values = (OCRepPayloadValue*)OICCalloc(1, sizeof(OCRepPayloadValue));
334         if (!payload->values)
335         {
336             return NULL;
337         }
338         payload->values->name = OICStrdup(name);
339         if (!payload->values->name)
340         {
341             OICFree(payload->values);
342             payload->values = NULL;
343             return NULL;
344         }
345         payload->values->type =type;
346         return payload->values;
347     }
348
349     while(val)
350     {
351         if (0 == strcmp(val->name, name))
352         {
353             OCFreeRepPayloadValueContents(val);
354             val->type = type;
355             return val;
356         }
357         else if (val->next == NULL)
358         {
359             val->next = (OCRepPayloadValue*)OICCalloc(1, sizeof(OCRepPayloadValue));
360             if (!val->next)
361             {
362                 return NULL;
363             }
364             val->next->name = OICStrdup(name);
365             if (!val->next->name)
366             {
367                 OICFree(val->next);
368                 val->next = NULL;
369                 return NULL;
370             }
371             val->next->type =type;
372             return val->next;
373         }
374
375         val = val->next;
376     }
377
378     OIC_LOG(ERROR, TAG, "FindAndSetValue reached point after while loop, pointer corruption?");
379     return NULL;
380 }
381
382 bool OCRepPayloadAddResourceType(OCRepPayload* payload, const char* resourceType)
383 {
384     return OCRepPayloadAddResourceTypeAsOwner(payload, OICStrdup(resourceType));
385 }
386
387 bool OCRepPayloadAddResourceTypeAsOwner(OCRepPayload* payload, char* resourceType)
388 {
389     if (!payload || !resourceType)
390     {
391         return false;
392     }
393
394     if (payload->types)
395     {
396         OCStringLL* cur = payload->types;
397         while(cur->next)
398         {
399             cur = cur->next;
400         }
401         cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
402
403         if (!cur->next)
404         {
405             return false;
406         }
407
408         cur->next->value = resourceType;
409         return true;
410     }
411     else
412     {
413         payload->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
414         if (!payload->types)
415         {
416             return false;
417         }
418         payload->types->value = resourceType;
419         return true;
420     }
421 }
422
423 bool OCRepPayloadAddInterface(OCRepPayload* payload, const char* interface)
424 {
425     return OCRepPayloadAddInterfaceAsOwner(payload, OICStrdup(interface));
426 }
427
428 bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* interface)
429 {
430     if (!payload || !interface)
431     {
432         return false;
433     }
434
435     if (payload->interfaces)
436     {
437         OCStringLL* cur = payload->interfaces;
438         while(cur->next)
439         {
440             cur = cur->next;
441         }
442         cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
443
444         if (!cur->next)
445         {
446             return false;
447         }
448         cur->next->value = interface;
449         return true;
450     }
451     else
452     {
453         payload->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
454         if (!payload->interfaces)
455         {
456             return false;
457         }
458         payload->interfaces->value = interface;
459         return true;
460     }
461 }
462
463 bool OCRepPayloadSetUri(OCRepPayload* payload, const char*  uri)
464 {
465     if (!payload)
466     {
467         return false;
468     }
469     OICFree(payload->uri);
470     payload->uri = OICStrdup(uri);
471     return payload->uri != NULL;
472 }
473
474 bool OCRepPayloadIsNull(const OCRepPayload* payload, const char* name)
475 {
476     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
477
478     if (!val)
479     {
480         return true;
481     }
482
483     return val->type == OCREP_PROP_NULL;
484 }
485
486 static bool OCRepPayloadSetProp(OCRepPayload* payload, const char* name,
487         void* value, OCRepPayloadPropType type)
488 {
489     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, type);
490     if (!val)
491     {
492         return false;
493     }
494     switch(type)
495     {
496         case OCREP_PROP_INT:
497                val->i = *(int64_t*)value;
498                break;
499         case OCREP_PROP_DOUBLE:
500                val->d = *(double*)value;
501                break;
502         case OCREP_PROP_BOOL:
503                val->b = *(bool*)value;
504                break;
505         case OCREP_PROP_OBJECT:
506                val->obj = (OCRepPayload*)value;
507                break;
508         case OCREP_PROP_STRING:
509                val->str = (char*)value;
510                return val->str != NULL;
511         case OCREP_PROP_BYTE_STRING:
512                val->ocByteStr = *(OCByteString*)value;
513                break;
514         case OCREP_PROP_NULL:
515                return val != NULL;
516         case OCREP_PROP_ARRAY:
517         default:
518                return false;
519     }
520
521     return true;
522 }
523
524 bool OCRepPayloadSetNull(OCRepPayload* payload, const char* name)
525 {
526     return OCRepPayloadSetProp(payload, name, NULL, OCREP_PROP_NULL);
527 }
528
529 bool OCRepPayloadSetPropInt(OCRepPayload* payload,
530         const char* name, int64_t value)
531 {
532     return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_INT);
533 }
534
535 bool OCRepPayloadGetPropInt(const OCRepPayload* payload, const char* name, int64_t* value)
536 {
537     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
538
539     if (!val || val->type != OCREP_PROP_INT)
540     {
541         return false;
542     }
543
544     *value = val->i;
545     return true;
546 }
547
548 bool OCRepPayloadSetPropDouble(OCRepPayload* payload,
549                                const char* name, double value)
550 {
551     return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_DOUBLE);
552 }
553
554 bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, double* value)
555 {
556     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
557
558     if (val)
559     {
560         if (val->type == OCREP_PROP_DOUBLE)
561         {
562             *value = val->d;
563             return true;
564         }
565         else if (val->type == OCREP_PROP_INT)
566         {
567             *value = val->i;
568             return true;
569         }
570     }
571
572     return false;
573 }
574
575 bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value)
576 {
577     char* temp = OICStrdup(value);
578     bool b = OCRepPayloadSetPropStringAsOwner(payload, name, temp);
579
580     if (!b)
581     {
582         OICFree(temp);
583     }
584     return b;
585 }
586
587 bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value)
588 {
589     return OCRepPayloadSetProp(payload, name, value, OCREP_PROP_STRING);
590 }
591
592 bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, char** value)
593 {
594     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
595
596     if (!val || val->type != OCREP_PROP_STRING)
597     {
598         return false;
599     }
600
601     *value = OICStrdup(val->str);
602     return *value != NULL;
603 }
604
605 bool OCRepPayloadSetPropByteString(OCRepPayload* payload, const char* name, OCByteString value)
606 {
607     if (!value.bytes || !value.len)
608     {
609         return false;
610     }
611
612     OCByteString ocByteStr = {
613                     .bytes = (uint8_t*)OICMalloc(value.len * sizeof(uint8_t)),
614                     .len = value.len };
615
616     if (!ocByteStr.bytes)
617     {
618         return false;
619     }
620     memcpy(ocByteStr.bytes, value.bytes, ocByteStr.len);
621
622     bool b = OCRepPayloadSetPropByteStringAsOwner(payload, name, &ocByteStr);
623
624     if (!b)
625     {
626         OICFree(ocByteStr.bytes);
627     }
628     return b;
629 }
630
631 bool OCRepPayloadSetPropByteStringAsOwner(OCRepPayload* payload, const char* name, OCByteString* value)
632 {
633     return OCRepPayloadSetProp(payload, name, value, OCREP_PROP_BYTE_STRING);
634 }
635
636 bool OCRepPayloadGetPropByteString(const OCRepPayload* payload, const char* name, OCByteString* value)
637 {
638     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
639
640     if (!val || val->type != OCREP_PROP_BYTE_STRING)
641     {
642         return false;
643     }
644
645     if (!value)
646     {
647         return false;
648     }
649
650     value->bytes = (uint8_t*)OICMalloc(val->ocByteStr.len * sizeof(uint8_t));
651     if (!value->bytes)
652     {
653         return false;
654     }
655     value->len = val->ocByteStr.len;
656     memcpy(value->bytes, val->ocByteStr.bytes, value->len);
657
658     return true;
659 }
660
661 bool OCRepPayloadSetPropBool(OCRepPayload* payload,
662                              const char* name, bool value)
663 {
664     return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_BOOL);
665 }
666
667 bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool* value)
668 {
669     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
670
671     if (!val || val->type != OCREP_PROP_BOOL)
672     {
673         return false;
674     }
675
676     *value = val->b;
677     return true;
678 }
679
680 bool OCRepPayloadSetPropObject(OCRepPayload* payload, const char* name, const OCRepPayload* value)
681 {
682     OCRepPayload* temp = OCRepPayloadClone(value);
683     bool b = OCRepPayloadSetPropObjectAsOwner(payload, name, temp);
684
685     if (!b)
686     {
687         OCRepPayloadDestroy(temp);
688     }
689     return b;
690 }
691
692 bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name, OCRepPayload* value)
693 {
694     return OCRepPayloadSetProp(payload, name, value, OCREP_PROP_OBJECT);
695 }
696
697 bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value)
698 {
699     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
700
701     if (!val || val->type != OCREP_PROP_OBJECT)
702     {
703         return false;
704     }
705
706     *value = OCRepPayloadClone(val->obj);
707     return *value != NULL;
708 }
709
710 size_t calcDimTotal(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
711 {
712     if (dimensions[0] == 0)
713     {
714         return 0;
715     }
716
717     size_t total = 1;
718     for(uint8_t i = 0; i < MAX_REP_ARRAY_DEPTH && dimensions[i] != 0; ++i)
719     {
720         total *= dimensions[i];
721     }
722     return total;
723 }
724
725
726 bool OCRepPayloadSetByteStringArrayAsOwner(OCRepPayload* payload, const char* name,
727         OCByteString* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
728 {
729     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
730
731     if (!val)
732     {
733         return false;
734     }
735
736     val->arr.type = OCREP_PROP_BYTE_STRING;
737     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
738     val->arr.ocByteStrArray = array;
739
740     return true;
741 }
742
743 bool OCRepPayloadSetByteStringArray(OCRepPayload* payload, const char* name,
744         const OCByteString* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
745 {
746     if (!array)
747     {
748         return NULL;
749     }
750
751     size_t dimTotal = calcDimTotal(dimensions);
752     if (dimTotal == 0)
753     {
754         return false;
755     }
756
757     OCByteString* newArray = (OCByteString*)OICCalloc(dimTotal, sizeof(OCByteString));
758
759     if (!newArray)
760     {
761         return false;
762     }
763
764     for (size_t i = 0; i < dimTotal; ++i)
765     {
766         newArray[i].bytes = (uint8_t*)OICMalloc(array[i].len * sizeof(uint8_t));
767         if (NULL == newArray[i].bytes)
768         {
769             for (size_t j = 0; j < i; ++j)
770             {
771                 OICFree(newArray[j].bytes);
772             }
773
774             OICFree(newArray);
775             return false;
776         }
777         newArray[i].len = array[i].len;
778         memcpy(newArray[i].bytes, array[i].bytes, newArray[i].len);
779     }
780
781     bool b = OCRepPayloadSetByteStringArrayAsOwner(payload, name, newArray, dimensions);
782     if (!b)
783     {
784         for (size_t i = 0; i < dimTotal; ++i)
785         {
786             OICFree(newArray[i].bytes);
787         }
788
789         OICFree(newArray);
790     }
791     return b;
792 }
793
794 bool OCRepPayloadGetByteStringArray(const OCRepPayload* payload, const char* name,
795         OCByteString** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
796 {
797     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
798
799     if (!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_BYTE_STRING
800             || !val->arr.ocByteStrArray)
801     {
802         return false;
803     }
804
805     size_t dimTotal = calcDimTotal(val->arr.dimensions);
806     if (dimTotal == 0)
807     {
808         return false;
809     }
810
811     *array = (OCByteString*)OICCalloc(dimTotal, sizeof(OCByteString));
812     if (!*array)
813     {
814         return false;
815     }
816
817     for (size_t i = 0; i < dimTotal; ++i)
818     {
819         OCByteString* tmp = &(*array)[i];
820         tmp->bytes = (uint8_t*)OICMalloc(val->arr.ocByteStrArray[i].len * sizeof(uint8_t));
821         if (NULL == tmp->bytes)
822         {
823             for (size_t j = 0; j < i; ++j)
824             {
825                 OCByteString* tmp = &(*array)[j];
826                 OICFree(tmp->bytes);
827             }
828             OICFree(*array);
829             *array = NULL;
830
831             return false;
832         }
833         tmp->len = val->arr.ocByteStrArray[i].len;
834         memcpy(tmp->bytes, val->arr.ocByteStrArray[i].bytes, tmp->len);
835     }
836
837     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
838     return true;
839 }
840
841
842 bool OCRepPayloadSetIntArrayAsOwner(OCRepPayload* payload, const char* name,
843         int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
844 {
845     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
846
847     if (!val)
848     {
849         return false;
850     }
851
852     val->arr.type = OCREP_PROP_INT;
853     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
854     val->arr.iArray = array;
855
856     return true;
857 }
858
859 bool OCRepPayloadSetIntArray(OCRepPayload* payload, const char* name,
860         const int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
861 {
862     size_t dimTotal = calcDimTotal(dimensions);
863     if (dimTotal == 0)
864     {
865         return false;
866     }
867
868     int64_t* newArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
869
870     if (!newArray)
871     {
872         return false;
873     }
874
875     memcpy(newArray, array, dimTotal * sizeof(int64_t));
876
877
878     bool b = OCRepPayloadSetIntArrayAsOwner(payload, name, newArray, dimensions);
879     if (!b)
880     {
881         OICFree(newArray);
882     }
883     return b;
884 }
885
886 bool OCRepPayloadGetIntArray(const OCRepPayload* payload, const char* name,
887         int64_t** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
888 {
889     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
890
891     if (!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_INT
892             || !val->arr.iArray)
893     {
894         return false;
895     }
896
897     size_t dimTotal = calcDimTotal(val->arr.dimensions);
898     if (dimTotal == 0)
899     {
900         return false;
901     }
902     *array = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
903     if (!*array)
904     {
905         return false;
906     }
907
908     memcpy(*array, val->arr.iArray, dimTotal * sizeof(int64_t));
909     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
910     return true;
911 }
912
913 bool OCRepPayloadSetDoubleArrayAsOwner(OCRepPayload* payload, const char* name,
914         double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
915 {
916     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
917
918     if (!val)
919     {
920         return false;
921     }
922
923     val->arr.type = OCREP_PROP_DOUBLE;
924     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
925     val->arr.dArray = array;
926
927     return true;
928 }
929 bool OCRepPayloadSetDoubleArray(OCRepPayload* payload, const char* name,
930         const double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
931 {
932     size_t dimTotal = calcDimTotal(dimensions);
933     if (dimTotal == 0)
934     {
935         return false;
936     }
937
938     double* newArray = (double*)OICMalloc(dimTotal * sizeof(double));
939
940     if (!newArray)
941     {
942         return false;
943     }
944
945     memcpy(newArray, array, dimTotal * sizeof(double));
946
947     bool b = OCRepPayloadSetDoubleArrayAsOwner(payload, name, newArray, dimensions);
948     if (!b)
949     {
950         OICFree(newArray);
951     }
952     return b;
953 }
954
955 bool OCRepPayloadGetDoubleArray(const OCRepPayload* payload, const char* name,
956         double** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
957 {
958     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
959
960     if (!val || val->type != OCREP_PROP_ARRAY ||
961         (val->arr.type != OCREP_PROP_DOUBLE && val->arr.type != OCREP_PROP_INT)
962             || !val->arr.dArray)
963     {
964         return false;
965     }
966
967     size_t dimTotal = calcDimTotal(val->arr.dimensions);
968     if (dimTotal == 0)
969     {
970         return false;
971     }
972     *array = (double*)OICMalloc(dimTotal * sizeof(double));
973     if (!*array)
974     {
975         return false;
976     }
977
978     if (val->arr.type == OCREP_PROP_DOUBLE)
979     {
980         memcpy(*array, val->arr.dArray, dimTotal * sizeof(double));
981     }
982     else
983     {
984         /* need to convert from integer */
985         size_t n = 0;
986         for ( ; n < dimTotal; ++n)
987         {
988             (*array)[n] = val->arr.iArray[n];
989         }
990     }
991     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
992     return true;
993 }
994
995 bool OCRepPayloadSetStringArrayAsOwner(OCRepPayload* payload, const char* name,
996         char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
997 {
998     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
999
1000     if (!val)
1001     {
1002         return false;
1003     }
1004
1005     val->arr.type = OCREP_PROP_STRING;
1006     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
1007     val->arr.strArray = array;
1008
1009     return true;
1010 }
1011 bool OCRepPayloadSetStringArray(OCRepPayload* payload, const char* name,
1012         const char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
1013 {
1014     size_t dimTotal = calcDimTotal(dimensions);
1015     if (dimTotal == 0)
1016     {
1017         return false;
1018     }
1019
1020     char** newArray = (char**)OICMalloc(dimTotal * sizeof(char*));
1021
1022     if (!newArray)
1023     {
1024         return false;
1025     }
1026
1027     for(size_t i = 0; i < dimTotal; ++i)
1028     {
1029         newArray[i] = OICStrdup(array[i]);
1030     }
1031
1032     bool b = OCRepPayloadSetStringArrayAsOwner(payload, name, newArray, dimensions);
1033
1034     if (!b)
1035     {
1036         for(size_t i = 0; i < dimTotal; ++i)
1037         {
1038             OICFree(newArray[i]);
1039         }
1040         OICFree(newArray);
1041     }
1042     return b;
1043 }
1044
1045 bool OCRepPayloadGetStringArray(const OCRepPayload* payload, const char* name,
1046         char*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
1047 {
1048     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
1049
1050     if (!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_STRING
1051             || !val->arr.strArray)
1052     {
1053         return false;
1054     }
1055
1056     size_t dimTotal = calcDimTotal(val->arr.dimensions);
1057     if (dimTotal == 0)
1058     {
1059         return false;
1060     }
1061     *array = (char**)OICMalloc(dimTotal * sizeof(char*));
1062     if (!*array)
1063     {
1064         return false;
1065     }
1066
1067     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
1068
1069     for(size_t i = 0; i < dimTotal; ++i)
1070     {
1071         (*array)[i] = OICStrdup(val->arr.strArray[i]);
1072     }
1073
1074     return true;
1075
1076 }
1077
1078 bool OCRepPayloadSetBoolArrayAsOwner(OCRepPayload* payload, const char* name,
1079         bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
1080 {
1081
1082     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
1083
1084     if (!val)
1085     {
1086         return false;
1087     }
1088
1089     val->arr.type = OCREP_PROP_BOOL;
1090     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
1091     val->arr.bArray = array;
1092
1093     return true;
1094 }
1095 bool OCRepPayloadSetBoolArray(OCRepPayload* payload, const char* name,
1096         const bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
1097 {
1098     size_t dimTotal = calcDimTotal(dimensions);
1099     if (dimTotal == 0)
1100     {
1101         return false;
1102     }
1103
1104     bool* newArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
1105
1106     if (!newArray)
1107     {
1108         return false;
1109     }
1110
1111     memcpy(newArray, array, dimTotal * sizeof(bool));
1112
1113
1114     bool b = OCRepPayloadSetBoolArrayAsOwner(payload, name, newArray, dimensions);
1115     if (!b)
1116     {
1117         OICFree(newArray);
1118     }
1119     return b;
1120 }
1121
1122 bool OCRepPayloadGetBoolArray(const OCRepPayload* payload, const char* name,
1123         bool** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
1124 {
1125     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
1126
1127     if (!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_BOOL
1128             || !val->arr.bArray)
1129     {
1130         return false;
1131     }
1132
1133     size_t dimTotal = calcDimTotal(val->arr.dimensions);
1134     if (dimTotal == 0)
1135     {
1136         return false;
1137     }
1138     *array = (bool*)OICMalloc(dimTotal * sizeof(bool));
1139     if (!*array)
1140     {
1141         return false;
1142     }
1143
1144     memcpy(*array, val->arr.bArray, dimTotal * sizeof(bool));
1145     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
1146     return true;
1147 }
1148
1149 bool OCRepPayloadSetPropObjectArrayAsOwner(OCRepPayload* payload, const char* name,
1150         OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
1151 {
1152     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
1153
1154     if (!val)
1155     {
1156         return false;
1157     }
1158
1159     val->arr.type = OCREP_PROP_OBJECT;
1160     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
1161     val->arr.objArray = array;
1162
1163     return true;
1164 }
1165
1166 bool OCRepPayloadSetPropObjectArray(OCRepPayload* payload, const char* name,
1167         const OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
1168 {
1169     size_t dimTotal = calcDimTotal(dimensions);
1170     if (dimTotal == 0)
1171     {
1172         return false;
1173     }
1174
1175     OCRepPayload** newArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
1176
1177     if (!newArray)
1178     {
1179         return false;
1180     }
1181
1182     for(size_t i = 0; i < dimTotal; ++i)
1183     {
1184         newArray[i] = OCRepPayloadClone(array[i]);
1185     }
1186
1187     bool b = OCRepPayloadSetPropObjectArrayAsOwner(payload, name, newArray, dimensions);
1188
1189     if (!b)
1190     {
1191         for(size_t i = 0; i < dimTotal; ++i)
1192         {
1193            OCRepPayloadDestroy(newArray[i]);
1194         }
1195         OICFree(newArray);
1196     }
1197     return b;
1198 }
1199
1200 bool OCRepPayloadGetPropObjectArray(const OCRepPayload* payload, const char* name,
1201         OCRepPayload*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
1202 {
1203     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
1204
1205     if (!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_OBJECT
1206             || !val->arr.objArray)
1207     {
1208         return false;
1209     }
1210
1211     size_t dimTotal = calcDimTotal(val->arr.dimensions);
1212     if (dimTotal == 0)
1213     {
1214         return false;
1215     }
1216     *array = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
1217     if (!*array)
1218     {
1219         return false;
1220     }
1221
1222     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
1223
1224     for(size_t i = 0; i < dimTotal; ++i)
1225     {
1226         (*array)[i] = OCRepPayloadClone(val->arr.objArray[i]);
1227     }
1228
1229     return true;
1230 }
1231
1232 void OCFreeOCStringLL(OCStringLL* ll)
1233 {
1234     if (!ll)
1235     {
1236         return;
1237     }
1238
1239     OCFreeOCStringLL(ll->next);
1240     OICFree(ll->value);
1241     OICFree(ll);
1242 }
1243
1244 OCStringLL* CloneOCStringLL (OCStringLL* ll)
1245 {
1246     if (!ll)
1247     {
1248         return NULL;
1249     }
1250
1251     OCStringLL *sourceIter = ll;
1252
1253     OCStringLL *destIter = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1254     if (!destIter)
1255     {
1256         return NULL;
1257     }
1258     destIter->value = OICStrdup (sourceIter->value);
1259
1260     OCStringLL *headOfClone = destIter;
1261
1262     sourceIter = sourceIter->next;
1263
1264     while (sourceIter)
1265     {
1266         destIter->next  = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1267         if (!destIter->next)
1268         {
1269             OCFreeOCStringLL (headOfClone);
1270             return NULL;
1271         }
1272         destIter->next->value = OICStrdup (sourceIter->value);
1273
1274         destIter = destIter->next;
1275         sourceIter = sourceIter->next;
1276     }
1277     return headOfClone;
1278 }
1279
1280 OCStringLL* OCCreateOCStringLL(const char* text)
1281 {
1282     char *token = NULL;
1283     char *head = NULL;
1284     char *tail = NULL;
1285     char *backup  = NULL;
1286     OCStringLL* result = NULL;
1287     OCStringLL* iter = NULL;
1288     OCStringLL* prev = NULL;
1289     static const char delim[] = { CSV_SEPARATOR, '\0' };
1290
1291     VERIFY_PARAM_NON_NULL(TAG, text, "Invalid parameter");
1292     backup = OICStrdup(text);
1293     VERIFY_PARAM_NON_NULL(TAG, backup, "Failed allocating memory");
1294
1295     for (head = backup; ; head = NULL)
1296     {
1297         token = (char *) strtok_r(head, delim, &tail);
1298         if (!token) break;
1299         iter = (OCStringLL *)OICCalloc(1,sizeof(OCStringLL));
1300         VERIFY_PARAM_NON_NULL(TAG, iter, "Failed allocating memory");
1301         if (!result)
1302         {
1303              result = iter;
1304         }
1305         else
1306         {
1307              prev->next = iter;
1308         }
1309         iter->value = OICStrdup(token);
1310         VERIFY_PARAM_NON_NULL(TAG, iter->value, "Failed allocating memory");
1311         prev = iter;
1312         iter = iter->next;
1313     }
1314     OICFree(backup);
1315     return result;
1316
1317 exit:
1318     OICFree(backup);
1319     OCFreeOCStringLL(result);
1320     return NULL;
1321 }
1322
1323 char* OCCreateString(const OCStringLL* ll)
1324 {
1325     char *str = NULL;
1326     char *pos = NULL;
1327     size_t len = 0;
1328     size_t sublen = 0;
1329     int count = 0;
1330
1331     if (!ll) return NULL;
1332
1333     for (const OCStringLL *it = ll; it ; it = it->next )
1334     {
1335         len += strlen(it->value) + 1;
1336     }
1337     len--; // renove trailing separator (just added above)
1338     str = (char*) malloc(len + 1);
1339     if (!str)
1340         return NULL;
1341
1342     pos = str;
1343     const OCStringLL *it = ll;
1344     while (it)
1345     {
1346         sublen = strlen(it->value);
1347         count = snprintf(pos, len + 1, "%s", it->value);
1348         if (count<sublen)
1349         {
1350             free(str);
1351             return NULL;
1352         }
1353         len-=sublen;
1354         pos+=count;
1355
1356         it = it->next;
1357         if (it)
1358         {
1359             *pos = CSV_SEPARATOR;
1360             len--;
1361             *(++pos) = '\0';
1362        }
1363     }
1364
1365     return str;
1366 }
1367
1368 OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
1369 {
1370     if (!payload)
1371     {
1372         return NULL;
1373     }
1374
1375     OCRepPayload *clone = OCRepPayloadCreate();
1376
1377     if (!clone)
1378     {
1379         return NULL;
1380     }
1381
1382     clone->uri = OICStrdup (payload->uri);
1383     clone->types = CloneOCStringLL (payload->types);
1384     clone->interfaces = CloneOCStringLL (payload->interfaces);
1385     clone->values = OCRepPayloadValueClone (payload->values);
1386
1387     return clone;
1388 }
1389
1390
1391 void OCRepPayloadDestroy(OCRepPayload* payload)
1392 {
1393     if (!payload)
1394     {
1395         return;
1396     }
1397
1398     OICFree(payload->uri);
1399     OCFreeOCStringLL(payload->types);
1400     OCFreeOCStringLL(payload->interfaces);
1401     OCFreeRepPayloadValue(payload->values);
1402     OCRepPayloadDestroy(payload->next);
1403     OICFree(payload);
1404 }
1405
1406 OCDiscoveryPayload* OCDiscoveryPayloadCreate()
1407 {
1408     OCDiscoveryPayload* payload = (OCDiscoveryPayload*)OICCalloc(1, sizeof(OCDiscoveryPayload));
1409
1410     if (!payload)
1411     {
1412         return NULL;
1413     }
1414
1415     payload->base.type = PAYLOAD_TYPE_DISCOVERY;
1416
1417     return payload;
1418 }
1419
1420 OCSecurityPayload* OCSecurityPayloadCreate(const uint8_t* securityData, size_t size)
1421 {
1422     OCSecurityPayload* payload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1423
1424     if (!payload)
1425     {
1426         return NULL;
1427     }
1428
1429     payload->base.type = PAYLOAD_TYPE_SECURITY;
1430     payload->securityData = (uint8_t *)OICCalloc(1, size);
1431     if (!payload->securityData)
1432     {
1433         OICFree(payload);
1434         return NULL;
1435     }
1436     memcpy(payload->securityData, (uint8_t *)securityData, size);
1437     payload->payloadSize = size;
1438
1439     return payload;
1440 }
1441
1442 void OCSecurityPayloadDestroy(OCSecurityPayload* payload)
1443 {
1444     if (!payload)
1445     {
1446         return;
1447     }
1448
1449     OICFree(payload->securityData);
1450     OICFree(payload);
1451 }
1452
1453 size_t OCDiscoveryPayloadGetResourceCount(OCDiscoveryPayload* payload)
1454 {
1455     size_t i = 0;
1456     OCResourcePayload* p = payload->resources;
1457     while(p)
1458     {
1459         ++i;
1460         p = p->next;
1461     }
1462     return i;
1463 }
1464
1465 OCResourcePayload* OCDiscoveryPayloadGetResource(OCDiscoveryPayload* payload, size_t index)
1466 {
1467     size_t i = 0;
1468     OCResourcePayload* p = payload->resources;
1469     while(p)
1470     {
1471         if (i == index)
1472         {
1473             return p;
1474         }
1475         ++i;
1476         p = p->next;
1477     }
1478     return NULL;
1479 }
1480
1481 static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t securePort,
1482                                          uint16_t tcpPort)
1483 {
1484     OCResourcePayload* pl = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
1485     if (!pl)
1486     {
1487         return NULL;
1488     }
1489
1490     pl->uri = OICStrdup(res->uri);
1491
1492     if (!pl->uri)
1493     {
1494         OCDiscoveryResourceDestroy(pl);
1495         return NULL;
1496     }
1497
1498     // types
1499     OCResourceType* typePtr = res->rsrcType;
1500
1501     if (typePtr != NULL)
1502     {
1503         pl->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1504         if (!pl->types)
1505         {
1506             OCDiscoveryResourceDestroy(pl);
1507             return NULL;
1508         }
1509         pl->types->value = OICStrdup(typePtr->resourcetypename);
1510         if (!pl->types->value)
1511         {
1512             OCDiscoveryResourceDestroy(pl);
1513             return NULL;
1514         }
1515
1516         OCStringLL* cur = pl->types;
1517         typePtr = typePtr->next;
1518         while(typePtr)
1519         {
1520             cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1521             if (!cur->next)
1522             {
1523                 OCDiscoveryResourceDestroy(pl);
1524                 return NULL;
1525             }
1526             cur->next->value = OICStrdup(typePtr->resourcetypename);
1527             if (!cur->next->value)
1528             {
1529                 OCDiscoveryResourceDestroy(pl);
1530                 return NULL;
1531             }
1532             cur = cur->next;
1533             typePtr = typePtr->next;
1534         }
1535     }
1536
1537     // interfaces
1538     OCResourceInterface* ifPtr = res->rsrcInterface;
1539     if (ifPtr != NULL)
1540     {
1541         pl->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1542         if (!pl->interfaces)
1543         {
1544             OCDiscoveryResourceDestroy(pl);
1545             return NULL;
1546         }
1547         pl->interfaces->value = OICStrdup(ifPtr->name);
1548         if (!pl->interfaces->value)
1549         {
1550             OCDiscoveryResourceDestroy(pl);
1551             return NULL;
1552         }
1553
1554         OCStringLL* cur = pl->interfaces;
1555         ifPtr = ifPtr->next;
1556         while(ifPtr && cur)
1557         {
1558             cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1559             if (!cur->next)
1560             {
1561                 OCDiscoveryResourceDestroy(pl);
1562                 return NULL;
1563             }
1564             cur->next->value = OICStrdup(ifPtr->name);
1565             if (!cur->next->value)
1566             {
1567                 OCDiscoveryResourceDestroy(pl);
1568                 return NULL;
1569             }
1570             cur = cur->next;
1571             ifPtr = ifPtr->next;
1572         }
1573     }
1574
1575     pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE);
1576     pl->secure = (res->resourceProperties & OC_SECURE) != 0;
1577     pl->port = securePort;
1578 #ifdef TCP_ADAPTER
1579     pl->tcpPort = tcpPort;
1580 #endif
1581     return pl;
1582 }
1583
1584 void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
1585                                    uint16_t securePort, uint16_t tcpPort)
1586 {
1587     OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, securePort, tcpPort));
1588 }
1589
1590 bool OCResourcePayloadAddStringLL(OCStringLL **stringLL, const char *value)
1591 {
1592     char *dup = OICStrdup(value);
1593     VERIFY_PARAM_NON_NULL(TAG, dup, "Failed copying string");
1594     VERIFY_PARAM_NON_NULL(TAG, value, "Invalid Parameters");
1595
1596     if (!*stringLL)
1597     {
1598         *stringLL = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
1599         VERIFY_PARAM_NON_NULL(TAG, *stringLL, "Failed allocating memory");
1600         (*stringLL)->value = dup;
1601         return true;
1602     }
1603     else
1604     {
1605         OCStringLL *temp = *stringLL;
1606         while(temp->next)
1607         {
1608             temp = temp->next;
1609         }
1610         temp->next = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
1611         VERIFY_PARAM_NON_NULL(TAG, temp->next, "Failed allocating memory");
1612         temp->next->value = dup;
1613         return true;
1614     }
1615 exit:
1616     OICFree(dup);
1617     return false;
1618 }
1619
1620 void OCDiscoveryPayloadAddNewResource(OCDiscoveryPayload* payload, OCResourcePayload* res)
1621 {
1622     if (!payload)
1623     {
1624         return;
1625     }
1626
1627     if (!payload->resources)
1628     {
1629         payload->resources = res;
1630     }
1631     else
1632     {
1633         OCResourcePayload* p = payload->resources;
1634         while(p->next)
1635         {
1636             p = p->next;
1637         }
1638         p->next = res;
1639     }
1640 }
1641
1642 void OCDiscoveryResourceDestroy(OCResourcePayload* payload)
1643 {
1644     if (!payload)
1645     {
1646         return;
1647     }
1648
1649     OICFree(payload->uri);
1650     OCFreeOCStringLL(payload->types);
1651     OCFreeOCStringLL(payload->interfaces);
1652     OCDiscoveryResourceDestroy(payload->next);
1653     OICFree(payload);
1654
1655 }
1656 void OCDiscoveryPayloadDestroy(OCDiscoveryPayload* payload)
1657 {
1658     if (!payload)
1659     {
1660         return;
1661     }
1662     OICFree(payload->sid);
1663     OICFree(payload->baseURI);
1664     OICFree(payload->uri);
1665     OCFreeOCStringLL(payload->type);
1666     OICFree(payload->name);
1667     OCFreeOCStringLL(payload->interface);
1668     OCDiscoveryResourceDestroy(payload->resources);
1669     OICFree(payload);
1670 }
1671
1672 OCDevicePayload* OCDevicePayloadCreate(const char* sid, const char* dname,
1673         const OCStringLL *types, const char* specVer, const char* dmVer)
1674 {
1675
1676     OCDevicePayload* payload = (OCDevicePayload*)OICCalloc(1, sizeof(OCDevicePayload));
1677
1678     if (!payload)
1679     {
1680         return NULL;
1681     }
1682
1683     payload->base.type = PAYLOAD_TYPE_DEVICE;
1684     payload->sid = OICStrdup(sid);
1685     if (sid && !payload->sid)
1686     {
1687         goto exit;
1688     }
1689
1690     payload->deviceName = OICStrdup(dname);
1691     if (dname && !payload->deviceName)
1692     {
1693         goto exit;
1694     }
1695
1696     payload->specVersion = OICStrdup(specVer);
1697     if (specVer && !payload->specVersion)
1698     {
1699         goto exit;
1700     }
1701
1702     payload->dataModelVersions = OCCreateOCStringLL(dmVer);
1703     if (!payload->dataModelVersions || (dmVer && !payload->dataModelVersions->value))
1704     {
1705         goto exit;
1706     }
1707
1708     OCResourcePayloadAddStringLL(&payload->interfaces, OC_RSRVD_INTERFACE_DEFAULT);
1709     OCResourcePayloadAddStringLL(&payload->interfaces, OC_RSRVD_INTERFACE_READ);
1710
1711     payload->types = CloneOCStringLL((OCStringLL *)types);
1712     if (types && !payload->types)
1713     {
1714         goto exit;
1715     }
1716
1717     return payload;
1718
1719 exit:
1720     OCDevicePayloadDestroy((OCDevicePayload*)payload);
1721     return NULL;
1722 }
1723
1724 void OCDevicePayloadDestroy(OCDevicePayload* payload)
1725 {
1726     if (!payload)
1727     {
1728         return;
1729     }
1730
1731     OICFree(payload->sid);
1732     OICFree(payload->deviceName);
1733     OICFree(payload->specVersion);
1734     OCFreeOCStringLL(payload->dataModelVersions);
1735     OCFreeOCStringLL(payload->types);
1736     OCFreeOCStringLL(payload->interfaces);
1737     OICFree(payload);
1738 }
1739
1740 static void OCCopyPlatformInfo(const OCPlatformInfo* platformInfo, OCPlatformPayload* target)
1741 {
1742     if (!platformInfo || !target)
1743     {
1744         return;
1745     }
1746
1747     target->info.platformID = OICStrdup(platformInfo->platformID);
1748     target->info.manufacturerName = OICStrdup(platformInfo->manufacturerName);
1749     target->info.manufacturerUrl = OICStrdup(platformInfo->manufacturerUrl);
1750     target->info.modelNumber = OICStrdup(platformInfo->modelNumber);
1751     target->info.dateOfManufacture = OICStrdup(platformInfo->dateOfManufacture);
1752     target->info.platformVersion = OICStrdup(platformInfo->platformVersion);
1753     target->info.operatingSystemVersion = OICStrdup(platformInfo->operatingSystemVersion);
1754     target->info.hardwareVersion = OICStrdup(platformInfo->hardwareVersion);
1755     target->info.firmwareVersion = OICStrdup(platformInfo->firmwareVersion);
1756     target->info.supportUrl = OICStrdup(platformInfo->supportUrl);
1757     target->info.systemTime = OICStrdup(platformInfo->systemTime);
1758 }
1759
1760 OCPlatformPayload* OCPlatformPayloadCreateAsOwner(OCPlatformInfo* platformInfo)
1761 {
1762     OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
1763     if (!payload)
1764     {
1765         return NULL;
1766     }
1767
1768     payload->base.type = PAYLOAD_TYPE_PLATFORM;
1769
1770     payload->info = *platformInfo;
1771
1772     return payload;
1773 }
1774
1775 OCPlatformPayload* OCPlatformPayloadCreate(const OCPlatformInfo* platformInfo)
1776 {
1777     OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
1778
1779     if (!payload)
1780     {
1781         return NULL;
1782     }
1783
1784     payload->base.type = PAYLOAD_TYPE_PLATFORM;
1785
1786     OCResourcePayloadAddStringLL(&payload->interfaces, OC_RSRVD_INTERFACE_DEFAULT);
1787     OCResourcePayloadAddStringLL(&payload->interfaces, OC_RSRVD_INTERFACE_READ);
1788
1789     OCResourcePayloadAddStringLL(&payload->rt, OC_RSRVD_RESOURCE_TYPE_PLATFORM);
1790     OCCopyPlatformInfo(platformInfo, payload);
1791
1792     return payload;
1793 }
1794
1795 void OCPlatformInfoDestroy(OCPlatformInfo *info)
1796 {
1797     OICFree(info->platformID);
1798     OICFree(info->manufacturerName);
1799     OICFree(info->manufacturerUrl);
1800     OICFree(info->modelNumber);
1801     OICFree(info->dateOfManufacture);
1802     OICFree(info->platformVersion);
1803     OICFree(info->operatingSystemVersion);
1804     OICFree(info->hardwareVersion);
1805     OICFree(info->firmwareVersion);
1806     OICFree(info->supportUrl);
1807     OICFree(info->systemTime);
1808 }
1809
1810 void OCPlatformPayloadDestroy(OCPlatformPayload* payload)
1811 {
1812     if (!payload)
1813     {
1814         return;
1815     }
1816     OICFree(payload->uri);
1817     OCPlatformInfoDestroy(&payload->info);
1818     OCFreeOCStringLL(payload->rt);
1819     OCFreeOCStringLL(payload->interfaces);
1820     OICFree(payload);
1821 }
1822
1823 OCPresencePayload* OCPresencePayloadCreate(uint32_t seqNum, uint32_t maxAge,
1824         OCPresenceTrigger trigger, const char* resourceType)
1825 {
1826     OCPresencePayload* payload = (OCPresencePayload*)OICCalloc(1, sizeof(OCPresencePayload));
1827     if (!payload)
1828     {
1829         return NULL;
1830     }
1831
1832     payload->base.type = PAYLOAD_TYPE_PRESENCE;
1833     payload->sequenceNumber = seqNum;
1834     payload->maxAge = maxAge;
1835     payload->trigger = trigger;
1836     payload->resourceType = OICStrdup(resourceType);
1837     return payload;
1838 }
1839
1840 void OCPresencePayloadDestroy(OCPresencePayload* payload)
1841 {
1842     if (!payload)
1843     {
1844         return;
1845     }
1846     OICFree(payload->resourceType);
1847     OICFree(payload);
1848 }