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