Merge branch 'master' into easysetup & CBOR changes
[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 static bool OCRepPayloadSetProp(OCRepPayload* payload, const char* name,
449         void* value, OCRepPayloadPropType type)
450 {
451     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, type);
452     if(!val)
453     {
454         return false;
455     }
456     switch(type)
457     {
458         case OCREP_PROP_INT:
459                val->i = *(int64_t*)value;
460                break;
461         case OCREP_PROP_DOUBLE:
462                val->d = *(double*)value;
463                break;
464         case OCREP_PROP_BOOL:
465                val->b = *(bool*)value;
466                break;
467         case OCREP_PROP_OBJECT:
468                val->obj = (OCRepPayload*)value;
469                break;
470         case OCREP_PROP_STRING:
471                val->str = (char*)value;
472                return val->str != NULL;
473         case OCREP_PROP_NULL:
474                return val != NULL;
475         case OCREP_PROP_ARRAY:
476         default:
477                return false;
478     }
479
480     return true;
481 }
482
483 bool OCRepPayloadSetNull(OCRepPayload* payload, const char* name)
484 {
485     return OCRepPayloadSetProp(payload, name, NULL, OCREP_PROP_NULL);
486 }
487
488 bool OCRepPayloadSetPropInt(OCRepPayload* payload,
489         const char* name, int64_t value)
490 {
491     return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_INT);
492 }
493
494 bool OCRepPayloadGetPropInt(const OCRepPayload* payload, const char* name, int64_t* value)
495 {
496     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
497
498     if(!val || val->type != OCREP_PROP_INT)
499     {
500         return false;
501     }
502
503     *value = val->i;
504     return true;
505 }
506
507 bool OCRepPayloadSetPropDouble(OCRepPayload* payload,
508         const char* name, double value)
509 {
510     return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_DOUBLE);
511 }
512
513 bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, double* value)
514 {
515     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
516
517     if(!val || val->type != OCREP_PROP_DOUBLE)
518     {
519         return false;
520     }
521
522     *value = val->d;
523     return true;
524 }
525
526 bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value)
527 {
528     char* temp = OICStrdup(value);
529     bool b = OCRepPayloadSetPropStringAsOwner(payload, name, temp);
530
531     if(!b)
532     {
533         OICFree(temp);
534     }
535     return b;
536 }
537
538 bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value)
539 {
540     return OCRepPayloadSetProp(payload, name, value, OCREP_PROP_STRING);
541 }
542
543 bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, const char** value)
544 {
545     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
546
547     if(!val || val->type != OCREP_PROP_STRING)
548     {
549         return false;
550     }
551
552     *value = OICStrdup(val->str);
553     return *value != NULL;
554 }
555
556 bool OCRepPayloadSetPropBool(OCRepPayload* payload,
557         const char* name, bool value)
558 {
559     return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_BOOL);
560 }
561
562 bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool* value)
563 {
564     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
565
566     if(!val || val->type != OCREP_PROP_BOOL)
567     {
568         return false;
569     }
570
571     *value = val->b;
572     return true;
573 }
574
575 bool OCRepPayloadSetPropObject(OCRepPayload* payload, const char* name, const OCRepPayload* value)
576 {
577     OCRepPayload* temp = OCRepPayloadClone(value);
578     bool b = OCRepPayloadSetPropObjectAsOwner(payload, name, temp);
579
580     if(!b)
581     {
582         OCRepPayloadDestroy(temp);
583     }
584     return b;
585 }
586
587 bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name, OCRepPayload* value)
588 {
589     return OCRepPayloadSetProp(payload, name, value, OCREP_PROP_OBJECT);
590 }
591
592 bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value)
593 {
594     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
595
596     if(!val || val->type != OCREP_PROP_OBJECT)
597     {
598         return false;
599     }
600
601     *value = OCRepPayloadClone(val->obj);
602     return *value != NULL;
603 }
604
605 size_t calcDimTotal(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
606 {
607     if(dimensions[0] == 0)
608     {
609         return 0;
610     }
611
612     size_t total = 1;
613     for(uint8_t i = 0; i < MAX_REP_ARRAY_DEPTH && dimensions[i] != 0; ++i)
614     {
615         total *= dimensions[i];
616     }
617     return total;
618 }
619
620 bool OCRepPayloadSetIntArrayAsOwner(OCRepPayload* payload, const char* name,
621         int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
622 {
623     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
624
625     if(!val)
626     {
627         return false;
628     }
629
630     val->arr.type = OCREP_PROP_INT;
631     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
632     val->arr.iArray = array;
633
634     return true;
635 }
636
637 bool OCRepPayloadSetIntArray(OCRepPayload* payload, const char* name,
638         const int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
639 {
640     size_t dimTotal = calcDimTotal(dimensions);
641     if(dimTotal == 0)
642     {
643         return false;
644     }
645
646     int64_t* newArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
647
648     if(!newArray)
649     {
650         return false;
651     }
652
653     memcpy(newArray, array, dimTotal * sizeof(int64_t));
654
655
656     bool b = OCRepPayloadSetIntArrayAsOwner(payload, name, newArray, dimensions);
657     if(!b)
658     {
659         OICFree(newArray);
660     }
661     return b;
662 }
663
664 bool OCRepPayloadGetIntArray(const OCRepPayload* payload, const char* name,
665         int64_t** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
666 {
667     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
668
669     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_INT
670             || !val->arr.iArray)
671     {
672         return false;
673     }
674
675     size_t dimTotal = calcDimTotal(val->arr.dimensions);
676     if(dimTotal == 0)
677     {
678         return false;
679     }
680     *array = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
681     if(!*array)
682     {
683         return false;
684     }
685
686     memcpy(*array, val->arr.iArray, dimTotal * sizeof(int64_t));
687     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
688     return true;
689 }
690
691 bool OCRepPayloadSetDoubleArrayAsOwner(OCRepPayload* payload, const char* name,
692         double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
693 {
694     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
695
696     if(!val)
697     {
698         return false;
699     }
700
701     val->arr.type = OCREP_PROP_DOUBLE;
702     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
703     val->arr.dArray = array;
704
705     return true;
706 }
707 bool OCRepPayloadSetDoubleArray(OCRepPayload* payload, const char* name,
708         const double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
709 {
710     size_t dimTotal = calcDimTotal(dimensions);
711     if(dimTotal == 0)
712     {
713         return false;
714     }
715
716     double* newArray = (double*)OICMalloc(dimTotal * sizeof(double));
717
718     if(!newArray)
719     {
720         return false;
721     }
722
723     memcpy(newArray, array, dimTotal * sizeof(double));
724
725     bool b = OCRepPayloadSetDoubleArrayAsOwner(payload, name, newArray, dimensions);
726     if(!b)
727     {
728         OICFree(newArray);
729     }
730     return b;
731 }
732
733 bool OCRepPayloadGetDoubleArray(const OCRepPayload* payload, const char* name,
734         double** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
735 {
736     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
737
738     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_DOUBLE
739             || !val->arr.dArray)
740     {
741         return false;
742     }
743
744     size_t dimTotal = calcDimTotal(val->arr.dimensions);
745     if(dimTotal == 0)
746     {
747         return false;
748     }
749     *array = (double*)OICMalloc(dimTotal * sizeof(double));
750     if(!*array)
751     {
752         return false;
753     }
754
755     memcpy(*array, val->arr.dArray, dimTotal * sizeof(double));
756     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
757     return true;
758 }
759
760 bool OCRepPayloadSetStringArrayAsOwner(OCRepPayload* payload, const char* name,
761         char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
762 {
763     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
764
765     if(!val)
766     {
767         return false;
768     }
769
770     val->arr.type = OCREP_PROP_STRING;
771     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
772     val->arr.strArray = array;
773
774     return true;
775 }
776 bool OCRepPayloadSetStringArray(OCRepPayload* payload, const char* name,
777         const char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
778 {
779     size_t dimTotal = calcDimTotal(dimensions);
780     if(dimTotal == 0)
781     {
782         return false;
783     }
784
785     char** newArray = (char**)OICMalloc(dimTotal * sizeof(char*));
786
787     if(!newArray)
788     {
789         return false;
790     }
791
792     for(size_t i = 0; i < dimTotal; ++i)
793     {
794         newArray[i] = OICStrdup(array[i]);
795     }
796
797     bool b = OCRepPayloadSetStringArrayAsOwner(payload, name, newArray, dimensions);
798
799     if(!b)
800     {
801         for(size_t i = 0; i < dimTotal; ++i)
802         {
803             OICFree(newArray[i]);
804         }
805         OICFree(newArray);
806     }
807     return b;
808 }
809
810 bool OCRepPayloadGetStringArray(const OCRepPayload* payload, const char* name,
811         char*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
812 {
813     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
814
815     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_STRING
816             || !val->arr.strArray)
817     {
818         return false;
819     }
820
821     size_t dimTotal = calcDimTotal(val->arr.dimensions);
822     if(dimTotal == 0)
823     {
824         return false;
825     }
826     *array = (char**)OICMalloc(dimTotal * sizeof(char*));
827     if(!*array)
828     {
829         return false;
830     }
831
832     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
833
834     for(size_t i = 0; i < dimTotal; ++i)
835     {
836         (*array)[i] = OICStrdup(val->arr.strArray[i]);
837     }
838
839     return true;
840
841 }
842
843 bool OCRepPayloadSetBoolArrayAsOwner(OCRepPayload* payload, const char* name,
844         bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
845 {
846
847     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
848
849     if(!val)
850     {
851         return false;
852     }
853
854     val->arr.type = OCREP_PROP_BOOL;
855     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
856     val->arr.bArray = array;
857
858     return true;
859 }
860 bool OCRepPayloadSetBoolArray(OCRepPayload* payload, const char* name,
861         const bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
862 {
863     size_t dimTotal = calcDimTotal(dimensions);
864     if(dimTotal == 0)
865     {
866         return false;
867     }
868
869     bool* newArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
870
871     if(!newArray)
872     {
873         return false;
874     }
875
876     memcpy(newArray, array, dimTotal * sizeof(bool));
877
878
879     bool b = OCRepPayloadSetBoolArrayAsOwner(payload, name, newArray, dimensions);
880     if(!b)
881     {
882         OICFree(newArray);
883     }
884     return b;
885 }
886
887 bool OCRepPayloadGetBoolArray(const OCRepPayload* payload, const char* name,
888         bool** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
889 {
890     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
891
892     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_BOOL
893             || !val->arr.bArray)
894     {
895         return false;
896     }
897
898     size_t dimTotal = calcDimTotal(val->arr.dimensions);
899     if(dimTotal == 0)
900     {
901         return false;
902     }
903     *array = (bool*)OICMalloc(dimTotal * sizeof(bool));
904     if(!*array)
905     {
906         return false;
907     }
908
909     memcpy(*array, val->arr.bArray, dimTotal * sizeof(bool));
910     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
911     return true;
912 }
913
914 bool OCRepPayloadSetPropObjectArrayAsOwner(OCRepPayload* payload, const char* name,
915         OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
916 {
917     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
918
919     if(!val)
920     {
921         return false;
922     }
923
924     val->arr.type = OCREP_PROP_OBJECT;
925     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
926     val->arr.objArray = array;
927
928     return true;
929 }
930
931 bool OCRepPayloadSetPropObjectArray(OCRepPayload* payload, const char* name,
932         const OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
933 {
934     size_t dimTotal = calcDimTotal(dimensions);
935     if(dimTotal == 0)
936     {
937         return false;
938     }
939
940     OCRepPayload** newArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
941
942     if(!newArray)
943     {
944         return false;
945     }
946
947     for(size_t i = 0; i < dimTotal; ++i)
948     {
949         newArray[i] = OCRepPayloadClone(array[i]);
950     }
951
952     bool b = OCRepPayloadSetPropObjectArrayAsOwner(payload, name, newArray, dimensions);
953
954     if(!b)
955     {
956         for(size_t i = 0; i < dimTotal; ++i)
957         {
958            OCRepPayloadDestroy(newArray[i]);
959         }
960         OICFree(newArray);
961     }
962     return b;
963 }
964
965 bool OCRepPayloadGetPropObjectArray(const OCRepPayload* payload, const char* name,
966         OCRepPayload*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
967 {
968     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
969
970     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_OBJECT
971             || !val->arr.objArray)
972     {
973         return false;
974     }
975
976     size_t dimTotal = calcDimTotal(val->arr.dimensions);
977     if(dimTotal == 0)
978     {
979         return false;
980     }
981     *array = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
982     if(!*array)
983     {
984         return false;
985     }
986
987     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
988
989     for(size_t i = 0; i < dimTotal; ++i)
990     {
991         (*array)[i] = OCRepPayloadClone(val->arr.objArray[i]);
992     }
993
994     return true;
995 }
996
997 void OCFreeOCStringLL(OCStringLL* ll)
998 {
999     if(!ll)
1000     {
1001         return;
1002     }
1003
1004     OCFreeOCStringLL(ll->next);
1005     OICFree(ll->value);
1006     OICFree(ll);
1007 }
1008
1009 OCStringLL* CloneOCStringLL (OCStringLL* ll)
1010 {
1011     if (!ll)
1012     {
1013         return NULL;
1014     }
1015
1016     OCStringLL *sourceIter = ll;
1017
1018     OCStringLL *destIter = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1019     if (!destIter)
1020     {
1021         return NULL;
1022     }
1023     destIter->value = OICStrdup (sourceIter->value);
1024
1025     OCStringLL *headOfClone = destIter;
1026
1027     sourceIter = sourceIter->next;
1028
1029     while (sourceIter)
1030     {
1031         destIter->next  = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1032         if (!destIter->next)
1033         {
1034             OCFreeOCStringLL (headOfClone);
1035             return NULL;
1036         }
1037         destIter->next->value = OICStrdup (sourceIter->value);
1038
1039         destIter = destIter->next;
1040         sourceIter = sourceIter->next;
1041     }
1042     return headOfClone;
1043 }
1044
1045 OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
1046 {
1047     if (!payload)
1048     {
1049         return NULL;
1050     }
1051
1052     OCRepPayload *clone = OCRepPayloadCreate();
1053
1054     if (!clone)
1055     {
1056         return NULL;
1057     }
1058
1059     clone->uri = OICStrdup (payload->uri);
1060     clone->types = CloneOCStringLL (payload->types);
1061     clone->interfaces = CloneOCStringLL (payload->interfaces);
1062     clone->values = OCRepPayloadValueClone (payload->values);
1063
1064     return clone;
1065 }
1066
1067
1068 void OCRepPayloadDestroy(OCRepPayload* payload)
1069 {
1070     if(!payload)
1071     {
1072         return;
1073     }
1074
1075     OICFree(payload->uri);
1076     OCFreeOCStringLL(payload->types);
1077     OCFreeOCStringLL(payload->interfaces);
1078     OCFreeRepPayloadValue(payload->values);
1079     OCRepPayloadDestroy(payload->next);
1080     OICFree(payload);
1081 }
1082
1083 OCDiscoveryPayload* OCDiscoveryPayloadCreate()
1084 {
1085     OCDiscoveryPayload* payload = (OCDiscoveryPayload*)OICCalloc(1, sizeof(OCDiscoveryPayload));
1086
1087     if(!payload)
1088     {
1089         return NULL;
1090     }
1091
1092     payload->base.type = PAYLOAD_TYPE_DISCOVERY;
1093
1094     return payload;
1095 }
1096
1097 OCSecurityPayload* OCSecurityPayloadCreate(const char* securityData)
1098 {
1099     OCSecurityPayload* payload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1100
1101     if(!payload)
1102     {
1103         return NULL;
1104     }
1105
1106     payload->base.type = PAYLOAD_TYPE_SECURITY;
1107     payload->securityData = OICStrdup(securityData);
1108
1109     return payload;
1110 }
1111
1112 void OCSecurityPayloadDestroy(OCSecurityPayload* payload)
1113 {
1114     if(!payload)
1115     {
1116         return;
1117     }
1118
1119     OICFree(payload->securityData);
1120     OICFree(payload);
1121 }
1122
1123 size_t OCDiscoveryPayloadGetResourceCount(OCDiscoveryPayload* payload)
1124 {
1125     size_t i = 0;
1126     OCResourcePayload* p = payload->resources;
1127     while(p)
1128     {
1129         ++i;
1130         p = p->next;
1131     }
1132     return i;
1133 }
1134
1135 OCResourcePayload* OCDiscoveryPayloadGetResource(OCDiscoveryPayload* payload, size_t index)
1136 {
1137     size_t i = 0;
1138     OCResourcePayload* p = payload->resources;
1139     while(p)
1140     {
1141         if(i == index)
1142         {
1143             return p;
1144         }
1145         ++i;
1146         p = p->next;
1147     }
1148     return NULL;
1149 }
1150
1151 static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
1152 {
1153     OCResourcePayload* pl = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
1154     if(!pl)
1155     {
1156         return NULL;
1157     }
1158
1159     pl->uri = OICStrdup(res->uri);
1160     pl->sid = (uint8_t*)OICCalloc(1, UUID_SIZE);
1161     if(!pl->uri || ! pl->sid)
1162     {
1163         FreeOCDiscoveryResource(pl);
1164         return NULL;
1165     }
1166     memcpy(pl->sid, OCGetServerInstanceID(), UUID_SIZE);
1167
1168     // types
1169     OCResourceType* typePtr = res->rsrcType;
1170
1171     if(typePtr != NULL)
1172     {
1173         pl->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1174         if(!pl->types)
1175         {
1176             FreeOCDiscoveryResource(pl);
1177             return NULL;
1178         }
1179         pl->types->value = OICStrdup(typePtr->resourcetypename);
1180         if(!pl->types->value)
1181         {
1182             FreeOCDiscoveryResource(pl);
1183             return NULL;
1184         }
1185
1186         OCStringLL* cur = pl->types;
1187         typePtr = typePtr->next;
1188         while(typePtr)
1189         {
1190             cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1191             if(!cur->next)
1192             {
1193                 FreeOCDiscoveryResource(pl);
1194                 return NULL;
1195             }
1196             cur->next->value = OICStrdup(typePtr->resourcetypename);
1197             if(!cur->next->value)
1198             {
1199                 FreeOCDiscoveryResource(pl);
1200                 return NULL;
1201             }
1202             cur = cur->next;
1203             typePtr = typePtr->next;
1204         }
1205     }
1206
1207     // interfaces
1208     OCResourceInterface* ifPtr = res->rsrcInterface;
1209     if(ifPtr != NULL)
1210     {
1211         pl->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1212         if(!pl->interfaces)
1213         {
1214             FreeOCDiscoveryResource(pl);
1215             return NULL;
1216         }
1217         pl->interfaces->value = OICStrdup(ifPtr->name);
1218         if(!pl->interfaces->value)
1219         {
1220             FreeOCDiscoveryResource(pl);
1221             return NULL;
1222         }
1223
1224         OCStringLL* cur = pl->interfaces;
1225         ifPtr = ifPtr->next;
1226         while(ifPtr)
1227         {
1228             cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1229             if(!cur->next)
1230             {
1231                 FreeOCDiscoveryResource(pl);
1232                 return NULL;
1233             }
1234             cur->next->value = OICStrdup(ifPtr->name);
1235             if(!cur->next->value)
1236             {
1237                 FreeOCDiscoveryResource(pl);
1238                 return NULL;
1239             }
1240             cur = cur->next;
1241             ifPtr = ifPtr->next;
1242         }
1243     }
1244
1245     pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE);
1246     pl->secure = (res->resourceProperties & OC_SECURE) != 0;
1247     pl->port = port;
1248
1249     return pl;
1250 }
1251
1252 void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
1253         uint16_t port)
1254 {
1255     OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, port));
1256 }
1257
1258 void OCDiscoveryPayloadAddNewResource(OCDiscoveryPayload* payload, OCResourcePayload* res)
1259 {
1260     if(!payload->resources)
1261     {
1262         payload->resources = res;
1263     }
1264     else
1265     {
1266         OCResourcePayload* p = payload->resources;
1267         while(p->next)
1268         {
1269             p = p->next;
1270         }
1271         p->next = res;
1272     }
1273 }
1274
1275 static void FreeOCDiscoveryResource(OCResourcePayload* payload)
1276 {
1277     if(!payload)
1278     {
1279         return;
1280     }
1281
1282     OICFree(payload->uri);
1283     OICFree(payload->sid);
1284     OCFreeOCStringLL(payload->types);
1285     OCFreeOCStringLL(payload->interfaces);
1286     FreeOCDiscoveryResource(payload->next);
1287     OICFree(payload);
1288
1289 }
1290 void OCDiscoveryPayloadDestroy(OCDiscoveryPayload* payload)
1291 {
1292     if(!payload)
1293     {
1294         return;
1295     }
1296
1297     FreeOCDiscoveryResource(payload->resources);
1298     OICFree(payload);
1299 }
1300
1301 OCDevicePayload* OCDevicePayloadCreate(const char* uri, const uint8_t* sid, const char* dname,
1302         const char* specVer, const char* dmVer)
1303 {
1304
1305     OCDevicePayload* payload = (OCDevicePayload*)OICCalloc(1, sizeof(OCDevicePayload));
1306
1307     if(!payload)
1308     {
1309         return NULL;
1310     }
1311
1312     payload->base.type = PAYLOAD_TYPE_DEVICE;
1313
1314     payload->uri = OICStrdup(uri);
1315     if(uri && !payload->uri)
1316     {
1317         goto exit;
1318     }
1319
1320     if(sid)
1321     {
1322         payload->sid = (uint8_t*)OICMalloc(UUID_SIZE);
1323         if(!payload->sid)
1324         {
1325             goto exit;
1326         }
1327         memcpy(payload->sid, sid, UUID_SIZE);
1328     }
1329
1330     payload->deviceName = OICStrdup(dname);
1331     if(dname && !payload->deviceName)
1332     {
1333         goto exit;
1334     }
1335
1336     payload->specVersion = OICStrdup(specVer);
1337     if(specVer && !payload->specVersion)
1338     {
1339         goto exit;
1340     }
1341
1342     payload->dataModelVersion = OICStrdup(dmVer);
1343     if(dmVer && !payload->dataModelVersion)
1344     {
1345         goto exit;
1346     }
1347
1348     return payload;
1349
1350 exit:
1351     OCDevicePayloadDestroy((OCDevicePayload*)payload);
1352     return NULL;
1353 }
1354
1355 void OCDevicePayloadDestroy(OCDevicePayload* payload)
1356 {
1357     if(!payload)
1358     {
1359         return;
1360     }
1361
1362     OICFree(payload->uri);
1363     OICFree(payload->sid);
1364     OICFree(payload->deviceName);
1365     OICFree(payload->specVersion);
1366     OICFree(payload->dataModelVersion);
1367     OICFree(payload);
1368 }
1369
1370 static void OCCopyPlatformInfo(const OCPlatformInfo* platformInfo, OCPlatformPayload* target)
1371 {
1372     target->info.platformID = OICStrdup(platformInfo->platformID);
1373     target->info.manufacturerName = OICStrdup(platformInfo->manufacturerName);
1374     target->info.manufacturerUrl = OICStrdup(platformInfo->manufacturerUrl);
1375     target->info.modelNumber = OICStrdup(platformInfo->modelNumber);
1376     target->info.dateOfManufacture = OICStrdup(platformInfo->dateOfManufacture);
1377     target->info.platformVersion = OICStrdup(platformInfo->platformVersion);
1378     target->info.operatingSystemVersion = OICStrdup(platformInfo->operatingSystemVersion);
1379     target->info.hardwareVersion = OICStrdup(platformInfo->hardwareVersion);
1380     target->info.firmwareVersion = OICStrdup(platformInfo->firmwareVersion);
1381     target->info.supportUrl = OICStrdup(platformInfo->supportUrl);
1382     target->info.systemTime = OICStrdup(platformInfo->systemTime);
1383 }
1384
1385 OCPlatformPayload* OCPlatformPayloadCreateAsOwner(char* uri, OCPlatformInfo* platformInfo)
1386 {
1387     OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
1388     if(!payload)
1389     {
1390         return NULL;
1391     }
1392
1393     payload->base.type = PAYLOAD_TYPE_PLATFORM;
1394     payload->uri = uri;
1395     payload->info = *platformInfo;
1396
1397     return payload;
1398 }
1399
1400 OCPlatformPayload* OCPlatformPayloadCreate(const char* uri, const OCPlatformInfo* platformInfo)
1401 {
1402     OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
1403
1404     if(!payload)
1405     {
1406         return NULL;
1407     }
1408
1409     payload->base.type = PAYLOAD_TYPE_PLATFORM;
1410     payload->uri = OICStrdup(uri);
1411     OCCopyPlatformInfo(platformInfo, payload);
1412
1413     return payload;
1414 }
1415
1416 void OCPlatformPayloadDestroy(OCPlatformPayload* payload)
1417 {
1418     if(!payload)
1419     {
1420         return;
1421     }
1422     OICFree(payload->uri);
1423     OICFree(payload->info.platformID);
1424     OICFree(payload->info.manufacturerName);
1425     OICFree(payload->info.manufacturerUrl);
1426     OICFree(payload->info.modelNumber);
1427     OICFree(payload->info.dateOfManufacture);
1428     OICFree(payload->info.platformVersion);
1429     OICFree(payload->info.operatingSystemVersion);
1430     OICFree(payload->info.hardwareVersion);
1431     OICFree(payload->info.firmwareVersion);
1432     OICFree(payload->info.supportUrl);
1433     OICFree(payload->info.systemTime);
1434     OICFree(payload);
1435 }
1436
1437 OCPresencePayload* OCPresencePayloadCreate(uint32_t seqNum, uint32_t maxAge,
1438         OCPresenceTrigger trigger, const char* resourceType)
1439 {
1440     OCPresencePayload* payload = (OCPresencePayload*)OICCalloc(1, sizeof(OCPresencePayload));
1441     if(!payload)
1442     {
1443         return NULL;
1444     }
1445
1446     payload->base.type = PAYLOAD_TYPE_PRESENCE;
1447     payload->sequenceNumber = seqNum;
1448     payload->maxAge = maxAge;
1449     payload->trigger = trigger;
1450     payload->resourceType = OICStrdup(resourceType);
1451     return payload;
1452 }
1453
1454 void OCPresencePayloadDestroy(OCPresencePayload* payload)
1455 {
1456     if(!payload)
1457     {
1458         return;
1459     }
1460     OICFree(payload->resourceType);
1461     OICFree(payload);
1462 }