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