Imported Upstream version 1.0.1
[platform/upstream/iotivity.git] / resource / csdk / stack / src / rdpayload.c
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics 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 #include "rdpayload.h"
21
22 #include "oic_malloc.h"
23 #include "oic_string.h"
24 #include "octypes.h"
25 #include "ocstack.h"
26 #include "ocpayload.h"
27 #include "payload_logging.h"
28
29 #define TAG "OCRDPayload"
30
31 #define CBOR_ROOT_ARRAY_LENGTH 1
32
33 static CborError FindStringInMap(CborValue *map, char *tags, char **value);
34 static CborError FindIntInMap(CborValue *map, char *tags, uint64_t *value);
35 static CborError FindStringLLInMap(const CborValue *linksMap, char *tag, OCStringLL **links);
36 static int64_t ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, const char *value);
37 static int64_t ConditionalAddIntToMap(CborEncoder *map, const char *tags, const size_t size, const uint64_t *value);
38 static int64_t AddStringLLToMap(CborEncoder *map, char *tag, const size_t size, OCStringLL *value);
39
40 int64_t OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t *outPayload, size_t *size)
41 {
42     if (!outPayload || !size)
43     {
44         OC_LOG(ERROR, TAG, "Invalid parameters.");
45         return OC_STACK_INVALID_PARAM;
46     }
47
48     CborEncoder encoder;
49     int flags = 0;
50     cbor_encoder_init(&encoder, outPayload, *size, flags);
51
52     CborError cborEncoderResult;
53     if (rdPayload->rdDiscovery)
54     {
55         CborEncoder map;
56         cborEncoderResult = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength);
57         if (CborNoError != cborEncoderResult)
58         {
59             OC_LOG(ERROR, TAG, "Failed creating discovery map.");
60             goto cbor_error;
61         }
62         if (CborNoError != ConditionalAddTextStringToMap(&map, OC_RSRVD_DEVICE_NAME,
63                 sizeof(OC_RSRVD_DEVICE_NAME) - 1, (char *)rdPayload->rdDiscovery->n.deviceName))
64         {
65             OC_LOG(ERROR, TAG, "Failed setting OC_RSRVD_DEVICE_NAME.");
66             goto cbor_error;
67         }
68         if (CborNoError != ConditionalAddTextStringToMap(&map, OC_RSRVD_DEVICE_ID,
69                 sizeof(OC_RSRVD_DEVICE_ID) - 1, (char *)rdPayload->rdDiscovery->di.id))
70         {
71             OC_LOG(ERROR, TAG, "Failed setting OC_RSRVD_DEVICE_ID.");
72             goto cbor_error;
73         }
74         uint64_t sel = (uint8_t) rdPayload->rdDiscovery->sel;
75         if (CborNoError != ConditionalAddIntToMap(&map, OC_RSRVD_RD_DISCOVERY_SEL,
76             sizeof(OC_RSRVD_RD_DISCOVERY_SEL) - 1, &sel))
77         {
78             OC_LOG(ERROR, TAG, "Failed setting OC_RSRVD_RD_DISCOVERY_SEL.");
79             goto cbor_error;
80         }
81         cborEncoderResult = cbor_encoder_close_container(&encoder, &map);
82         if (CborNoError != cborEncoderResult)
83         {
84             OC_LOG(ERROR, TAG, "Failed closing discovery map.");
85             goto cbor_error;
86         }
87     }
88     else if (rdPayload->rdPublish)
89     {
90         CborEncoder colArray;
91         cborEncoderResult = cbor_encoder_create_array(&encoder, &colArray, CborIndefiniteLength);
92         if (CborNoError != cborEncoderResult)
93         {
94             OC_LOG(ERROR, TAG, "Failed creating collection array.");
95             goto cbor_error;
96         }
97
98         OCResourceCollectionPayload *rdPublish = rdPayload->rdPublish;
99         while (rdPublish)
100         {
101             if (OC_STACK_OK != OCTagsPayloadToCbor(rdPublish->tags, &colArray))
102             {
103                 OC_LOG(ERROR, TAG, "Failed creating tags payload.");
104                 goto cbor_error;
105             }
106             if (OC_STACK_OK != OCLinksPayloadToCbor(rdPublish->setLinks, &colArray))
107             {
108                 OC_LOG(ERROR, TAG, "Failed creating links payload.");
109                 goto cbor_error;
110             }
111             rdPublish = rdPublish->next;
112         }
113         cborEncoderResult = cbor_encoder_close_container(&encoder, &colArray);
114         if (CborNoError != cborEncoderResult)
115         {
116             OC_LOG(ERROR, TAG, "Failed closing collection array.");
117             goto cbor_error;
118         }
119     }
120     else
121     {
122         CborEncoder map;
123         cborEncoderResult = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength);
124         if (CborNoError != cborEncoderResult)
125         {
126             OC_LOG(ERROR, TAG, "Failed creating discovery map.");
127             goto cbor_error;
128         }
129         cborEncoderResult = cbor_encoder_close_container(&encoder, &map);
130         if (CborNoError != cborEncoderResult)
131         {
132             OC_LOG(ERROR, TAG, "Failed creating discovery map.");
133             goto cbor_error;
134         }
135     }
136     *size = encoder.ptr - outPayload;
137
138     return OC_STACK_OK;
139 cbor_error:
140     OICFree(outPayload);
141     return OC_STACK_ERROR;
142 }
143
144 OCStackResult OCTagsPayloadToCbor(OCTagsPayload *tags, CborEncoder *setMap)
145 {
146     CborEncoder tagsMap;
147     CborError cborEncoderResult = cbor_encoder_create_map(setMap, &tagsMap, CborIndefiniteLength);
148     if (CborNoError != cborEncoderResult)
149     {
150         OC_LOG(ERROR, TAG, "Failed creating TAGS map.");
151         return OC_STACK_ERROR;
152     }
153
154     if (CborNoError != ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DEVICE_NAME,
155             sizeof(OC_RSRVD_DEVICE_NAME) - 1, (char *)tags->n.deviceName))
156     {
157         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_DEVICE_NAME in TAGS map.");
158         return OC_STACK_ERROR;
159     }
160     if (CborNoError != ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DEVICE_ID,
161             sizeof(OC_RSRVD_DEVICE_ID) - 1, (char *)tags->di.id))
162     {
163         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_DEVICE_ID in TAGS map.");
164         return OC_STACK_ERROR;
165     }
166     if (CborNoError != ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_RTS,
167             sizeof(OC_RSRVD_RTS) - 1, (char *)tags->rts))
168     {
169         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_RTS in TAGS map.");
170         return OC_STACK_ERROR;
171     }
172     if (CborNoError != ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DREL,
173             sizeof(OC_RSRVD_DREL) - 1, (char *)tags->drel))
174     {
175         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_DREL in TAGS map.");
176         return OC_STACK_ERROR;
177     }
178     if (CborNoError != ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_BASE_URI,
179             sizeof(OC_RSRVD_BASE_URI) - 1, (char *)tags->baseURI))
180     {
181         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_BASE_URI in TAGS map.");
182         return OC_STACK_ERROR;
183     }
184     uint64_t temp = (uint64_t)tags->bitmap;
185     if (CborNoError != ConditionalAddIntToMap(&tagsMap, OC_RSRVD_BITMAP,
186             sizeof(OC_RSRVD_BITMAP) - 1, &temp))
187     {
188         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_BITMAP in TAGS map.");
189         return OC_STACK_ERROR;
190     }
191     temp = (uint64_t)tags->port;
192     if (CborNoError != ConditionalAddIntToMap(&tagsMap, OC_RSRVD_HOSTING_PORT,
193             sizeof(OC_RSRVD_HOSTING_PORT) - 1, &temp))
194     {
195         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_HOSTING_PORT in TAGS map.");
196         return OC_STACK_ERROR;
197     }
198     temp = (uint64_t)tags->ins;
199     if (CborNoError != ConditionalAddIntToMap(&tagsMap, OC_RSRVD_INS,
200             sizeof(OC_RSRVD_INS) - 1, &temp))
201     {
202         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_INS in TAGS map.");
203         return OC_STACK_ERROR;
204     }
205     temp = (uint64_t)tags->ttl;
206     if (CborNoError != ConditionalAddIntToMap(&tagsMap, OC_RSRVD_TTL,
207             sizeof(OC_RSRVD_TTL) - 1, &temp))
208     {
209         OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_TTL in TAGS map.");
210         return OC_STACK_ERROR;
211     }
212     cborEncoderResult = cbor_encoder_close_container(setMap, &tagsMap);
213     if (CborNoError != cborEncoderResult)
214     {
215         OC_LOG(ERROR, TAG, "Failed closing TAGS map.");
216         return OC_STACK_ERROR;
217     }
218     return OC_STACK_OK;
219 }
220
221 OCStackResult OCLinksPayloadToCbor(OCLinksPayload *rtPtr, CborEncoder *setMap)
222 {
223     CborEncoder linksArray;
224     CborError cborEncoderResult;
225
226     cborEncoderResult = cbor_encoder_create_array(setMap, &linksArray, CborIndefiniteLength);
227     if (CborNoError != cborEncoderResult)
228     {
229         OC_LOG(ERROR, TAG, "Failed creating LINKS array.");
230         return OC_STACK_ERROR;
231     }
232     while (rtPtr)
233     {
234         CborEncoder linksMap;
235         cborEncoderResult = cbor_encoder_create_map(&linksArray, &linksMap,
236                 CborIndefiniteLength);
237         if (CborNoError != cborEncoderResult)
238         {
239             OC_LOG(ERROR, TAG, "Failed creating LINKS map.");
240             return OC_STACK_ERROR;
241         }
242         if (CborNoError != ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_HREF,
243                 sizeof(OC_RSRVD_HREF) - 1, rtPtr->href))
244         {
245             OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_HREF in LINKS map.");
246             return OC_STACK_ERROR;
247         }
248         if (CborNoError != ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_REL,
249                 sizeof(OC_RSRVD_REL) - 1,  rtPtr->rel))
250         {
251             OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_REL in LINKS map.");
252             return OC_STACK_ERROR;
253         }
254         if (CborNoError != ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_TITLE,
255                 sizeof(OC_RSRVD_TITLE) - 1, rtPtr->title))
256         {
257             OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_TITLE in LINKS map.");
258             return OC_STACK_ERROR;
259         }
260         if (CborNoError != ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_URI,
261                 sizeof(OC_RSRVD_URI) - 1, rtPtr->uri))
262         {
263             OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_URI in LINKS map.");
264             return OC_STACK_ERROR;
265         }
266         if (CborNoError != AddStringLLToMap(&linksMap, OC_RSRVD_RESOURCE_TYPE,
267                 sizeof(OC_RSRVD_RESOURCE_TYPE) - 1, rtPtr->rt))
268         {
269             OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_RESOURCE_TYPE in LINKS map.");
270             return OC_STACK_ERROR;
271         }
272         if (CborNoError != AddStringLLToMap(&linksMap, OC_RSRVD_INTERFACE,
273                 sizeof(OC_RSRVD_INTERFACE) - 1, rtPtr->itf))
274         {
275             OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_INTERFACE in LINKS map.");
276             return OC_STACK_ERROR;
277         }
278         if (CborNoError != AddStringLLToMap(&linksMap, OC_RSRVD_MEDIA_TYPE,
279                 sizeof(OC_RSRVD_MEDIA_TYPE) - 1, rtPtr->mt))
280         {
281             OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_MEDIA_TYPE in LINKS map.");
282             return OC_STACK_ERROR;
283         }
284         uint64_t temp = (uint64_t)rtPtr->ins;
285         if (CborNoError != ConditionalAddIntToMap(&linksMap, OC_RSRVD_INS,
286             sizeof(OC_RSRVD_INS) - 1, &temp))
287         {
288             OC_LOG(ERROR, TAG, "Failed adding OC_RSRVD_INS in LINKS map.");
289             return OC_STACK_ERROR;
290         }
291         cborEncoderResult = cbor_encoder_close_container(&linksArray, &linksMap);
292         if (CborNoError != cborEncoderResult)
293         {
294             OC_LOG(ERROR, TAG, "Failed closing LINKS map.");
295             return OC_STACK_ERROR;
296         }
297         rtPtr = rtPtr->next;
298     }
299     cborEncoderResult = cbor_encoder_close_container(setMap, &linksArray);
300     if (CborNoError != cborEncoderResult)
301     {
302         OC_LOG(ERROR, TAG, "Failed closing LINKS array.");
303         return OC_STACK_ERROR;;
304     }
305     return OC_STACK_OK;
306 }
307
308 OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPayload)
309 {
310     CborValue *rdCBORPayload = (CborValue *)cborPayload;
311     CborError cborFindResult;
312
313     OCRDPayload *rdPayload = OCRDPayloadCreate();
314     if (!rdPayload)
315     {
316         goto no_memory;
317     }
318
319     if (cbor_value_is_array(rdCBORPayload))
320     {
321         OCLinksPayload *linksPayload = NULL;
322         OCTagsPayload *tagsPayload = NULL;
323
324         while (cbor_value_is_container(rdCBORPayload))
325         {
326             // enter tags map
327             CborValue tags;
328             cborFindResult = cbor_value_enter_container(rdCBORPayload, &tags);
329             if (cborFindResult != CborNoError)
330             {
331                 goto cbor_error;
332             }
333             if (OC_STACK_OK != OCTagsCborToPayload(&tags, &tagsPayload))
334             {
335                 OCFreeTagsResource(tagsPayload);
336                 goto cbor_error;
337             }
338             OCTagsLog(DEBUG, tagsPayload);
339             if (OC_STACK_OK != OCLinksCborToPayload(&tags, &linksPayload))
340             {
341                 OCFreeLinksResource(linksPayload);
342                 OCFreeTagsResource(tagsPayload);
343                 goto cbor_error;
344             }
345             OCLinksLog(DEBUG, linksPayload);
346             // Move from tags payload to links array.
347             if (CborNoError != cbor_value_advance(rdCBORPayload))
348             {
349                 OC_LOG(DEBUG, TAG, "Failed advancing from tags payload to links.");
350                 OCFreeLinksResource(linksPayload);
351                 OCFreeTagsResource(tagsPayload);
352                 goto cbor_error;
353             }
354         }
355         rdPayload->rdPublish = OCCopyCollectionResource(tagsPayload, linksPayload);
356         if (!rdPayload->rdPublish)
357         {
358             goto cbor_error;
359         }
360     }
361     else if (cbor_value_is_map(rdCBORPayload))
362     {
363         char *name = NULL;
364         if (CborNoError != FindStringInMap(rdCBORPayload, OC_RSRVD_DEVICE_NAME, &name))
365         {
366             goto cbor_error;
367         }
368         char *id = NULL;
369         if (CborNoError != FindStringInMap(rdCBORPayload, OC_RSRVD_DEVICE_ID, &id))
370         {
371             goto cbor_error;
372         }
373         uint64_t biasFactor = 0;
374         if (CborNoError != FindIntInMap(rdCBORPayload, OC_RSRVD_RD_DISCOVERY_SEL, &biasFactor))
375         {
376             goto cbor_error;
377         }
378         rdPayload->rdDiscovery = OCRDDiscoveryPayloadCreate(name, id, (uint8_t)biasFactor);
379         if (!rdPayload->rdDiscovery)
380         {
381             goto no_memory;
382         }
383         OICFree(id);
384         OICFree(name);
385         cborFindResult =  cbor_value_advance(rdCBORPayload);
386         if (CborNoError != cborFindResult)
387         {
388             goto cbor_error;
389         }
390     }
391     OC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
392     *outPayload = (OCPayload *)rdPayload;
393     return OC_STACK_OK;
394 no_memory:
395     OC_LOG(ERROR, TAG, "Failed allocating memory.");
396     OCRDPayloadDestroy(rdPayload);
397     return OC_STACK_NO_MEMORY;
398
399 cbor_error:
400     OCRDPayloadDestroy(rdPayload);
401     return OC_STACK_ERROR;
402 }
403
404 static CborError FindStringInMap(CborValue *map, char *tags, char **value)
405 {
406     CborValue curVal;
407     size_t len;
408     CborError cborFindResult = cbor_value_map_find_value(map, tags, &curVal);
409     if (CborNoError == cborFindResult && cbor_value_is_text_string(&curVal))
410     {
411         cborFindResult = cbor_value_dup_text_string(&curVal, value, &len, NULL);
412         if (CborNoError != cborFindResult)
413         {
414             OC_LOG_V(ERROR, TAG, "Failed finding value for tag %s .", tags);
415             return cborFindResult;
416         }
417     }
418     return CborNoError;
419 }
420
421 static CborError FindIntInMap(CborValue *map, char *tags, uint64_t *value)
422 {
423     CborValue curVal;
424     CborError cborFindResult = cbor_value_map_find_value(map, tags, &curVal);
425     if (CborNoError == cborFindResult && cbor_value_is_unsigned_integer(&curVal))
426     {
427         cborFindResult = cbor_value_get_uint64(&curVal, value);
428         if (CborNoError != cborFindResult)
429         {
430             OC_LOG_V(ERROR, TAG, "Failed finding value for tag %s .", tags);
431             return cborFindResult;
432         }
433     }
434     return CborNoError;
435 }
436
437 static CborError FindStringLLInMap(const CborValue *linksMap, char *tag, OCStringLL **links)
438 {
439     size_t len;
440     CborError cborFindResult;
441     CborValue rtArray;
442     cborFindResult = cbor_value_map_find_value(linksMap, tag, &rtArray);
443     if (CborNoError != cborFindResult)
444     {
445         return CborUnknownError;
446     }
447     CborValue rtVal;
448     cborFindResult = cbor_value_enter_container(&rtArray, &rtVal);
449     if (CborNoError != cborFindResult)
450     {
451         return CborUnknownError;
452     }
453     OCStringLL* llPtr = *links;
454     while (cbor_value_is_text_string(&rtVal))
455     {
456         if (llPtr == NULL)
457         {
458             llPtr = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
459             if (!llPtr)
460             {
461                 return CborUnknownError;
462             }
463             *links = llPtr;
464         }
465         else if(llPtr)
466         {
467             while (llPtr->next)
468             {
469                 llPtr = llPtr->next;
470             }
471             llPtr->next = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
472             if (!llPtr->next)
473             {
474                 return CborUnknownError;
475             }
476         }
477         cborFindResult = cbor_value_dup_text_string(&rtVal, &(llPtr->value), &len, NULL);
478         if (CborNoError != cborFindResult)
479         {
480             return CborUnknownError;
481         }
482         cborFindResult = cbor_value_advance(&rtVal);
483         if (CborNoError != cborFindResult)
484         {
485             return CborUnknownError;
486         }
487     }
488
489     cborFindResult = cbor_value_leave_container(&rtArray, &rtVal);
490     return cborFindResult;
491 }
492
493 OCStackResult OCTagsCborToPayload(CborValue *tagsMap, OCTagsPayload **tagsPayload)
494 {
495     OCTagsPayload *tags = (OCTagsPayload *)OICCalloc(1, sizeof(OCTagsPayload));
496     if (!tags)
497     {
498         return OC_STACK_NO_MEMORY;
499     }
500     if (cbor_value_is_map(tagsMap))
501     {
502         if (CborNoError != FindStringInMap(tagsMap, OC_RSRVD_DEVICE_NAME, &tags->n.deviceName))
503         {
504             OCFreeTagsResource(tags);
505             return OC_STACK_ERROR;
506         }
507         if (CborNoError != FindStringInMap(tagsMap, OC_RSRVD_DREL, &tags->drel))
508         {
509             OCFreeTagsResource(tags);
510             return OC_STACK_ERROR;
511         }
512         if (CborNoError != FindStringInMap(tagsMap, OC_RSRVD_RTS, &tags->rts))
513         {
514             OCFreeTagsResource(tags);
515             return OC_STACK_ERROR;
516         }
517         if (CborNoError != FindStringInMap(tagsMap, OC_RSRVD_BASE_URI, &tags->baseURI))
518         {
519             OCFreeTagsResource(tags);
520             return OC_STACK_ERROR;
521         }
522         char *id = NULL;
523         if (CborNoError != FindStringInMap(tagsMap, OC_RSRVD_DEVICE_ID, &id))
524         {
525             OCFreeTagsResource(tags);
526             return OC_STACK_ERROR;
527         }
528         if (id)
529         {
530             OICStrcpy((char*)tags->di.id, MAX_IDENTITY_SIZE, id);
531             tags->di.id_length = MAX_IDENTITY_SIZE;
532             OICFree(id);
533         }
534         uint64_t temp;
535         if (CborNoError != FindIntInMap(tagsMap, OC_RSRVD_HOSTING_PORT, &temp))
536         {
537             OCFreeTagsResource(tags);
538             return OC_STACK_ERROR;
539         }
540         tags->port = (uint16_t) temp;
541         if (CborNoError != FindIntInMap(tagsMap, OC_RSRVD_BITMAP, &temp))
542         {
543             OCFreeTagsResource(tags);
544             return OC_STACK_ERROR;
545         }
546         tags->bitmap = (uint8_t) temp;
547         if (CborNoError != FindIntInMap(tagsMap, OC_RSRVD_INS, &temp))
548         {
549             OCFreeTagsResource(tags);
550             return OC_STACK_ERROR;
551         }
552         tags->ins = (uint8_t) temp;
553         if (CborNoError != FindIntInMap(tagsMap, OC_RSRVD_TTL, &temp))
554         {
555             OCFreeTagsResource(tags);
556             return OC_STACK_ERROR;
557         }
558         tags->ttl = (uint32_t) temp;
559
560         if (CborNoError != cbor_value_advance(tagsMap))
561         {
562             OCFreeTagsResource(tags);
563             return OC_STACK_ERROR;
564         }
565     }
566     *tagsPayload = tags;
567     return OC_STACK_OK;
568 }
569
570 OCStackResult OCLinksCborToPayload(CborValue *linksArray, OCLinksPayload **linksPayload)
571 {
572     CborValue linksMap;
573     CborError cborFindResult = cbor_value_enter_container(linksArray, &linksMap);
574     if (CborNoError != cborFindResult)
575     {
576         OC_LOG(ERROR, TAG, "Failed enter links map");
577         return OC_STACK_ERROR;
578     }
579
580     while (cbor_value_is_map(&linksMap))
581     {
582         OCLinksPayload *setLinks = (OCLinksPayload *)OICCalloc(1, sizeof(OCLinksPayload));
583         if (!setLinks)
584         {
585             OC_LOG(ERROR, TAG, "Failed allocating memory.");
586             OCFreeLinksResource(*linksPayload);
587             return OC_STACK_NO_MEMORY;
588         }
589         cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_HREF, &setLinks->href);
590         if (CborNoError != cborFindResult)
591         {
592             OCFreeLinksResource(*linksPayload);
593             OCFreeLinksResource(setLinks);
594             return OC_STACK_ERROR;
595         }
596         cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_REL, &setLinks->rel);
597         if (CborNoError != cborFindResult)
598         {
599             OCFreeLinksResource(*linksPayload);
600             OCFreeLinksResource(setLinks);
601             return OC_STACK_ERROR;
602         }
603
604         cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_TITLE, &setLinks->title);
605         if (CborNoError != cborFindResult)
606         {
607             OCFreeLinksResource(*linksPayload);
608             OCFreeLinksResource(setLinks);
609             return OC_STACK_ERROR;
610         }
611         cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_URI, &setLinks->uri);
612         if (CborNoError != cborFindResult)
613         {
614             OCFreeLinksResource(*linksPayload);
615             OCFreeLinksResource(setLinks);
616             return OC_STACK_ERROR;
617         }
618         cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_RESOURCE_TYPE, &setLinks->rt);
619         if (CborNoError != cborFindResult)
620         {
621             OCFreeLinksResource(*linksPayload);
622             OCFreeLinksResource(setLinks);
623             return OC_STACK_ERROR;
624         }
625         cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_INTERFACE, &setLinks->itf);
626         if (CborNoError != cborFindResult)
627         {
628             OCFreeLinksResource(*linksPayload);
629             OCFreeLinksResource(setLinks);
630             return OC_STACK_ERROR;
631         }
632         cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_MEDIA_TYPE, &setLinks->mt);
633         if (CborNoError != cborFindResult)
634         {
635             OCFreeLinksResource(*linksPayload);
636             OCFreeLinksResource(setLinks);
637             return OC_STACK_ERROR;
638         }
639         uint64_t temp;
640         cborFindResult = FindIntInMap(&linksMap, OC_RSRVD_INS, &temp);
641         if (CborNoError != cborFindResult)
642         {
643             OCFreeLinksResource(*linksPayload);
644             OCFreeLinksResource(setLinks);
645             return OC_STACK_ERROR;
646         }
647         setLinks->ins = (uint8_t) temp;
648
649         if (!*linksPayload)
650         {
651             *linksPayload = setLinks;
652         }
653         else
654         {
655             OCLinksPayload *temp = *linksPayload;
656             while (temp->next)
657             {
658                 temp = temp->next;
659             }
660             temp->next = setLinks;
661         }
662         cborFindResult = cbor_value_advance(&linksMap);
663         if (CborNoError != cborFindResult)
664         {
665             OC_LOG(ERROR, TAG, "Failed advancing links map");
666             OCFreeLinksResource(*linksPayload);
667             OCFreeLinksResource(setLinks);
668             return OC_STACK_ERROR;
669         }
670     }
671     return OC_STACK_OK;
672 }
673
674 static int64_t AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
675         const char* value)
676 {
677     return cbor_encode_text_string(map, key, keylen) |
678            cbor_encode_text_string(map, value, strlen(value));
679 }
680
681 static int64_t ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
682         const char* value)
683 {
684     return value ? AddTextStringToMap(map, key, keylen, value) : 0;
685 }
686
687 static int64_t ConditionalAddIntToMap(CborEncoder *map, const char *tags, const size_t size,
688     const uint64_t *value)
689 {
690     return (*value) ? (cbor_encode_text_string(map, tags, size) |
691                      cbor_encode_uint(map, *value)): 0;
692 }
693
694 static int64_t AddStringLLToMap(CborEncoder *map, char *tag, const size_t size, OCStringLL *value)
695 {
696     CborEncoder array;
697     CborError cborEncoderResult;
698     cborEncoderResult = cbor_encode_text_string(map, tag, size);
699     if (CborNoError != cborEncoderResult)
700     {
701         return cborEncoderResult;
702     }
703     cborEncoderResult = cbor_encoder_create_array(map, &array, CborIndefiniteLength);
704     if (CborNoError != cborEncoderResult)
705     {
706         return cborEncoderResult;
707     }
708     OCStringLL *strType = value;
709     while (strType)
710     {
711         cborEncoderResult = cbor_encode_text_string(&array, strType->value, strlen(strType->value));
712         if (CborNoError != cborEncoderResult)
713         {
714             return cborEncoderResult;
715         }
716         strType = strType->next;
717     }
718     cborEncoderResult = cbor_encoder_close_container(map, &array);
719     if (CborNoError != cborEncoderResult)
720     {
721         return cborEncoderResult;
722     }
723     return cborEncoderResult;
724 }
725
726 OCRDPayload *OCRDPayloadCreate()
727 {
728     OCRDPayload *rdPayload = (OCRDPayload *)OICCalloc(1, sizeof(OCRDPayload));
729
730     if (!rdPayload)
731     {
732         return NULL;
733     }
734
735     rdPayload->base.type = PAYLOAD_TYPE_RD;
736
737     return rdPayload;
738 }
739
740 OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(const char *deviceName, const char *id, int biasFactor)
741 {
742     OCRDDiscoveryPayload *discoveryPayload = (OCRDDiscoveryPayload *)OICCalloc(1, sizeof(OCRDDiscoveryPayload));
743
744     if (!discoveryPayload)
745     {
746         return NULL;
747     }
748
749     if (deviceName)
750     {
751         discoveryPayload->n.deviceName = OICStrdup(deviceName);
752         if (!discoveryPayload->n.deviceName)
753         {
754             OICFree(discoveryPayload);
755             return NULL;
756         }
757     }
758     if (id)
759     {
760         OICStrcpy((char*)discoveryPayload->di.id, MAX_IDENTITY_SIZE, id);
761     }
762
763     discoveryPayload->sel = biasFactor;
764
765     return discoveryPayload;
766 }
767
768 void OCRDPayloadDestroy(OCRDPayload *payload)
769 {
770     if (!payload)
771     {
772         return;
773     }
774
775     if (payload->rdDiscovery)
776     {
777         if (payload->rdDiscovery->n.deviceName)
778         {
779             OICFree(payload->rdDiscovery->n.deviceName);
780         }
781         OICFree(payload->rdDiscovery);
782     }
783
784     if (payload->rdPublish)
785     {
786         for (OCResourceCollectionPayload *col = payload->rdPublish; col; )
787         {
788             if (col->setLinks)
789             {
790                 OCFreeLinksResource(col->setLinks);
791             }
792
793             if (col->tags)
794             {
795                 OCFreeTagsResource(col->tags);
796             }
797             OCResourceCollectionPayload *temp = col->next;
798             OICFree(col);
799             col = temp;
800         }
801     }
802
803     OICFree(payload);
804 }
805
806 OCTagsPayload* OCCopyTagsResources(const char *deviceName, const unsigned char *id, const char *baseURI,
807         uint8_t bitmap, uint16_t port, uint8_t ins, const char *rts,const  char *drel, uint32_t ttl)
808 {
809     OCTagsPayload *tags = (OCTagsPayload *)OICCalloc(1, sizeof(OCTagsPayload));
810     if (!tags)
811     {
812         return NULL;
813     }
814         if (deviceName)
815     {
816         tags->n.deviceName = OICStrdup(deviceName);
817         if (!tags->n.deviceName)
818         {
819             goto memory_allocation_failed;
820         }
821     }
822     if (id)
823     {
824         OICStrcpy((char*)tags->di.id, MAX_IDENTITY_SIZE, (char *)id);
825         if (!tags->di.id)
826         {
827             goto memory_allocation_failed;
828         }
829     }
830     if (baseURI)
831     {
832         tags->baseURI = OICStrdup(baseURI);
833         if (!tags->baseURI)
834         {
835             goto memory_allocation_failed;
836         }
837     }
838     tags->bitmap = bitmap;
839     tags->port = port;
840     tags->ins = ins;
841     if (rts)
842     {
843         tags->rts = OICStrdup(rts);
844         if (!tags->rts)
845         {
846             goto memory_allocation_failed;
847         }
848     }
849     if (drel)
850     {
851         tags->drel = OICStrdup(drel);
852         if (!tags->drel)
853         {
854             goto memory_allocation_failed;
855         }
856     }
857     tags->ttl = ttl;
858     return tags;
859
860 memory_allocation_failed:
861     OC_LOG(ERROR, TAG, "Memory allocation failed.");
862     OCFreeTagsResource(tags);
863     return NULL;
864 }
865
866 OCLinksPayload* OCCopyLinksResources(const char *href, OCStringLL *rt, OCStringLL *itf,
867         const char *rel, bool obs, const char *title, const char *uri, uint8_t ins, OCStringLL *mt)
868 {
869     OCLinksPayload *links = (OCLinksPayload *)OICCalloc(1, sizeof(OCLinksPayload));
870     if (!links)
871     {
872         OC_LOG(ERROR, TAG, "Failed allocating memory.");
873         return NULL;
874     }
875     if (href)
876     {
877         links->href = OICStrdup(href);
878         if (!links->href)
879         {
880             goto memory_allocation_failed;
881         }
882     }
883     if (rt)
884     {
885         links->rt = CloneOCStringLL(rt);
886         if (!links->rt)
887         {
888             goto memory_allocation_failed;
889         }
890     }
891     if (itf)
892     {
893         links->itf = CloneOCStringLL(itf);
894         if (!links->itf)
895         {
896             goto memory_allocation_failed;
897         }
898     }
899     if (rel)
900     {
901         links->rel = OICStrdup(rel);
902         if (!links->rel)
903         {
904             goto memory_allocation_failed;
905         }
906     }
907     links->obs = obs;
908     if (title)
909     {
910         links->title = OICStrdup(title);
911         if (!links->title)
912         {
913             goto memory_allocation_failed;
914         }
915     }
916     if (uri)
917     {
918         links->uri = OICStrdup(uri);
919         if (!links->uri)
920         {
921             goto memory_allocation_failed;
922         }
923     }
924     links->ins = ins;
925     if (mt)
926     {
927         links->mt = CloneOCStringLL(mt);
928         if (!links->mt)
929         {
930             goto memory_allocation_failed;
931         }
932     }
933     links->next = NULL;
934     return links;
935
936 memory_allocation_failed:
937     OC_LOG(ERROR, TAG, "Memory allocation failed.");
938     OCFreeLinksResource(links);
939     return NULL;
940 }
941
942 void OCLinksAddResource(OCDiscoveryPayload *payload, const char *href, OCStringLL *rt,
943     OCStringLL *itf, const char *rel, bool obs, const char *title, const char *uri,
944     uint8_t ins, OCStringLL *mt)
945 {
946     if(!payload->collectionResources->setLinks)
947     {
948         payload->collectionResources->setLinks =
949             OCCopyLinksResources(href, rt, itf, rel, obs, title, uri, ins, mt);
950     }
951     else
952     {
953         OCLinksPayload *p = payload->collectionResources->setLinks;
954         while (p->next)
955         {
956             p = p->next;
957         }
958         p->next = OCCopyLinksResources(href, rt, itf, rel, obs, title, uri, ins, mt);
959     }
960 }
961
962 OCResourceCollectionPayload* OCCopyCollectionResource(OCTagsPayload *tags, OCLinksPayload *links)
963 {
964     if (!tags || !links)
965     {
966         return NULL;
967     }
968     OCResourceCollectionPayload *pl = (OCResourceCollectionPayload *)OICCalloc(1, sizeof(OCResourceCollectionPayload));
969     if(!pl)
970     {
971         OC_LOG(ERROR, TAG, "Failed allocating memory for the OCResourceCollectionPayload.");
972         return NULL;
973     }
974     pl->tags = tags;
975     pl->setLinks = links;
976
977     return pl;
978 }
979
980 OCStackResult OCDiscoveryCollectionPayloadAddResource(OCDiscoveryPayload *payload, OCTagsPayload *tags, OCLinksPayload *links)
981 {
982     OCResourceCollectionPayload* res = OCCopyCollectionResource(tags, links);
983     if (res == NULL)
984     {
985         return OC_STACK_NO_MEMORY;
986     }
987     if(!payload->collectionResources)
988     {
989         payload->collectionResources = res;
990     }
991     else
992     {
993         OCResourceCollectionPayload *p = payload->collectionResources;
994         while(p->next)
995         {
996             p = p->next;
997         }
998         p->next = res;
999     }
1000     return OC_STACK_OK;
1001 }
1002
1003 void OCFreeLinksResource(OCLinksPayload *payload)
1004 {
1005     if (!payload)
1006     {
1007         return;
1008     }
1009     OICFree(payload->href);
1010     OCFreeOCStringLL(payload->rt);
1011     OCFreeOCStringLL(payload->itf);
1012     OICFree(payload->rel);
1013     OICFree(payload->title);
1014     OICFree(payload->uri);
1015     OCFreeOCStringLL(payload->mt);
1016     OCFreeLinksResource(payload->next);
1017     OICFree(payload);
1018 }
1019
1020 void OCFreeTagsResource(OCTagsPayload *payload)
1021 {
1022     if (!payload)
1023     {
1024         return;
1025     }
1026     OICFree(payload->n.deviceName);
1027     OICFree(payload->baseURI);
1028     OICFree(payload->rts);
1029     OICFree(payload->drel);
1030     OICFree(payload);
1031 }
1032
1033 void OCFreeCollectionResource(OCResourceCollectionPayload *payload)
1034 {
1035     if (!payload)
1036     {
1037         return;
1038     }
1039     if (payload->tags)
1040     {
1041         OCFreeTagsResource(payload->tags);
1042     }
1043     if (payload->setLinks)
1044     {
1045         OCFreeLinksResource(payload->setLinks);
1046     }
1047     OCFreeCollectionResource(payload->next);
1048     OICFree(payload);
1049 }
1050
1051 void OCDiscoveryCollectionPayloadDestroy(OCDiscoveryPayload* payload)
1052 {
1053     if(!payload)
1054     {
1055         return;
1056     }
1057
1058     OCFreeCollectionResource(payload->collectionResources);
1059     OICFree(payload);
1060 }
1061
1062
1063 void OCTagsLog(const LogLevel level, const OCTagsPayload *tags)
1064 {
1065     if (tags)
1066     {
1067         if (tags->n.deviceName)
1068         {
1069             OC_LOG_V(level, TAG, " Device Name : %s ",tags->n.deviceName);
1070         }
1071         if (tags->baseURI)
1072         {
1073             OC_LOG_V(level, TAG, " Base URI : %s ",tags->baseURI);
1074         }
1075         OC_LOG_V(level, TAG, " Device ID : %s ",tags->di.id);
1076         OC_LOG_V(level, TAG, " Bitmap : %d ",tags->bitmap);
1077         OC_LOG_V(level, TAG, " Port : %d ",tags->port);
1078         OC_LOG_V(level, TAG, " Ins : %d ",tags->ins);
1079         OC_LOG_V(level, TAG, " Ttl : %d ",tags->ttl);
1080
1081         if (tags->rts)
1082         {
1083             OC_LOG_V(level, TAG, " RTS : %s ",tags->rts);
1084         }
1085         if (tags->drel)
1086         {
1087             OC_LOG_V(level, TAG, " DREL : %s ",tags->drel);
1088         }
1089     }
1090 }
1091
1092 void OCLinksLog(const LogLevel level, const OCLinksPayload *links)
1093 {
1094     while (links)
1095     {
1096         if (links->href)
1097         {
1098             OC_LOG_V(level, TAG, " href: %s ",links->href);
1099         }
1100         OC_LOG(level, TAG, " RT: ");
1101         OCStringLL *rt = links->rt;
1102         while (rt)
1103         {
1104             if (rt->value)
1105             {
1106                 OC_LOG_V(level, TAG, "   %s", rt->value);
1107             }
1108             rt = rt->next;
1109         }
1110         OC_LOG(level, TAG, " IF: ");
1111         OCStringLL *itf = links->itf;
1112         while (itf)
1113         {
1114             if (itf->value)
1115             {
1116                 OC_LOG_V(level, TAG, "   %s", itf->value);
1117             }
1118             itf = itf->next;
1119         }
1120         OC_LOG(level, TAG, " MT: ");
1121         OCStringLL *mt = links->mt;
1122         while (mt)
1123         {
1124             if (mt->value)
1125             {
1126                 OC_LOG_V(level, TAG, "   %s", mt->value);
1127             }
1128             mt = mt->next;
1129         }
1130         OC_LOG_V(level, TAG, " INS: %d", links->ins);
1131         OC_LOG_V(level, TAG, " OBS: %d", links->obs);
1132         if (links->rel)
1133         {
1134             OC_LOG_V(level, TAG, " REL: %s", links->rel);
1135         }
1136         if (links->title)
1137         {
1138             OC_LOG_V(level, TAG, " TITLE: %s", links->title);
1139         }
1140         if (links->uri)
1141         {
1142             OC_LOG_V(level, TAG, " URI: %s", links->uri);
1143         }
1144         links = links->next;
1145     }
1146 }