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