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