1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 // Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2001 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2001 base specification,
26 // Refer http://pubs.opengroup.org/onlinepubs/009695399/
27 // Required for strok_r
28 #define _POSIX_C_SOURCE 200112L
32 #include "ocpayload.h"
33 #include "oic_string.h"
34 #include "oic_malloc.h"
35 #include "ocpayloadcbor.h"
36 #include "ocstackinternal.h"
37 #include "payload_logging.h"
38 #include "platform_features.h"
39 #include "ocendpoint.h"
41 #define TAG "OIC_RI_PAYLOADPARSE"
44 * The length of UINT64_MAX as a decimal string.
46 #define UINT64_MAX_STRLEN 20
48 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *arrayVal);
49 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *repParent, bool isRoot);
50 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *arrayVal);
51 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *arrayVal);
52 static OCStackResult OCParseSecurityPayload(OCPayload **outPayload, const uint8_t *payload, size_t size);
54 OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadType payloadType,
55 const uint8_t *payload, size_t payloadSize)
57 OCStackResult result = OC_STACK_MALFORMED_RESPONSE;
60 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Conversion of outPayload failed");
61 VERIFY_PARAM_NON_NULL(TAG, payload, "Invalid cbor payload value");
63 OIC_LOG_V(INFO, TAG, "CBOR Parsing size: %zu of Payload Type: %d, Payload:",
64 payloadSize, payloadType);
69 err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue);
70 VERIFY_CBOR_SUCCESS(TAG, err, "Failed initializing init value")
74 case PAYLOAD_TYPE_DISCOVERY:
75 result = OCParseDiscoveryPayload(outPayload, &rootValue);
77 case PAYLOAD_TYPE_REPRESENTATION:
78 result = OCParseRepPayload(outPayload, &rootValue);
80 case PAYLOAD_TYPE_PRESENCE:
81 result = OCParsePresencePayload(outPayload, &rootValue);
83 case PAYLOAD_TYPE_SECURITY:
84 result = OCParseSecurityPayload(outPayload, payload, payloadSize);
87 OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
88 result = OC_STACK_INVALID_PARAM;
92 OIC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
98 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, const uint8_t *payload,
103 *outPayload = (OCPayload *)OCSecurityPayloadCreate(payload, size);
112 static char* InPlaceStringTrim(char* str)
114 while (str[0] == ' ')
119 size_t lastchar = strlen(str);
121 while (str[lastchar] == ' ')
123 str[lastchar] = '\0';
130 static CborError OCParseStringLL(CborValue *map, char *type, OCStringLL **resource)
133 CborError err = cbor_value_map_find_value(map, type, &val);
134 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL TAG");
136 if (cbor_value_is_array(&val))
139 err = cbor_value_enter_container(&val, &txtStr);
140 VERIFY_CBOR_SUCCESS(TAG, err, "to enter container");
141 while (cbor_value_is_text_string(&txtStr))
145 err = cbor_value_dup_text_string(&txtStr, &input, &len, NULL);
146 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value.");
149 char *savePtr = NULL;
150 char *curPtr = strtok_r(input, " ", &savePtr);
153 char *trimmed = InPlaceStringTrim(curPtr);
154 if (trimmed && strlen(trimmed) > 0)
156 if (!OCResourcePayloadAddStringLL(resource, trimmed))
158 return CborErrorOutOfMemory;
161 curPtr = strtok_r(NULL, " ", &savePtr);
163 free(input); // Free *TinyCBOR allocated* string.
165 if (cbor_value_is_text_string(&txtStr))
167 err = cbor_value_advance(&txtStr);
168 VERIFY_CBOR_SUCCESS(TAG, err, "to advance string value");
176 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
178 OCStackResult ret = OC_STACK_INVALID_PARAM;
179 OCResourcePayload *resource = NULL;
180 OCDiscoveryPayload *temp = NULL;
181 OCDiscoveryPayload *rootPayload = NULL;
182 OCDiscoveryPayload *curPayload = NULL;
183 OCEndpointPayload *endpoint = NULL;
185 CborError err = CborNoError;
188 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
189 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
190 if (cbor_value_is_array(rootValue))
192 // Root value is already inside the main root array
195 // Enter the main root map
196 ret = OC_STACK_MALFORMED_RESPONSE;
197 err = cbor_value_enter_container(rootValue, &rootMap);
198 VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
199 while (cbor_value_is_map(&rootMap))
201 ret = OC_STACK_NO_MEMORY;
202 temp = OCDiscoveryPayloadCreate();
203 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed error initializing discovery payload");
207 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
208 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
209 if (cbor_value_is_valid(&curVal))
211 if (cbor_value_is_byte_string(&curVal))
213 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(temp->sid), &len, NULL);
214 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
216 else if (cbor_value_is_text_string(&curVal))
218 err = cbor_value_dup_text_string(&curVal, &(temp->sid), &len, NULL);
219 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
223 // BaseURI - Not a mandatory field
224 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
225 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri tag");
226 if (cbor_value_is_text_string(&curVal))
228 err = cbor_value_dup_text_string(&curVal, &(temp->baseURI), &len, NULL);
229 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
232 // RT - Not a mandatory field
233 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
234 if (cbor_value_is_valid(&curVal))
236 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->type);
237 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type");
240 // IF - Not a mandatory field
241 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal);
242 if (cbor_value_is_valid(&curVal))
244 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->iface);
245 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface");
248 // Name - Not a mandatory field
249 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_NAME, &curVal);
250 if (cbor_value_is_text_string(&curVal))
252 err = cbor_value_dup_text_string(&curVal, &temp->name, &len, NULL);
253 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name");
256 // Look for Links which will have an array as the value
258 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
259 VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
261 // Enter the links array and start iterating through the array processing
262 // each resource which shows up as a map.
263 CborValue resourceMap;
264 err = cbor_value_enter_container(&linkMap, &resourceMap);
265 VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
267 while (cbor_value_is_map(&resourceMap))
271 resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
272 VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
275 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
276 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
277 err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
278 VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
280 // Rel - Not a mandatory field
281 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_REL, &curVal);
282 VERIFY_CBOR_SUCCESS(TAG, err, "to find rel tag");
283 if (cbor_value_is_valid(&curVal))
285 err = cbor_value_dup_text_string(&curVal, &(resource->rel), &len, NULL);
286 VERIFY_CBOR_SUCCESS(TAG, err, "to find rel value");
290 err = OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
291 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
294 err = OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
295 if (CborNoError != err)
297 if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
299 OIC_LOG(ERROR, TAG, "Failed to add string to StringLL");
306 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
307 VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
310 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
311 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
312 err = cbor_value_get_int(&curVal, &bitmap);
313 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
314 resource->bitmap = (uint8_t)bitmap;
317 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
318 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure tag");
319 if (cbor_value_is_boolean(&curVal))
321 err = cbor_value_get_boolean(&curVal, &(resource->secure));
322 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
326 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
327 VERIFY_CBOR_SUCCESS(TAG, err, "to find port tag");
328 if (cbor_value_is_integer(&curVal))
332 err = cbor_value_get_int(&curVal, &port);
333 VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
334 resource->port = (uint16_t)port;
339 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TCP_PORT, &curVal);
340 if (cbor_value_is_integer(&curVal))
344 err = cbor_value_get_int(&curVal, &tcpPort);
345 VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp port value");
346 resource->tcpPort = (uint16_t)tcpPort;
351 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TLS_PORT, &curVal);
352 if (cbor_value_is_integer(&curVal))
356 err = cbor_value_get_int(&curVal, &tlsPort);
357 VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp tls port value");
358 resource->tcpPort = (uint16_t)tlsPort;
364 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_ENDPOINTS, &epsMap);
365 VERIFY_CBOR_SUCCESS(TAG, err, "to find eps tag");
367 if (cbor_value_is_array(&epsMap))
370 err = cbor_value_enter_container(&epsMap, &epMap);
371 VERIFY_CBOR_SUCCESS(TAG, err, "to enter endpoint map");
373 while (cbor_value_is_map(&epMap))
377 char *endpointStr = NULL;
378 OCStackResult ret = OC_STACK_ERROR;
379 endpoint = (OCEndpointPayload *)OICCalloc(1, sizeof(OCEndpointPayload));
380 VERIFY_PARAM_NON_NULL(TAG, endpoint, "Failed allocating endpoint payload");
383 err = cbor_value_map_find_value(&epMap, OC_RSRVD_ENDPOINT, &curVal);
384 VERIFY_CBOR_SUCCESS(TAG, err, "to find endpoint tag");
385 err = cbor_value_dup_text_string(&curVal, &endpointStr, &len, NULL);
386 VERIFY_CBOR_SUCCESS(TAG, err, "to find endpoint value");
388 ret = OCParseEndpointString(endpointStr, endpoint);
389 OICFree(endpointStr);
391 if (OC_STACK_OK == ret)
394 err = cbor_value_map_find_value(&epMap, OC_RSRVD_PRIORITY, &curVal);
395 VERIFY_CBOR_SUCCESS(TAG, err, "to find priority tag");
396 err = cbor_value_get_int(&curVal, &pri);
397 VERIFY_CBOR_SUCCESS(TAG, err, "to find priority value");
398 endpoint->pri = (uint16_t)pri;
399 OCResourcePayloadAddNewEndpoint(resource, endpoint);
404 if (OC_STACK_ADAPTER_NOT_ENABLED == ret)
406 OIC_LOG(ERROR, TAG, "Ignore unrecognized endpoint info");
409 OCDiscoveryEndpointDestroy(endpoint);
413 err = cbor_value_advance(&epMap);
414 VERIFY_CBOR_SUCCESS(TAG, err, "to advance endpoint map");
417 err = cbor_value_leave_container(&epsMap, &epMap);
418 VERIFY_CBOR_SUCCESS(TAG, err, "to leave eps map");
421 err = cbor_value_advance(&resourceMap);
422 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
424 OCDiscoveryPayloadAddNewResource(temp, resource);
427 err = cbor_value_leave_container(&linkMap, &resourceMap);
428 VERIFY_CBOR_SUCCESS(TAG, err, "to leave resource map");
430 err = cbor_value_advance(&rootMap);
431 VERIFY_CBOR_SUCCESS(TAG, err, "to advance root map");
433 if(rootPayload == NULL)
440 curPayload->next = temp;
441 curPayload = curPayload->next;
445 err = cbor_value_leave_container(rootValue, &rootMap);
446 VERIFY_CBOR_SUCCESS(TAG, err, "to leave root map");
451 OIC_LOG(ERROR, TAG, "Malformed packet ");
455 *outPayload = (OCPayload *)rootPayload;
456 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
461 OCDiscoveryEndpointDestroy(endpoint);
462 OCDiscoveryResourceDestroy(resource);
463 OCDiscoveryPayloadDestroy(rootPayload);
467 static OCRepPayloadPropType DecodeCborType(CborType type)
472 return OCREP_PROP_NULL;
473 case CborIntegerType:
474 return OCREP_PROP_INT;
477 return OCREP_PROP_DOUBLE;
478 case CborBooleanType:
479 return OCREP_PROP_BOOL;
480 case CborTextStringType:
481 return OCREP_PROP_STRING;
482 case CborByteStringType:
483 return OCREP_PROP_BYTE_STRING;
485 return OCREP_PROP_OBJECT;
487 return OCREP_PROP_ARRAY;
489 return OCREP_PROP_NULL;
493 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
494 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
496 CborValue insideArray;
497 *type = OCREP_PROP_NULL;
498 dimensions[0] = dimensions[1] = dimensions[2] = 0;
500 CborError err = cbor_value_enter_container(parent, &insideArray);
501 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
503 while (cbor_value_is_valid(&insideArray))
505 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
507 if (tempType == OCREP_PROP_ARRAY)
509 size_t subdim[MAX_REP_ARRAY_DEPTH];
510 tempType = OCREP_PROP_NULL;
511 err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
512 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
516 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
519 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
520 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
522 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
524 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
525 return CborUnknownError;
527 else if (*type == OCREP_PROP_NULL)
529 // We don't know the type of this array yet, so the assignment is OK
533 else if (*type == OCREP_PROP_NULL)
535 // We don't know the type of this array yet, so the assignment is OK
538 // tempType is allowed to be NULL, since it might now know the answer yet
539 else if (tempType != OCREP_PROP_NULL && *type != tempType)
541 // this is an invalid situation!
542 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
543 return CborUnknownError;
547 err = cbor_value_advance(&insideArray);
548 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
555 static size_t getAllocSize(OCRepPayloadPropType type)
560 return sizeof (int64_t);
561 case OCREP_PROP_DOUBLE:
562 return sizeof (double);
563 case OCREP_PROP_BOOL:
564 return sizeof (bool);
565 case OCREP_PROP_STRING:
566 return sizeof (char*);
567 case OCREP_PROP_BYTE_STRING:
568 return sizeof (OCByteString);
569 case OCREP_PROP_OBJECT:
570 return sizeof (OCRepPayload*);
576 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
579 (dimensions[1] == 0 ? 1 : dimensions[1]) *
580 (dimensions[2] == 0 ? 1 : dimensions[2]) *
584 static CborError OCParseArrayFillArray(const CborValue *parent,
585 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
587 CborValue insideArray;
590 char *tempStr = NULL;
591 OCByteString ocByteStr = { .bytes = NULL, .len = 0};
593 OCRepPayload *tempPl = NULL;
595 size_t newdim[MAX_REP_ARRAY_DEPTH];
596 newdim[0] = dimensions[1];
597 newdim[1] = dimensions[2];
600 CborError err = cbor_value_enter_container(parent, &insideArray);
601 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
603 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
605 bool noAdvance = false;
606 if (cbor_value_get_type(&insideArray) != CborNullType)
611 if (dimensions[1] == 0)
613 err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
617 err = OCParseArrayFillArray(&insideArray, newdim, type,
618 &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
621 case OCREP_PROP_DOUBLE:
622 if (dimensions[1] == 0)
624 double *d = &(((double*)targetArray)[i]);
625 if (cbor_value_get_type(&insideArray) == CborDoubleType)
627 err = cbor_value_get_double(&insideArray, d);
633 err = cbor_value_get_float(&insideArray, &f);
640 err = OCParseArrayFillArray(&insideArray, newdim, type,
641 &(((double*)targetArray)[arrayStep(dimensions, i)]));
644 case OCREP_PROP_BOOL:
645 if (dimensions[1] == 0)
647 err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
651 err = OCParseArrayFillArray(&insideArray, newdim, type,
652 &(((bool*)targetArray)[arrayStep(dimensions, i)]));
655 case OCREP_PROP_STRING:
656 if (dimensions[1] == 0)
658 err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
659 ((char**)targetArray)[i] = tempStr;
664 err = OCParseArrayFillArray(&insideArray, newdim, type,
665 &(((char**)targetArray)[arrayStep(dimensions, i)]));
668 case OCREP_PROP_BYTE_STRING:
669 if (dimensions[1] == 0)
671 err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
672 &(ocByteStr.len), NULL);
673 ((OCByteString*)targetArray)[i] = ocByteStr;
677 err = OCParseArrayFillArray(&insideArray, newdim, type,
678 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
681 case OCREP_PROP_OBJECT:
682 if (dimensions[1] == 0)
684 err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
685 ((OCRepPayload**)targetArray)[i] = tempPl;
691 err = OCParseArrayFillArray(&insideArray, newdim, type,
692 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
696 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
697 err = CborErrorUnknownType;
700 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
703 if (!noAdvance && cbor_value_is_valid(&insideArray))
705 err = cbor_value_advance(&insideArray);
706 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
714 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
718 OCRepPayloadPropType type = OCREP_PROP_NULL;
719 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
722 size_t allocSize = 0;
724 CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
725 VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
727 if (type == OCREP_PROP_NULL)
729 res = OCRepPayloadSetNull(out, name);
730 err = (CborError) !res;
731 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
735 dimTotal = calcDimTotal(dimensions);
736 allocSize = getAllocSize(type);
737 arr = OICCalloc(dimTotal, allocSize);
738 VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
740 res = OCParseArrayFillArray(container, dimensions, type, arr);
741 VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
746 res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
748 case OCREP_PROP_DOUBLE:
749 res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
751 case OCREP_PROP_BOOL:
752 res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
754 case OCREP_PROP_STRING:
755 res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
757 case OCREP_PROP_BYTE_STRING:
758 res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
760 case OCREP_PROP_OBJECT:
761 res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
764 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
767 err = (CborError) !res;
768 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
771 if (type == OCREP_PROP_STRING)
773 for(size_t i = 0; i < dimTotal; ++i)
775 OICFree(((char**)arr)[i]);
778 if (type == OCREP_PROP_BYTE_STRING)
780 for(size_t i = 0; i < dimTotal; ++i)
782 OICFree(((OCByteString*)arr)[i].bytes);
785 if (type == OCREP_PROP_OBJECT)
787 for(size_t i = 0; i < dimTotal; ++i)
789 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
796 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
798 CborError err = CborUnknownError;
801 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
802 VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
804 if (cbor_value_is_map(objMap) || cbor_value_is_array(objMap))
808 *outPayload = OCRepPayloadCreate();
811 return CborErrorOutOfMemory;
815 OCRepPayload *curPayload = *outPayload;
817 uint64_t arrayIndex = 0;
820 err = cbor_value_enter_container(objMap, &repMap);
821 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
823 while (!err && cbor_value_is_valid(&repMap))
825 if (cbor_value_is_map(objMap) && cbor_value_is_text_string(&repMap))
827 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
828 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
829 err = cbor_value_advance(&repMap);
830 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
833 ((0 == strcmp(OC_RSRVD_HREF, name)) ||
834 (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
835 (0 == strcmp(OC_RSRVD_INTERFACE, name))))
837 err = cbor_value_advance(&repMap);
838 free(name); // Free *TinyCBOR allocated* string.
842 else if (cbor_value_is_array(objMap))
844 name = (char*)OICCalloc(UINT64_MAX_STRLEN + 1, sizeof(char));
845 VERIFY_PARAM_NON_NULL(TAG, name, "Failed allocating tag name in the map");
847 snprintf(name, UINT64_MAX_STRLEN + 1, "%" PRIu64, arrayIndex);
850 * Some libc implementations do not support the PRIu64 format
851 * specifier. Since we don't expect huge heterogeneous arrays,
852 * we should never hit the error path below in practice.
854 if (arrayIndex <= UINT32_MAX)
856 snprintf(name, UINT64_MAX_STRLEN + 1, "%" PRIu32, (uint32_t)arrayIndex);
860 err = CborErrorDataTooLarge;
866 CborType type = cbor_value_get_type(&repMap);
870 res = OCRepPayloadSetNull(curPayload, name);
872 case CborIntegerType:
875 err = cbor_value_get_int64(&repMap, &intval);
876 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
877 res = OCRepPayloadSetPropInt(curPayload, name, intval);
882 double doubleval = 0;
883 err = cbor_value_get_double(&repMap, &doubleval);
884 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
885 res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
888 case CborBooleanType:
890 bool boolval = false;
891 err = cbor_value_get_boolean(&repMap, &boolval);
892 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
893 res = OCRepPayloadSetPropBool(curPayload, name, boolval);
896 case CborTextStringType:
899 err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
900 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
901 res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
904 case CborByteStringType:
906 uint8_t* bytestrval = NULL;
907 err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
908 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
909 OCByteString tmp = {.bytes = bytestrval, .len = len};
910 res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
915 OCRepPayload *pl = NULL;
916 err = OCParseSingleRepPayload(&pl, &repMap, false);
917 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
918 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
922 err = OCParseArray(curPayload, name, &repMap);
923 if (err != CborNoError)
925 // OCParseArray will fail if the array contains mixed types, try
926 // to parse as payload with non-negative integer value names
927 OCRepPayload *pl = NULL;
928 err = OCParseSingleRepPayload(&pl, &repMap, false);
929 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
930 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
934 OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
937 if (type != CborArrayType)
939 err = (CborError) !res;
941 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
943 if (type != CborMapType && cbor_value_is_valid(&repMap))
945 err = cbor_value_advance(&repMap);
946 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
952 if (cbor_value_is_container(objMap))
954 err = cbor_value_leave_container(objMap, &repMap);
955 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
962 OCRepPayloadDestroy(*outPayload);
967 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
969 OCStackResult ret = OC_STACK_INVALID_PARAM;
971 OCRepPayload *temp = NULL;
972 OCRepPayload *rootPayload = NULL;
973 OCRepPayload *curPayload = NULL;
974 CborValue rootMap = *root;
975 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
976 VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
979 if (cbor_value_is_array(root))
981 err = cbor_value_enter_container(root, &rootMap);
982 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
984 while (cbor_value_is_valid(&rootMap))
986 temp = OCRepPayloadCreate();
987 ret = OC_STACK_NO_MEMORY;
988 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
991 ret = OC_STACK_MALFORMED_RESPONSE;
993 // temporary fix to check for malformed cbor payload
994 if (!cbor_value_is_map(&rootMap) && !cbor_value_is_array(&rootMap)){
998 if (cbor_value_is_map(&rootMap))
1000 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
1001 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
1002 if (cbor_value_is_text_string(&curVal))
1005 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
1006 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1011 if (cbor_value_is_map(&rootMap))
1013 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1015 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1016 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1021 if (cbor_value_is_map(&rootMap))
1023 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1025 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1026 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1030 if (cbor_value_is_map(&rootMap))
1032 err = OCParseSingleRepPayload(&temp, &rootMap, true);
1033 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1036 if(rootPayload == NULL)
1043 curPayload->next = temp;
1044 curPayload = curPayload->next;
1047 if (cbor_value_is_array(&rootMap))
1049 err = cbor_value_advance(&rootMap);
1050 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1053 *outPayload = (OCPayload *)rootPayload;
1057 OCRepPayloadDestroy(temp);
1058 OCRepPayloadDestroy(rootPayload);
1059 OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1063 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1065 OCStackResult ret = OC_STACK_INVALID_PARAM;
1066 OCPresencePayload *payload = NULL;
1067 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1071 payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1072 ret = OC_STACK_NO_MEMORY;
1073 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1074 payload->base.type = PAYLOAD_TYPE_PRESENCE;
1075 ret = OC_STACK_MALFORMED_RESPONSE;
1077 if (cbor_value_is_map(rootValue))
1084 CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1085 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1086 err = cbor_value_get_uint64(&curVal, &temp);
1087 payload->sequenceNumber = (uint32_t)temp;
1088 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1091 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1092 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1094 err = cbor_value_get_uint64(&curVal, &temp);
1095 payload->maxAge = (uint32_t)temp;
1096 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1099 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1100 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1101 err = cbor_value_get_simple_type(&curVal, &trigger);
1102 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1103 payload->trigger = (OCPresenceTrigger)trigger;
1105 // Resource type name
1106 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1107 VERIFY_CBOR_SUCCESS(TAG, err, "to find res type tag");
1108 if (cbor_value_is_text_string(&curVal))
1111 err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1112 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1115 err = cbor_value_advance(rootValue);
1116 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1118 *outPayload = (OCPayload *)payload;
1122 OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1123 OCPresencePayloadDestroy(payload);