RDServer discovery functionality
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocpayloadconvert.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 #include "ocpayloadcbor.h"
22 #include <stdlib.h>
23 #include "oic_malloc.h"
24 #include "logger.h"
25 #include "ocpayload.h"
26 #include "ocrandom.h"
27 #include "ocresourcehandler.h"
28 #include "cbor.h"
29
30 #define TAG PCF("OCPayloadConvert")
31
32 static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload,
33         size_t* size);
34 static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload,
35         size_t* size);
36 static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload,
37         size_t* size);
38 static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size);
39 static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload, uint8_t** outPayload,
40         size_t* size);
41 static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload,
42         size_t* size);
43
44 bool AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
45         const char* value);
46
47 bool ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
48         const char* value);
49
50
51 OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* size)
52 {
53     OC_LOG_V(INFO, TAG, "Converting payload of type %d", payload->type);
54     switch(payload->type)
55     {
56         case PAYLOAD_TYPE_DISCOVERY:
57             return OCConvertDiscoveryPayload((OCDiscoveryPayload*)payload, outPayload, size);
58         case PAYLOAD_TYPE_DEVICE:
59             return OCConvertDevicePayload((OCDevicePayload*)payload, outPayload, size);
60         case PAYLOAD_TYPE_PLATFORM:
61             return OCConvertPlatformPayload((OCPlatformPayload*)payload, outPayload, size);
62         case PAYLOAD_TYPE_REPRESENTATION:
63             return OCConvertRepPayload((OCRepPayload*)payload, outPayload, size);
64         case PAYLOAD_TYPE_PRESENCE:
65             return OCConvertPresencePayload((OCPresencePayload*)payload, outPayload, size);
66         case PAYLOAD_TYPE_SECURITY:
67             return OCConvertSecurityPayload((OCSecurityPayload*)payload, outPayload, size);
68 #ifdef WITH_RD
69         case PAYLOAD_TYPE_RD:
70             return OCRDPayloadToCbor((OCRDPayload*)payload, outPayload, size);
71 #endif
72         default:
73             OC_LOG_V(INFO,TAG, "ConvertPayload default %d", payload->type);
74             return OC_STACK_NOTIMPL;
75     }
76 }
77
78 static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload,
79         size_t* size)
80 {
81     *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
82     *size = MAX_REQUEST_LENGTH;
83
84     if(!*outPayload)
85     {
86         return OC_STACK_NO_MEMORY;
87     }
88
89     CborEncoder encoder;
90     bool err = false;
91
92     cbor_encoder_init(&encoder, *outPayload, *size, 0);
93
94     CborEncoder rootArray;
95     err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
96     err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_SECURITY);
97
98     CborEncoder map;
99
100     err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
101
102     if(payload->securityData)
103     {
104         err = err || AddTextStringToMap(&map, OC_RSRVD_REPRESENTATION,
105                 sizeof(OC_RSRVD_REPRESENTATION) - 1,
106                 payload->securityData);
107     }
108
109     err = err || cbor_encoder_close_container(&rootArray, &map);
110
111     err = err || cbor_encoder_close_container(&encoder, &rootArray);
112
113     if(err)
114     {
115         OC_LOG_V(ERROR, TAG, "Convert Security Payload failed", err);
116         OICFree(*outPayload);
117         return OC_STACK_ERROR;
118     }
119
120     *size = encoder.ptr - *outPayload;
121     uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
122
123     if(!tempPayload)
124     {
125         OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
126         OICFree(*outPayload);
127         return OC_STACK_ERROR;
128     }
129
130     *outPayload = tempPayload;
131     return OC_STACK_OK;
132 }
133
134 static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload,
135         size_t* size)
136 {
137     *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
138     *size = MAX_REQUEST_LENGTH;
139
140     if(!*outPayload)
141     {
142         return OC_STACK_NO_MEMORY;
143     }
144
145     CborEncoder encoder = {0};
146     bool err = false;
147     size_t resourceCount =  OCDiscoveryPayloadGetResourceCount(payload);
148
149     cbor_encoder_init(&encoder, *outPayload, *size, 0);
150
151     CborEncoder rootArray;
152     err = err || cbor_encoder_create_array(&encoder, &rootArray, 1 + resourceCount);
153     err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DISCOVERY);
154
155     for(size_t i = 0; i < resourceCount; ++i)
156     {
157         CborEncoder map;
158         OCResourcePayload* resource = OCDiscoveryPayloadGetResource(payload, i);
159
160         if(!resource)
161         {
162             OICFree(*outPayload);
163             return OC_STACK_INVALID_PARAM;
164         }
165
166         err = err || cbor_encoder_create_map(&rootArray, &map, 3);
167         // Uri
168         err = err || AddTextStringToMap(&map, OC_RSRVD_HREF,
169                 sizeof(OC_RSRVD_HREF) - 1,
170                 resource->uri);
171
172         // Server ID
173         err = err || cbor_encode_text_string(&map, OC_RSRVD_SERVER_INSTANCE_ID,
174                 sizeof(OC_RSRVD_SERVER_INSTANCE_ID) - 1);
175         err = err || cbor_encode_byte_string(&map, resource->sid, UUID_SIZE);
176         // Prop Tag
177         {
178             CborEncoder propMap;
179             err = err || cbor_encode_text_string(&map, OC_RSRVD_PROPERTY,
180                     sizeof(OC_RSRVD_PROPERTY) -1 );
181             err = err || cbor_encoder_create_map(&map, &propMap, 3);
182
183             // Resource Type
184             {
185                 CborEncoder rtArray;
186                 err = err || cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE,
187                     sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
188                 err = err || cbor_encoder_create_array(&propMap, &rtArray, CborIndefiniteLength);
189
190                 OCStringLL* rtPtr = resource->types;
191                 while(rtPtr)
192                 {
193                     err = err || cbor_encode_text_string(&rtArray, rtPtr->value,
194                             strlen(rtPtr->value));
195                     rtPtr = rtPtr->next;
196                 }
197
198                 err = err || cbor_encoder_close_container(&propMap, &rtArray);
199             }
200
201             // Interface Types
202             {
203                 CborEncoder ifArray;
204                 err = err || cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE,
205                         sizeof(OC_RSRVD_INTERFACE) - 1);
206                 err = err || cbor_encoder_create_array(&propMap, &ifArray, CborIndefiniteLength);
207                 OCStringLL* ifPtr = resource->interfaces;
208
209                 while(ifPtr)
210                 {
211                     err = err || cbor_encode_text_string(&ifArray, ifPtr->value,
212                         strlen(ifPtr->value));
213                     ifPtr= ifPtr->next;
214                 }
215
216                 err = err || cbor_encoder_close_container(&propMap, &ifArray);
217             }
218             // Policy
219             {
220                 CborEncoder policyMap;
221                 err = err || cbor_encode_text_string(&propMap, OC_RSRVD_POLICY,
222                         sizeof(OC_RSRVD_POLICY) - 1);
223                 err = err || cbor_encoder_create_map(&propMap, &policyMap, CborIndefiniteLength);
224
225                 // Bitmap
226                 err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP,
227                         sizeof(OC_RSRVD_BITMAP) - 1);
228                 err = err || cbor_encode_uint(&policyMap, resource->bitmap);
229
230                 if(resource->secure)
231                 {
232                     err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE,
233                             sizeof(OC_RSRVD_SECURE) - 1);
234                     err = err || cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE);
235
236                     if(resource->port != 0)
237                     {
238                         err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT,
239                                 sizeof(OC_RSRVD_HOSTING_PORT) - 1);
240                         err = err || cbor_encode_uint(&policyMap, resource->port);
241                     }
242                 }
243
244                 err = err || cbor_encoder_close_container(&propMap, &policyMap);
245             }
246             // Close
247             err = err || cbor_encoder_close_container(&map, &propMap);
248         }
249         // Close Item
250         err = err || cbor_encoder_close_container(&rootArray, &map);
251     }
252     // Close main array
253     err = err || cbor_encoder_close_container(&encoder, &rootArray);
254
255     if(err)
256     {
257         OC_LOG_V(ERROR, TAG, "Convert Discovery Payload failed with : %d", err);
258         return OC_STACK_ERROR;
259     }
260
261     *size = encoder.ptr - *outPayload;
262     uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
263
264     if(!tempPayload)
265     {
266         OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
267         OICFree(*outPayload);
268         return OC_STACK_ERROR;
269     }
270
271     *outPayload = tempPayload;
272     return OC_STACK_OK;
273 }
274
275 static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload,
276         size_t* size)
277 {
278     *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
279     *size = MAX_REQUEST_LENGTH;
280
281     if(!*outPayload)
282     {
283         return OC_STACK_NO_MEMORY;
284     }
285
286     CborEncoder encoder = {0};
287     bool err = false;
288
289     cbor_encoder_init(&encoder, *outPayload, *size, 0);
290     CborEncoder rootArray;
291     err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
292     err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DEVICE);
293
294     {
295         CborEncoder map;
296         err = err || cbor_encoder_create_map(&rootArray, &map, 2);
297
298         // uri
299         err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
300                 payload->uri);
301
302         // Rep Map
303         {
304             CborEncoder repMap;
305             err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION,
306                     sizeof(OC_RSRVD_REPRESENTATION) - 1);
307             err = err || cbor_encoder_create_map(&map, &repMap, 4);
308
309             // Device ID
310             err = err || cbor_encode_text_string(&repMap, OC_RSRVD_DEVICE_ID,
311                     sizeof(OC_RSRVD_DEVICE_ID) - 1);
312             err = err || cbor_encode_byte_string(&repMap, payload->sid, UUID_SIZE);
313
314             // Device Name
315             err = err || AddTextStringToMap(&repMap, OC_RSRVD_DEVICE_NAME,
316                     sizeof(OC_RSRVD_DEVICE_NAME) - 1,
317                     payload->deviceName);
318
319             // Device Spec Version
320             err = err || AddTextStringToMap(&repMap, OC_RSRVD_SPEC_VERSION,
321                     sizeof(OC_RSRVD_SPEC_VERSION) - 1,
322                     payload->specVersion);
323
324             // Device data Model Version
325             err = err || AddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION,
326                     sizeof(OC_RSRVD_DATA_MODEL_VERSION) - 1,
327                     payload->dataModelVersion);
328
329             err = err || cbor_encoder_close_container(&map, &repMap);
330         }
331
332         // Close Map
333         err = err || cbor_encoder_close_container(&rootArray, &map);
334     }
335
336     // Close main array
337     err = err || cbor_encoder_close_container(&encoder, &rootArray);
338
339     if(err)
340     {
341         OC_LOG_V(ERROR, TAG, "Convert Device Payload failed with : %d", err);
342         return OC_STACK_ERROR;
343     }
344
345     *size = encoder.ptr - *outPayload;
346     uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
347
348     if(!tempPayload)
349     {
350         OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
351         OICFree(*outPayload);
352         return OC_STACK_ERROR;
353     }
354
355     *outPayload = tempPayload;
356     return OC_STACK_OK;
357 }
358
359 static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload,
360         size_t* size)
361 {
362     *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
363     *size = MAX_REQUEST_LENGTH;
364
365     if(!*outPayload)
366     {
367         return OC_STACK_NO_MEMORY;
368     }
369
370     CborEncoder encoder = {0};
371     bool err = false;
372
373     cbor_encoder_init(&encoder, *outPayload, *size, 0);
374     CborEncoder rootArray;
375     err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
376     err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PLATFORM);
377     {
378         CborEncoder map;
379         err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
380
381         // uri
382         err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
383                 payload->uri);
384
385         // Rep Map
386         {
387             CborEncoder repMap;
388             err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION,
389                     sizeof(OC_RSRVD_REPRESENTATION) - 1);
390             err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength);
391
392             // Platform ID
393             err = err || AddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_ID,
394                     sizeof(OC_RSRVD_PLATFORM_ID) - 1,
395                     payload->info.platformID);
396
397             // MFG Name
398             err = err || AddTextStringToMap(&repMap, OC_RSRVD_MFG_NAME,
399                     sizeof(OC_RSRVD_MFG_NAME) - 1,
400                     payload->info.manufacturerName);
401
402             // MFG Url
403             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_URL,
404                     sizeof(OC_RSRVD_MFG_URL) - 1,
405                     payload->info.manufacturerUrl);
406
407             // Model Num
408             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MODEL_NUM,
409                     sizeof(OC_RSRVD_MODEL_NUM) - 1,
410                     payload->info.modelNumber);
411
412             // Date of Mfg
413             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_DATE,
414                     sizeof(OC_RSRVD_MFG_DATE) - 1,
415                     payload->info.dateOfManufacture);
416
417             // Platform Version
418             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_VERSION,
419                     sizeof(OC_RSRVD_PLATFORM_VERSION) - 1,
420                     payload->info.platformVersion);
421
422             // OS Version
423             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_OS_VERSION,
424                     sizeof(OC_RSRVD_OS_VERSION) - 1,
425                     payload->info.operatingSystemVersion);
426
427             // Hardware Version
428             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_HARDWARE_VERSION,
429                     sizeof(OC_RSRVD_HARDWARE_VERSION) - 1,
430                     payload->info.hardwareVersion);
431
432             // Firmware Version
433             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_FIRMWARE_VERSION,
434                     sizeof(OC_RSRVD_FIRMWARE_VERSION) - 1,
435                     payload->info.firmwareVersion);
436
437             // Support URL
438             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SUPPORT_URL,
439                     sizeof(OC_RSRVD_SUPPORT_URL) - 1,
440                     payload->info.supportUrl);
441
442             // System Time
443             err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SYSTEM_TIME,
444                     sizeof(OC_RSRVD_SYSTEM_TIME) - 1,
445                     payload->info.systemTime);
446             err = err || cbor_encoder_close_container(&map, &repMap);
447         }
448
449         // Close Map
450         err = err || cbor_encoder_close_container(&rootArray, &map);
451     }
452
453     // Close main array
454     err = err || cbor_encoder_close_container(&encoder, &rootArray);
455
456     if(err)
457     {
458         OC_LOG_V(ERROR, TAG, "Convert Platform Payload failed with : %d", err);
459         return OC_STACK_ERROR;
460     }
461
462     *size = encoder.ptr - *outPayload;
463     uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
464
465     if(!tempPayload)
466     {
467         OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
468         OICFree(*outPayload);
469         return OC_STACK_ERROR;
470     }
471
472     *outPayload = tempPayload;
473
474     return OC_STACK_OK;
475 }
476
477 static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload);
478
479 static bool OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray)
480 {
481     CborEncoder array;
482     bool err = false;
483
484     err = err || cbor_encoder_create_array(parent, &array, CborIndefiniteLength);
485     err = err || cbor_encode_uint(&array, valArray->type);
486     for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++i)
487     {
488         err = err || cbor_encode_uint(&array, valArray->dimensions[i]);
489     }
490
491     size_t dimTotal = calcDimTotal(valArray->dimensions);
492
493     for(size_t i = 0; i < dimTotal; ++i)
494     {
495         switch(valArray->type)
496         {
497             case OCREP_PROP_NULL:
498                 OC_LOG(ERROR, TAG, PCF("ConvertArray Invalid NULL"));
499                 err = CborUnknownError;
500                 break;
501             case OCREP_PROP_INT:
502                 err = err || cbor_encode_int(&array, valArray->iArray[i]);
503                 break;
504             case OCREP_PROP_DOUBLE:
505                 err = err || cbor_encode_double(&array, valArray->dArray[i]);
506                 break;
507             case OCREP_PROP_BOOL:
508                 err = err || cbor_encode_boolean(&array, valArray->bArray[i]);
509                 break;
510             case OCREP_PROP_STRING:
511                 err = err || cbor_encode_text_string(&array, valArray->strArray[i],
512                         strlen(valArray->strArray[i]));
513                 break;
514             case OCREP_PROP_OBJECT:
515                 err = OCConvertSingleRepPayload(&array, valArray->objArray[i]);
516                 break;
517             case OCREP_PROP_ARRAY:
518                 OC_LOG(ERROR, TAG, PCF("ConvertArray Invalid child array"));
519                 err = CborUnknownError;
520                 break;
521         }
522     }
523
524     err = err || cbor_encoder_close_container(parent, &array);
525     return err;
526 }
527
528 static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload)
529 {
530     bool err = false;
531     CborEncoder map;
532     err = err || cbor_encoder_create_map(parent, &map, CborIndefiniteLength);
533
534     // Uri
535     err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_HREF,
536             sizeof(OC_RSRVD_HREF) - 1,
537             payload->uri);
538
539     // Prop Map
540     // resource types, interfaces
541     if(payload->types || payload->interfaces)
542     {
543         OC_LOG_V(INFO, TAG, "Payload has types or interfaces");
544         err = err || cbor_encode_text_string(&map,
545                 OC_RSRVD_PROPERTY,
546                 sizeof(OC_RSRVD_PROPERTY) - 1);
547         CborEncoder propMap;
548         err = err || cbor_encoder_create_map(&map, &propMap, 2);
549
550         CborEncoder curArray;
551         if(payload->types)
552         {
553             err = err || cbor_encode_text_string(&propMap,
554                     OC_RSRVD_RESOURCE_TYPE,
555                     sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
556             err = err || cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength);
557             OCStringLL* val = payload->types;
558             while(val)
559             {
560                 err = err || cbor_encode_text_string(&curArray, val->value, strlen(val->value));
561                 val = val->next;
562             }
563             err = err || cbor_encoder_close_container(&propMap, &curArray);
564         }
565         if(payload->interfaces)
566         {
567             err = err || cbor_encode_text_string(&propMap,
568                     OC_RSRVD_INTERFACE,
569                     sizeof(OC_RSRVD_INTERFACE) - 1);
570             err = err || cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength);
571             OCStringLL* val = payload->interfaces;
572             while(val)
573             {
574                 err = err || cbor_encode_text_string(&curArray, val->value, strlen(val->value));
575                 val = val->next;
576             }
577             err = err || cbor_encoder_close_container(&propMap, &curArray);
578         }
579         err = err || cbor_encoder_close_container(&map, &propMap);
580     }
581
582     // Rep Map
583     {
584         CborEncoder repMap;
585         err = err || cbor_encode_text_string(&map,
586                 OC_RSRVD_REPRESENTATION,
587                 sizeof(OC_RSRVD_REPRESENTATION) - 1);
588         err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength);
589         OCRepPayloadValue* value = payload->values;
590         while(value)
591         {
592             err = err || cbor_encode_text_string(&repMap,
593                     value->name,
594                     strlen(value->name));
595             switch(value->type)
596             {
597                 case OCREP_PROP_NULL:
598                     err = err || cbor_encode_null(&repMap);
599                     break;
600                 case OCREP_PROP_INT:
601                     err = err || cbor_encode_int(&repMap,
602                             value->i);
603                     break;
604                 case OCREP_PROP_DOUBLE:
605                     err = err || cbor_encode_double(&repMap,
606                             value->d);
607                     break;
608                 case OCREP_PROP_BOOL:
609                     err = err || cbor_encode_boolean(&repMap,
610                             value->b);
611                     break;
612                 case OCREP_PROP_STRING:
613                     err = err || cbor_encode_text_string(&repMap,
614                             value->str, strlen(value->str));
615                     break;
616                 case OCREP_PROP_OBJECT:
617                     err = err || OCConvertSingleRepPayload(&repMap, value->obj);
618                     break;
619                 case OCREP_PROP_ARRAY:
620                     err = err || OCConvertArray(&repMap, &value->arr);
621                     break;
622                 default:
623                     OC_LOG_V(ERROR, TAG, "Invalid Prop type: %d",
624                             value->type);
625                     break;
626             }
627             value = value->next;
628         }
629
630         err = err || cbor_encoder_close_container(&map, &repMap);
631     }
632
633     // Close Map
634     err = err || cbor_encoder_close_container(parent, &map);
635
636     return err;
637 }
638
639 static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size)
640 {
641     *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
642     *size = MAX_REQUEST_LENGTH;
643
644     if(!*outPayload)
645     {
646         return OC_STACK_NO_MEMORY;
647     }
648
649     CborEncoder encoder = {0};
650     bool err = false;
651
652     cbor_encoder_init(&encoder, *outPayload, *size, 0);
653     CborEncoder rootArray;
654     err = err || cbor_encoder_create_array(&encoder, &rootArray, CborIndefiniteLength);
655     err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_REPRESENTATION);
656
657     while(payload != NULL && !err)
658     {
659         err = err || OCConvertSingleRepPayload(&rootArray, payload);
660         payload = payload->next;
661     }
662
663     // Close main array
664     err = err || cbor_encoder_close_container(&encoder, &rootArray);
665
666     if(err)
667     {
668         OC_LOG_V(ERROR, TAG, "Convert Rep Payload failed with : %d", err);
669         return OC_STACK_ERROR;
670     }
671
672     *size = encoder.ptr - *outPayload;
673     uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
674
675     if(!tempPayload)
676     {
677         OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
678         OICFree(*outPayload);
679         return OC_STACK_ERROR;
680     }
681
682     *outPayload = tempPayload;
683
684     return OC_STACK_OK;
685 }
686
687 static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload,
688         uint8_t** outPayload, size_t* size)
689 {
690     *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
691     *size = MAX_REQUEST_LENGTH;
692
693     if(!*outPayload)
694     {
695         return OC_STACK_NO_MEMORY;
696     }
697
698     CborEncoder encoder = {0};
699     bool err = false;
700
701     cbor_encoder_init(&encoder, *outPayload, *size, 0);
702     CborEncoder rootArray;
703
704     err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
705     err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PRESENCE);
706
707
708     CborEncoder map;
709     err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
710
711     // Sequence Number
712     err = err || cbor_encode_text_string(&map,
713             OC_RSRVD_NONCE,
714             sizeof(OC_RSRVD_NONCE) - 1);
715     err = err || cbor_encode_uint(&map, payload->sequenceNumber);
716
717     // Max Age
718     err = err || cbor_encode_text_string(&map,
719             OC_RSRVD_TTL,
720             sizeof(OC_RSRVD_TTL) - 1);
721     err = err || cbor_encode_uint(&map, payload->maxAge);
722
723     // Trigger
724     const char* triggerStr = convertTriggerEnumToString(payload->trigger);
725     err = err || AddTextStringToMap(&map, OC_RSRVD_TRIGGER, sizeof(OC_RSRVD_TRIGGER) - 1,
726             triggerStr);
727
728     // Resource type name
729     if(payload->trigger != OC_PRESENCE_TRIGGER_DELETE)
730     {
731         err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_RESOURCE_TYPE,
732                 sizeof(OC_RSRVD_RESOURCE_TYPE) - 1, payload->resourceType);
733     }
734
735     // Close Map
736     err = err || cbor_encoder_close_container(&rootArray, &map);
737     err = err || cbor_encoder_close_container(&encoder, &rootArray);
738
739     if(err)
740     {
741         OC_LOG_V(ERROR, TAG, "Convert Presence Payload failed with : %d", err);
742         return OC_STACK_ERROR;
743     }
744
745     *size = encoder.ptr - *outPayload;
746     uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
747
748     if(!tempPayload)
749     {
750         OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
751         OICFree(*outPayload);
752         return OC_STACK_ERROR;
753     }
754
755     *outPayload = tempPayload;
756
757     return OC_STACK_OK;
758 }
759
760 bool AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
761         const char* value)
762 {
763     return cbor_encode_text_string(map, key, keylen) ||
764            cbor_encode_text_string(map, value, strlen(value));
765 }
766
767 bool ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
768         const char* value)
769 {
770     return value ? AddTextStringToMap(map, key, keylen, value) : false;
771 }