cb0b629881d02d1453d4047deb0c7338dead38f5
[platform/upstream/iotivity.git] / service / resource-directory / src / rd_payload.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 "rd_payload.h"
21
22 #include "oic_malloc.h"
23 #include "oic_string.h"
24
25 #include "octypes.h"
26 #include "ocstack.h"
27
28 #define TAG PCF("OCRDPayload")
29
30 #define CBOR_ROOT_ARRAY_LENGTH 1
31 #define CBOR_LINK_ARRAY_LENGTH 3
32
33 static void linksPayloadDestroy(OCRDLinksPayload *linkPayload)
34 {
35     OCRDLinksPayload *links = linkPayload;
36
37     while (links)
38     {
39         OICFree(links->href);
40         OICFree(links->rt);
41         OICFree(links->itf);
42         OCRDLinksPayload *tmp = links;
43         links = links->next;
44         OICFree(tmp);
45     }
46 }
47
48 OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t *outPayload, size_t *size)
49 {
50     if (!outPayload || !size)
51     {
52         OC_LOG_V(ERROR, TAG, "Invalid parameters.");
53         return OC_STACK_ERROR;
54     }
55
56     CborEncoder encoder;
57     int flags = 0;
58     cbor_encoder_init(&encoder, outPayload, *size, flags);
59
60     CborEncoder rootArray;
61     CborError cborEncoderResult;
62     cborEncoderResult = cbor_encoder_create_array(&encoder, &rootArray, CBOR_ROOT_ARRAY_LENGTH);
63     if (CborNoError != cborEncoderResult)
64     {
65         OC_LOG_V(ERROR, TAG, "Failed creating cbor array.");
66         goto exit;
67     }
68
69     CborEncoder map;
70     cborEncoderResult = cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
71     if (CborNoError != cborEncoderResult)
72     {
73         OC_LOG_V(ERROR, TAG, "Failed creating cbor map.");
74         goto exit;
75     }
76
77     cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_CONTENT_TYPE,
78         sizeof(OC_RSRVD_CONTENT_TYPE) - 1);
79     if (CborNoError != cborEncoderResult)
80     {
81         OC_LOG_V(ERROR, TAG, "Failed setting content type.");
82         goto exit;
83     }
84
85     cborEncoderResult = cbor_encode_uint(&map, rdPayload->payloadType);
86     if (CborNoError != cborEncoderResult)
87     {
88         OC_LOG_V(ERROR, TAG, "Failed setting rdPayload->payloadType.");
89         goto exit;
90     }
91
92     if (rdPayload->payloadType == RD_PAYLOAD_TYPE_DISCOVERY)
93     {
94         if (rdPayload->rdDiscovery && rdPayload->rdDiscovery->sel)
95         {
96             cborEncoderResult = cbor_encode_text_string(&map,
97                 OC_RSRVD_RD_DISCOVERY_SEL, sizeof(OC_RSRVD_RD_DISCOVERY_SEL) -1);
98             if (CborNoError != cborEncoderResult)
99             {
100                 OC_LOG_V(ERROR, TAG, "Failed setting discovery sel type.");
101                 goto exit;
102             }
103             cborEncoderResult = cbor_encode_uint(&map, rdPayload->rdDiscovery->sel);
104             if (CborNoError != cborEncoderResult)
105             {
106                 OC_LOG_V(ERROR, TAG, "Failed setting discovery sel value.");
107                 goto exit;
108             }
109         }
110         else
111         {
112             OC_LOG_V(ERROR, TAG, "Missing sel parameter in the discovery payload.");
113             goto exit;
114         }
115     }
116     else if (rdPayload->payloadType == RD_PAYLOAD_TYPE_PUBLISH)
117     {
118         cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_TTL, sizeof(OC_RSRVD_TTL) - 1);
119         if (CborNoError != cborEncoderResult)
120         {
121             OC_LOG_V(ERROR, TAG, "Failed setting publish ttl type.");
122             goto exit;
123         }
124
125         cborEncoderResult = cbor_encode_uint(&map, rdPayload->rdPublish->ttl);
126         if (CborNoError != cborEncoderResult)
127         {
128             OC_LOG_V(ERROR, TAG, "Failed setting publish ttl value.");
129             goto exit;
130         }
131
132         CborEncoder linksArray;
133         cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_LINKS, sizeof(OC_RSRVD_LINKS) - 1);
134         if (CborNoError != cborEncoderResult)
135         {
136             OC_LOG_V(ERROR, TAG, "Failed setting publish links type.");
137             goto exit;
138         }
139
140         cborEncoderResult = cbor_encoder_create_array(&map, &linksArray, CborIndefiniteLength);
141         if (CborNoError != cborEncoderResult)
142         {
143             OC_LOG_V(ERROR, TAG, "Failed setting publish links array.");
144             goto exit;
145         }
146
147         {
148             OCRDLinksPayload *rtPtr = rdPayload->rdPublish->links;
149             while(rtPtr)
150             {
151                 CborEncoder linksMap;
152                 cborEncoderResult = cbor_encoder_create_map(&linksArray, &linksMap, CBOR_LINK_ARRAY_LENGTH);
153                 if (CborNoError != cborEncoderResult)
154                 {
155                     OC_LOG_V(ERROR, TAG, "Failed setting publish map.");
156                     goto exit;
157                 }
158
159                 cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_HREF,
160                         sizeof(OC_RSRVD_HREF) - 1);
161                 if (CborNoError != cborEncoderResult)
162                 {
163                     OC_LOG_V(ERROR, TAG, "Failed setting publish href type.");
164                     goto exit;
165                 }
166
167                 cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->href,
168                         strlen(rtPtr->href));
169                 if (CborNoError != cborEncoderResult)
170                 {
171                     OC_LOG_V(ERROR, TAG, "Failed setting publish href value.");
172                     goto exit;
173                 }
174
175                 cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_INTERFACE,
176                         sizeof(OC_RSRVD_INTERFACE) - 1);
177                 if (CborNoError != cborEncoderResult)
178                 {
179                     OC_LOG_V(ERROR, TAG, "Failed setting publish itf type.");
180                     goto exit;
181                 }
182
183                 cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->itf,
184                         strlen(rtPtr->itf));
185                 if (CborNoError != cborEncoderResult)
186                 {
187                     OC_LOG_V(ERROR, TAG, "Failed setting publish itf value.");
188                     goto exit;
189                 }
190
191                 cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_RESOURCE_TYPE,
192                         sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
193                 if (CborNoError != cborEncoderResult)
194                 {
195                     OC_LOG_V(ERROR, TAG, "Failed setting publish rt type.");
196                     goto exit;
197                 }
198
199                 cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->rt,
200                         strlen(rtPtr->rt));
201                 if (CborNoError != cborEncoderResult)
202                 {
203                     OC_LOG_V(ERROR, TAG, "Failed setting publish rt value.");
204                     goto exit;
205                 }
206
207                 cborEncoderResult = cbor_encoder_close_container(&linksArray, &linksMap);
208                 if (CborNoError != cborEncoderResult)
209                 {
210                     OC_LOG_V(ERROR, TAG, "Failed closing linksMap publish map.");
211                     goto exit;
212                 }
213
214                 rtPtr = rtPtr->next;
215             }
216         }
217         cborEncoderResult = cbor_encoder_close_container(&map, &linksArray);
218         if (CborNoError != cborEncoderResult)
219         {
220             OC_LOG_V(ERROR, TAG, "Failed closing linksArray container.");
221             goto exit;
222         }
223     }
224
225     cborEncoderResult = cbor_encoder_close_container(&rootArray, &map);
226     if (CborNoError != cborEncoderResult)
227     {
228         OC_LOG_V(ERROR, TAG, "Failed closing map container.");
229         goto exit;
230     }
231
232     cborEncoderResult = cbor_encoder_close_container(&encoder, &rootArray);
233     if (CborNoError != cborEncoderResult)
234     {
235         OC_LOG_V(ERROR, TAG, "Failed closing encoder container.");
236         goto exit;
237     }
238
239     *size = encoder.ptr - outPayload;
240     return OC_STACK_OK;
241
242 exit:
243     OICFree(outPayload);
244     return OC_STACK_ERROR;
245 }
246
247 OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPayload)
248 {
249     CborValue *rdCBORPayload = (CborValue *)cborPayload;
250     OCRDPayload *rdPayload = NULL;
251
252     if (!cbor_value_is_map(rdCBORPayload))
253     {
254         OC_LOG_V(ERROR, TAG, "RD CBOR Payload is not in map format.");
255         return OC_STACK_ERROR;
256     }
257     else
258     {
259         CborValue curVal;
260         CborError cborFindResult;
261         cborFindResult = cbor_value_map_find_value(rdCBORPayload,
262             OC_RSRVD_CONTENT_TYPE, &curVal);
263         if (CborNoError != cborFindResult)
264         {
265             OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_CONTENT_TYPE type in the payload.");
266             goto exit;
267         }
268
269         int payloadType = 0 ;
270         if (cbor_value_is_valid(&curVal))
271         {
272             cborFindResult = cbor_value_get_int(&curVal, &payloadType);
273             if (CborNoError != cborFindResult)
274             {
275                 OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_CONTENT_TYPE value in the payload.");
276                 goto exit;
277             }
278         }
279
280         rdPayload = OCRDPayloadCreate(payloadType);
281         if (!rdPayload)
282         {
283             goto no_memory;
284         }
285
286         if (RD_PAYLOAD_TYPE_DISCOVERY == payloadType)
287         {
288             cborFindResult = cbor_value_map_find_value(rdCBORPayload,
289                 OC_RSRVD_RD_DISCOVERY_SEL, &curVal);
290             if (CborNoError != cborFindResult)
291             {
292                 OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_RD_DISCOVERY_SEL type in the payload.");
293                 goto exit;
294             }
295
296             int biasFactor = 0;
297             if (cbor_value_is_valid(&curVal))
298             {
299                 cborFindResult = cbor_value_get_int(&curVal, &biasFactor);
300                 if (CborNoError != cborFindResult)
301                 {
302                     OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_RD_DISCOVERY_SEL value in the payload.");
303                     goto exit;
304                 }
305             }
306
307             rdPayload->rdDiscovery = OCRDDiscoveryPayloadCreate(biasFactor);
308             if (!rdPayload->rdDiscovery)
309             {
310                 goto no_memory;
311             }
312         }
313         else if (RD_PAYLOAD_TYPE_PUBLISH == payloadType)
314         {    // TTL
315             int ttl = 0;
316             cborFindResult = cbor_value_map_find_value(rdCBORPayload, OC_RSRVD_TTL, &curVal);
317             if (CborNoError != cborFindResult)
318             {
319                 OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_TTL type in the payload.");
320                 goto exit;
321             }
322
323             cborFindResult = cbor_value_get_int(&curVal, &ttl);
324             if (CborNoError != cborFindResult)
325             {
326                 OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_TTL value in the payload.");
327                 goto exit;
328             }
329
330             // Link Array
331             CborValue linkArray;
332             cborFindResult = cbor_value_map_find_value(rdCBORPayload, OC_RSRVD_LINKS, &linkArray);
333             if (CborNoError != cborFindResult)
334             {
335                 OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_LINKS type in the payload.");
336                 goto exit;
337             }
338
339             CborValue linkVal;
340             cborFindResult = cbor_value_enter_container(&linkArray, &linkVal);
341             if (CborNoError != cborFindResult)
342             {
343                 OC_LOG_V(ERROR, TAG, "Failed entering linkArray container in the payload.");
344                 goto exit;
345             }
346
347             OCRDLinksPayload *links = NULL;
348             while(cbor_value_is_map(&linkVal))
349             {
350                 char *href = NULL;
351                 char *itf = NULL;
352                 char *rt = NULL;
353                 size_t len;
354
355                 cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_HREF, &curVal);
356                 if (CborNoError != cborFindResult)
357                 {
358                     OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_HREF type in the payload.");
359                     goto exit;
360                 }
361
362                 cborFindResult = cbor_value_dup_text_string(&curVal, &href, &len, NULL);
363                 if (CborNoError != cborFindResult)
364                 {
365                     OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_HREF value in the payload.");
366                     goto exit;
367                 }
368
369                 cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_INTERFACE, &curVal);
370                 if (CborNoError != cborFindResult)
371                 {
372                     OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_INTERFACE type in the payload.");
373                     goto exit;
374                 }
375
376                 cborFindResult = cbor_value_dup_text_string(&curVal, &itf, &len, NULL);
377                 if (CborNoError != cborFindResult)
378                 {
379                     OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_INTERFACE value in the payload.");
380                     goto exit;
381                 }
382
383                 cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
384                 if (CborNoError != cborFindResult)
385                 {
386                     OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_RESOURCE_TYPE type in the payload.");
387                     goto exit;
388                 }
389
390                 cborFindResult = cbor_value_dup_text_string(&curVal, &rt, &len, NULL);
391                 if (CborNoError != cborFindResult)
392                 {
393                     OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_RESOURCE_TYPE value in the payload.");
394                     goto exit;
395                 }
396
397                 OCRDLinksPayloadCreate(href, rt, itf, &links);
398                 if (!links)
399                 {
400                     goto no_memory;
401                 }
402
403                 cborFindResult = cbor_value_advance(&linkVal);
404                 if (CborNoError != cborFindResult)
405                 {
406                         OC_LOG_V(ERROR, TAG, "Failed advancing the linkVal payload.");
407                         goto exit;
408                 }
409             }
410             cborFindResult = cbor_value_advance(&linkArray);
411             if (CborNoError != cborFindResult)
412             {
413                 OC_LOG_V(ERROR, TAG, "Failed advancing the linkArray payload.");
414                 goto exit;
415             }
416             rdPayload->rdPublish = OCRDPublishPayloadCreate(ttl, links);
417             if (!rdPayload->rdPublish)
418             {
419                 goto no_memory;
420             }
421         }
422
423         OCRDPayloadLog(DEBUG, TAG, rdPayload);
424         cborFindResult = cbor_value_advance(rdCBORPayload);
425         if (CborNoError != cborFindResult)
426         {
427             OC_LOG_V(ERROR, TAG, "Failed advancing the payload.");
428             goto exit;
429         }
430         *outPayload = (OCPayload *)rdPayload;
431     }
432     return OC_STACK_OK;
433 no_memory:
434     OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
435     OCRDPayloadDestroy(rdPayload);
436     return OC_STACK_NO_MEMORY;
437
438 exit:
439     OCRDPayloadDestroy(rdPayload);
440     return OC_STACK_ERROR;
441 }
442
443 OCRDPayload *OCRDPayloadCreate(OCRDPayloadType payloadType)
444 {
445     OCRDPayload *rdPayload = (OCRDPayload *)OICCalloc(1, sizeof(OCRDPayload));
446
447     if (!rdPayload)
448     {
449         return NULL;
450     }
451
452     rdPayload->base.type = PAYLOAD_TYPE_RD;
453     rdPayload->payloadType = payloadType;
454
455     return rdPayload;
456 }
457
458 void OCRDLinksPayloadCreate(const char *uri, const char *rt, const char *itf,
459         OCRDLinksPayload **linksPayload)
460 {
461     OCRDLinksPayload *payload = OICCalloc(1, sizeof(OCRDLinksPayload));
462     if (!payload)
463     {
464         goto no_memory;
465     }
466
467     payload->href = OICStrdup(uri);
468     if (!payload->href)
469     {
470         goto no_memory;
471     }
472
473     payload->rt = OICStrdup(rt);
474     if (!payload->rt)
475     {
476         goto no_memory;
477     }
478
479     payload->itf = OICStrdup(itf);
480     if (!payload->itf)
481     {
482         goto no_memory;
483     }
484
485     payload->next = NULL;
486
487     if (*linksPayload == NULL)
488     {
489         *linksPayload = payload;
490     }
491     else
492     {
493         OCRDLinksPayload *temp = *linksPayload;
494         while (temp->next)
495         {
496             temp = temp->next;
497         }
498         temp->next = payload;
499     }
500     return;
501
502 no_memory:
503     OC_LOG_V(ERROR, TAG, "Memory allocation failed.");
504     linksPayloadDestroy(payload);
505 }
506
507 OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor)
508 {
509     OCRDDiscoveryPayload *discoveryPayload = OICCalloc(1, sizeof(OCRDDiscoveryPayload));
510
511     if (!discoveryPayload)
512     {
513         return NULL;
514     }
515     discoveryPayload->sel = biasFactor;
516
517     return discoveryPayload;
518 }
519
520
521 OCRDPublishPayload* OCRDPublishPayloadCreate(int ttl,
522         OCRDLinksPayload *linksPayload)
523 {
524     OCRDPublishPayload *rdPublish = OICCalloc(1, sizeof(OCRDPublishPayload));
525     if (!rdPublish)
526     {
527         return NULL;
528     }
529
530     //TODO: Find way of device device id.
531     // rdPayload->rdPublish->id = (uint8_t *)OICCalloc(1, UUID_SIZE);
532     // memcpy(rdPayload->rdPublish->id, , UUID_SIZE);
533     //TODO: Find way of device device name.
534     // rdPayload->rdPublish->n = (char*)OICCalloc(1, strlen(name));
535     // memcpy(rdPayload->rdPublish->n, , strlen(name));
536     rdPublish->ttl = ttl; // TODO Expose API to allow user to set this value.
537     rdPublish->links = linksPayload;
538
539     return rdPublish;
540 }
541
542 void OCRDPayloadDestroy(OCRDPayload *payload)
543 {
544     if (!payload)
545     {
546         return;
547     }
548
549     if (payload->rdDiscovery)
550     {
551         OICFree(payload->rdDiscovery);
552     }
553
554     if (payload->rdPublish)
555     {
556         if (payload->rdPublish->links)
557         {
558             linksPayloadDestroy(payload->rdPublish->links);
559         }
560
561         if (payload->rdPublish->deviceName.deviceName)
562         {
563             OICFree(payload->rdPublish->deviceName.deviceName);
564         }
565
566         OICFree(payload->rdPublish);
567     }
568
569     OICFree(payload);
570 }
571
572 void OCRDPayloadLog(LogLevel level, const char *tag, const OCRDPayload *payload)
573 {
574     if (!payload)
575     {
576         return;
577     }
578
579     OC_LOG_V(level, tag, "BaseType : %d", payload->base.type);
580     OC_LOG_V(level, tag, "RD Payload Type : %d", payload->payloadType);
581
582     if (payload->rdDiscovery)
583     {
584         OC_LOG_V(level, tag, "RD Payload Discovery BIAS : %d", payload->rdDiscovery->sel);
585     }
586     OCRDPublishPayloadLog(level, tag, payload->rdPublish);
587 }
588
589 void OCRDPublishPayloadLog(LogLevel level, const char *tag, const OCRDPublishPayload *rdPublish)
590 {
591     if (rdPublish)
592     {
593         if (rdPublish->deviceName.deviceName)
594         {
595             OC_LOG_V(level, tag, "RD Payload Pulish Name : %s", rdPublish->deviceName.deviceName);
596         }
597
598         if (rdPublish->deviceId.id)
599         {
600             OC_LOG_V(level, tag, "RD Payload Publish ID : %s",  rdPublish->deviceId.id);
601         }
602
603         OC_LOG_V(level, tag, "RD Payload Publish TTL : %d", rdPublish->ttl);
604
605         if (rdPublish->links)
606         {
607             for (OCRDLinksPayload *temp = rdPublish->links; temp; temp = temp->next)
608             {
609                 OC_LOG_V(level, tag, "RD Payload Publish Link HREF : %s", temp->href);
610                 OC_LOG_V(level, tag, "RD Payload Publish Link RT : %s", temp->rt);
611                 OC_LOG_V(level, tag, "RD Payload Publish Link ITF : %s", temp->itf);
612             }
613         }
614     }
615 }