RD query handling
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocpayload.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21
22 #include "ocpayload.h"
23 #include "octypes.h"
24 #include <string.h>
25 #include "oic_malloc.h"
26 #include "oic_string.h"
27 #include "ocstackinternal.h"
28 #include "ocresource.h"
29 #include "logger.h"
30
31 #define TAG "OCPayload"
32 static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val);
33 static void FreeOCDiscoveryResource(OCResourcePayload* payload);
34
35 void OCPayloadDestroy(OCPayload* payload)
36 {
37     if(!payload)
38     {
39         return;
40     }
41
42     switch(payload->type)
43     {
44         case PAYLOAD_TYPE_REPRESENTATION:
45             OCRepPayloadDestroy((OCRepPayload*)payload);
46             break;
47         case PAYLOAD_TYPE_DISCOVERY:
48             OCDiscoveryPayloadDestroy((OCDiscoveryPayload*)payload);
49             break;
50         case PAYLOAD_TYPE_DEVICE:
51             OCDevicePayloadDestroy((OCDevicePayload*)payload);
52             break;
53         case PAYLOAD_TYPE_PLATFORM:
54             OCPlatformPayloadDestroy((OCPlatformPayload*)payload);
55             break;
56         case PAYLOAD_TYPE_PRESENCE:
57             OCPresencePayloadDestroy((OCPresencePayload*)payload);
58             break;
59         case PAYLOAD_TYPE_SECURITY:
60             OCSecurityPayloadDestroy((OCSecurityPayload*)payload);
61             break;
62 #ifdef WITH_RD
63         case PAYLOAD_TYPE_RD:
64            OCRDPayloadDestroy((OCRDPayload*)payload);
65            break;
66 #endif
67         default:
68             OC_LOG_V(ERROR, TAG, "Unsupported payload type in destroy: %d", payload->type);
69             OICFree(payload);
70             break;
71     }
72 }
73 OCRepPayload* OCRepPayloadCreate()
74 {
75     OCRepPayload* payload = (OCRepPayload*)OICCalloc(1, sizeof(OCRepPayload));
76
77     if(!payload)
78     {
79         return NULL;
80     }
81
82     payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
83
84     return payload;
85 }
86
87 void OCRepPayloadAppend(OCRepPayload* parent, OCRepPayload* child)
88 {
89     if(!parent)
90     {
91         return;
92     }
93
94     while(parent->next)
95     {
96         parent = parent->next;
97     }
98
99     parent->next= child;
100     child->next = NULL;
101 }
102
103 static OCRepPayloadValue* OCRepPayloadFindValue(const OCRepPayload* payload, const char* name)
104 {
105     if(!payload || !name)
106     {
107         return NULL;
108     }
109
110     OCRepPayloadValue* val = payload->values;
111     while(val)
112     {
113         if(0 == strcmp(val->name, name))
114         {
115             return val;
116         }
117         val = val->next;
118     }
119
120     return NULL;
121
122 }
123
124 static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue* source)
125 {
126     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, PCF("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, PCF("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 bool OCRepPayloadSetNull(OCRepPayload* payload, const char* name)
454 {
455     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_NULL);
456     return val != NULL;
457 }
458
459 bool OCRepPayloadSetPropInt(OCRepPayload* payload,
460         const char* name, int64_t value)
461 {
462     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_INT);
463
464     if(!val)
465     {
466         return false;
467     }
468
469     val->i = value;
470     return true;
471 }
472
473 bool OCRepPayloadGetPropInt(const OCRepPayload* payload, const char* name, int64_t* value)
474 {
475     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
476
477     if(!val || val->type != OCREP_PROP_INT)
478     {
479         return false;
480     }
481
482     *value = val->i;
483     return true;
484 }
485
486 bool OCRepPayloadSetPropDouble(OCRepPayload* payload,
487         const char* name, double value)
488 {
489     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_DOUBLE);
490
491     if(!val )
492     {
493         return false;
494     }
495
496     val->d = value;
497     return true;
498 }
499
500 bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, double* value)
501 {
502     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
503
504     if(!val || val->type != OCREP_PROP_DOUBLE)
505     {
506         return false;
507     }
508
509     *value = val->d;
510     return true;
511 }
512
513 bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value)
514 {
515     char* temp = OICStrdup(value);
516     bool b = OCRepPayloadSetPropStringAsOwner(payload, name, temp);
517
518     if(!b)
519     {
520         OICFree(temp);
521     }
522     return b;
523 }
524
525 bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value)
526 {
527     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_STRING);
528
529     if(!val)
530     {
531         return false;
532     }
533
534     val->str = value;
535     return val->str != NULL;
536 }
537
538 bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, const char** value)
539 {
540     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
541
542     if(!val || val->type != OCREP_PROP_STRING)
543     {
544         return false;
545     }
546
547     *value = OICStrdup(val->str);
548     return *value != NULL;
549 }
550
551 bool OCRepPayloadSetPropBool(OCRepPayload* payload,
552         const char* name, bool value)
553 {
554     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_BOOL);
555
556     if(!val)
557     {
558         return false;
559     }
560
561     val->b = value;
562     return true;
563 }
564
565 bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool* value)
566 {
567     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
568
569     if(!val || val->type != OCREP_PROP_BOOL)
570     {
571         return false;
572     }
573
574     *value = val->b;
575     return true;
576 }
577
578 bool OCRepPayloadSetPropObject(OCRepPayload* payload, const char* name, const OCRepPayload* value)
579 {
580     OCRepPayload* temp = OCRepPayloadClone(value);
581     bool b = OCRepPayloadSetPropObjectAsOwner(payload, name, temp);
582
583     if(!b)
584     {
585         OCRepPayloadDestroy(temp);
586     }
587     return b;
588 }
589
590 bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name, OCRepPayload* value)
591 {
592     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_OBJECT);
593
594     if(!val)
595     {
596         return false;
597     }
598
599     val->obj = value;
600     return true;
601 }
602
603 bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value)
604 {
605     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
606
607     if(!val || val->type != OCREP_PROP_OBJECT)
608     {
609         return false;
610     }
611
612     *value = OCRepPayloadClone(val->obj);
613     return *value != NULL;
614 }
615
616 size_t calcDimTotal(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
617 {
618     if(dimensions[0] == 0)
619     {
620         return 0;
621     }
622
623     size_t total = 1;
624     for(uint8_t i = 0; i < MAX_REP_ARRAY_DEPTH && dimensions[i] != 0; ++i)
625     {
626         total *= dimensions[i];
627     }
628     return total;
629 }
630
631 bool OCRepPayloadSetIntArrayAsOwner(OCRepPayload* payload, const char* name,
632         int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
633 {
634     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
635
636     if(!val)
637     {
638         return false;
639     }
640
641     val->arr.type = OCREP_PROP_INT;
642     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
643     val->arr.iArray = array;
644
645     return true;
646 }
647
648 bool OCRepPayloadSetIntArray(OCRepPayload* payload, const char* name,
649         const int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
650 {
651     size_t dimTotal = calcDimTotal(dimensions);
652     if(dimTotal == 0)
653     {
654         return false;
655     }
656
657     int64_t* newArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
658
659     if(!newArray)
660     {
661         return false;
662     }
663
664     memcpy(newArray, array, dimTotal * sizeof(int64_t));
665
666
667     bool b = OCRepPayloadSetIntArrayAsOwner(payload, name, newArray, dimensions);
668     if(!b)
669     {
670         OICFree(newArray);
671     }
672     return b;
673 }
674
675 bool OCRepPayloadGetIntArray(const OCRepPayload* payload, const char* name,
676         int64_t** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
677 {
678     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
679
680     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_INT
681             || !val->arr.iArray)
682     {
683         return false;
684     }
685
686     size_t dimTotal = calcDimTotal(val->arr.dimensions);
687     if(dimTotal == 0)
688     {
689         return false;
690     }
691     *array = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
692     if(!*array)
693     {
694         return false;
695     }
696
697     memcpy(*array, val->arr.iArray, dimTotal * sizeof(int64_t));
698     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
699     return true;
700 }
701
702 bool OCRepPayloadSetDoubleArrayAsOwner(OCRepPayload* payload, const char* name,
703         double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
704 {
705     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
706
707     if(!val)
708     {
709         return false;
710     }
711
712     val->arr.type = OCREP_PROP_DOUBLE;
713     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
714     val->arr.dArray = array;
715
716     return true;
717 }
718 bool OCRepPayloadSetDoubleArray(OCRepPayload* payload, const char* name,
719         const double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
720 {
721     size_t dimTotal = calcDimTotal(dimensions);
722     if(dimTotal == 0)
723     {
724         return false;
725     }
726
727     double* newArray = (double*)OICMalloc(dimTotal * sizeof(double));
728
729     if(!newArray)
730     {
731         return false;
732     }
733
734     memcpy(newArray, array, dimTotal * sizeof(double));
735
736     bool b = OCRepPayloadSetDoubleArrayAsOwner(payload, name, newArray, dimensions);
737     if(!b)
738     {
739         OICFree(newArray);
740     }
741     return b;
742 }
743
744 bool OCRepPayloadGetDoubleArray(const OCRepPayload* payload, const char* name,
745         double** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
746 {
747     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
748
749     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_DOUBLE
750             || !val->arr.dArray)
751     {
752         return false;
753     }
754
755     size_t dimTotal = calcDimTotal(val->arr.dimensions);
756     if(dimTotal == 0)
757     {
758         return false;
759     }
760     *array = (double*)OICMalloc(dimTotal * sizeof(double));
761     if(!*array)
762     {
763         return false;
764     }
765
766     memcpy(*array, val->arr.dArray, dimTotal * sizeof(double));
767     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
768     return true;
769 }
770
771 bool OCRepPayloadSetStringArrayAsOwner(OCRepPayload* payload, const char* name,
772         char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
773 {
774     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
775
776     if(!val)
777     {
778         return false;
779     }
780
781     val->arr.type = OCREP_PROP_STRING;
782     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
783     val->arr.strArray = array;
784
785     return true;
786 }
787 bool OCRepPayloadSetStringArray(OCRepPayload* payload, const char* name,
788         const char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
789 {
790     size_t dimTotal = calcDimTotal(dimensions);
791     if(dimTotal == 0)
792     {
793         return false;
794     }
795
796     char** newArray = (char**)OICMalloc(dimTotal * sizeof(char*));
797
798     if(!newArray)
799     {
800         return false;
801     }
802
803     for(size_t i = 0; i < dimTotal; ++i)
804     {
805         newArray[i] = OICStrdup(array[i]);
806     }
807
808     bool b = OCRepPayloadSetStringArrayAsOwner(payload, name, newArray, dimensions);
809
810     if(!b)
811     {
812         for(size_t i = 0; i < dimTotal; ++i)
813         {
814             OICFree(newArray[i]);
815         }
816         OICFree(newArray);
817     }
818     return b;
819 }
820
821 bool OCRepPayloadGetStringArray(const OCRepPayload* payload, const char* name,
822         char*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
823 {
824     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
825
826     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_STRING
827             || !val->arr.strArray)
828     {
829         return false;
830     }
831
832     size_t dimTotal = calcDimTotal(val->arr.dimensions);
833     if(dimTotal == 0)
834     {
835         return false;
836     }
837     *array = (char**)OICMalloc(dimTotal * sizeof(char*));
838     if(!*array)
839     {
840         return false;
841     }
842
843     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
844
845     for(size_t i = 0; i < dimTotal; ++i)
846     {
847         (*array)[i] = OICStrdup(val->arr.strArray[i]);
848     }
849
850     return true;
851
852 }
853
854 bool OCRepPayloadSetBoolArrayAsOwner(OCRepPayload* payload, const char* name,
855         bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
856 {
857
858     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
859
860     if(!val)
861     {
862         return false;
863     }
864
865     val->arr.type = OCREP_PROP_BOOL;
866     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
867     val->arr.bArray = array;
868
869     return true;
870 }
871 bool OCRepPayloadSetBoolArray(OCRepPayload* payload, const char* name,
872         const bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
873 {
874     size_t dimTotal = calcDimTotal(dimensions);
875     if(dimTotal == 0)
876     {
877         return false;
878     }
879
880     bool* newArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
881
882     if(!newArray)
883     {
884         return false;
885     }
886
887     memcpy(newArray, array, dimTotal * sizeof(bool));
888
889
890     bool b = OCRepPayloadSetBoolArrayAsOwner(payload, name, newArray, dimensions);
891     if(!b)
892     {
893         OICFree(newArray);
894     }
895     return b;
896 }
897
898 bool OCRepPayloadGetBoolArray(const OCRepPayload* payload, const char* name,
899         bool** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
900 {
901     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
902
903     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_BOOL
904             || !val->arr.bArray)
905     {
906         return false;
907     }
908
909     size_t dimTotal = calcDimTotal(val->arr.dimensions);
910     if(dimTotal == 0)
911     {
912         return false;
913     }
914     *array = (bool*)OICMalloc(dimTotal * sizeof(bool));
915     if(!*array)
916     {
917         return false;
918     }
919
920     memcpy(*array, val->arr.bArray, dimTotal * sizeof(bool));
921     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
922     return true;
923 }
924
925 bool OCRepPayloadSetPropObjectArrayAsOwner(OCRepPayload* payload, const char* name,
926         OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
927 {
928     OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
929
930     if(!val)
931     {
932         return false;
933     }
934
935     val->arr.type = OCREP_PROP_OBJECT;
936     memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
937     val->arr.objArray = array;
938
939     return true;
940 }
941
942 bool OCRepPayloadSetPropObjectArray(OCRepPayload* payload, const char* name,
943         const OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
944 {
945     size_t dimTotal = calcDimTotal(dimensions);
946     if(dimTotal == 0)
947     {
948         return false;
949     }
950
951     OCRepPayload** newArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
952
953     if(!newArray)
954     {
955         return false;
956     }
957
958     for(size_t i = 0; i < dimTotal; ++i)
959     {
960         newArray[i] = OCRepPayloadClone(array[i]);
961     }
962
963     bool b = OCRepPayloadSetPropObjectArrayAsOwner(payload, name, newArray, dimensions);
964
965     if(!b)
966     {
967         for(size_t i = 0; i < dimTotal; ++i)
968         {
969            OCRepPayloadDestroy(newArray[i]);
970         }
971         OICFree(newArray);
972     }
973     return b;
974 }
975
976 bool OCRepPayloadGetPropObjectArray(const OCRepPayload* payload, const char* name,
977         OCRepPayload*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
978 {
979     OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
980
981     if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_OBJECT
982             || !val->arr.objArray)
983     {
984         return false;
985     }
986
987     size_t dimTotal = calcDimTotal(val->arr.dimensions);
988     if(dimTotal == 0)
989     {
990         return false;
991     }
992     *array = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
993     if(!*array)
994     {
995         return false;
996     }
997
998     memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
999
1000     for(size_t i = 0; i < dimTotal; ++i)
1001     {
1002         (*array)[i] = OCRepPayloadClone(val->arr.objArray[i]);
1003     }
1004
1005     return true;
1006 }
1007
1008 void OCFreeOCStringLL(OCStringLL* ll)
1009 {
1010     if(!ll)
1011     {
1012         return;
1013     }
1014
1015     OCFreeOCStringLL(ll->next);
1016     OICFree(ll->value);
1017     OICFree(ll);
1018 }
1019
1020 OCStringLL* CloneOCStringLL (OCStringLL* ll)
1021 {
1022     if (!ll)
1023     {
1024         return NULL;
1025     }
1026
1027     OCStringLL *sourceIter = ll;
1028
1029     OCStringLL *destIter = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1030     if (!destIter)
1031     {
1032         return NULL;
1033     }
1034     destIter->value = OICStrdup (sourceIter->value);
1035
1036     OCStringLL *headOfClone = destIter;
1037
1038     sourceIter = sourceIter->next;
1039
1040     while (sourceIter)
1041     {
1042         destIter->next  = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1043         if (!destIter->next)
1044         {
1045             OCFreeOCStringLL (headOfClone);
1046             return NULL;
1047         }
1048         destIter->next->value = OICStrdup (sourceIter->value);
1049
1050         destIter = destIter->next;
1051         sourceIter = sourceIter->next;
1052     }
1053     return headOfClone;
1054 }
1055
1056 OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
1057 {
1058     if (!payload)
1059     {
1060         return NULL;
1061     }
1062
1063     OCRepPayload *clone = OCRepPayloadCreate();
1064
1065     if (!clone)
1066     {
1067         return NULL;
1068     }
1069
1070     clone->uri = OICStrdup (payload->uri);
1071     clone->types = CloneOCStringLL (payload->types);
1072     clone->interfaces = CloneOCStringLL (payload->interfaces);
1073     clone->values = OCRepPayloadValueClone (payload->values);
1074
1075     return clone;
1076 }
1077
1078
1079 void OCRepPayloadDestroy(OCRepPayload* payload)
1080 {
1081     if(!payload)
1082     {
1083         return;
1084     }
1085
1086     OICFree(payload->uri);
1087     OCFreeOCStringLL(payload->types);
1088     OCFreeOCStringLL(payload->interfaces);
1089     OCFreeRepPayloadValue(payload->values);
1090     OCRepPayloadDestroy(payload->next);
1091     OICFree(payload);
1092 }
1093
1094 OCDiscoveryPayload* OCDiscoveryPayloadCreate()
1095 {
1096     OCDiscoveryPayload* payload = (OCDiscoveryPayload*)OICCalloc(1, sizeof(OCDiscoveryPayload));
1097
1098     if(!payload)
1099     {
1100         return NULL;
1101     }
1102
1103     payload->base.type = PAYLOAD_TYPE_DISCOVERY;
1104
1105     return payload;
1106 }
1107
1108 OCSecurityPayload* OCSecurityPayloadCreate(const char* securityData)
1109 {
1110     OCSecurityPayload* payload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1111
1112     if(!payload)
1113     {
1114         return NULL;
1115     }
1116
1117     payload->base.type = PAYLOAD_TYPE_SECURITY;
1118     payload->securityData = OICStrdup(securityData);
1119
1120     return payload;
1121 }
1122
1123 void OCSecurityPayloadDestroy(OCSecurityPayload* payload)
1124 {
1125     if(!payload)
1126     {
1127         return;
1128     }
1129
1130     OICFree(payload->securityData);
1131     OICFree(payload);
1132 }
1133
1134 size_t OCDiscoveryPayloadGetResourceCount(OCDiscoveryPayload* payload)
1135 {
1136     size_t i = 0;
1137     OCResourcePayload* p = payload->resources;
1138     while(p)
1139     {
1140         ++i;
1141         p = p->next;
1142     }
1143     return i;
1144 }
1145
1146 OCResourcePayload* OCDiscoveryPayloadGetResource(OCDiscoveryPayload* payload, size_t index)
1147 {
1148     size_t i = 0;
1149     OCResourcePayload* p = payload->resources;
1150     while(p)
1151     {
1152         if(i == index)
1153         {
1154             return p;
1155         }
1156         ++i;
1157         p = p->next;
1158     }
1159     return NULL;
1160 }
1161
1162 static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
1163 {
1164     OCResourcePayload* pl = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
1165     if(!pl)
1166     {
1167         return NULL;
1168     }
1169
1170     pl->uri = OICStrdup(res->uri);
1171     pl->sid = (uint8_t*)OICCalloc(1, UUID_SIZE);
1172     if(!pl->uri || ! pl->sid)
1173     {
1174         FreeOCDiscoveryResource(pl);
1175         return NULL;
1176     }
1177     memcpy(pl->sid, OCGetServerInstanceID(), UUID_SIZE);
1178
1179     // types
1180     OCResourceType* typePtr = res->rsrcType;
1181
1182     if(typePtr != NULL)
1183     {
1184         pl->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1185         if(!pl->types)
1186         {
1187             FreeOCDiscoveryResource(pl);
1188             return NULL;
1189         }
1190         pl->types->value = OICStrdup(typePtr->resourcetypename);
1191         if(!pl->types->value)
1192         {
1193             FreeOCDiscoveryResource(pl);
1194             return NULL;
1195         }
1196
1197         OCStringLL* cur = pl->types;
1198         typePtr = typePtr->next;
1199         while(typePtr)
1200         {
1201             cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1202             if(!cur->next)
1203             {
1204                 FreeOCDiscoveryResource(pl);
1205                 return NULL;
1206             }
1207             cur->next->value = OICStrdup(typePtr->resourcetypename);
1208             if(!cur->next->value)
1209             {
1210                 FreeOCDiscoveryResource(pl);
1211                 return NULL;
1212             }
1213             cur = cur->next;
1214             typePtr = typePtr->next;
1215         }
1216     }
1217
1218     // interfaces
1219     OCResourceInterface* ifPtr = res->rsrcInterface;
1220     if(ifPtr != NULL)
1221     {
1222         pl->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1223         if(!pl->interfaces)
1224         {
1225             FreeOCDiscoveryResource(pl);
1226             return NULL;
1227         }
1228         pl->interfaces->value = OICStrdup(ifPtr->name);
1229         if(!pl->interfaces->value)
1230         {
1231             FreeOCDiscoveryResource(pl);
1232             return NULL;
1233         }
1234
1235         OCStringLL* cur = pl->interfaces;
1236         ifPtr = ifPtr->next;
1237         while(ifPtr)
1238         {
1239             cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1240             if(!cur->next)
1241             {
1242                 FreeOCDiscoveryResource(pl);
1243                 return NULL;
1244             }
1245             cur->next->value = OICStrdup(ifPtr->name);
1246             if(!cur->next->value)
1247             {
1248                 FreeOCDiscoveryResource(pl);
1249                 return NULL;
1250             }
1251             cur = cur->next;
1252             ifPtr = ifPtr->next;
1253         }
1254     }
1255
1256     pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE);
1257     pl->secure = (res->resourceProperties & OC_SECURE) != 0;
1258     pl->port = port;
1259
1260     return pl;
1261 }
1262
1263 void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
1264         uint16_t port)
1265 {
1266     OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, port));
1267 }
1268
1269 void OCDiscoveryPayloadAddNewResource(OCDiscoveryPayload* payload, OCResourcePayload* res)
1270 {
1271     if(!payload->resources)
1272     {
1273         payload->resources = res;
1274     }
1275     else
1276     {
1277         OCResourcePayload* p = payload->resources;
1278         while(p->next)
1279         {
1280             p = p->next;
1281         }
1282         p->next = res;
1283     }
1284 }
1285
1286 static void FreeOCDiscoveryResource(OCResourcePayload* payload)
1287 {
1288     if(!payload)
1289     {
1290         return;
1291     }
1292
1293     OICFree(payload->uri);
1294     OICFree(payload->sid);
1295     OCFreeOCStringLL(payload->types);
1296     OCFreeOCStringLL(payload->interfaces);
1297     FreeOCDiscoveryResource(payload->next);
1298     OICFree(payload);
1299
1300 }
1301 void OCDiscoveryPayloadDestroy(OCDiscoveryPayload* payload)
1302 {
1303     if(!payload)
1304     {
1305         return;
1306     }
1307
1308     FreeOCDiscoveryResource(payload->resources);
1309     OICFree(payload);
1310 }
1311
1312 OCDevicePayload* OCDevicePayloadCreate(const char* uri, const uint8_t* sid, const char* dname,
1313         const char* specVer, const char* dmVer)
1314 {
1315
1316     OCDevicePayload* payload = (OCDevicePayload*)OICCalloc(1, sizeof(OCDevicePayload));
1317
1318     if(!payload)
1319     {
1320         return NULL;
1321     }
1322
1323     payload->base.type = PAYLOAD_TYPE_DEVICE;
1324
1325     payload->uri = OICStrdup(uri);
1326     if(uri && !payload->uri)
1327     {
1328         goto exit;
1329     }
1330
1331     if(sid)
1332     {
1333         payload->sid = (uint8_t*)OICMalloc(UUID_SIZE);
1334         if(!payload->sid)
1335         {
1336             goto exit;
1337         }
1338         memcpy(payload->sid, sid, UUID_SIZE);
1339     }
1340
1341     payload->deviceName = OICStrdup(dname);
1342     if(dname && !payload->deviceName)
1343     {
1344         goto exit;
1345     }
1346
1347     payload->specVersion = OICStrdup(specVer);
1348     if(specVer && !payload->specVersion)
1349     {
1350         goto exit;
1351     }
1352
1353     payload->dataModelVersion = OICStrdup(dmVer);
1354     if(dmVer && !payload->dataModelVersion)
1355     {
1356         goto exit;
1357     }
1358
1359     return payload;
1360
1361 exit:
1362     OCDevicePayloadDestroy((OCDevicePayload*)payload);
1363     return NULL;
1364 }
1365
1366 void OCDevicePayloadDestroy(OCDevicePayload* payload)
1367 {
1368     if(!payload)
1369     {
1370         return;
1371     }
1372
1373     OICFree(payload->uri);
1374     OICFree(payload->sid);
1375     OICFree(payload->deviceName);
1376     OICFree(payload->specVersion);
1377     OICFree(payload->dataModelVersion);
1378     OICFree(payload);
1379 }
1380
1381 static void OCCopyPlatformInfo(const OCPlatformInfo* platformInfo, OCPlatformPayload* target)
1382 {
1383     target->info.platformID = OICStrdup(platformInfo->platformID);
1384     target->info.manufacturerName = OICStrdup(platformInfo->manufacturerName);
1385     target->info.manufacturerUrl = OICStrdup(platformInfo->manufacturerUrl);
1386     target->info.modelNumber = OICStrdup(platformInfo->modelNumber);
1387     target->info.dateOfManufacture = OICStrdup(platformInfo->dateOfManufacture);
1388     target->info.platformVersion = OICStrdup(platformInfo->platformVersion);
1389     target->info.operatingSystemVersion = OICStrdup(platformInfo->operatingSystemVersion);
1390     target->info.hardwareVersion = OICStrdup(platformInfo->hardwareVersion);
1391     target->info.firmwareVersion = OICStrdup(platformInfo->firmwareVersion);
1392     target->info.supportUrl = OICStrdup(platformInfo->supportUrl);
1393     target->info.systemTime = OICStrdup(platformInfo->systemTime);
1394 }
1395
1396 OCPlatformPayload* OCPlatformPayloadCreateAsOwner(char* uri, OCPlatformInfo* platformInfo)
1397 {
1398     OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
1399     if(!payload)
1400     {
1401         return NULL;
1402     }
1403
1404     payload->base.type = PAYLOAD_TYPE_PLATFORM;
1405     payload->uri = uri;
1406     payload->info = *platformInfo;
1407
1408     return payload;
1409 }
1410
1411 OCPlatformPayload* OCPlatformPayloadCreate(const char* uri, const OCPlatformInfo* platformInfo)
1412 {
1413     OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
1414
1415     if(!payload)
1416     {
1417         return NULL;
1418     }
1419
1420     payload->base.type = PAYLOAD_TYPE_PLATFORM;
1421     payload->uri = OICStrdup(uri);
1422     OCCopyPlatformInfo(platformInfo, payload);
1423
1424     return payload;
1425 }
1426
1427 void OCPlatformPayloadDestroy(OCPlatformPayload* payload)
1428 {
1429     if(!payload)
1430     {
1431         return;
1432     }
1433     OICFree(payload->uri);
1434     OICFree(payload->info.platformID);
1435     OICFree(payload->info.manufacturerName);
1436     OICFree(payload->info.manufacturerUrl);
1437     OICFree(payload->info.modelNumber);
1438     OICFree(payload->info.dateOfManufacture);
1439     OICFree(payload->info.platformVersion);
1440     OICFree(payload->info.operatingSystemVersion);
1441     OICFree(payload->info.hardwareVersion);
1442     OICFree(payload->info.firmwareVersion);
1443     OICFree(payload->info.supportUrl);
1444     OICFree(payload->info.systemTime);
1445     OICFree(payload);
1446 }
1447
1448 OCPresencePayload* OCPresencePayloadCreate(uint32_t seqNum, uint32_t maxAge,
1449         OCPresenceTrigger trigger, const char* resourceType)
1450 {
1451     OCPresencePayload* payload = (OCPresencePayload*)OICCalloc(1, sizeof(OCPresencePayload));
1452     if(!payload)
1453     {
1454         return NULL;
1455     }
1456
1457     payload->base.type = PAYLOAD_TYPE_PRESENCE;
1458     payload->sequenceNumber = seqNum;
1459     payload->maxAge = maxAge;
1460     payload->trigger = trigger;
1461     payload->resourceType = OICStrdup(resourceType);
1462     return payload;
1463 }
1464
1465 void OCPresencePayloadDestroy(OCPresencePayload* payload)
1466 {
1467     if(!payload)
1468     {
1469         return;
1470     }
1471     OICFree(payload->resourceType);
1472     OICFree(payload);
1473 }