Merge branch 'master' into simulator.
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocpayloadparse.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 // 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
29 #include <string.h>
30 #include "ocpayloadcbor.h"
31 #include <stdlib.h>
32 #include "logger.h"
33 #include "oic_string.h"
34 #include "oic_malloc.h"
35 #include "ocstackinternal.h"
36 #include "ocpayload.h"
37 #include "cbor.h"
38 #include "oic_string.h"
39 #include "payload_logging.h"
40 #include "rdpayload.h"
41
42 #define TAG "OCPayloadParse"
43
44 static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal);
45 static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal);
46 static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* arrayVal);
47 static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repParent);
48 static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayVal);
49 static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal);
50 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal);
51
52 OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType,
53         const uint8_t* payload, size_t payloadSize)
54 {
55     CborParser parser;
56     CborValue rootValue;
57     bool err = false;
58
59     OC_LOG_V(INFO, TAG, "CBOR Parsing size: %zu", payloadSize);
60     if((err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue)) != false)
61     {
62         OC_LOG_V(ERROR, TAG, "CBOR Parser init failed: %d", err);
63         return OC_STACK_ERROR;
64     }
65
66     OCStackResult result = OC_STACK_ERROR;
67     switch(payloadType)
68     {
69         case PAYLOAD_TYPE_DISCOVERY:
70             result = OCParseDiscoveryPayload(outPayload, &rootValue);
71             break;
72         case PAYLOAD_TYPE_DEVICE:
73             result = OCParseDevicePayload(outPayload, &rootValue);
74             break;
75         case PAYLOAD_TYPE_PLATFORM:
76             result = OCParsePlatformPayload(outPayload, &rootValue);
77             break;
78         case PAYLOAD_TYPE_REPRESENTATION:
79             result = OCParseRepPayload(outPayload, &rootValue);
80             break;
81         case PAYLOAD_TYPE_PRESENCE:
82             result = OCParsePresencePayload(outPayload, &rootValue);
83             break;
84         case PAYLOAD_TYPE_SECURITY:
85             result = OCParseSecurityPayload(outPayload, &rootValue);
86             break;
87         case PAYLOAD_TYPE_RD:
88             result = OCRDCborToPayload(&rootValue, outPayload);
89             break;
90         default:
91             OC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
92             result = OC_STACK_ERROR;
93             break;
94     }
95
96     if(result != OC_STACK_OK)
97     {
98         OC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
99     }
100
101     return result;
102 }
103
104 void OCFreeOCStringLL(OCStringLL* ll);
105
106 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* rootValue)
107 {
108     if (!outPayload)
109     {
110         return OC_STACK_INVALID_PARAM;
111     }
112
113     bool err = false;
114     char * securityData = NULL;
115     CborValue map;
116     size_t len;
117
118     err = err || cbor_value_enter_container(rootValue, &map);
119     err = err || cbor_value_dup_text_string(&map, &securityData, &len, NULL);
120     err = err || cbor_value_leave_container(rootValue, &map);
121
122     if(err)
123     {
124         OC_LOG(ERROR, TAG, "Cbor in error condition");
125         OICFree(securityData);
126         return OC_STACK_MALFORMED_RESPONSE;
127     }
128
129     *outPayload = (OCPayload*)OCSecurityPayloadCreate(securityData);
130     OICFree(securityData);
131
132     return OC_STACK_OK;
133
134 }
135
136 static char* InPlaceStringTrim(char* str)
137 {
138     while (str[0] == ' ')
139     {
140         ++str;
141     }
142
143     size_t lastchar = strlen(str);
144
145     while (str[lastchar] == ' ')
146     {
147         str[lastchar] = '\0';
148         --lastchar;
149     }
150
151     return str;
152 }
153
154 static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* rootValue)
155 {
156     if (!outPayload)
157     {
158         return OC_STACK_INVALID_PARAM;
159     }
160
161     bool err = false;
162     OCResourcePayload* resource = NULL;
163     uint16_t resourceCount = 0;
164     CborValue resourceMap = { 0 };
165
166     OCDiscoveryPayload* out = OCDiscoveryPayloadCreate();
167     if(!out)
168     {
169         return OC_STACK_NO_MEMORY;
170     }
171
172     // Root value is already inside the main root array
173     CborValue rootMap = { 0 };
174
175     // Enter the main root map
176     err = err || cbor_value_enter_container(rootValue, &rootMap);
177     // Look for DI
178     CborValue curVal = { 0 };
179     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
180     if (CborNoError != err)
181     {
182         OC_LOG(ERROR, TAG, "Cbor find value failed.");
183         goto malformed_cbor;
184     }
185     size_t len;
186     err = cbor_value_dup_byte_string(&curVal, &(out->sid), &len, NULL);
187
188     // BaseURI - Not a mandatory field
189     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
190     if (CborNoError == err && cbor_value_is_valid(&curVal))
191     {
192         err = cbor_value_dup_text_string(&curVal, &(out->baseURI), &len, NULL);
193         if (CborNoError != err)
194         {
195             OC_LOG(ERROR, TAG, "baseURI failed.");
196             goto malformed_cbor;
197         }
198     }
199
200     // Look for Links which will have an array as the value
201     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &curVal);
202     if (CborNoError != err)
203     {
204         OC_LOG(ERROR, TAG, "Cbor find value failed.");
205         goto malformed_cbor;
206     }
207
208     // Enter the links array and start iterating through the array processing
209     // each resource which shows up as a map.
210     err = err || cbor_value_enter_container(&curVal, &resourceMap);
211
212     while (cbor_value_is_map(&resourceMap))
213     {
214         resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
215         if(!resource)
216         {
217             OC_LOG(ERROR, TAG, "Memory allocation failed");
218             OCDiscoveryPayloadDestroy(out);
219             return OC_STACK_NO_MEMORY;
220         }
221
222         // Uri
223         CborValue uriVal = { 0 };
224         err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &uriVal);
225         if (CborNoError != err)
226         {
227             OC_LOG(ERROR, TAG, "Cbor finding href type failed.");
228             goto malformed_cbor;
229         }
230         err = cbor_value_dup_text_string(&uriVal, &(resource->uri), &len, NULL);
231         if (CborNoError != err)
232         {
233             OC_LOG(ERROR, TAG, "Cbor finding href value failed.");
234             goto malformed_cbor;
235         }
236         // ResourceTypes
237         CborValue rtVal = { 0 };
238         err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &rtVal);
239         if (CborNoError != err)
240         {
241             OC_LOG(ERROR, TAG, "Cbor finding rt type failed.");
242             goto malformed_cbor;
243         }
244         if (cbor_value_is_text_string(&rtVal))
245         {
246             char* input = NULL;
247             char* savePtr;
248             err = cbor_value_dup_text_string(&rtVal, &input, &len, NULL);
249             if (CborNoError != err)
250             {
251                 OC_LOG(ERROR, TAG, "Cbor finding rt value failed.");
252                 goto malformed_cbor;
253             }
254             if (input)
255             {
256                 char* curPtr = strtok_r(input, " ", &savePtr);
257
258                 while (curPtr)
259                 {
260                     char* trimmed = InPlaceStringTrim(curPtr);
261                     if (trimmed[0] !='\0')
262                     {
263                         if (!OCResourcePayloadAddResourceType(resource, trimmed))
264                         {
265                             OICFree(resource->uri);
266                             OCFreeOCStringLL(resource->types);
267                             OICFree(resource);
268                             OCDiscoveryPayloadDestroy(out);
269                             return OC_STACK_NO_MEMORY;
270                         }
271                     }
272                     curPtr = strtok_r(NULL, " ", &savePtr);
273                 }
274                 OICFree(input);
275             }
276         }
277
278         // Interface Types
279         CborValue ifVal = { 0 };
280         err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_INTERFACE, &ifVal);
281         if (CborNoError != err)
282         {
283             OC_LOG(ERROR, TAG, "Cbor finding if type failed.");
284             goto malformed_cbor;
285         }
286         if (!err && cbor_value_is_text_string(&ifVal))
287         {
288             char* input = NULL;
289             char* savePtr;
290             err = cbor_value_dup_text_string(&ifVal, &input, &len, NULL);
291             if (CborNoError != err)
292             {
293                 OC_LOG(ERROR, TAG, "Cbor finding if value failed.");
294                 goto malformed_cbor;
295             }
296             if (input)
297             {
298                 char* curPtr = strtok_r(input, " ", &savePtr);
299
300                 while (curPtr)
301                 {
302                     char* trimmed = InPlaceStringTrim(curPtr);
303                     if (trimmed[0] !='\0')
304                     {
305                         if (!OCResourcePayloadAddInterface(resource, trimmed))
306                         {
307                             OICFree(resource->uri);
308                             OCFreeOCStringLL(resource->types);
309                             OICFree(resource);
310                             OCDiscoveryPayloadDestroy(out);
311                             return OC_STACK_NO_MEMORY;
312                         }
313                     }
314                     curPtr = strtok_r(NULL, " ", &savePtr);
315                 }
316                 OICFree(input);
317             }
318         }
319
320         // Policy
321         CborValue policyMap = { 0 };
322         err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
323         if (CborNoError != err)
324         {
325             OC_LOG(ERROR, TAG, "Cbor finding policy type failed.");
326             goto malformed_cbor;
327         }
328         // Bitmap
329         CborValue val = { 0 };
330         err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &val);
331         if (CborNoError != err)
332         {
333             OC_LOG(ERROR, TAG, "Cbor finding bitmap type failed.");
334             goto malformed_cbor;
335         }
336         uint64_t temp = 0;
337         err = cbor_value_get_uint64(&val, &temp);
338         if (CborNoError != err)
339         {
340             OC_LOG(ERROR, TAG, "Cbor finding bitmap value failed.");
341             goto malformed_cbor;
342         }
343         resource->bitmap = (uint8_t)temp;
344         // Secure Flag
345         err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &val);
346         if (CborNoError != err)
347         {
348             OC_LOG(ERROR, TAG, "Cbor finding secure type failed.");
349             goto malformed_cbor;
350         }
351         if(cbor_value_is_valid(&val))
352         {
353             err = cbor_value_get_boolean(&val, &(resource->secure));
354             if (CborNoError != err)
355             {
356                 OC_LOG(ERROR, TAG, "Cbor finding secure value failed.");
357                 goto malformed_cbor;
358             }
359             // Port
360             CborValue port = { 0 };
361             err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT,
362                             &port);
363             if (CborNoError != err)
364             {
365                 OC_LOG(ERROR, TAG, "Cbor finding port type failed.");
366                 goto malformed_cbor;
367             }
368             if (cbor_value_is_valid(&port))
369             {
370                 err = cbor_value_get_uint64(&port, &temp);
371                 if (CborNoError != err)
372                 {
373                     OC_LOG(ERROR, TAG, "Cbor finding port value failed.");
374                     goto malformed_cbor;
375                 }
376                 resource->port = (uint16_t)temp;
377             }
378         }
379         else if (out->baseURI)
380         {
381             // Port
382             CborValue port = { 0 };
383             err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &port);
384             if (CborNoError != err)
385             {
386                 OC_LOG(ERROR, TAG, "Cbor finding port type failed.");
387                 goto malformed_cbor;
388             }
389             if(cbor_value_is_valid(&port))
390             {
391                 err = cbor_value_get_uint64(&port, &temp);
392                 if (CborNoError != err)
393                 {
394                     OC_LOG(ERROR, TAG, "Cbor finding port value failed.");
395                     goto malformed_cbor;
396                 }
397                 resource->port = (uint16_t)temp;
398             }
399         }
400
401         err = cbor_value_advance(&resourceMap);
402         if (CborNoError != err)
403         {
404             OC_LOG(ERROR, TAG, "Cbor advance value failed.");
405             goto malformed_cbor;
406         }
407         ++resourceCount;
408         OCDiscoveryPayloadAddNewResource(out, resource);
409     }
410
411     err = err || cbor_value_leave_container(rootValue, &resourceMap);
412
413     *outPayload = (OCPayload*)out;
414     return OC_STACK_OK;
415
416 malformed_cbor:
417     OICFree(resource->uri);
418     OCFreeOCStringLL(resource->types);
419     OCFreeOCStringLL(resource->interfaces);
420     OICFree(resource);
421     OCDiscoveryPayloadDestroy(out);
422     return OC_STACK_MALFORMED_RESPONSE;
423 }
424
425 static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* rootValue)
426 {
427     if (!outPayload)
428     {
429         return OC_STACK_INVALID_PARAM;
430     }
431
432     bool err = false;
433
434     if(cbor_value_is_map(rootValue))
435     {
436         uint8_t* sid = NULL;
437         char* dname = NULL;
438         char* specVer = NULL;
439         char* dmVer = NULL;
440
441         CborValue repVal;
442         // Device ID
443         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &repVal);
444         size_t len;
445         if(cbor_value_is_valid(&repVal))
446         {
447             err = err || cbor_value_dup_byte_string(&repVal, &sid, &len, NULL);
448         }
449         // Device Name
450         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &repVal);
451         if(cbor_value_is_valid(&repVal))
452         {
453             err = err || cbor_value_dup_text_string(&repVal, &dname, &len, NULL);
454         }
455         // Device Spec Version
456         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &repVal);
457         if(cbor_value_is_valid(&repVal))
458         {
459             err = err || cbor_value_dup_text_string(&repVal, &specVer, &len, NULL);
460         }
461
462         // Data Model Version
463         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &repVal);
464         if (cbor_value_is_valid(&repVal))
465         {
466             err = err || cbor_value_dup_text_string(&repVal, &dmVer, &len, NULL);
467         }
468
469         err = err || cbor_value_advance(rootValue);
470
471         if(err)
472         {
473             OICFree(sid);
474             OICFree(dname);
475             OICFree(specVer);
476             OICFree(dmVer);
477             OC_LOG_V(ERROR, TAG, "CBOR in error condition %d", err);
478             return OC_STACK_MALFORMED_RESPONSE;
479         }
480
481         *outPayload = (OCPayload*)OCDevicePayloadCreate(sid, dname, specVer, dmVer);
482
483         OICFree(sid);
484         OICFree(dname);
485         OICFree(specVer);
486         OICFree(dmVer);
487         if(!*outPayload)
488         {
489             return OC_STACK_NO_MEMORY;
490         }
491
492         return OC_STACK_OK;
493     }
494     else
495     {
496         OC_LOG(ERROR, TAG, "Root device node was not a map");
497         return OC_STACK_MALFORMED_RESPONSE;
498     }
499
500 }
501
502 static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* rootValue)
503 {
504     if (!outPayload)
505     {
506         return OC_STACK_INVALID_PARAM;
507     }
508
509     bool err = false;
510
511     if(cbor_value_is_map(rootValue))
512     {
513         OCPlatformInfo info = {0};
514
515         CborValue repVal;
516         size_t len;
517         // Platform ID
518         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
519         if(cbor_value_is_valid(&repVal))
520          {
521              err = err || cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
522          }
523
524          // MFG Name
525          err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
526          if(cbor_value_is_valid(&repVal))
527          {
528              err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
529          }
530
531         // MFG URL
532         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
533         if(cbor_value_is_valid(&repVal))
534         {
535              err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
536         }
537
538         // Model Num
539         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
540         if(cbor_value_is_valid(&repVal))
541         {
542              err = err || cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
543         }
544
545         // Date of Mfg
546         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
547         if(cbor_value_is_valid(&repVal))
548         {
549              err = err || cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len,
550                     NULL);
551         }
552
553         // Platform Version
554         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
555         if(cbor_value_is_valid(&repVal))
556         {
557              err = err || cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
558         }
559
560         // OS Version
561         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
562         if(cbor_value_is_valid(&repVal))
563         {
564              err = err || cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion),
565                     &len, NULL);
566         }
567
568         // Hardware Version
569         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
570         if(cbor_value_is_valid(&repVal))
571         {
572              err = err || cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len,
573                     NULL);
574         }
575
576         // Firmware Version
577         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
578         if(cbor_value_is_valid(&repVal))
579         {
580              err = err || cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len,
581                     NULL);
582         }
583
584         // Support URL
585         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
586         if(cbor_value_is_valid(&repVal))
587         {
588              err = err || cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
589         }
590
591         // System Time
592         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
593         if(cbor_value_is_valid(&repVal))
594         {
595              err = err || cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
596         }
597
598         err = err || cbor_value_advance(rootValue);
599
600         if(err)
601         {
602             OICFree(info.dateOfManufacture);
603             OICFree(info.firmwareVersion);
604             OICFree(info.hardwareVersion);
605             OICFree(info.manufacturerName);
606             OICFree(info.manufacturerUrl);
607             OICFree(info.modelNumber);
608             OICFree(info.operatingSystemVersion);
609             OICFree(info.platformID);
610             OICFree(info.platformVersion);
611             OICFree(info.supportUrl);
612             OICFree(info.systemTime);
613             OC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
614             return OC_STACK_MALFORMED_RESPONSE;
615         }
616
617         *outPayload = (OCPayload*)OCPlatformPayloadCreateAsOwner(&info);
618
619         if(!*outPayload)
620         {
621             return OC_STACK_NO_MEMORY;
622         }
623
624         return OC_STACK_OK;
625     }
626     else
627     {
628         OC_LOG(ERROR, TAG, "Root device node was not a map");
629         return OC_STACK_MALFORMED_RESPONSE;
630     }
631 }
632
633 static OCRepPayloadPropType DecodeCborType(CborType type)
634 {
635     switch (type)
636     {
637             case CborNullType:
638                 return OCREP_PROP_NULL;
639             case CborIntegerType:
640                 return OCREP_PROP_INT;
641             case CborDoubleType:
642                 return OCREP_PROP_DOUBLE;
643             case CborBooleanType:
644                 return OCREP_PROP_BOOL;
645             case CborTextStringType:
646                 return OCREP_PROP_STRING;
647             case CborByteStringType:
648                 return OCREP_PROP_BYTE_STRING;
649             case CborMapType:
650                 return OCREP_PROP_OBJECT;
651             case CborArrayType:
652                 return OCREP_PROP_ARRAY;
653             default:
654                 return OCREP_PROP_NULL;
655     }
656 }
657 static bool OCParseArrayFindDimensionsAndType(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
658         OCRepPayloadPropType* type)
659 {
660     bool err = false;
661     CborValue insideArray;
662     *type = OCREP_PROP_NULL;
663     dimensions[0] = dimensions[1] = dimensions[2] = 0;
664
665     err = err || cbor_value_enter_container(parent, &insideArray);
666
667     while (cbor_value_is_valid(&insideArray))
668     {
669         OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
670
671         if (tempType == OCREP_PROP_ARRAY)
672         {
673             size_t subdim[MAX_REP_ARRAY_DEPTH];
674             tempType = OCREP_PROP_NULL;
675             err = err || OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
676
677             if (subdim[2] != 0)
678             {
679                 OC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
680             }
681
682             dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
683             dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
684
685             if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL
686                     && *type != tempType)
687             {
688                 OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
689                 return true;
690             }
691             else if (*type == OCREP_PROP_NULL)
692             {
693                 // We don't know the type of this array yet, so the assignment is OK
694                 *type = tempType;
695             }
696         }
697         else if (*type == OCREP_PROP_NULL)
698         {
699             // We don't know the type of this array yet, so the assignment is OK
700             *type = tempType;
701         }
702         // tempType is allowed to be NULL, since it might now know the answer yet
703         else if (tempType != OCREP_PROP_NULL && *type != tempType)
704         {
705             // this is an invalid situation!
706             OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
707             return true;
708         }
709
710         ++dimensions[0];
711         cbor_value_advance(&insideArray);
712     }
713
714     return err;
715 }
716
717 static size_t getAllocSize(OCRepPayloadPropType type)
718 {
719     switch (type)
720     {
721         case OCREP_PROP_INT:
722             return sizeof (int64_t);
723         case OCREP_PROP_DOUBLE:
724             return sizeof (double);
725         case OCREP_PROP_BOOL:
726             return sizeof (bool);
727         case OCREP_PROP_STRING:
728             return sizeof (char*);
729         case OCREP_PROP_BYTE_STRING:
730             return sizeof (OCByteString);
731         case OCREP_PROP_OBJECT:
732             return sizeof (OCRepPayload*);
733         default:
734             return 0;
735     }
736 }
737
738 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
739 {
740     return
741         (dimensions[1] == 0 ? 1 : dimensions[1]) *
742         (dimensions[2] == 0 ? 1 : dimensions[2]) *
743         elementNum;
744 }
745
746 static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
747         OCRepPayloadPropType type, void* targetArray)
748 {
749     bool err = false;
750     CborValue insideArray;
751
752     err = err || cbor_value_enter_container(parent, &insideArray);
753
754     size_t i = 0;
755     char* tempStr = NULL;
756     OCByteString ocByteStr = { .bytes = NULL, .len = 0};
757     size_t tempLen = 0;
758     OCRepPayload* tempPl = NULL;
759
760     size_t newdim[MAX_REP_ARRAY_DEPTH];
761     newdim[0] = dimensions[1];
762     newdim[1] = dimensions[2];
763     newdim[2] = 0;
764
765     while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
766     {
767         bool noAdvance = false;
768         if (cbor_value_get_type(&insideArray) != CborNullType)
769         {
770             switch (type)
771             {
772                 case OCREP_PROP_INT:
773                     if (dimensions[1] == 0)
774                     {
775                         err = err || cbor_value_get_int64(&insideArray,
776                                 &(((int64_t*)targetArray)[i]));
777                     }
778                     else
779                     {
780                         err = err || OCParseArrayFillArray(&insideArray, newdim,
781                             type,
782                             &(((int64_t*)targetArray)[arrayStep(dimensions, i)])
783                             );
784                     }
785                     break;
786                 case OCREP_PROP_DOUBLE:
787                     if (dimensions[1] == 0)
788                     {
789                         err = err || cbor_value_get_double(&insideArray,
790                                 &(((double*)targetArray)[i]));
791                     }
792                     else
793                     {
794                         err = err || OCParseArrayFillArray(&insideArray, newdim,
795                             type,
796                             &(((double*)targetArray)[arrayStep(dimensions, i)])
797                             );
798                     }
799                     break;
800                 case OCREP_PROP_BOOL:
801                     if (dimensions[1] == 0)
802                     {
803                         err = err || cbor_value_get_boolean(&insideArray,
804                                 &(((bool*)targetArray)[i]));
805                     }
806                     else
807                     {
808                         err = err || OCParseArrayFillArray(&insideArray, newdim,
809                             type,
810                             &(((bool*)targetArray)[arrayStep(dimensions, i)])
811                             );
812                     }
813                     break;
814                 case OCREP_PROP_STRING:
815                     if (dimensions[1] == 0)
816                     {
817                         err = err || cbor_value_dup_text_string(&insideArray,
818                                 &tempStr, &tempLen, NULL);
819                         ((char**)targetArray)[i] = tempStr;
820                         tempStr = NULL;
821                     }
822                     else
823                     {
824                         err = err || OCParseArrayFillArray(&insideArray, newdim,
825                             type,
826                             &(((char**)targetArray)[arrayStep(dimensions, i)])
827                             );
828                     }
829                     break;
830                 case OCREP_PROP_BYTE_STRING:
831                     if (dimensions[1] == 0)
832                     {
833                         err = err || cbor_value_dup_byte_string(&insideArray,
834                                 &(ocByteStr.bytes), &(ocByteStr.len), NULL);
835                         ((OCByteString*)targetArray)[i] = ocByteStr;
836                     }
837                     else
838                     {
839                         err = err || OCParseArrayFillArray(&insideArray, newdim,
840                                 type,
841                                 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)])
842                                 );
843                     }
844                     break;
845                 case OCREP_PROP_OBJECT:
846                     if (dimensions[1] == 0)
847                     {
848                         err = err || OCParseSingleRepPayload(&tempPl, &insideArray);
849                         ((OCRepPayload**)targetArray)[i] = tempPl;
850                         tempPl = NULL;
851                         noAdvance = true;
852                     }
853                     else
854                     {
855                         err = err || OCParseArrayFillArray(&insideArray, newdim,
856                             type,
857                             &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)])
858                             );
859                     }
860                     break;
861                 default:
862                     OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
863                     err = true;
864                     break;
865             }
866         }
867         ++i;
868         if (!noAdvance && cbor_value_is_valid(&insideArray))
869         {
870             err = err || cbor_value_advance(&insideArray);
871         }
872     }
873
874     return err;
875 }
876
877 static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
878 {
879     OCRepPayloadPropType type;
880     size_t dimensions[MAX_REP_ARRAY_DEPTH];
881     bool err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
882
883     if (err)
884     {
885         OC_LOG(ERROR, TAG, "Array details weren't clear");
886         return err;
887     }
888
889     if (type == OCREP_PROP_NULL)
890     {
891         err = err || OCRepPayloadSetNull(out, name);
892         err = err || cbor_value_advance(container);
893         return err;
894     }
895
896     size_t dimTotal = calcDimTotal(dimensions);
897     size_t allocSize = getAllocSize(type);
898     void* arr = OICCalloc(dimTotal, allocSize);
899
900     if (!arr)
901     {
902         OC_LOG(ERROR, TAG, "Array Parse allocation failed");
903         return true;
904     }
905
906     err = err || OCParseArrayFillArray(container, dimensions, type, arr);
907
908     switch (type)
909     {
910         case OCREP_PROP_INT:
911             if (err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
912             {
913                 OICFree(arr);
914                 err = true;
915             }
916             break;
917         case OCREP_PROP_DOUBLE:
918             if (err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
919             {
920                 OICFree(arr);
921                 err = true;
922             }
923             break;
924         case OCREP_PROP_BOOL:
925             if (err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
926             {
927                 OICFree(arr);
928                 err = true;
929             }
930             break;
931         case OCREP_PROP_STRING:
932             if (err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
933             {
934                 for(size_t i = 0; i < dimTotal; ++i)
935                 {
936                     OICFree(((char**)arr)[i]);
937                 }
938                 OICFree(arr);
939                 err = true;
940             }
941             break;
942         case OCREP_PROP_BYTE_STRING:
943             if (err || !OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString*)arr, dimensions))
944             {
945                 for (size_t i = 0; i < dimTotal; ++i)
946                 {
947                     OICFree(((OCByteString*)arr)[i].bytes);
948                 }
949                 OICFree(arr);
950                 err = true;
951             }
952             break;
953         case OCREP_PROP_OBJECT:
954             if (err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
955             {
956                 for(size_t i = 0; i < dimTotal; ++i)
957                 {
958                     OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
959                 }
960                 OICFree(arr);
961                 err = true;
962             }
963             break;
964         default:
965             OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
966             err = true;
967             break;
968     }
969
970     return err;
971 }
972
973 static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue *objMap)
974 {
975     if (!outPayload)
976     {
977         return false;
978     }
979
980     bool err = false;
981
982     if (cbor_value_is_map(objMap))
983     {
984         if (!*outPayload)
985         {
986             *outPayload = OCRepPayloadCreate();
987             if(!*outPayload)
988             {
989                 return CborErrorOutOfMemory;
990             }
991         }
992
993         OCRepPayload* curPayload = *outPayload;
994
995         size_t len;
996         CborValue repMap;
997         err = err || cbor_value_enter_container(objMap, &repMap);
998
999         while(!err && cbor_value_is_valid(&repMap))
1000         {
1001             char* name;
1002             err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
1003             err = err || cbor_value_advance(&repMap);
1004
1005             CborType type = cbor_value_get_type(&repMap);
1006             switch(type)
1007             {
1008                 case CborNullType:
1009                     err = !OCRepPayloadSetNull(curPayload, name);
1010                     break;
1011                 case CborIntegerType:
1012                     {
1013                         int64_t intval = 0;
1014                         err = err || cbor_value_get_int64(&repMap, &intval);
1015                         if (!err)
1016                         {
1017                             err = !OCRepPayloadSetPropInt(curPayload, name, intval);
1018                         }
1019                     }
1020                     break;
1021                 case CborDoubleType:
1022                     {
1023                         double doubleval = 0;
1024                         err = err || cbor_value_get_double(&repMap, &doubleval);
1025                         if (!err)
1026                         {
1027                             err = !OCRepPayloadSetPropDouble(curPayload, name, doubleval);
1028                         }
1029                     }
1030                     break;
1031                 case CborBooleanType:
1032                     {
1033                         bool boolval = false;
1034                         err = err || cbor_value_get_boolean(&repMap, &boolval);
1035                         if (!err)
1036                         {
1037                             err = !OCRepPayloadSetPropBool(curPayload, name, boolval);
1038                         }
1039                     }
1040                     break;
1041                 case CborTextStringType:
1042                     {
1043                         char* strval = NULL;
1044                         err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
1045                         if (!err)
1046                         {
1047                             err = !OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
1048                         }
1049                     }
1050                     break;
1051                 case CborByteStringType:
1052                     {
1053                         uint8_t* bytestrval = NULL;
1054                         err = err || cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
1055                         if (!err)
1056                         {
1057                             OCByteString tmp = {.bytes = bytestrval, .len = len};
1058                             err = !OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
1059                         }
1060                     }
1061                     break;
1062                 case CborMapType:
1063                     {
1064                         OCRepPayload *pl = NULL;
1065                         err = err || OCParseSingleRepPayload(&pl, &repMap);
1066                         if (!err)
1067                         {
1068                             err = !OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
1069                         }
1070                     }
1071                     break;
1072                 case CborArrayType:
1073                     err = err || OCParseArray(curPayload, name, &repMap);
1074                     break;
1075                 default:
1076                     OC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
1077                     err = true;
1078             }
1079
1080             if (type != CborMapType && cbor_value_is_valid(&repMap))
1081             {
1082                 err = err || cbor_value_advance(&repMap);
1083             }
1084             OICFree(name);
1085         }
1086
1087         err = err || cbor_value_leave_container(objMap, &repMap);
1088
1089         if(err)
1090         {
1091             OCRepPayloadDestroy(*outPayload);
1092             *outPayload = NULL;
1093         }
1094     }
1095
1096     return err;
1097 }
1098
1099 static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* rootMap)
1100 {
1101     if (!outPayload)
1102     {
1103         return OC_STACK_INVALID_PARAM;
1104     }
1105
1106     OCRepPayload *rootPayload = NULL;
1107     OCRepPayload *curPayload = NULL;
1108     OCRepPayload *temp = OCRepPayloadCreate();
1109     if (!temp)
1110     {
1111         return OC_STACK_NO_MEMORY;
1112     }
1113
1114     CborValue curVal;
1115     bool err = false;
1116     size_t len;
1117     err = err || cbor_value_map_find_value(rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
1118     if(cbor_value_is_text_string(&curVal))
1119     {
1120         char* allRt = NULL;
1121         err = err || cbor_value_dup_text_string(&curVal, &allRt, &len, NULL);
1122         if (allRt)
1123         {
1124             char* savePtr;
1125             char* curPtr = strtok_r(allRt, " ", &savePtr);
1126             while (curPtr)
1127             {
1128                 char* trimmed = InPlaceStringTrim(curPtr);
1129                 if (trimmed[0] != '\0')
1130                 {
1131                     OCRepPayloadAddResourceType(temp, curPtr);
1132                 }
1133                 curPtr = strtok_r(NULL, " ", &savePtr);
1134             }
1135         }
1136         OICFree(allRt);
1137     }
1138
1139     err = err || cbor_value_map_find_value(rootMap, OC_RSRVD_INTERFACE, &curVal);
1140     if(cbor_value_is_text_string(&curVal))
1141     {
1142         char* allIf = NULL;
1143         err = err || cbor_value_dup_text_string(&curVal, &allIf, &len, NULL);
1144         if (allIf)
1145         {
1146             char* savePtr;
1147             char* curPtr = strtok_r(allIf, " ", &savePtr);
1148             while (curPtr)
1149             {
1150                 char* trimmed = InPlaceStringTrim(curPtr);
1151                 if (trimmed[0] != '\0')
1152                 {
1153                     OCRepPayloadAddInterface(temp, curPtr);
1154                 }
1155                 curPtr = strtok_r(NULL, " ", &savePtr);
1156             }
1157         }
1158         OICFree(allIf);
1159     }
1160
1161     while (!err && cbor_value_is_map(rootMap))
1162     {
1163          err = err || OCParseSingleRepPayload(&temp, rootMap);
1164
1165         if(rootPayload == NULL)
1166         {
1167             rootPayload = temp;
1168             curPayload = temp;
1169         }
1170         else
1171         {
1172             curPayload->next = temp;
1173             curPayload = curPayload->next;
1174         }
1175
1176         if (cbor_value_is_valid(rootMap))
1177         {
1178             err = err || cbor_value_advance(rootMap);
1179         }
1180
1181         if(err)
1182         {
1183             OCRepPayloadDestroy(rootPayload);
1184             OC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1185             return OC_STACK_MALFORMED_RESPONSE;
1186         }
1187     }
1188
1189     *outPayload = (OCPayload*)rootPayload;
1190
1191     return OC_STACK_OK;
1192 }
1193
1194 static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* rootValue)
1195 {
1196     if (!outPayload)
1197     {
1198         return OC_STACK_INVALID_PARAM;
1199     }
1200
1201     bool err = false;
1202
1203     if(cbor_value_is_map(rootValue))
1204     {
1205         uint64_t seqNum = 0;
1206         uint64_t maxAge = 0;
1207         OCPresenceTrigger trigger = OC_PRESENCE_TRIGGER_CREATE;
1208         char* tempStr = NULL;
1209         size_t len = 0;
1210
1211         CborValue curVal;
1212         // Sequence Number
1213         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1214         err = err || cbor_value_get_uint64(&curVal, &seqNum);
1215
1216         // Max Age
1217         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1218         err = err || cbor_value_get_uint64(&curVal, &maxAge);
1219
1220         // Trigger
1221         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1222         err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
1223         trigger = convertTriggerStringToEnum(tempStr);
1224         OICFree(tempStr);
1225         tempStr = NULL;
1226
1227         // Resource type name
1228         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1229         if(cbor_value_is_valid(&curVal))
1230         {
1231              err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
1232         }
1233
1234         err = err || cbor_value_advance(rootValue);
1235
1236         if(!err)
1237         {
1238             *outPayload = (OCPayload*)OCPresencePayloadCreate(seqNum, maxAge, trigger, tempStr);
1239         }
1240         OICFree(tempStr);
1241
1242         if(err)
1243         {
1244             OCPayloadDestroy(*outPayload);
1245             OC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1246             return OC_STACK_MALFORMED_RESPONSE;
1247         }
1248
1249         if(!*outPayload)
1250         {
1251             return OC_STACK_NO_MEMORY;
1252         }
1253
1254         return OC_STACK_OK;
1255     }
1256     else
1257     {
1258         OC_LOG(ERROR, TAG, "Root presence node was not a map");
1259         return OC_STACK_MALFORMED_RESPONSE;
1260     }
1261 }