Fixed a large amount of memory leaks/ Null pointer dereferences
[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
22 #include "ocpayload.h"
23 #include "octypes.h"
24 #include <string.h>
25 #include "oic_malloc.h"
26 #include "oic_string.h"
27 #include "ocstackinternal.h"
28 #include "ocresource.h"
29 #include "logger.h"
30
31 #define TAG "OCPayload"
32 static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val);
33 static void FreeOCDiscoveryResource(OCResourcePayload* payload);
34
35 void OCPayloadDestroy(OCPayload* payload)
36 {
37     if(!payload)
38     {
39         return;
40     }
41
42     switch(payload->type)
43     {
44         case PAYLOAD_TYPE_REPRESENTATION:
45             OCRepPayloadDestroy((OCRepPayload*)payload);
46             break;
47         case PAYLOAD_TYPE_DISCOVERY:
48             OCDiscoveryPayloadDestroy((OCDiscoveryPayload*)payload);
49             break;
50         case PAYLOAD_TYPE_DEVICE:
51             OCDevicePayloadDestroy((OCDevicePayload*)payload);
52             break;
53         case PAYLOAD_TYPE_PLATFORM:
54             OCPlatformPayloadDestroy((OCPlatformPayload*)payload);
55             break;
56         case PAYLOAD_TYPE_PRESENCE:
57             OCPresencePayloadDestroy((OCPresencePayload*)payload);
58             break;
59         case PAYLOAD_TYPE_SECURITY:
60             OCSecurityPayloadDestroy((OCSecurityPayload*)payload);
61             break;
62         default:
63             OC_LOG_V(ERROR, TAG, "Unsupported payload type in destroy: %d", payload->type);
64             OICFree(payload);
65             break;
66     }
67 }
68 OCRepPayload* OCRepPayloadCreate()
69 {
70     OCRepPayload* payload = (OCRepPayload*)OICCalloc(1, sizeof(OCRepPayload));
71
72     if(!payload)
73     {
74         return NULL;
75     }
76
77     payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
78
79     return payload;
80 }
81
82 void OCRepPayloadAppend(OCRepPayload* parent, OCRepPayload* child)
83 {
84     if(!parent)
85     {
86         return;
87     }
88
89     while(parent->next)
90     {
91         parent = parent->next;
92     }
93
94     parent->next= child;
95     child->next = NULL;
96 }
97
98 static OCRepPayloadValue* OCRepPayloadFindValue(const OCRepPayload* payload, const char* name)
99 {
100     if(!payload || !name)
101     {
102         return NULL;
103     }
104
105     OCRepPayloadValue* val = payload->values;
106     while(val)
107     {
108         if(0 == strcmp(val->name, name))
109         {
110             return val;
111         }
112         val = val->next;
113     }
114
115     return NULL;
116
117 }
118
119 static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue* source)
120 {
121     size_t dimTotal = calcDimTotal(source->arr.dimensions);
122     switch(source->arr.type)
123     {
124         case OCREP_PROP_INT:
125             dest->arr.iArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
126             memcpy(dest->arr.iArray, source->arr.iArray, dimTotal * sizeof(int64_t));
127             break;
128         case OCREP_PROP_DOUBLE:
129             dest->arr.dArray = (double*)OICMalloc(dimTotal * sizeof(double));
130             memcpy(dest->arr.dArray, source->arr.dArray, dimTotal * sizeof(double));
131             break;
132         case OCREP_PROP_BOOL:
133             dest->arr.bArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
134             memcpy(dest->arr.bArray, source->arr.bArray, dimTotal * sizeof(bool));
135             break;
136         case OCREP_PROP_STRING:
137             dest->arr.strArray = (char**)OICMalloc(dimTotal * sizeof(char*));
138             for(size_t i = 0; i < dimTotal; ++i)
139             {
140                 dest->arr.strArray[i] = OICStrdup(source->arr.strArray[i]);
141             }
142             break;
143         case OCREP_PROP_ARRAY:
144             dest->arr.objArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
145             for(size_t i = 0; i < dimTotal; ++i)
146             {
147                 dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
148             }
149             break;
150         default:
151             OC_LOG(ERROR, TAG, PCF("CopyPropertyValueArray invalid type"));
152             break;
153     }
154 }
155
156 static void OCCopyPropertyValue (OCRepPayloadValue *dest, OCRepPayloadValue *source)
157 {
158     if (!source || !dest)
159     {
160         return;
161     }
162
163     switch(source->type)
164     {
165         case OCREP_PROP_STRING:
166             dest->str = OICStrdup(source->str);
167             break;
168         case OCREP_PROP_OBJECT:
169             dest->obj = OCRepPayloadClone(source->obj);
170             break;
171         case OCREP_PROP_ARRAY:
172             OCCopyPropertyValueArray(dest, source);
173             break;
174         default:
175             // Nothing to do for the trivially copyable types.
176             break;
177     }
178 }
179
180 static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val)
181 {
182     if(!val)
183     {
184         return;
185     }
186
187     if(val->type == OCREP_PROP_STRING)
188     {
189         OICFree(val->str);
190     }
191     else if (val->type == OCREP_PROP_OBJECT)
192     {
193         OCRepPayloadDestroy(val->obj);
194     }
195     else if (val->type == OCREP_PROP_ARRAY)
196     {
197         size_t dimTotal = calcDimTotal(val->arr.dimensions);
198         switch(val->arr.type)
199         {
200             case OCREP_PROP_INT:
201             case OCREP_PROP_DOUBLE:
202             case OCREP_PROP_BOOL:
203                 // Since this is a union, iArray will
204                 // point to all of the above
205                 OICFree(val->arr.iArray);
206                 break;
207             case OCREP_PROP_STRING:
208                 for(size_t i = 0; i< dimTotal;++i)
209                 {
210                     OICFree(val->arr.strArray[i]);
211                 }
212                 OICFree(val->arr.strArray);
213                 break;
214             case OCREP_PROP_OBJECT:
215                 for(size_t i = 0; i< dimTotal;++i)
216                 {
217                     OCRepPayloadDestroy(val->arr.objArray[i]);
218                 }
219                 OICFree(val->arr.objArray);
220                 break;
221             case OCREP_PROP_NULL:
222             case OCREP_PROP_ARRAY:
223                 OC_LOG_V(ERROR, TAG, "FreeRepPayloadValueContents: Illegal type\
224                         inside an array: %d", val->arr.type);
225                 break;
226         }
227     }
228 }
229
230 static void OCFreeRepPayloadValue(OCRepPayloadValue* val)
231 {
232     if(!val)
233     {
234         return;
235     }
236
237     OICFree(val->name);
238     OCFreeRepPayloadValueContents(val);
239     OCFreeRepPayloadValue(val->next);
240     OICFree(val);
241 }
242 static OCRepPayloadValue* OCRepPayloadValueClone (OCRepPayloadValue* source)
243 {
244     if (!source)
245     {
246         return NULL;
247     }
248
249     OCRepPayloadValue *sourceIter = source;
250     OCRepPayloadValue *destIter = (OCRepPayloadValue*) OICCalloc(1, sizeof(OCRepPayloadValue));
251     if (!destIter)
252     {
253         return NULL;
254     }
255
256     OCRepPayloadValue *headOfClone = destIter;
257
258     // Copy payload type and non pointer types in union.
259     *destIter = *sourceIter;
260     destIter->name = OICStrdup (sourceIter->name);
261     OCCopyPropertyValue (destIter, sourceIter);
262
263     sourceIter = sourceIter->next;
264
265     while (sourceIter)
266     {
267         destIter->next = (OCRepPayloadValue*) OICCalloc(1, sizeof(OCRepPayloadValue));
268         if (!destIter->next)
269         {
270             OCFreeRepPayloadValue (headOfClone);
271             return NULL;
272         }
273
274         *(destIter->next) = *sourceIter;
275         destIter->next->name = OICStrdup (sourceIter->name);
276         OCCopyPropertyValue (destIter->next, sourceIter);
277
278         sourceIter = sourceIter->next;
279         destIter = destIter->next;
280     }
281     return headOfClone;
282 }
283
284 static OCRepPayloadValue* OCRepPayloadFindAndSetValue(OCRepPayload* payload, const char* name,
285         OCRepPayloadPropType type)
286 {
287     if(!payload || !name)
288     {
289         return NULL;
290     }
291
292     OCRepPayloadValue* val = payload->values;
293     if(val == NULL)
294     {
295         payload->values = (OCRepPayloadValue*)OICCalloc(1, sizeof(OCRepPayloadValue));
296         if(!payload->values)
297         {
298             return NULL;
299         }
300         payload->values->name = OICStrdup(name);
301         if(!payload->values->name)
302         {
303             OICFree(payload->values);
304             payload->values = NULL;
305             return NULL;
306         }
307         payload->values->type =type;
308         return payload->values;
309     }
310
311     while(val)
312     {
313         if(0 == strcmp(val->name, name))
314         {
315             OCFreeRepPayloadValueContents(val);
316             val->type = type;
317             return val;
318         }
319         else if(val->next == NULL)
320         {
321             val->next = (OCRepPayloadValue*)OICCalloc(1, sizeof(OCRepPayloadValue));
322             if(!val->next)
323             {
324                 return NULL;
325             }
326             val->next->name = OICStrdup(name);
327             if(!val->next->name)
328             {
329                 OICFree(val->next);
330                 val->next = NULL;
331                 return NULL;
332             }
333             val->next->type =type;
334             return val->next;
335         }
336
337         val = val->next;
338     }
339
340     OC_LOG(ERROR, TAG, PCF("FindAndSetValue reached point after while loop, pointer corruption?"));
341     return NULL;
342 }
343
344 bool OCRepPayloadAddResourceType(OCRepPayload* payload, const char* resourceType)
345 {
346     return OCRepPayloadAddResourceTypeAsOwner(payload, OICStrdup(resourceType));
347 }
348
349 bool OCRepPayloadAddResourceTypeAsOwner(OCRepPayload* payload, char* resourceType)
350 {
351     if(!payload || !resourceType)
352     {
353         return false;
354     }
355
356     if(payload->types)
357     {
358         OCStringLL* cur = payload->types;
359         while(cur->next)
360         {
361             cur = cur->next;
362         }
363         cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
364
365         if(!cur->next)
366         {
367             return false;
368         }
369
370         cur->next->value = resourceType;
371         return true;
372     }
373     else
374     {
375         payload->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
376         if(!payload->types)
377         {
378             return false;
379         }
380         payload->types->value = resourceType;
381         return true;
382     }
383 }
384
385 bool OCRepPayloadAddInterface(OCRepPayload* payload, const char* interface)
386 {
387     return OCRepPayloadAddInterfaceAsOwner(payload, OICStrdup(interface));
388 }
389
390 bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* interface)
391 {
392     if(!payload || !interface)
393     {
394         return false;
395     }
396
397     if(payload->interfaces)
398     {
399         OCStringLL* cur = payload->interfaces;
400         while(cur->next)
401         {
402             cur = cur->next;
403         }
404         cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
405
406         if(!cur->next)
407         {
408             return false;
409         }
410         cur->next->value = interface;
411         return true;
412     }
413     else
414     {
415         payload->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
416         if(!payload->interfaces)
417         {
418             return false;
419         }
420         payload->interfaces->value = interface;
421         return true;
422     }
423 }
424
425 bool OCRepPayloadSetUri(OCRepPayload* payload, const char*  uri)
426 {
427     if(!payload)
428     {
429         return false;
430     }
431
432     payload->uri = OICStrdup(uri);
433     return payload->uri != NULL;
434 }
435
436 bool OCRepPayloadIsNull(const OCRepPayload* payload, const char* name)
437 {
438     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
439
440     if(!val)
441     {
442         return false;
443     }
444
445     return val->type == OCREP_PROP_NULL;
446 }
447
448 bool OCRepPayloadSetNull(OCRepPayload* payload, const char* name)
449 {
450     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_NULL);
451     return val != NULL;
452 }
453
454 bool OCRepPayloadSetPropInt(OCRepPayload* payload,
455         const char* name, int64_t value)
456 {
457     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_INT);
458
459     if(!val)
460     {
461         return false;
462     }
463
464     val->i = value;
465     return true;
466 }
467
468 bool OCRepPayloadGetPropInt(const OCRepPayload* payload, const char* name, int64_t* value)
469 {
470     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
471
472     if(!val || val->type != OCREP_PROP_INT)
473     {
474         return false;
475     }
476
477     *value = val->i;
478     return true;
479 }
480
481 bool OCRepPayloadSetPropDouble(OCRepPayload* payload,
482         const char* name, double value)
483 {
484     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_DOUBLE);
485
486     if(!val )
487     {
488         return false;
489     }
490
491     val->d = value;
492     return true;
493 }
494
495 bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, double* value)
496 {
497     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
498
499     if(!val || val->type != OCREP_PROP_DOUBLE)
500     {
501         return false;
502     }
503
504     *value = val->d;
505     return true;
506 }
507
508 bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value)
509 {
510     char* temp = OICStrdup(value);
511     bool b = OCRepPayloadSetPropStringAsOwner(payload, name, temp);
512
513     if(!b)
514     {
515         OICFree(temp);
516     }
517     return b;
518 }
519
520 bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value)
521 {
522     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_STRING);
523
524     if(!val)
525     {
526         return false;
527     }
528
529     val->str = value;
530     return val->str != NULL;
531 }
532
533 bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, const char** value)
534 {
535     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
536
537     if(!val || val->type != OCREP_PROP_STRING)
538     {
539         return false;
540     }
541
542     *value = OICStrdup(val->str);
543     return *value != NULL;
544 }
545
546 bool OCRepPayloadSetPropBool(OCRepPayload* payload,
547         const char* name, bool value)
548 {
549     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_BOOL);
550
551     if(!val)
552     {
553         return false;
554     }
555
556     val->b = value;
557     return true;
558 }
559
560 bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool* value)
561 {
562     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
563
564     if(!val || val->type != OCREP_PROP_BOOL)
565     {
566         return false;
567     }
568
569     *value = val->b;
570     return true;
571 }
572
573 bool OCRepPayloadSetPropObject(OCRepPayload* payload, const char* name, const OCRepPayload* value)
574 {
575     OCRepPayload* temp = OCRepPayloadClone(value);
576     bool b = OCRepPayloadSetPropObjectAsOwner(payload, name, temp);
577
578     if(!b)
579     {
580         OCRepPayloadDestroy(temp);
581     }
582     return b;
583 }
584
585 bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name, OCRepPayload* value)
586 {
587     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_OBJECT);
588
589     if(!val)
590     {
591         return false;
592     }
593
594     val->obj = value;
595     return true;
596 }
597
598 bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value)
599 {
600     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
601
602     if(!val || val->type != OCREP_PROP_OBJECT)
603     {
604         return false;
605     }
606
607     *value = OCRepPayloadClone(val->obj);
608     return *value != NULL;
609 }
610
611 size_t calcDimTotal(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
612 {
613     if(dimensions[0] == 0)
614     {
615         return 0;
616     }
617
618     size_t total = 1;
619     for(uint8_t i = 0; i < MAX_REP_ARRAY_DEPTH && dimensions[i] != 0; ++i)
620     {
621         total *= dimensions[i];
622     }
623     return total;
624 }
625
626 bool OCRepPayloadSetIntArrayAsOwner(OCRepPayload* payload, const char* name,
627         int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
628 {
629     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
630
631     if(!val)
632     {
633         return false;
634     }
635
636     val->arr.type = OCREP_PROP_INT;
637     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
638     val->arr.iArray = array;
639
640     return true;
641 }
642
643 bool OCRepPayloadSetIntArray(OCRepPayload* payload, const char* name,
644         const int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
645 {
646     size_t dimTotal = calcDimTotal(dimensions);
647     if(dimTotal == 0)
648     {
649         return false;
650     }
651
652     int64_t* newArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
653
654     if(!newArray)
655     {
656         return false;
657     }
658
659     memcpy(newArray, array, dimTotal * sizeof(int64_t));
660
661
662     bool b = OCRepPayloadSetIntArrayAsOwner(payload, name, newArray, dimensions);
663     if(!b)
664     {
665         OICFree(newArray);
666     }
667     return b;
668 }
669
670 bool OCRepPayloadGetIntArray(const OCRepPayload* payload, const char* name,
671         int64_t** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
672 {
673     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
674
675     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_INT
676             || !val->arr.iArray)
677     {
678         return false;
679     }
680
681     size_t dimTotal = calcDimTotal(val->arr.dimensions);
682     if(dimTotal == 0)
683     {
684         return false;
685     }
686     *array = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
687     if(!*array)
688     {
689         return false;
690     }
691
692     memcpy(*array, val->arr.iArray, dimTotal * sizeof(int64_t));
693     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
694     return true;
695 }
696
697 bool OCRepPayloadSetDoubleArrayAsOwner(OCRepPayload* payload, const char* name,
698         double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
699 {
700     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
701
702     if(!val)
703     {
704         return false;
705     }
706
707     val->arr.type = OCREP_PROP_DOUBLE;
708     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
709     val->arr.dArray = array;
710
711     return true;
712 }
713 bool OCRepPayloadSetDoubleArray(OCRepPayload* payload, const char* name,
714         const double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
715 {
716     size_t dimTotal = calcDimTotal(dimensions);
717     if(dimTotal == 0)
718     {
719         return false;
720     }
721
722     double* newArray = (double*)OICMalloc(dimTotal * sizeof(double));
723
724     if(!newArray)
725     {
726         return false;
727     }
728
729     memcpy(newArray, array, dimTotal * sizeof(double));
730
731     bool b = OCRepPayloadSetDoubleArrayAsOwner(payload, name, newArray, dimensions);
732     if(!b)
733     {
734         OICFree(newArray);
735     }
736     return b;
737 }
738
739 bool OCRepPayloadGetDoubleArray(const OCRepPayload* payload, const char* name,
740         double** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
741 {
742     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
743
744     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_DOUBLE
745             || !val->arr.dArray)
746     {
747         return false;
748     }
749
750     size_t dimTotal = calcDimTotal(val->arr.dimensions);
751     if(dimTotal == 0)
752     {
753         return false;
754     }
755     *array = (double*)OICMalloc(dimTotal * sizeof(double));
756     if(!*array)
757     {
758         return false;
759     }
760
761     memcpy(*array, val->arr.dArray, dimTotal * sizeof(double));
762     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
763     return true;
764 }
765
766 bool OCRepPayloadSetStringArrayAsOwner(OCRepPayload* payload, const char* name,
767         char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
768 {
769     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
770
771     if(!val)
772     {
773         return false;
774     }
775
776     val->arr.type = OCREP_PROP_STRING;
777     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
778     val->arr.strArray = array;
779
780     return true;
781 }
782 bool OCRepPayloadSetStringArray(OCRepPayload* payload, const char* name,
783         const char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
784 {
785     size_t dimTotal = calcDimTotal(dimensions);
786     if(dimTotal == 0)
787     {
788         return false;
789     }
790
791     char** newArray = (char**)OICMalloc(dimTotal * sizeof(char*));
792
793     if(!newArray)
794     {
795         return false;
796     }
797
798     for(size_t i = 0; i < dimTotal; ++i)
799     {
800         newArray[i] = OICStrdup(array[i]);
801     }
802
803     bool b = OCRepPayloadSetStringArrayAsOwner(payload, name, newArray, dimensions);
804
805     if(!b)
806     {
807         for(size_t i = 0; i < dimTotal; ++i)
808         {
809             OICFree(newArray[i]);
810         }
811         OICFree(newArray);
812     }
813     return b;
814 }
815
816 bool OCRepPayloadGetStringArray(const OCRepPayload* payload, const char* name,
817         char*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
818 {
819     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
820
821     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_STRING
822             || !val->arr.strArray)
823     {
824         return false;
825     }
826
827     size_t dimTotal = calcDimTotal(val->arr.dimensions);
828     if(dimTotal == 0)
829     {
830         return false;
831     }
832     *array = (char**)OICMalloc(dimTotal * sizeof(char*));
833     if(!*array)
834     {
835         return false;
836     }
837
838     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
839
840     for(size_t i = 0; i < dimTotal; ++i)
841     {
842         (*array)[i] = OICStrdup(val->arr.strArray[i]);
843     }
844
845     return true;
846
847 }
848
849 bool OCRepPayloadSetBoolArrayAsOwner(OCRepPayload* payload, const char* name,
850         bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
851 {
852
853     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
854
855     if(!val)
856     {
857         return false;
858     }
859
860     val->arr.type = OCREP_PROP_BOOL;
861     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
862     val->arr.bArray = array;
863
864     return true;
865 }
866 bool OCRepPayloadSetBoolArray(OCRepPayload* payload, const char* name,
867         const bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
868 {
869     size_t dimTotal = calcDimTotal(dimensions);
870     if(dimTotal == 0)
871     {
872         return false;
873     }
874
875     bool* newArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
876
877     if(!newArray)
878     {
879         return false;
880     }
881
882     memcpy(newArray, array, dimTotal * sizeof(bool));
883
884
885     bool b = OCRepPayloadSetBoolArrayAsOwner(payload, name, newArray, dimensions);
886     if(!b)
887     {
888         OICFree(newArray);
889     }
890     return b;
891 }
892
893 bool OCRepPayloadGetBoolArray(const OCRepPayload* payload, const char* name,
894         bool** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
895 {
896     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
897
898     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_BOOL
899             || !val->arr.bArray)
900     {
901         return false;
902     }
903
904     size_t dimTotal = calcDimTotal(val->arr.dimensions);
905     if(dimTotal == 0)
906     {
907         return false;
908     }
909     *array = (bool*)OICMalloc(dimTotal * sizeof(bool));
910     if(!*array)
911     {
912         return false;
913     }
914
915     memcpy(*array, val->arr.bArray, dimTotal * sizeof(bool));
916     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
917     return true;
918 }
919
920 bool OCRepPayloadSetPropObjectArrayAsOwner(OCRepPayload* payload, const char* name,
921         OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
922 {
923     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
924
925     if(!val)
926     {
927         return false;
928     }
929
930     val->arr.type = OCREP_PROP_OBJECT;
931     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
932     val->arr.objArray = array;
933
934     return true;
935 }
936
937 bool OCRepPayloadSetPropObjectArray(OCRepPayload* payload, const char* name,
938         const OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
939 {
940     size_t dimTotal = calcDimTotal(dimensions);
941     if(dimTotal == 0)
942     {
943         return false;
944     }
945
946     OCRepPayload** newArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
947
948     if(!newArray)
949     {
950         return false;
951     }
952
953     for(size_t i = 0; i < dimTotal; ++i)
954     {
955         newArray[i] = OCRepPayloadClone(array[i]);
956     }
957
958     bool b = OCRepPayloadSetPropObjectArrayAsOwner(payload, name, newArray, dimensions);
959
960     if(!b)
961     {
962         for(size_t i = 0; i < dimTotal; ++i)
963         {
964            OCRepPayloadDestroy(newArray[i]);
965         }
966         OICFree(newArray);
967     }
968     return b;
969 }
970
971 bool OCRepPayloadGetPropObjectArray(const OCRepPayload* payload, const char* name,
972         OCRepPayload*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
973 {
974     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
975
976     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_OBJECT
977             || !val->arr.objArray)
978     {
979         return false;
980     }
981
982     size_t dimTotal = calcDimTotal(val->arr.dimensions);
983     if(dimTotal == 0)
984     {
985         return false;
986     }
987     *array = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
988     if(!*array)
989     {
990         return false;
991     }
992
993     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
994
995     for(size_t i = 0; i < dimTotal; ++i)
996     {
997         (*array)[i] = OCRepPayloadClone(val->arr.objArray[i]);
998     }
999
1000     return true;
1001 }
1002
1003 void OCFreeOCStringLL(OCStringLL* ll)
1004 {
1005     if(!ll)
1006     {
1007         return;
1008     }
1009
1010     OCFreeOCStringLL(ll->next);
1011     OICFree(ll->value);
1012     OICFree(ll);
1013 }
1014
1015 OCStringLL* CloneOCStringLL (OCStringLL* ll)
1016 {
1017     if (!ll)
1018     {
1019         return NULL;
1020     }
1021
1022     OCStringLL *sourceIter = ll;
1023
1024     OCStringLL *destIter = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1025     if (!destIter)
1026     {
1027         return NULL;
1028     }
1029     destIter->value = OICStrdup (sourceIter->value);
1030
1031     OCStringLL *headOfClone = destIter;
1032
1033     sourceIter = sourceIter->next;
1034
1035     while (sourceIter)
1036     {
1037         destIter->next  = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1038         if (!destIter->next)
1039         {
1040             OCFreeOCStringLL (headOfClone);
1041             return NULL;
1042         }
1043         destIter->next->value = OICStrdup (sourceIter->value);
1044
1045         destIter = destIter->next;
1046         sourceIter = sourceIter->next;
1047     }
1048     return headOfClone;
1049 }
1050
1051 OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
1052 {
1053     if (!payload)
1054     {
1055         return NULL;
1056     }
1057
1058     OCRepPayload *clone = OCRepPayloadCreate();
1059
1060     if (!clone)
1061     {
1062         return NULL;
1063     }
1064
1065     clone->uri = OICStrdup (payload->uri);
1066     clone->types = CloneOCStringLL (payload->types);
1067     clone->interfaces = CloneOCStringLL (payload->interfaces);
1068     clone->values = OCRepPayloadValueClone (payload->values);
1069
1070     return clone;
1071 }
1072
1073
1074 void OCRepPayloadDestroy(OCRepPayload* payload)
1075 {
1076     if(!payload)
1077     {
1078         return;
1079     }
1080
1081     OICFree(payload->uri);
1082     OCFreeOCStringLL(payload->types);
1083     OCFreeOCStringLL(payload->interfaces);
1084     OCFreeRepPayloadValue(payload->values);
1085     OCRepPayloadDestroy(payload->next);
1086     OICFree(payload);
1087 }
1088
1089 OCDiscoveryPayload* OCDiscoveryPayloadCreate()
1090 {
1091     OCDiscoveryPayload* payload = (OCDiscoveryPayload*)OICCalloc(1, sizeof(OCDiscoveryPayload));
1092
1093     if(!payload)
1094     {
1095         return NULL;
1096     }
1097
1098     payload->base.type = PAYLOAD_TYPE_DISCOVERY;
1099
1100     return payload;
1101 }
1102
1103 OCSecurityPayload* OCSecurityPayloadCreate(const char* securityData)
1104 {
1105     OCSecurityPayload* payload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1106
1107     if(!payload)
1108     {
1109         return NULL;
1110     }
1111
1112     payload->base.type = PAYLOAD_TYPE_SECURITY;
1113     payload->securityData = OICStrdup(securityData);
1114
1115     return payload;
1116 }
1117
1118 void OCSecurityPayloadDestroy(OCSecurityPayload* payload)
1119 {
1120     if(!payload)
1121     {
1122         return;
1123     }
1124
1125     OICFree(payload->securityData);
1126     OICFree(payload);
1127 }
1128
1129 size_t OCDiscoveryPayloadGetResourceCount(OCDiscoveryPayload* payload)
1130 {
1131     size_t i = 0;
1132     OCResourcePayload* p = payload->resources;
1133     while(p)
1134     {
1135         ++i;
1136         p = p->next;
1137     }
1138     return i;
1139 }
1140
1141 OCResourcePayload* OCDiscoveryPayloadGetResource(OCDiscoveryPayload* payload, size_t index)
1142 {
1143     size_t i = 0;
1144     OCResourcePayload* p = payload->resources;
1145     while(p)
1146     {
1147         if(i == index)
1148         {
1149             return p;
1150         }
1151         ++i;
1152         p = p->next;
1153     }
1154     return NULL;
1155 }
1156
1157 static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
1158 {
1159     OCResourcePayload* pl = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
1160     if(!pl)
1161     {
1162         return NULL;
1163     }
1164
1165     pl->uri = OICStrdup(res->uri);
1166     pl->sid = (uint8_t*)OICCalloc(1, UUID_SIZE);
1167     if(!pl->uri || ! pl->sid)
1168     {
1169         FreeOCDiscoveryResource(pl);
1170         return NULL;
1171     }
1172     memcpy(pl->sid, OCGetServerInstanceID(), UUID_SIZE);
1173
1174     // types
1175     OCResourceType* typePtr = res->rsrcType;
1176
1177     if(typePtr != NULL)
1178     {
1179         pl->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1180         if(!pl->types)
1181         {
1182             FreeOCDiscoveryResource(pl);
1183             return NULL;
1184         }
1185         pl->types->value = OICStrdup(typePtr->resourcetypename);
1186         if(!pl->types->value)
1187         {
1188             FreeOCDiscoveryResource(pl);
1189             return NULL;
1190         }
1191
1192         OCStringLL* cur = pl->types;
1193         typePtr = typePtr->next;
1194         while(typePtr)
1195         {
1196             cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1197             if(!cur->next)
1198             {
1199                 FreeOCDiscoveryResource(pl);
1200                 return NULL;
1201             }
1202             cur->next->value = OICStrdup(typePtr->resourcetypename);
1203             if(!cur->next->value)
1204             {
1205                 FreeOCDiscoveryResource(pl);
1206                 return NULL;
1207             }
1208             cur = cur->next;
1209             typePtr = typePtr->next;
1210         }
1211     }
1212
1213     // interfaces
1214     OCResourceInterface* ifPtr = res->rsrcInterface;
1215     if(ifPtr != NULL)
1216     {
1217         pl->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1218         if(!pl->interfaces)
1219         {
1220             FreeOCDiscoveryResource(pl);
1221             return NULL;
1222         }
1223         pl->interfaces->value = OICStrdup(ifPtr->name);
1224         if(!pl->interfaces->value)
1225         {
1226             FreeOCDiscoveryResource(pl);
1227             return NULL;
1228         }
1229
1230         OCStringLL* cur = pl->interfaces;
1231         ifPtr = ifPtr->next;
1232         while(ifPtr)
1233         {
1234             cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1235             if(!cur->next)
1236             {
1237                 FreeOCDiscoveryResource(pl);
1238                 return NULL;
1239             }
1240             cur->next->value = OICStrdup(ifPtr->name);
1241             if(!cur->next->value)
1242             {
1243                 FreeOCDiscoveryResource(pl);
1244                 return NULL;
1245             }
1246             cur = cur->next;
1247             ifPtr = ifPtr->next;
1248         }
1249     }
1250
1251     pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE);
1252     pl->secure = (res->resourceProperties & OC_SECURE) != 0;
1253     pl->port = port;
1254
1255     return pl;
1256 }
1257
1258 void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
1259         uint16_t port)
1260 {
1261     OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, port));
1262 }
1263
1264 void OCDiscoveryPayloadAddNewResource(OCDiscoveryPayload* payload, OCResourcePayload* res)
1265 {
1266     if(!payload->resources)
1267     {
1268         payload->resources = res;
1269     }
1270     else
1271     {
1272         OCResourcePayload* p = payload->resources;
1273         while(p->next)
1274         {
1275             p = p->next;
1276         }
1277         p->next = res;
1278     }
1279 }
1280
1281 static void FreeOCDiscoveryResource(OCResourcePayload* payload)
1282 {
1283     if(!payload)
1284     {
1285         return;
1286     }
1287
1288     OICFree(payload->uri);
1289     OICFree(payload->sid);
1290     OCFreeOCStringLL(payload->types);
1291     OCFreeOCStringLL(payload->interfaces);
1292     FreeOCDiscoveryResource(payload->next);
1293     OICFree(payload);
1294
1295 }
1296 void OCDiscoveryPayloadDestroy(OCDiscoveryPayload* payload)
1297 {
1298     if(!payload)
1299     {
1300         return;
1301     }
1302
1303     FreeOCDiscoveryResource(payload->resources);
1304     OICFree(payload);
1305 }
1306
1307 OCDevicePayload* OCDevicePayloadCreate(const char* uri, const uint8_t* sid, const char* dname,
1308         const char* specVer, const char* dmVer)
1309 {
1310
1311     OCDevicePayload* payload = (OCDevicePayload*)OICCalloc(1, sizeof(OCDevicePayload));
1312
1313     if(!payload)
1314     {
1315         return NULL;
1316     }
1317
1318     payload->base.type = PAYLOAD_TYPE_DEVICE;
1319
1320     payload->uri = OICStrdup(uri);
1321     if(uri && !payload->uri)
1322     {
1323         goto exit;
1324     }
1325
1326     if(sid)
1327     {
1328         payload->sid = (uint8_t*)OICMalloc(UUID_SIZE);
1329         if(!payload->sid)
1330         {
1331             goto exit;
1332         }
1333         memcpy(payload->sid, sid, UUID_SIZE);
1334     }
1335
1336     payload->deviceName = OICStrdup(dname);
1337     if(dname && !payload->deviceName)
1338     {
1339         goto exit;
1340     }
1341
1342     payload->specVersion = OICStrdup(specVer);
1343     if(specVer && !payload->specVersion)
1344     {
1345         goto exit;
1346     }
1347
1348     payload->dataModelVersion = OICStrdup(dmVer);
1349     if(dmVer && !payload->dataModelVersion)
1350     {
1351         goto exit;
1352     }
1353
1354     return payload;
1355
1356 exit:
1357     OCDevicePayloadDestroy((OCDevicePayload*)payload);
1358     return NULL;
1359 }
1360
1361 void OCDevicePayloadDestroy(OCDevicePayload* payload)
1362 {
1363     if(!payload)
1364     {
1365         return;
1366     }
1367
1368     OICFree(payload->uri);
1369     OICFree(payload->sid);
1370     OICFree(payload->deviceName);
1371     OICFree(payload->specVersion);
1372     OICFree(payload->dataModelVersion);
1373     OICFree(payload);
1374 }
1375
1376 static void OCCopyPlatformInfo(const OCPlatformInfo* platformInfo, OCPlatformPayload* target)
1377 {
1378     target->info.platformID = OICStrdup(platformInfo->platformID);
1379     target->info.manufacturerName = OICStrdup(platformInfo->manufacturerName);
1380     target->info.manufacturerUrl = OICStrdup(platformInfo->manufacturerUrl);
1381     target->info.modelNumber = OICStrdup(platformInfo->modelNumber);
1382     target->info.dateOfManufacture = OICStrdup(platformInfo->dateOfManufacture);
1383     target->info.platformVersion = OICStrdup(platformInfo->platformVersion);
1384     target->info.operatingSystemVersion = OICStrdup(platformInfo->operatingSystemVersion);
1385     target->info.hardwareVersion = OICStrdup(platformInfo->hardwareVersion);
1386     target->info.firmwareVersion = OICStrdup(platformInfo->firmwareVersion);
1387     target->info.supportUrl = OICStrdup(platformInfo->supportUrl);
1388     target->info.systemTime = OICStrdup(platformInfo->systemTime);
1389 }
1390
1391 OCPlatformPayload* OCPlatformPayloadCreateAsOwner(char* uri, OCPlatformInfo* platformInfo)
1392 {
1393     OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
1394     if(!payload)
1395     {
1396         return NULL;
1397     }
1398
1399     payload->base.type = PAYLOAD_TYPE_PLATFORM;
1400     payload->uri = uri;
1401     payload->info = *platformInfo;
1402
1403     return payload;
1404 }
1405
1406 OCPlatformPayload* OCPlatformPayloadCreate(const char* uri, const OCPlatformInfo* platformInfo)
1407 {
1408     OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
1409
1410     if(!payload)
1411     {
1412         return NULL;
1413     }
1414
1415     payload->base.type = PAYLOAD_TYPE_PLATFORM;
1416     payload->uri = OICStrdup(uri);
1417     OCCopyPlatformInfo(platformInfo, payload);
1418
1419     return payload;
1420 }
1421
1422 void OCPlatformPayloadDestroy(OCPlatformPayload* payload)
1423 {
1424     if(!payload)
1425     {
1426         return;
1427     }
1428     OICFree(payload->uri);
1429     OICFree(payload->info.platformID);
1430     OICFree(payload->info.manufacturerName);
1431     OICFree(payload->info.manufacturerUrl);
1432     OICFree(payload->info.modelNumber);
1433     OICFree(payload->info.dateOfManufacture);
1434     OICFree(payload->info.platformVersion);
1435     OICFree(payload->info.operatingSystemVersion);
1436     OICFree(payload->info.hardwareVersion);
1437     OICFree(payload->info.firmwareVersion);
1438     OICFree(payload->info.supportUrl);
1439     OICFree(payload->info.systemTime);
1440     OICFree(payload);
1441 }
1442
1443 OCPresencePayload* OCPresencePayloadCreate(uint32_t seqNum, uint32_t maxAge,
1444         OCPresenceTrigger trigger, const char* resourceType)
1445 {
1446     OCPresencePayload* payload = (OCPresencePayload*)OICCalloc(1, sizeof(OCPresencePayload));
1447     if(!payload)
1448     {
1449         return NULL;
1450     }
1451
1452     payload->base.type = PAYLOAD_TYPE_PRESENCE;
1453     payload->sequenceNumber = seqNum;
1454     payload->maxAge = maxAge;
1455     payload->trigger = trigger;
1456     payload->resourceType = OICStrdup(resourceType);
1457     return payload;
1458 }
1459
1460 void OCPresencePayloadDestroy(OCPresencePayload* payload)
1461 {
1462     if(!payload)
1463     {
1464         return;
1465     }
1466     OICFree(payload->resourceType);
1467     OICFree(payload);
1468 }