Merge branch 'master' into cloud-interface
[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 "OIC_RI_RDPAYLOAD"
30
31 #define CBOR_ROOT_ARRAY_LENGTH 1
32
33 static CborError OCTagsPayloadToCbor(OCTagsPayload *tags, CborEncoder *setMap);
34 static CborError OCLinksPayloadToCbor(OCLinksPayload *rtPtr, CborEncoder *setMap);
35 static CborError OCTagsCborToPayload(CborValue *tagsMap, OCTagsPayload **tagsPayload);
36 static CborError OCLinksCborToPayload(CborValue *linksArray, OCLinksPayload **linksPayload);
37 static CborError FindStringInMap(CborValue *map, char *tags, char **value);
38 static CborError FindIntInMap(CborValue *map, char *tags, uint64_t *value);
39 static CborError FindStringLLInMap(const CborValue *linksMap, char *tag, OCStringLL **links);
40 static CborError ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, const char *value);
41 static CborError ConditionalAddIntToMap(CborEncoder *map, const char *tags, const size_t size, const uint64_t *value);
42 static CborError AddStringLLToMap(CborEncoder *map, char *tag, const size_t size, OCStringLL *value);
43
44 CborError OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t *outPayload, size_t *size)
45 {
46     CborError cborEncoderResult = CborErrorIO;
47     int flags = 0;
48     CborEncoder encoder;
49     VERIFY_PARAM_NON_NULL(TAG, rdPayload, "Invalid input parameter rdPayload");
50     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid input parameter outPayload");
51     VERIFY_PARAM_NON_NULL(TAG, size, "Invalid input parameter size");
52
53     cbor_encoder_init(&encoder, outPayload, *size, flags);
54
55     if (rdPayload->rdDiscovery)
56     {
57         CborEncoder map;
58         cborEncoderResult = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength);
59         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create discovery map");
60
61         cborEncoderResult = ConditionalAddTextStringToMap(&map, OC_RSRVD_DEVICE_NAME,
62                 sizeof(OC_RSRVD_DEVICE_NAME) - 1, (char *)rdPayload->rdDiscovery->n.deviceName);
63         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_DEVICE_NAME in map");
64
65         cborEncoderResult = ConditionalAddTextStringToMap(&map, OC_RSRVD_DEVICE_ID,
66                 sizeof(OC_RSRVD_DEVICE_ID) - 1, (char *)rdPayload->rdDiscovery->di.id);
67         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_DEVICE_ID in map");
68
69         cborEncoderResult = ConditionalAddIntToMap(&map, OC_RSRVD_RD_DISCOVERY_SEL,
70             sizeof(OC_RSRVD_RD_DISCOVERY_SEL) - 1, (uint64_t *)&rdPayload->rdDiscovery->sel);
71         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add RD_DISCOVERY_SEL in map");
72
73         cborEncoderResult = cbor_encoder_close_container(&encoder, &map);
74         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing discovery map");
75     }
76     else if (rdPayload->rdPublish)
77     {
78         CborEncoder colArray;
79         cborEncoderResult = cbor_encoder_create_array(&encoder, &colArray, CborIndefiniteLength);
80         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create collection array");
81
82         OCResourceCollectionPayload *rdPublish = rdPayload->rdPublish;
83         while (rdPublish)
84         {
85             cborEncoderResult = OCTagsPayloadToCbor(rdPublish->tags, &colArray);
86             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding tags payload");
87             cborEncoderResult = OCLinksPayloadToCbor(rdPublish->setLinks, &colArray);
88             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding setLinks payload");
89             rdPublish = rdPublish->next;
90         }
91         cborEncoderResult = cbor_encoder_close_container(&encoder, &colArray);
92         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing collection array");
93     }
94     else
95     {
96         CborEncoder map;
97         cborEncoderResult = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength);
98         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed entering discovery map");
99         cborEncoderResult = cbor_encoder_close_container(&encoder, &map);
100         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing discovery map");
101     }
102     *size = encoder.ptr - outPayload;
103
104     return cborEncoderResult;
105
106 exit:
107     OICFree(outPayload);
108     return cborEncoderResult;
109 }
110
111 static CborError OCTagsPayloadToCbor(OCTagsPayload *tags, CborEncoder *setMap)
112 {
113     CborEncoder tagsMap;
114     CborError cborEncoderResult = cbor_encoder_create_map(setMap, &tagsMap, CborIndefiniteLength);
115     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create tags map");
116
117     cborEncoderResult = ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DEVICE_NAME,
118             sizeof(OC_RSRVD_DEVICE_NAME) - 1, (char *)tags->n.deviceName);
119     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_DEVICE_NAME in tags map");
120
121     cborEncoderResult = ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DEVICE_ID,
122             sizeof(OC_RSRVD_DEVICE_ID) - 1, (char *)tags->di.id);
123     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_DEVICE_ID in tags map");
124
125     cborEncoderResult = ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_RTS,
126             sizeof(OC_RSRVD_RTS) - 1, (char *)tags->rts);
127     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_RTS in tags map");
128
129     cborEncoderResult = ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DREL,
130             sizeof(OC_RSRVD_DREL) - 1, (char *)tags->drel);
131     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_DREL in tags map");
132
133     cborEncoderResult = ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_BASE_URI,
134             sizeof(OC_RSRVD_BASE_URI) - 1, (char *)tags->baseURI);
135     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_BASE_URI in tags map");
136
137     cborEncoderResult = ConditionalAddIntToMap(&tagsMap, OC_RSRVD_BITMAP,
138             sizeof(OC_RSRVD_BITMAP) - 1, (uint64_t *)&tags->bitmap);
139     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_BITMAP in tags map");
140
141     cborEncoderResult = ConditionalAddIntToMap(&tagsMap, OC_RSRVD_HOSTING_PORT,
142             sizeof(OC_RSRVD_HOSTING_PORT) - 1, (uint64_t *)&tags->port);
143     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_HOSTING_PORT in tags map");
144
145     cborEncoderResult = ConditionalAddIntToMap(&tagsMap, OC_RSRVD_INS, sizeof(OC_RSRVD_INS) - 1,
146             (uint64_t *)&tags->ins);
147     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_INS in tags map");
148
149     cborEncoderResult = ConditionalAddIntToMap(&tagsMap, OC_RSRVD_TTL, sizeof(OC_RSRVD_TTL) - 1,
150             (uint64_t *)&tags->ttl);
151     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_TTL in tags map");
152
153     cborEncoderResult = cbor_encoder_close_container(setMap, &tagsMap);
154     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close container");
155
156 exit:
157     return cborEncoderResult;
158 }
159
160 static CborError OCLinksPayloadToCbor(OCLinksPayload *rtPtr, CborEncoder *setMap)
161 {
162     CborEncoder linksArray;
163     CborError cborEncoderResult;
164
165     cborEncoderResult = cbor_encoder_create_array(setMap, &linksArray, CborIndefiniteLength);
166     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create Links array");
167
168     while (rtPtr)
169     {
170         CborEncoder linksMap;
171         cborEncoderResult = cbor_encoder_create_map(&linksArray, &linksMap, CborIndefiniteLength);
172         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create Links map");
173
174         cborEncoderResult = ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_HREF,
175                 sizeof(OC_RSRVD_HREF) - 1, rtPtr->href);
176         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_HREF in Links map");
177
178         cborEncoderResult = ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_REL,
179                 sizeof(OC_RSRVD_REL) - 1,  rtPtr->rel);
180         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_REL in Links map");
181
182         cborEncoderResult = ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_TITLE,
183                 sizeof(OC_RSRVD_TITLE) - 1, rtPtr->title);
184         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_TITLE in Links map");
185
186         cborEncoderResult = ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_URI,
187                 sizeof(OC_RSRVD_URI) - 1, rtPtr->uri);
188         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_URI in Links map");
189
190         cborEncoderResult = AddStringLLToMap(&linksMap, OC_RSRVD_RESOURCE_TYPE,
191                 sizeof(OC_RSRVD_RESOURCE_TYPE) - 1, rtPtr->rt);
192         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_RT in Links map");
193
194         cborEncoderResult = AddStringLLToMap(&linksMap, OC_RSRVD_INTERFACE,
195                 sizeof(OC_RSRVD_INTERFACE) - 1, rtPtr->itf);
196         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_ITF in Links map");
197
198         cborEncoderResult = AddStringLLToMap(&linksMap, OC_RSRVD_MEDIA_TYPE,
199                 sizeof(OC_RSRVD_MEDIA_TYPE) - 1, rtPtr->mt);
200         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_MT in Links map");
201
202         cborEncoderResult = ConditionalAddIntToMap(&linksMap, OC_RSRVD_INS,
203                 sizeof(OC_RSRVD_INS) - 1, (uint64_t *)&rtPtr->ins);
204         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_INS in Links map");
205
206         cborEncoderResult = cbor_encoder_close_container(&linksArray, &linksMap);
207         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing Links map");
208
209         rtPtr = rtPtr->next;
210     }
211     cborEncoderResult = cbor_encoder_close_container(setMap, &linksArray);
212     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing links array");
213
214 exit:
215     return cborEncoderResult;
216 }
217
218 OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPayload)
219 {
220     CborValue *rdCBORPayload = (CborValue *)cborPayload;
221     OCStackResult ret = OC_STACK_NO_MEMORY;
222     CborError cborFindResult;
223
224     OCRDPayload *rdPayload = OCRDPayloadCreate();
225     VERIFY_PARAM_NON_NULL(TAG, rdPayload, "Failed allocating rdPayload");
226
227     ret = OC_STACK_MALFORMED_RESPONSE;
228
229     if (cbor_value_is_array(rdCBORPayload))
230     {
231         OCLinksPayload *linksPayload = NULL;
232         OCTagsPayload *tagsPayload = NULL;
233
234         while (cbor_value_is_container(rdCBORPayload))
235         {
236             // enter tags map
237             CborValue tags;
238             cborFindResult = cbor_value_enter_container(rdCBORPayload, &tags);
239             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed entering tags container.");
240
241             cborFindResult= OCTagsCborToPayload(&tags, &tagsPayload);
242             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed parsing tags payload.");
243             OCTagsLog(DEBUG, tagsPayload);
244
245             cborFindResult = OCLinksCborToPayload(&tags, &linksPayload);
246             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed parsing links payload.");
247             OCLinksLog(DEBUG, linksPayload);
248
249             // Move from tags payload to links array.
250             cborFindResult = cbor_value_advance(rdCBORPayload);
251             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing rdCborPayload.");
252         }
253         rdPayload->rdPublish = OCCopyCollectionResource(tagsPayload, linksPayload);
254         VERIFY_PARAM_NON_NULL(TAG, rdPayload->rdPublish, "Failed allocating rdPayload->rdPublish");
255     }
256     else if (cbor_value_is_map(rdCBORPayload))
257     {
258         rdPayload->rdDiscovery = (OCRDDiscoveryPayload *)OICCalloc(1, sizeof(OCRDDiscoveryPayload));
259         VERIFY_PARAM_NON_NULL(TAG, rdPayload->rdDiscovery, "Failed allocating discoveryPayload");
260
261         cborFindResult = FindStringInMap(rdCBORPayload, OC_RSRVD_DEVICE_NAME,
262                 &rdPayload->rdDiscovery->n.deviceName);
263         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding OC_RSRVD_DEVICE_NAME.");
264         cborFindResult = FindStringInMap(rdCBORPayload, OC_RSRVD_DEVICE_ID,
265                 &rdPayload->rdDiscovery->n.deviceName);
266         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding OC_RSRVD_DEVICE_ID.");
267
268         cborFindResult = FindIntInMap(rdCBORPayload, OC_RSRVD_RD_DISCOVERY_SEL,
269                 (uint64_t *)&rdPayload->rdDiscovery->sel);
270         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding OC_RSRVD_RD_DISCOVERY_SEL.");
271
272         cborFindResult =  cbor_value_advance(rdCBORPayload);
273         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing rdCBORPayload.");
274     }
275     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
276     *outPayload = (OCPayload *)rdPayload;
277     return OC_STACK_OK;
278
279 exit:
280     OCRDPayloadDestroy(rdPayload);
281     return ret;
282 }
283
284 static CborError FindStringInMap(CborValue *map, char *tags, char **value)
285 {
286     CborValue curVal;
287     CborError cborFindResult = cbor_value_map_find_value(map, tags, &curVal);
288     if (CborNoError == cborFindResult && cbor_value_is_text_string(&curVal))
289     {
290         size_t len = 0;
291         cborFindResult = cbor_value_dup_text_string(&curVal, value, &len, NULL);
292     }
293     return cborFindResult;
294 }
295
296 static CborError FindIntInMap(CborValue *map, char *tags, uint64_t *value)
297 {
298     CborValue curVal;
299     CborError cborFindResult = cbor_value_map_find_value(map, tags, &curVal);
300     if (CborNoError == cborFindResult && cbor_value_is_unsigned_integer(&curVal))
301     {
302         cborFindResult = cbor_value_get_uint64(&curVal, value);
303     }
304     return cborFindResult;
305 }
306
307 static CborError FindStringLLInMap(const CborValue *linksMap, char *tag, OCStringLL **links)
308 {
309     size_t len;
310     CborValue rtArray;
311     OCStringLL* llPtr = *links;
312     CborError cborFindResult = cbor_value_map_find_value(linksMap, tag, &rtArray);
313     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding tag");
314
315     CborValue rtVal;
316     cborFindResult = cbor_value_enter_container(&rtArray, &rtVal);
317     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed entering container");
318
319     while (cbor_value_is_text_string(&rtVal))
320     {
321         if (llPtr == NULL)
322         {
323             llPtr = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
324             VERIFY_PARAM_NON_NULL(TAG, llPtr, "Failed allocating OCStringLL");
325             *links = llPtr;
326         }
327         else if(llPtr)
328         {
329             while (llPtr->next)
330             {
331                 llPtr = llPtr->next;
332             }
333             llPtr->next = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL));
334             VERIFY_PARAM_NON_NULL(TAG, llPtr->next, "Failed allocating OCStringLL->next");
335         }
336         cborFindResult = cbor_value_dup_text_string(&rtVal, &(llPtr->value), &len, NULL);
337         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed duplicating value");
338         cborFindResult = cbor_value_advance(&rtVal);
339         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing OCStringLL");
340     }
341
342     cborFindResult = cbor_value_leave_container(&rtArray, &rtVal);
343     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed leaving container");
344
345 exit:
346     return cborFindResult;
347 }
348
349 static CborError OCTagsCborToPayload(CborValue *tagsMap, OCTagsPayload **tagsPayload)
350 {
351     CborError cborFindResult = CborErrorOutOfMemory;
352     OCTagsPayload *tags = (OCTagsPayload *)OICCalloc(1, sizeof(OCTagsPayload));
353     VERIFY_PARAM_NON_NULL(TAG, tags, "Failed allocating tags");
354
355     if (cbor_value_is_map(tagsMap))
356     {
357         cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_DEVICE_NAME, &tags->n.deviceName);
358         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding deviceName");
359         cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_DREL, &tags->drel);
360         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding drel");
361         cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_RTS, &tags->rts);
362         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding rts");
363         cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_BASE_URI, &tags->baseURI);
364         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding baseURI");
365         cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_DEVICE_ID, (char **) &tags->di.id);
366         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding deviceId");
367         cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_HOSTING_PORT, (uint64_t *)&tags->port);
368         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding port");
369         cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_BITMAP, (uint64_t *)&tags->bitmap);
370         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding bitmap");
371         cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_INS, (uint64_t *)&tags->ins);
372         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ins");
373         cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_TTL, (uint64_t *)&tags->ttl);
374         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ttl");
375         cborFindResult = cbor_value_advance(tagsMap);
376         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing bitmap");
377     }
378     *tagsPayload = tags;
379     return cborFindResult;
380
381 exit:
382     OCFreeTagsResource(tags);
383     return cborFindResult;
384 }
385
386 static CborError OCLinksCborToPayload(CborValue *linksArray, OCLinksPayload **linksPayload)
387 {
388     CborValue linksMap;
389     OCLinksPayload *setLinks = NULL;
390     CborError cborFindResult = cbor_value_enter_container(linksArray, &linksMap);
391     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed entering links map container");
392
393     while (cbor_value_is_map(&linksMap))
394     {
395         setLinks = (OCLinksPayload *)OICCalloc(1, sizeof(OCLinksPayload));
396         VERIFY_PARAM_NON_NULL(TAG, setLinks, "Failed allocating setLinks");
397
398         cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_HREF, &setLinks->href);
399         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding href value");
400
401         cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_REL, &setLinks->rel);
402         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding rel value");
403
404         cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_TITLE, &setLinks->title);
405         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding title value");
406
407         cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_URI, &setLinks->uri);
408         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding uri value");
409
410         cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_RESOURCE_TYPE, &setLinks->rt);
411         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding rt value");
412
413         cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_INTERFACE, &setLinks->itf);
414         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding itf value");
415
416         cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_MEDIA_TYPE, &setLinks->mt);
417         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding mt value");
418
419         cborFindResult = FindIntInMap(&linksMap, OC_RSRVD_INS, (uint64_t *) &setLinks->ins);
420         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ins value");
421
422         if (!*linksPayload)
423         {
424             *linksPayload = setLinks;
425         }
426         else
427         {
428             OCLinksPayload *temp = *linksPayload;
429             while (temp->next)
430             {
431                 temp = temp->next;
432             }
433             temp->next = setLinks;
434         }
435         cborFindResult = cbor_value_advance(&linksMap);
436         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing links map");
437     }
438
439     return cborFindResult;
440
441 exit:
442     OCFreeLinksResource(*linksPayload);
443     OCFreeLinksResource(setLinks);
444     return cborFindResult;
445 }
446
447 static CborError AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
448         const char* value)
449 {
450     CborError err = cbor_encode_text_string(map, key, keylen);
451     VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting key value");
452     err = cbor_encode_text_string(map, value, strlen(value));
453 exit:
454     return err;
455 }
456
457 static CborError ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
458         const char* value)
459 {
460     return value ? AddTextStringToMap(map, key, keylen, value) : CborNoError;
461 }
462
463 static CborError ConditionalAddIntToMap(CborEncoder *map, const char *tags, const size_t size,
464     const uint64_t *value)
465 {
466     CborError err = CborUnknownError;
467     if (*value)
468     {
469         err = cbor_encode_text_string(map, tags, size);
470         VERIFY_CBOR_SUCCESS(TAG, err, "failed setting value");
471         err = cbor_encode_uint(map, *value);
472     }
473 exit:
474     return err;
475 }
476
477 static CborError AddStringLLToMap(CborEncoder *map, char *tag, const size_t size, OCStringLL *value)
478 {
479     CborEncoder array;
480     CborError cborEncoderResult;
481     OCStringLL *strType = value;
482     cborEncoderResult = cbor_encode_text_string(map, tag, size);
483     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed encoding string tag name");
484     cborEncoderResult = cbor_encoder_create_array(map, &array, CborIndefiniteLength);
485     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed creating stringLL array");
486     while (strType)
487     {
488         cborEncoderResult = cbor_encode_text_string(&array, strType->value, strlen(strType->value));
489         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed encoding string value");
490         strType = strType->next;
491     }
492     cborEncoderResult = cbor_encoder_close_container(map, &array);
493     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing string array");
494 exit:
495     return cborEncoderResult;
496 }
497
498 OCRDPayload *OCRDPayloadCreate()
499 {
500     OCRDPayload *rdPayload = (OCRDPayload *)OICCalloc(1, sizeof(OCRDPayload));
501     VERIFY_PARAM_NON_NULL(TAG, rdPayload, "Failed allocating rdPayload");
502     rdPayload->base.type = PAYLOAD_TYPE_RD;
503
504 exit:
505     return rdPayload;
506 }
507
508 OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(const char *deviceName, const char *id, int biasFactor)
509 {
510     OCRDDiscoveryPayload *discoveryPayload = (OCRDDiscoveryPayload *)OICCalloc(1, sizeof(OCRDDiscoveryPayload));
511     VERIFY_PARAM_NON_NULL(TAG, discoveryPayload, "Failed allocating memory for discovery payload");
512
513     if (deviceName)
514     {
515         discoveryPayload->n.deviceName = OICStrdup(deviceName);
516         VERIFY_PARAM_NON_NULL(TAG, discoveryPayload->n.deviceName,
517                 "Failed allocating memory for discovery device name");
518     }
519     if (id)
520     {
521         OICStrcpy((char*)discoveryPayload->di.id, MAX_IDENTITY_SIZE, id);
522     }
523
524     discoveryPayload->sel = biasFactor;
525     return discoveryPayload;
526 exit:
527     OICFree(discoveryPayload);
528     discoveryPayload = NULL;
529     return discoveryPayload;
530 }
531
532 void OCRDPayloadDestroy(OCRDPayload *payload)
533 {
534     if (!payload)
535     {
536         return;
537     }
538
539     if (payload->rdDiscovery)
540     {
541         if (payload->rdDiscovery->n.deviceName)
542         {
543             OICFree(payload->rdDiscovery->n.deviceName);
544         }
545         OICFree(payload->rdDiscovery);
546     }
547
548     if (payload->rdPublish)
549     {
550         for (OCResourceCollectionPayload *col = payload->rdPublish; col; )
551         {
552             if (col->setLinks)
553             {
554                 OCFreeLinksResource(col->setLinks);
555             }
556
557             if (col->tags)
558             {
559                 OCFreeTagsResource(col->tags);
560             }
561             OCResourceCollectionPayload *temp = col->next;
562             OICFree(col);
563             col = temp;
564         }
565     }
566
567     OICFree(payload);
568 }
569
570 OCTagsPayload* OCCopyTagsResources(const char *deviceName, const unsigned char *id, const char *baseURI,
571         uint8_t bitmap, uint16_t port, uint8_t ins, const char *rts,const  char *drel, uint32_t ttl)
572 {
573     OCTagsPayload *tags = (OCTagsPayload *)OICCalloc(1, sizeof(OCTagsPayload));
574     if (!tags)
575     {
576         return NULL;
577     }
578         if (deviceName)
579     {
580         tags->n.deviceName = OICStrdup(deviceName);
581         if (!tags->n.deviceName)
582         {
583             goto memory_allocation_failed;
584         }
585     }
586     if (id)
587     {
588         OICStrcpy((char*)tags->di.id, MAX_IDENTITY_SIZE, (char *)id);
589         if (!tags->di.id)
590         {
591             goto memory_allocation_failed;
592         }
593     }
594     if (baseURI)
595     {
596         tags->baseURI = OICStrdup(baseURI);
597         if (!tags->baseURI)
598         {
599             goto memory_allocation_failed;
600         }
601     }
602     tags->bitmap = bitmap;
603     tags->port = port;
604     tags->ins = ins;
605     if (rts)
606     {
607         tags->rts = OICStrdup(rts);
608         if (!tags->rts)
609         {
610             goto memory_allocation_failed;
611         }
612     }
613     if (drel)
614     {
615         tags->drel = OICStrdup(drel);
616         if (!tags->drel)
617         {
618             goto memory_allocation_failed;
619         }
620     }
621     tags->ttl = ttl;
622     return tags;
623
624 memory_allocation_failed:
625     OIC_LOG(ERROR, TAG, "Memory allocation failed.");
626     OCFreeTagsResource(tags);
627     return NULL;
628 }
629
630 OCLinksPayload* OCCopyLinksResources(const char *href, OCStringLL *rt, OCStringLL *itf,
631         const char *rel, bool obs, const char *title, const char *uri, uint8_t ins, OCStringLL *mt)
632 {
633     OCLinksPayload *links = (OCLinksPayload *)OICCalloc(1, sizeof(OCLinksPayload));
634     if (!links)
635     {
636         OIC_LOG(ERROR, TAG, "Failed allocating memory.");
637         return NULL;
638     }
639     if (href)
640     {
641         links->href = OICStrdup(href);
642         if (!links->href)
643         {
644             goto memory_allocation_failed;
645         }
646     }
647     if (rt)
648     {
649         links->rt = CloneOCStringLL(rt);
650         if (!links->rt)
651         {
652             goto memory_allocation_failed;
653         }
654     }
655     if (itf)
656     {
657         links->itf = CloneOCStringLL(itf);
658         if (!links->itf)
659         {
660             goto memory_allocation_failed;
661         }
662     }
663     if (rel)
664     {
665         links->rel = OICStrdup(rel);
666         if (!links->rel)
667         {
668             goto memory_allocation_failed;
669         }
670     }
671     links->obs = obs;
672     if (title)
673     {
674         links->title = OICStrdup(title);
675         if (!links->title)
676         {
677             goto memory_allocation_failed;
678         }
679     }
680     if (uri)
681     {
682         links->uri = OICStrdup(uri);
683         if (!links->uri)
684         {
685             goto memory_allocation_failed;
686         }
687     }
688     links->ins = ins;
689     if (mt)
690     {
691         links->mt = CloneOCStringLL(mt);
692         if (!links->mt)
693         {
694             goto memory_allocation_failed;
695         }
696     }
697     links->next = NULL;
698     return links;
699
700 memory_allocation_failed:
701     OIC_LOG(ERROR, TAG, "Memory allocation failed.");
702     OCFreeLinksResource(links);
703     return NULL;
704 }
705
706 OCResourceCollectionPayload* OCCopyCollectionResource(OCTagsPayload *tags, OCLinksPayload *links)
707 {
708     OCResourceCollectionPayload *pl =  NULL;
709     VERIFY_PARAM_NON_NULL(TAG, tags, "Invalid param tags");
710     VERIFY_PARAM_NON_NULL(TAG, links, "Invalid param links");
711
712     pl = (OCResourceCollectionPayload *)OICCalloc(1, sizeof(OCResourceCollectionPayload));
713     VERIFY_PARAM_NON_NULL(TAG, pl, "Failed allocating memory for the OCResourceCollectionPayload");
714
715     pl->tags = tags;
716     pl->setLinks = links;
717
718 exit:
719     return pl;
720 }
721
722 void OCFreeLinksResource(OCLinksPayload *payload)
723 {
724     if (!payload)
725     {
726         return;
727     }
728     OICFree(payload->href);
729     OCFreeOCStringLL(payload->rt);
730     OCFreeOCStringLL(payload->itf);
731     OICFree(payload->rel);
732     OICFree(payload->title);
733     OICFree(payload->uri);
734     OCFreeOCStringLL(payload->mt);
735     OCFreeLinksResource(payload->next);
736     OICFree(payload);
737 }
738
739 void OCFreeTagsResource(OCTagsPayload *payload)
740 {
741     if (!payload)
742     {
743         return;
744     }
745     OICFree(payload->n.deviceName);
746     OICFree(payload->baseURI);
747     OICFree(payload->rts);
748     OICFree(payload->drel);
749     OICFree(payload);
750 }
751
752 void OCFreeCollectionResource(OCResourceCollectionPayload *payload)
753 {
754     if (!payload)
755     {
756         return;
757     }
758     if (payload->tags)
759     {
760         OCFreeTagsResource(payload->tags);
761     }
762     if (payload->setLinks)
763     {
764         OCFreeLinksResource(payload->setLinks);
765     }
766     OCFreeCollectionResource(payload->next);
767     OICFree(payload);
768 }
769
770 void OCTagsLog(const LogLevel level, const OCTagsPayload *tags)
771 {
772     if (tags)
773     {
774         if (tags->n.deviceName)
775         {
776             OIC_LOG_V(level, TAG, " Device Name : %s ",tags->n.deviceName);
777         }
778         if (tags->baseURI)
779         {
780             OIC_LOG_V(level, TAG, " Base URI : %s ",tags->baseURI);
781         }
782         OIC_LOG_V(level, TAG, " Device ID : %s ",tags->di.id);
783         OIC_LOG_V(level, TAG, " Bitmap : %d ",tags->bitmap);
784         OIC_LOG_V(level, TAG, " Port : %d ",tags->port);
785         OIC_LOG_V(level, TAG, " Ins : %d ",tags->ins);
786         OIC_LOG_V(level, TAG, " Ttl : %d ",tags->ttl);
787
788         if (tags->rts)
789         {
790             OIC_LOG_V(level, TAG, " RTS : %s ",tags->rts);
791         }
792         if (tags->drel)
793         {
794             OIC_LOG_V(level, TAG, " DREL : %s ",tags->drel);
795         }
796     }
797     else
798     {
799         (void) level;
800     }
801 }
802
803 void OCLinksLog(const LogLevel level, const OCLinksPayload *links)
804 {
805     while (links)
806     {
807         if (links->href)
808         {
809             OIC_LOG_V(level, TAG, " href: %s ",links->href);
810         }
811         OIC_LOG(level, TAG, " RT: ");
812         OCStringLL *rt = links->rt;
813         while (rt)
814         {
815             if (rt->value)
816             {
817                 OIC_LOG_V(level, TAG, "   %s", rt->value);
818             }
819             rt = rt->next;
820         }
821         OIC_LOG(level, TAG, " IF: ");
822         OCStringLL *itf = links->itf;
823         while (itf)
824         {
825             if (itf->value)
826             {
827                 OIC_LOG_V(level, TAG, "   %s", itf->value);
828             }
829             itf = itf->next;
830         }
831         OIC_LOG(level, TAG, " MT: ");
832         OCStringLL *mt = links->mt;
833         while (mt)
834         {
835             if (mt->value)
836             {
837                 OIC_LOG_V(level, TAG, "   %s", mt->value);
838             }
839             mt = mt->next;
840         }
841         OIC_LOG_V(level, TAG, " INS: %d", links->ins);
842         OIC_LOG_V(level, TAG, " OBS: %d", links->obs);
843         if (links->rel)
844         {
845             OIC_LOG_V(level, TAG, " REL: %s", links->rel);
846         }
847         if (links->title)
848         {
849             OIC_LOG_V(level, TAG, " TITLE: %s", links->title);
850         }
851         if (links->uri)
852         {
853             OIC_LOG_V(level, TAG, " URI: %s", links->uri);
854         }
855         links = links->next;
856     }
857     if (!links)
858     {
859         (void) level;
860     }
861 }