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);
65 OIC_LOG_BUFFER(DEBUG, TAG, payload, payloadSize);
70 err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue);
71 VERIFY_CBOR_SUCCESS(TAG, err, "Failed initializing init value")
75 case PAYLOAD_TYPE_DISCOVERY:
76 result = OCParseDiscoveryPayload(outPayload, &rootValue);
78 case PAYLOAD_TYPE_REPRESENTATION:
79 result = OCParseRepPayload(outPayload, &rootValue);
81 case PAYLOAD_TYPE_PRESENCE:
82 result = OCParsePresencePayload(outPayload, &rootValue);
84 case PAYLOAD_TYPE_SECURITY:
85 result = OCParseSecurityPayload(outPayload, payload, payloadSize);
88 OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
89 result = OC_STACK_INVALID_PARAM;
93 OIC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
99 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, const uint8_t *payload,
104 *outPayload = (OCPayload *)OCSecurityPayloadCreate(payload, size);
113 static char* InPlaceStringTrim(char* str)
115 while (str[0] == ' ')
120 size_t lastchar = strlen(str);
122 while (str[lastchar] == ' ')
124 str[lastchar] = '\0';
131 static CborError OCParseStringLL(CborValue *map, char *type, OCStringLL **resource)
134 CborError err = cbor_value_map_find_value(map, type, &val);
135 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL TAG");
137 if (cbor_value_is_array(&val))
140 err = cbor_value_enter_container(&val, &txtStr);
141 VERIFY_CBOR_SUCCESS(TAG, err, "to enter container");
142 while (cbor_value_is_text_string(&txtStr))
146 err = cbor_value_dup_text_string(&txtStr, &input, &len, NULL);
147 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value.");
150 char *savePtr = NULL;
151 char *curPtr = strtok_r(input, " ", &savePtr);
154 char *trimmed = InPlaceStringTrim(curPtr);
155 if (trimmed && strlen(trimmed) > 0)
157 if (!OCResourcePayloadAddStringLL(resource, trimmed))
159 return CborErrorOutOfMemory;
162 curPtr = strtok_r(NULL, " ", &savePtr);
164 free(input); // Free *TinyCBOR allocated* string.
166 if (cbor_value_is_text_string(&txtStr))
168 err = cbor_value_advance(&txtStr);
169 VERIFY_CBOR_SUCCESS(TAG, err, "to advance string value");
177 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
179 OCStackResult ret = OC_STACK_INVALID_PARAM;
180 OCResourcePayload *resource = NULL;
181 OCDiscoveryPayload *temp = NULL;
182 OCDiscoveryPayload *rootPayload = NULL;
183 OCDiscoveryPayload *curPayload = NULL;
184 OCEndpointPayload *endpoint = NULL;
186 CborError err = CborNoError;
189 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
190 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
191 if (cbor_value_is_array(rootValue))
193 // Root value is already inside the main root array
196 // Enter the main root map
197 ret = OC_STACK_MALFORMED_RESPONSE;
198 err = cbor_value_enter_container(rootValue, &rootMap);
199 VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
200 while (cbor_value_is_map(&rootMap))
202 ret = OC_STACK_NO_MEMORY;
203 temp = OCDiscoveryPayloadCreate();
204 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed error initializing discovery payload");
208 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
209 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
210 if (cbor_value_is_valid(&curVal))
212 if (cbor_value_is_byte_string(&curVal))
214 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(temp->sid), &len, NULL);
215 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
217 else if (cbor_value_is_text_string(&curVal))
219 err = cbor_value_dup_text_string(&curVal, &(temp->sid), &len, NULL);
220 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
224 // BaseURI - Not a mandatory field
225 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
226 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri tag");
227 if (cbor_value_is_text_string(&curVal))
229 err = cbor_value_dup_text_string(&curVal, &(temp->baseURI), &len, NULL);
230 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
233 // RT - Not a mandatory field
234 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
235 if (cbor_value_is_valid(&curVal))
237 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->type);
238 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type");
241 // IF - Not a mandatory field
242 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal);
243 if (cbor_value_is_valid(&curVal))
245 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->iface);
246 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface");
249 // Name - Not a mandatory field
250 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_NAME, &curVal);
251 if (cbor_value_is_text_string(&curVal))
253 err = cbor_value_dup_text_string(&curVal, &temp->name, &len, NULL);
254 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name");
257 // Look for Links which will have an array as the value
259 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
260 VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
262 // Enter the links array and start iterating through the array processing
263 // each resource which shows up as a map.
264 CborValue resourceMap;
265 err = cbor_value_enter_container(&linkMap, &resourceMap);
266 VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
268 while (cbor_value_is_map(&resourceMap))
272 resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
273 VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
276 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
277 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
278 err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
279 VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
281 // Rel - Not a mandatory field
282 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_REL, &curVal);
283 VERIFY_CBOR_SUCCESS(TAG, err, "to find rel tag");
284 if (cbor_value_is_valid(&curVal))
286 err = cbor_value_dup_text_string(&curVal, &(resource->rel), &len, NULL);
287 VERIFY_CBOR_SUCCESS(TAG, err, "to find rel value");
291 err = OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
292 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
295 err = OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
296 if (CborNoError != err)
298 if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
300 OIC_LOG(ERROR, TAG, "Failed to add string to StringLL");
307 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
308 VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
311 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
312 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
313 err = cbor_value_get_int(&curVal, &bitmap);
314 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
315 resource->bitmap = (uint8_t)bitmap;
318 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
319 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure tag");
320 if (cbor_value_is_boolean(&curVal))
322 err = cbor_value_get_boolean(&curVal, &(resource->secure));
323 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
327 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
328 VERIFY_CBOR_SUCCESS(TAG, err, "to find port tag");
329 if (cbor_value_is_integer(&curVal))
333 err = cbor_value_get_int(&curVal, &port);
334 VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
335 resource->port = (uint16_t)port;
340 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TCP_PORT, &curVal);
341 if (cbor_value_is_integer(&curVal))
345 err = cbor_value_get_int(&curVal, &tcpPort);
346 VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp port value");
347 resource->tcpPort = (uint16_t)tcpPort;
352 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TLS_PORT, &curVal);
353 if (cbor_value_is_integer(&curVal))
357 err = cbor_value_get_int(&curVal, &tlsPort);
358 VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp tls port value");
359 resource->tcpPort = (uint16_t)tlsPort;
365 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_ENDPOINTS, &epsMap);
366 VERIFY_CBOR_SUCCESS(TAG, err, "to find eps tag");
368 if (cbor_value_is_array(&epsMap))
371 err = cbor_value_enter_container(&epsMap, &epMap);
372 VERIFY_CBOR_SUCCESS(TAG, err, "to enter endpoint map");
374 while (cbor_value_is_map(&epMap))
378 char *endpointStr = NULL;
379 OCStackResult ret = OC_STACK_ERROR;
380 endpoint = (OCEndpointPayload *)OICCalloc(1, sizeof(OCEndpointPayload));
381 VERIFY_PARAM_NON_NULL(TAG, endpoint, "Failed allocating endpoint payload");
384 err = cbor_value_map_find_value(&epMap, OC_RSRVD_ENDPOINT, &curVal);
385 VERIFY_CBOR_SUCCESS(TAG, err, "to find endpoint tag");
386 err = cbor_value_dup_text_string(&curVal, &endpointStr, &len, NULL);
387 VERIFY_CBOR_SUCCESS(TAG, err, "to find endpoint value");
389 ret = OCParseEndpointString(endpointStr, endpoint);
390 OICFree(endpointStr);
392 if (OC_STACK_OK == ret)
395 err = cbor_value_map_find_value(&epMap, OC_RSRVD_PRIORITY, &curVal);
396 VERIFY_CBOR_SUCCESS(TAG, err, "to find priority tag");
397 err = cbor_value_get_int(&curVal, &pri);
398 VERIFY_CBOR_SUCCESS(TAG, err, "to find priority value");
399 endpoint->pri = (uint16_t)pri;
400 OCResourcePayloadAddNewEndpoint(resource, endpoint);
405 if (OC_STACK_ADAPTER_NOT_ENABLED == ret)
407 OIC_LOG(ERROR, TAG, "Ignore unrecognized endpoint info");
410 OCDiscoveryEndpointDestroy(endpoint);
414 err = cbor_value_advance(&epMap);
415 VERIFY_CBOR_SUCCESS(TAG, err, "to advance endpoint map");
418 err = cbor_value_leave_container(&epsMap, &epMap);
419 VERIFY_CBOR_SUCCESS(TAG, err, "to leave eps map");
422 err = cbor_value_advance(&resourceMap);
423 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
425 OCDiscoveryPayloadAddNewResource(temp, resource);
428 err = cbor_value_leave_container(&linkMap, &resourceMap);
429 VERIFY_CBOR_SUCCESS(TAG, err, "to leave resource map");
431 err = cbor_value_advance(&rootMap);
432 VERIFY_CBOR_SUCCESS(TAG, err, "to advance root map");
434 if(rootPayload == NULL)
441 curPayload->next = temp;
442 curPayload = curPayload->next;
446 err = cbor_value_leave_container(rootValue, &rootMap);
447 VERIFY_CBOR_SUCCESS(TAG, err, "to leave root map");
452 OIC_LOG(ERROR, TAG, "Malformed packet ");
456 *outPayload = (OCPayload *)rootPayload;
457 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
462 OCDiscoveryEndpointDestroy(endpoint);
463 OCDiscoveryResourceDestroy(resource);
464 OCDiscoveryPayloadDestroy(rootPayload);
468 static OCRepPayloadPropType DecodeCborType(CborType type)
473 return OCREP_PROP_NULL;
474 case CborIntegerType:
475 return OCREP_PROP_INT;
478 return OCREP_PROP_DOUBLE;
479 case CborBooleanType:
480 return OCREP_PROP_BOOL;
481 case CborTextStringType:
482 return OCREP_PROP_STRING;
483 case CborByteStringType:
484 return OCREP_PROP_BYTE_STRING;
486 return OCREP_PROP_OBJECT;
488 return OCREP_PROP_ARRAY;
490 return OCREP_PROP_NULL;
494 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
495 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
497 CborValue insideArray;
498 *type = OCREP_PROP_NULL;
499 dimensions[0] = dimensions[1] = dimensions[2] = 0;
501 CborError err = cbor_value_enter_container(parent, &insideArray);
502 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
504 while (cbor_value_is_valid(&insideArray))
506 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
508 if (tempType == OCREP_PROP_ARRAY)
510 size_t subdim[MAX_REP_ARRAY_DEPTH];
511 tempType = OCREP_PROP_NULL;
512 err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
513 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
517 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
520 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
521 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
523 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
525 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
526 return CborUnknownError;
528 else if (*type == OCREP_PROP_NULL)
530 // We don't know the type of this array yet, so the assignment is OK
534 else if (*type == OCREP_PROP_NULL)
536 // We don't know the type of this array yet, so the assignment is OK
539 // tempType is allowed to be NULL, since it might now know the answer yet
540 else if (tempType != OCREP_PROP_NULL && *type != tempType)
542 // this is an invalid situation!
543 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
544 return CborUnknownError;
548 err = cbor_value_advance(&insideArray);
549 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
556 static size_t getAllocSize(OCRepPayloadPropType type)
561 return sizeof (int64_t);
562 case OCREP_PROP_DOUBLE:
563 return sizeof (double);
564 case OCREP_PROP_BOOL:
565 return sizeof (bool);
566 case OCREP_PROP_STRING:
567 return sizeof (char*);
568 case OCREP_PROP_BYTE_STRING:
569 return sizeof (OCByteString);
570 case OCREP_PROP_OBJECT:
571 return sizeof (OCRepPayload*);
577 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
580 (dimensions[1] == 0 ? 1 : dimensions[1]) *
581 (dimensions[2] == 0 ? 1 : dimensions[2]) *
585 static CborError OCParseArrayFillArray(const CborValue *parent,
586 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
588 CborValue insideArray;
591 char *tempStr = NULL;
592 OCByteString ocByteStr = { .bytes = NULL, .len = 0};
594 OCRepPayload *tempPl = NULL;
596 size_t newdim[MAX_REP_ARRAY_DEPTH];
597 newdim[0] = dimensions[1];
598 newdim[1] = dimensions[2];
601 CborError err = cbor_value_enter_container(parent, &insideArray);
602 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
604 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
606 bool noAdvance = false;
607 if (cbor_value_get_type(&insideArray) != CborNullType)
612 if (dimensions[1] == 0)
614 err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
618 err = OCParseArrayFillArray(&insideArray, newdim, type,
619 &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
622 case OCREP_PROP_DOUBLE:
623 if (dimensions[1] == 0)
625 double *d = &(((double*)targetArray)[i]);
626 if (cbor_value_get_type(&insideArray) == CborDoubleType)
628 err = cbor_value_get_double(&insideArray, d);
634 err = cbor_value_get_float(&insideArray, &f);
641 err = OCParseArrayFillArray(&insideArray, newdim, type,
642 &(((double*)targetArray)[arrayStep(dimensions, i)]));
645 case OCREP_PROP_BOOL:
646 if (dimensions[1] == 0)
648 err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
652 err = OCParseArrayFillArray(&insideArray, newdim, type,
653 &(((bool*)targetArray)[arrayStep(dimensions, i)]));
656 case OCREP_PROP_STRING:
657 if (dimensions[1] == 0)
659 err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
660 ((char**)targetArray)[i] = tempStr;
665 err = OCParseArrayFillArray(&insideArray, newdim, type,
666 &(((char**)targetArray)[arrayStep(dimensions, i)]));
669 case OCREP_PROP_BYTE_STRING:
670 if (dimensions[1] == 0)
672 err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
673 &(ocByteStr.len), NULL);
674 ((OCByteString*)targetArray)[i] = ocByteStr;
678 err = OCParseArrayFillArray(&insideArray, newdim, type,
679 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
682 case OCREP_PROP_OBJECT:
683 if (dimensions[1] == 0)
685 err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
686 ((OCRepPayload**)targetArray)[i] = tempPl;
692 err = OCParseArrayFillArray(&insideArray, newdim, type,
693 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
697 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
698 err = CborErrorUnknownType;
701 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
704 if (!noAdvance && cbor_value_is_valid(&insideArray))
706 err = cbor_value_advance(&insideArray);
707 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
715 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
719 OCRepPayloadPropType type = OCREP_PROP_NULL;
720 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
723 size_t allocSize = 0;
725 CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
726 VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
728 if (type == OCREP_PROP_NULL)
730 res = OCRepPayloadSetNull(out, name);
731 err = (CborError) !res;
732 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
736 dimTotal = calcDimTotal(dimensions);
737 allocSize = getAllocSize(type);
738 arr = OICCalloc(dimTotal, allocSize);
739 VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
741 res = OCParseArrayFillArray(container, dimensions, type, arr);
742 VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
747 res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
749 case OCREP_PROP_DOUBLE:
750 res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
752 case OCREP_PROP_BOOL:
753 res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
755 case OCREP_PROP_STRING:
756 res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
758 case OCREP_PROP_BYTE_STRING:
759 res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
761 case OCREP_PROP_OBJECT:
762 res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
765 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
768 err = (CborError) !res;
769 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
772 if (type == OCREP_PROP_STRING)
774 for(size_t i = 0; i < dimTotal; ++i)
776 OICFree(((char**)arr)[i]);
779 if (type == OCREP_PROP_BYTE_STRING)
781 for(size_t i = 0; i < dimTotal; ++i)
783 OICFree(((OCByteString*)arr)[i].bytes);
786 if (type == OCREP_PROP_OBJECT)
788 for(size_t i = 0; i < dimTotal; ++i)
790 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
797 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
799 CborError err = CborUnknownError;
802 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
803 VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
805 if (cbor_value_is_map(objMap) || cbor_value_is_array(objMap))
809 *outPayload = OCRepPayloadCreate();
812 return CborErrorOutOfMemory;
816 OCRepPayload *curPayload = *outPayload;
818 uint64_t arrayIndex = 0;
821 err = cbor_value_enter_container(objMap, &repMap);
822 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
824 while (!err && cbor_value_is_valid(&repMap))
826 if (cbor_value_is_map(objMap) && cbor_value_is_text_string(&repMap))
828 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
829 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
830 err = cbor_value_advance(&repMap);
831 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
834 ((0 == strcmp(OC_RSRVD_HREF, name)) ||
835 (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
836 (0 == strcmp(OC_RSRVD_INTERFACE, name))))
838 err = cbor_value_advance(&repMap);
839 free(name); // Free *TinyCBOR allocated* string.
843 else if (cbor_value_is_array(objMap))
845 name = (char*)OICCalloc(UINT64_MAX_STRLEN + 1, sizeof(char));
846 VERIFY_PARAM_NON_NULL(TAG, name, "Failed allocating tag name in the map");
848 snprintf(name, UINT64_MAX_STRLEN + 1, "%" PRIu64, arrayIndex);
851 * Some libc implementations do not support the PRIu64 format
852 * specifier. Since we don't expect huge heterogeneous arrays,
853 * we should never hit the error path below in practice.
855 if (arrayIndex <= UINT32_MAX)
857 snprintf(name, UINT64_MAX_STRLEN + 1, "%" PRIu32, (uint32_t)arrayIndex);
861 err = CborErrorDataTooLarge;
867 CborType type = cbor_value_get_type(&repMap);
871 res = OCRepPayloadSetNull(curPayload, name);
873 case CborIntegerType:
876 err = cbor_value_get_int64(&repMap, &intval);
877 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
878 res = OCRepPayloadSetPropInt(curPayload, name, intval);
883 double doubleval = 0;
884 err = cbor_value_get_double(&repMap, &doubleval);
885 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
886 res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
889 case CborBooleanType:
891 bool boolval = false;
892 err = cbor_value_get_boolean(&repMap, &boolval);
893 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
894 res = OCRepPayloadSetPropBool(curPayload, name, boolval);
897 case CborTextStringType:
900 err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
901 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
902 res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
905 case CborByteStringType:
907 uint8_t* bytestrval = NULL;
908 err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
909 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
910 OCByteString tmp = {.bytes = bytestrval, .len = len};
911 res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
916 OCRepPayload *pl = NULL;
917 err = OCParseSingleRepPayload(&pl, &repMap, false);
918 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
919 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
923 err = OCParseArray(curPayload, name, &repMap);
924 if (err != CborNoError)
926 // OCParseArray will fail if the array contains mixed types, try
927 // to parse as payload with non-negative integer value names
928 OCRepPayload *pl = NULL;
929 err = OCParseSingleRepPayload(&pl, &repMap, false);
930 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
931 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
935 OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
938 if (type != CborArrayType)
940 err = (CborError) !res;
942 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
944 if (type != CborMapType && cbor_value_is_valid(&repMap))
946 err = cbor_value_advance(&repMap);
947 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
953 if (cbor_value_is_container(objMap))
955 err = cbor_value_leave_container(objMap, &repMap);
956 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
963 OCRepPayloadDestroy(*outPayload);
968 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
970 OCStackResult ret = OC_STACK_INVALID_PARAM;
972 OCRepPayload *temp = NULL;
973 OCRepPayload *rootPayload = NULL;
974 OCRepPayload *curPayload = NULL;
975 CborValue rootMap = *root;
976 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
977 VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
980 if (cbor_value_is_array(root))
982 err = cbor_value_enter_container(root, &rootMap);
983 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
985 while (cbor_value_is_valid(&rootMap))
987 temp = OCRepPayloadCreate();
988 ret = OC_STACK_NO_MEMORY;
989 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
992 ret = OC_STACK_MALFORMED_RESPONSE;
994 // temporary fix to check for malformed cbor payload
995 if (!cbor_value_is_map(&rootMap) && !cbor_value_is_array(&rootMap)){
999 if (cbor_value_is_map(&rootMap))
1001 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
1002 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
1003 if (cbor_value_is_text_string(&curVal))
1006 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
1007 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1012 if (cbor_value_is_map(&rootMap))
1014 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1016 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1017 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1022 if (cbor_value_is_map(&rootMap))
1024 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1026 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1027 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1031 if (cbor_value_is_map(&rootMap))
1033 err = OCParseSingleRepPayload(&temp, &rootMap, true);
1034 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1037 if(rootPayload == NULL)
1044 curPayload->next = temp;
1045 curPayload = curPayload->next;
1048 if (cbor_value_is_array(&rootMap))
1050 err = cbor_value_advance(&rootMap);
1051 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1054 *outPayload = (OCPayload *)rootPayload;
1058 OCRepPayloadDestroy(temp);
1059 OCRepPayloadDestroy(rootPayload);
1060 OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1064 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1066 OCStackResult ret = OC_STACK_INVALID_PARAM;
1067 OCPresencePayload *payload = NULL;
1068 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1072 payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1073 ret = OC_STACK_NO_MEMORY;
1074 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1075 payload->base.type = PAYLOAD_TYPE_PRESENCE;
1076 ret = OC_STACK_MALFORMED_RESPONSE;
1078 if (cbor_value_is_map(rootValue))
1085 CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1086 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1087 err = cbor_value_get_uint64(&curVal, &temp);
1088 payload->sequenceNumber = (uint32_t)temp;
1089 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1092 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1093 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1095 err = cbor_value_get_uint64(&curVal, &temp);
1096 payload->maxAge = (uint32_t)temp;
1097 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1100 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1101 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1102 err = cbor_value_get_simple_type(&curVal, &trigger);
1103 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1104 payload->trigger = (OCPresenceTrigger)trigger;
1106 // Resource type name
1107 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1108 VERIFY_CBOR_SUCCESS(TAG, err, "to find res type tag");
1109 if (cbor_value_is_text_string(&curVal))
1112 err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1113 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1116 err = cbor_value_advance(rootValue);
1117 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1119 *outPayload = (OCPayload *)payload;
1123 OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1124 OCPresencePayloadDestroy(payload);