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