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