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