Merge branch 'master' into simulator
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / caprotocolmessage.c
1 /******************************************************************
2  *
3  * Copyright 2014 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
21 // Defining _BSD_SOURCE or _DEFAULT_SOURCE causes header files to expose
22 // definitions that may otherwise be skipped. Skipping can cause implicit
23 // declaration warnings and/or bugs and subtle problems in code execution.
24 // For glibc information on feature test macros,
25 // Refer http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
26 //
27 // This file requires #define use due to random() and srandom()
28 // For details on compatibility and glibc support,
29 // Refer http://www.gnu.org/software/libc/manual/html_node/BSD-Random.html
30 #define _DEFAULT_SOURCE
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdbool.h>
36 #ifdef HAVE_TIME_H
37 #include <time.h>
38 #endif
39
40 #include "caprotocolmessage.h"
41 #include "logger.h"
42 #include "oic_malloc.h"
43 #include "oic_string.h"
44
45 // ARM GCC compiler doesnt define srandom function.
46 #if defined(ARDUINO) && !defined(ARDUINO_ARCH_SAM)
47 #define HAVE_SRANDOM 1
48 #endif
49
50 #define TAG "CA_PRTCL_MSG"
51
52 /**
53  * @def VERIFY_NON_NULL_RET
54  * @brief Macro to verify the validity of input argument
55  */
56 #define VERIFY_NON_NULL_RET(arg, log_tag, log_message,ret) \
57     if (NULL == arg ){ \
58         OIC_LOG_V(ERROR, log_tag, "Invalid input:%s", log_message); \
59         return ret; \
60     }
61
62 #define CA_BUFSIZE (128)
63 #define CA_PDU_MIN_SIZE (4)
64 #define CA_PORT_BUFFER_SIZE (4)
65
66 static const char COAP_URI_HEADER[] = "coap://[::]/";
67
68 static unsigned int SEED = 0;
69
70 CAResult_t CAGetRequestInfoFromPDU(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo)
71 {
72     OIC_LOG(DEBUG, TAG, "IN");
73
74     if (NULL == pdu || NULL == outReqInfo)
75     {
76         OIC_LOG(ERROR, TAG, "parameter is null");
77         return CA_STATUS_INVALID_PARAM;
78     }
79
80     uint32_t code = CA_NOT_FOUND;
81     CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &(outReqInfo->info));
82     outReqInfo->method = code;
83
84     OIC_LOG(DEBUG, TAG, "OUT");
85     return ret;
86 }
87
88 CAResult_t CAGetResponseInfoFromPDU(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo)
89 {
90     OIC_LOG(DEBUG, TAG, "IN");
91
92     if (NULL == pdu || NULL == outResInfo)
93     {
94         OIC_LOG(ERROR, TAG, "parameter is null");
95         return CA_STATUS_INVALID_PARAM;
96     }
97
98     uint32_t code = CA_NOT_FOUND;
99     CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &(outResInfo->info));
100     outResInfo->result = code;
101
102     OIC_LOG(DEBUG, TAG, "OUT");
103     return ret;
104 }
105
106 CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, CAErrorInfo_t *errorInfo)
107 {
108     OIC_LOG(DEBUG, TAG, "IN");
109
110     if (!pdu)
111     {
112         OIC_LOG(ERROR, TAG, "parameter is null");
113         return CA_STATUS_INVALID_PARAM;
114     }
115
116     uint32_t code = 0;
117     CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &errorInfo->info);
118     OIC_LOG(DEBUG, TAG, "OUT");
119     return ret;
120 }
121
122 coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info)
123 {
124     OIC_LOG(DEBUG, TAG, "IN");
125
126     coap_pdu_t *pdu = NULL;
127
128     // RESET have to use only 4byte (empty message)
129     // and ACKNOWLEDGE can use empty message when code is empty.
130     if (CA_MSG_RESET == info->type || (CA_EMPTY == code && CA_MSG_ACKNOWLEDGE == info->type))
131     {
132         OIC_LOG(DEBUG, TAG, "code is empty");
133         if (!(pdu = CAGeneratePDUImpl((code_t) code, NULL, info, NULL, 0)))
134         {
135             OIC_LOG(ERROR, TAG, "pdu NULL");
136             return NULL;
137         }
138     }
139     else
140     {
141         coap_list_t *optlist = NULL;
142
143         if (CA_MSG_ACKNOWLEDGE != info->type)
144         {
145             const char *uri = info->resourceUri;
146             if (NULL == uri)
147             {
148                 OIC_LOG(ERROR, TAG, "uri NULL");
149                 return NULL;
150             }
151
152             uint32_t length = strlen(uri);
153             if (CA_MAX_URI_LENGTH < length)
154             {
155                 OIC_LOG(ERROR, TAG, "URI len err");
156                 return NULL;
157             }
158
159             uint32_t uriLength = length + sizeof(COAP_URI_HEADER);
160             char *coapUri = (char *) OICCalloc(1, uriLength);
161             if (NULL == coapUri)
162             {
163                 OIC_LOG(ERROR, TAG, "out of memory");
164                 return NULL;
165             }
166             OICStrcat(coapUri, uriLength, COAP_URI_HEADER);
167             OICStrcat(coapUri, uriLength, uri);
168
169             // parsing options in URI
170             CAResult_t res = CAParseURI(coapUri, &optlist);
171             if (CA_STATUS_OK != res)
172             {
173                 if (optlist)
174                 {
175                     coap_delete_list(optlist);
176                 }
177                 OICFree(coapUri);
178                 return NULL;
179             }
180
181             OICFree(coapUri);
182         }
183         // parsing options in HeadOption
184         CAResult_t ret = CAParseHeadOption(code, info, &optlist);
185         if (CA_STATUS_OK != ret)
186         {
187             coap_delete_list(optlist);
188             return NULL;
189         }
190         pdu = CAGeneratePDUImpl((code_t) code, optlist, info, info->payload, info->payloadSize);
191         if (NULL == pdu)
192         {
193             OIC_LOG(ERROR, TAG, "pdu NULL");
194             coap_delete_list(optlist);
195             return NULL;
196         }
197
198         // free option list
199         coap_delete_list(optlist);
200     }
201
202     // pdu print method : coap_show_pdu(pdu);
203     OIC_LOG(DEBUG, TAG, "OUT");
204     return pdu;
205 }
206
207 coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)
208 {
209     OIC_LOG(DEBUG, TAG, "IN");
210
211     if (NULL == data)
212     {
213         OIC_LOG(ERROR, TAG, "data is null");
214         return NULL;
215     }
216
217     coap_pdu_t *outpdu = coap_new_pdu();
218     if (NULL == outpdu)
219     {
220         OIC_LOG(ERROR, TAG, "outpdu is null");
221         return NULL;
222     }
223
224     if (0 >= coap_pdu_parse((unsigned char *) data, length, outpdu))
225     {
226         OIC_LOG(ERROR, TAG, "pdu parse failed");
227         coap_delete_pdu(outpdu);
228         return NULL;
229     }
230
231     if (outCode)
232     {
233         (*outCode) = (uint32_t) CA_RESPONSE_CODE(outpdu->hdr->code);
234     }
235
236     OIC_LOG(DEBUG, TAG, "OUT");
237     return outpdu;
238 }
239
240 coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t *info,
241                               const uint8_t *payload, size_t payloadSize)
242 {
243     OIC_LOG(DEBUG, TAG, "IN");
244     VERIFY_NON_NULL_RET(info, TAG, "info is NULL", NULL);
245
246     coap_pdu_t *pdu = coap_new_pdu();
247
248     if (NULL == pdu)
249     {
250         OIC_LOG(ERROR, TAG, "malloc failed");
251         return NULL;
252     }
253
254     OIC_LOG_V(DEBUG, TAG, "msgID is %d", info->messageId);
255     uint16_t message_id;
256     if (0 == info->messageId)
257     {
258         /* initialize message id */
259         prng((uint8_t * ) &message_id, sizeof(message_id));
260
261         OIC_LOG_V(DEBUG, TAG, "gen msg id=%d", message_id);
262     }
263     else
264     {
265         /* use saved message id */
266         message_id = info->messageId;
267     }
268     pdu->hdr->id = message_id;
269     OIC_LOG_V(DEBUG, TAG, "messageId in pdu is %d, %d", message_id, pdu->hdr->id);
270
271     pdu->hdr->type = info->type;
272     pdu->hdr->code = COAP_RESPONSE_CODE(code);
273
274     if (info->token && CA_EMPTY != code)
275     {
276         uint32_t tokenLength = info->tokenLength;
277         OIC_LOG_V(DEBUG, TAG, "token info token length: %d, token :", tokenLength);
278         OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *)info->token, tokenLength);
279
280         int32_t ret = coap_add_token(pdu, tokenLength, (unsigned char *)info->token);
281         if (0 == ret)
282         {
283             OIC_LOG(ERROR, TAG, "can't add token");
284         }
285     }
286
287     if (options)
288     {
289         for (coap_list_t *opt = options; opt; opt = opt->next)
290         {
291             OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.",
292                       COAP_OPTION_DATA(*(coap_option *) opt->data));
293             coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
294                             COAP_OPTION_LENGTH(*(coap_option *) opt->data),
295                             COAP_OPTION_DATA(*(coap_option *) opt->data));
296         }
297     }
298
299 #ifndef WITH_BWT
300     if (NULL != payload)
301     {
302         coap_add_data(pdu, payloadSize, (const unsigned char *) payload);
303     }
304 #else
305     (void)payload;
306     (void)payloadSize;
307 #endif
308
309     OIC_LOG(DEBUG, TAG, "OUT");
310     return pdu;
311 }
312
313 CAResult_t CAParseURI(const char *uriInfo, coap_list_t **optlist)
314 {
315     OIC_LOG(DEBUG, TAG, "IN");
316
317     if (NULL == uriInfo)
318     {
319         OIC_LOG(ERROR, TAG, "uriInfo is null");
320         return CA_STATUS_INVALID_PARAM;
321     }
322
323     OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);
324
325     if (NULL == optlist)
326     {
327         OIC_LOG(ERROR, TAG, "optlist is null");
328         return CA_STATUS_INVALID_PARAM;
329     }
330
331     /* split arg into Uri-* options */
332     coap_uri_t uri;
333     coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
334
335     if (uri.port != COAP_DEFAULT_PORT)
336     {
337         unsigned char portbuf[CA_PORT_BUFFER_SIZE] = { 0 };
338         int ret = coap_insert(optlist,
339                               CACreateNewOptionNode(COAP_OPTION_URI_PORT,
340                                                     coap_encode_var_bytes(portbuf, uri.port),
341                                                     (char *)portbuf),
342                               CAOrderOpts);
343         if (ret <= 0)
344         {
345             return CA_STATUS_INVALID_PARAM;
346         }
347     }
348
349     if (uri.path.s && uri.path.length)
350     {
351         CAResult_t ret = CAParseUriPartial(uri.path.s, uri.path.length,
352                                            COAP_OPTION_URI_PATH, optlist);
353         if (CA_STATUS_OK != ret)
354         {
355             OIC_LOG(ERROR, TAG, "CAParseUriPartial failed(uri path)");
356             return ret;
357         }
358     }
359
360     if (uri.query.s && uri.query.length)
361     {
362         CAResult_t ret = CAParseUriPartial(uri.query.s, uri.query.length, COAP_OPTION_URI_QUERY,
363                                            optlist);
364         if (CA_STATUS_OK != ret)
365         {
366             OIC_LOG(ERROR, TAG, "CAParseUriPartial failed(uri query)");
367             return ret;
368         }
369     }
370
371     OIC_LOG(DEBUG, TAG, "OUT");
372     return CA_STATUS_OK;
373 }
374
375 CAResult_t CAParseUriPartial(const unsigned char *str, size_t length, int target,
376                              coap_list_t **optlist)
377 {
378     if (!optlist)
379     {
380         OIC_LOG(ERROR, TAG, "optlist is null");
381         return CA_STATUS_INVALID_PARAM;
382     }
383
384     if ((target != COAP_OPTION_URI_PATH) && (target != COAP_OPTION_URI_QUERY))
385     {
386         // should never occur. Log just in case.
387         OIC_LOG(DEBUG, TAG, "Unexpected URI component.");
388         return CA_NOT_SUPPORTED;
389     }
390     else if (str && length)
391     {
392         unsigned char uriBuffer[CA_BUFSIZE] = { 0 };
393         unsigned char *pBuf = uriBuffer;
394         size_t buflen = sizeof(uriBuffer);
395         int res = (target == COAP_OPTION_URI_PATH) ? coap_split_path(str, length, pBuf, &buflen) :
396                                                      coap_split_query(str, length, pBuf, &buflen);
397
398         if (res > 0)
399         {
400             size_t prevIdx = 0;
401             while (res--)
402             {
403                 int ret = coap_insert(optlist,
404                                       CACreateNewOptionNode(target, COAP_OPT_LENGTH(pBuf),
405                                                             (char *)COAP_OPT_VALUE(pBuf)),
406                                       CAOrderOpts);
407                 if (ret <= 0)
408                 {
409                     return CA_STATUS_INVALID_PARAM;
410                 }
411
412                 size_t optSize = COAP_OPT_SIZE(pBuf);
413                 if ((prevIdx + optSize) < buflen)
414                 {
415                     pBuf += optSize;
416                     prevIdx += optSize;
417                 }
418             }
419         }
420         else
421         {
422             OIC_LOG_V(ERROR, TAG, "Problem parsing URI : %d for %d", res, target);
423             return CA_STATUS_FAILED;
424         }
425     }
426     else
427     {
428         OIC_LOG(ERROR, TAG, "str or length is not available");
429         return CA_STATUS_FAILED;
430     }
431
432     return CA_STATUS_OK;
433 }
434
435 CAResult_t CAParseHeadOption(uint32_t code, const CAInfo_t *info, coap_list_t **optlist)
436 {
437     (void)code;
438     OIC_LOG(DEBUG, TAG, "IN");
439     VERIFY_NON_NULL_RET(info, TAG, "info is NULL", CA_STATUS_INVALID_PARAM);
440
441     OIC_LOG_V(DEBUG, TAG, "parse Head Opt: %d", info->numOptions);
442
443     if (!optlist)
444     {
445         OIC_LOG(ERROR, TAG, "optlist is null");
446         return CA_STATUS_INVALID_PARAM;
447     }
448
449     for (uint32_t i = 0; i < info->numOptions; i++)
450     {
451         if(!(info->options + i))
452         {
453             OIC_LOG(ERROR, TAG, "options is not available");
454             return CA_STATUS_FAILED;
455         }
456
457         uint32_t id = (info->options + i)->optionID;
458         if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
459         {
460             OIC_LOG_V(DEBUG, TAG, "not Header Opt: %d", id);
461         }
462         else
463         {
464             if ((info->options + i)->optionData && (info->options + i)->optionLength > 0)
465             {
466                 OIC_LOG_V(DEBUG, TAG, "Head opt ID: %d", id);
467                 OIC_LOG_V(DEBUG, TAG, "Head opt data: %s", (info->options + i)->optionData);
468                 OIC_LOG_V(DEBUG, TAG, "Head opt length: %d", (info->options + i)->optionLength);
469                 int ret = coap_insert(optlist,
470                                       CACreateNewOptionNode(id, (info->options + i)->optionLength,
471                                                             (info->options + i)->optionData),
472                                       CAOrderOpts);
473                 if (ret <= 0)
474                 {
475                     return CA_STATUS_INVALID_PARAM;
476                 }
477             }
478         }
479     }
480
481     OIC_LOG(DEBUG, TAG, "OUT");
482     return CA_STATUS_OK;
483 }
484
485 coap_list_t *CACreateNewOptionNode(uint16_t key, uint32_t length, const char *data)
486 {
487     OIC_LOG(DEBUG, TAG, "IN");
488
489     if (!data)
490     {
491         OIC_LOG(ERROR, TAG, "invalid pointer parameter");
492         return NULL;
493     }
494
495     coap_option *option = coap_malloc(sizeof(coap_option) + length + 1);
496     if (!option)
497     {
498         OIC_LOG(ERROR, TAG, "Out of memory");
499         return NULL;
500     }
501     memset(option, 0, sizeof(coap_option) + length + 1);
502
503     COAP_OPTION_KEY(*option) = key;
504     COAP_OPTION_LENGTH(*option) = length;
505     memcpy(COAP_OPTION_DATA(*option), data, length);
506
507     /* we can pass NULL here as delete function since option is released automatically  */
508     coap_list_t *node = coap_new_listnode(option, NULL);
509
510     if (!node)
511     {
512         OIC_LOG(ERROR, TAG, "node is NULL");
513         coap_free(option);
514         return NULL;
515     }
516
517     OIC_LOG(DEBUG, TAG, "OUT");
518     return node;
519 }
520
521 int CAOrderOpts(void *a, void *b)
522 {
523     OIC_LOG(DEBUG, TAG, "IN");
524     if (!a || !b)
525     {
526         return a < b ? -1 : 1;
527     }
528
529     if (COAP_OPTION_KEY(*(coap_option *) a) < COAP_OPTION_KEY(*(coap_option * ) b))
530     {
531         return -1;
532     }
533
534     OIC_LOG(DEBUG, TAG, "OUT");
535     return COAP_OPTION_KEY(*(coap_option *) a) == COAP_OPTION_KEY(*(coap_option * ) b);
536 }
537
538 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
539 {
540     OIC_LOG(DEBUG, TAG, "IN");
541     uint32_t count = 0;
542     coap_opt_t *option;
543
544     while ((option = coap_option_next(&opt_iter)))
545     {
546         if (COAP_OPTION_URI_PATH != opt_iter.type && COAP_OPTION_URI_QUERY != opt_iter.type
547             && COAP_OPTION_BLOCK1 != opt_iter.type && COAP_OPTION_BLOCK2 != opt_iter.type
548             && COAP_OPTION_SIZE1 != opt_iter.type && COAP_OPTION_SIZE2 != opt_iter.type)
549         {
550             count++;
551         }
552     }
553
554     OIC_LOG(DEBUG, TAG, "OUT");
555     return count;
556 }
557
558 CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo)
559 {
560     OIC_LOG(DEBUG, TAG, "IN");
561
562     if (!pdu || !outCode || !outInfo)
563     {
564         OIC_LOG(ERROR, TAG, "NULL pointer param");
565         return CA_STATUS_INVALID_PARAM;
566     }
567
568     coap_opt_iterator_t opt_iter;
569     coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
570
571     if (outCode)
572     {
573         (*outCode) = (uint32_t) CA_RESPONSE_CODE(pdu->hdr->code);
574     }
575
576     // init HeaderOption list
577     uint32_t count = CAGetOptionCount(opt_iter);
578     memset(outInfo, 0, sizeof(*outInfo));
579
580     outInfo->numOptions = count;
581
582     // set type
583     outInfo->type = pdu->hdr->type;
584
585     // set message id
586     outInfo->messageId = pdu->hdr->id;
587
588     if (count > 0)
589     {
590         outInfo->options = (CAHeaderOption_t *) OICCalloc(count, sizeof(CAHeaderOption_t));
591         if (NULL == outInfo->options)
592         {
593             OIC_LOG(ERROR, TAG, "Out of memory");
594             return CA_MEMORY_ALLOC_FAILED;
595         }
596     }
597
598     coap_opt_t *option;
599     char optionResult[CA_MAX_URI_LENGTH] = {0};
600     uint32_t idx = 0;
601     uint32_t optionLength = 0;
602     bool isfirstsetflag = false;
603     bool isQueryBeingProcessed = false;
604
605     while ((option = coap_option_next(&opt_iter)))
606     {
607         char buf[COAP_MAX_PDU_SIZE] = {0};
608         if (CAGetOptionData((uint8_t *)(COAP_OPT_VALUE(option)),
609                             COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf)))
610         {
611             OIC_LOG_V(DEBUG, TAG, "COAP URI element : %s", buf);
612             uint32_t bufLength = strlen(buf);
613             if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
614             {
615                 if (false == isfirstsetflag)
616                 {
617                     isfirstsetflag = true;
618                     optionResult[optionLength] = '/';
619                     optionLength++;
620                     // Make sure there is enough room in the optionResult buffer
621                     if ((optionLength + bufLength) < sizeof(optionResult))
622                     {
623                         memcpy(&optionResult[optionLength], buf, bufLength);
624                         optionLength += bufLength;
625                     }
626                     else
627                     {
628                         goto exit;
629                     }
630                 }
631                 else
632                 {
633                     if (COAP_OPTION_URI_PATH == opt_iter.type)
634                     {
635                         // Make sure there is enough room in the optionResult buffer
636                         if (optionLength < sizeof(optionResult))
637                         {
638                             optionResult[optionLength] = '/';
639                             optionLength++;
640                         }
641                         else
642                         {
643                             goto exit;
644                         }
645                     }
646                     else if (COAP_OPTION_URI_QUERY == opt_iter.type)
647                     {
648                         if (false == isQueryBeingProcessed)
649                         {
650                             // Make sure there is enough room in the optionResult buffer
651                             if (optionLength < sizeof(optionResult))
652                             {
653                                 optionResult[optionLength] = '?';
654                                 optionLength++;
655                                 isQueryBeingProcessed = true;
656                             }
657                             else
658                             {
659                                 goto exit;
660                             }
661                         }
662                         else
663                         {
664                             // Make sure there is enough room in the optionResult buffer
665                             if (optionLength < sizeof(optionResult))
666                             {
667                                 optionResult[optionLength] = ';';
668                                 optionLength++;
669                             }
670                             else
671                             {
672                                 goto exit;
673                             }
674                         }
675                     }
676                     // Make sure there is enough room in the optionResult buffer
677                     if ((optionLength + bufLength) < sizeof(optionResult))
678                     {
679                         memcpy(&optionResult[optionLength], buf, bufLength);
680                         optionLength += bufLength;
681                     }
682                     else
683                     {
684                         goto exit;
685                     }
686                 }
687             }
688             else if (COAP_OPTION_BLOCK1 == opt_iter.type || COAP_OPTION_BLOCK2 == opt_iter.type
689                     || COAP_OPTION_SIZE1 == opt_iter.type || COAP_OPTION_SIZE2 == opt_iter.type)
690             {
691                 OIC_LOG_V(DEBUG, TAG, "option[%d] will be filtering", opt_iter.type);
692             }
693             else
694             {
695                 if (idx < count)
696                 {
697                     uint32_t length = bufLength;
698
699                     if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)
700                     {
701                         outInfo->options[idx].optionID = opt_iter.type;
702                         outInfo->options[idx].optionLength = length;
703                         outInfo->options[idx].protocolID = CA_COAP_ID;
704                         memcpy(outInfo->options[idx].optionData, buf, length);
705                         idx++;
706                     }
707                 }
708             }
709         }
710     }
711
712     // set token data
713     if (pdu->hdr->token_length > 0)
714     {
715         OIC_LOG_V(DEBUG, TAG, "inside token length : %d", pdu->hdr->token_length);
716         outInfo->token = (char *) OICMalloc(pdu->hdr->token_length);
717         if (NULL == outInfo->token)
718         {
719             OIC_LOG(ERROR, TAG, "Out of memory");
720             OICFree(outInfo->options);
721             return CA_MEMORY_ALLOC_FAILED;
722         }
723         memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length);
724     }
725
726     outInfo->tokenLength = pdu->hdr->token_length;
727
728     // set payload data
729     size_t dataSize;
730     uint8_t *data;
731     if (coap_get_data(pdu, &dataSize, &data))
732     {
733         OIC_LOG(DEBUG, TAG, "inside pdu->data");
734         outInfo->payload = (uint8_t *) OICMalloc(dataSize);
735         if (NULL == outInfo->payload)
736         {
737             OIC_LOG(ERROR, TAG, "Out of memory");
738             OICFree(outInfo->options);
739             OICFree(outInfo->token);
740             return CA_MEMORY_ALLOC_FAILED;
741         }
742         memcpy(outInfo->payload, pdu->data, dataSize);
743         outInfo->payloadSize = dataSize;
744     }
745
746     uint32_t length = strlen(optionResult);
747     OIC_LOG_V(DEBUG, TAG, "URL length:%d", length);
748
749     outInfo->resourceUri = OICMalloc(length + 1);
750     if (!outInfo->resourceUri)
751     {
752         OIC_LOG(ERROR, TAG, "Out of memory");
753         OICFree(outInfo->options);
754         OICFree(outInfo->token);
755         return CA_MEMORY_ALLOC_FAILED;
756     }
757     OICStrcpy(outInfo->resourceUri, length + 1, optionResult);
758     OIC_LOG_V(DEBUG, TAG, "made URL : %s, %s", optionResult, outInfo->resourceUri);
759
760     OIC_LOG(DEBUG, TAG, "OUT");
761     return CA_STATUS_OK;
762
763 exit:
764     OIC_LOG(ERROR, TAG, "buffer too small");
765     OICFree(outInfo->options);
766     return CA_STATUS_FAILED;
767 }
768
769 CAResult_t CAGetTokenFromPDU(const coap_hdr_t *pdu_hdr, CAInfo_t *outInfo)
770 {
771     OIC_LOG(DEBUG, TAG, "IN");
772     if (NULL == pdu_hdr)
773     {
774         OIC_LOG(ERROR, TAG, "pdu_hdr is null");
775         return CA_STATUS_INVALID_PARAM;
776     }
777
778     if (NULL == outInfo)
779     {
780         OIC_LOG(ERROR, TAG, "outInfo is null");
781         return CA_STATUS_INVALID_PARAM;
782     }
783
784     // set token data
785     if (pdu_hdr->token_length > 0)
786     {
787         OIC_LOG_V(DEBUG, TAG, "token len:%d", pdu_hdr->token_length);
788         outInfo->token = (char *) OICMalloc(pdu_hdr->token_length);
789         if (NULL == outInfo->token)
790         {
791             OIC_LOG(ERROR, TAG, "out of memory");
792             return CA_MEMORY_ALLOC_FAILED;
793         }
794         memcpy(outInfo->token, pdu_hdr->token, pdu_hdr->token_length);
795     }
796
797     outInfo->tokenLength = pdu_hdr->token_length;
798
799     OIC_LOG(DEBUG, TAG, "OUT");
800
801     return CA_STATUS_OK;
802 }
803
804 CAResult_t CAGenerateTokenInternal(CAToken_t *token, uint8_t tokenLength)
805 {
806     OIC_LOG(DEBUG, TAG, "IN");
807
808     if (!token)
809     {
810         OIC_LOG(ERROR, TAG, "invalid token pointer");
811         return CA_STATUS_INVALID_PARAM;
812     }
813
814     if ((tokenLength > CA_MAX_TOKEN_LEN) || (0 == tokenLength))
815     {
816         OIC_LOG(ERROR, TAG, "invalid token length");
817         return CA_STATUS_INVALID_PARAM;
818     }
819
820     if (SEED == 0)
821     {
822 #ifdef ARDUINO
823         SEED = now();
824 #else
825         SEED = time(NULL);
826 #endif
827         if (SEED == (unsigned int)((time_t)-1))
828         {
829             OIC_LOG(ERROR, TAG, "seed is not made");
830             SEED = 0;
831             return CA_STATUS_FAILED;
832         }
833 #if HAVE_SRANDOM
834         srandom(SEED);
835 #else
836         srand(SEED);
837 #endif
838     }
839
840     // memory allocation
841     char *temp = (char *) OICCalloc(tokenLength, sizeof(char));
842     if (NULL == temp)
843     {
844         OIC_LOG(ERROR, TAG, "Out of memory");
845         return CA_MEMORY_ALLOC_FAILED;
846     }
847
848     // set random byte
849     for (uint8_t index = 0; index < tokenLength; index++)
850     {
851         // use valid characters
852 #ifdef ARDUINO
853         temp[index] = rand() & 0x00FF;
854 #else
855         temp[index] = random() & 0x00FF;
856 #endif
857     }
858
859     // save token
860     *token = temp;
861
862     OIC_LOG_V(DEBUG, TAG, "token len:%d, token:", tokenLength);
863     OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *)(*token), tokenLength);
864
865     OIC_LOG(DEBUG, TAG, "OUT");
866     return CA_STATUS_OK;
867 }
868
869 void CADestroyTokenInternal(CAToken_t token)
870 {
871     OIC_LOG(DEBUG, TAG, "IN");
872     OICFree(token);
873     OIC_LOG(DEBUG, TAG, "OUT");
874 }
875
876 void CADestroyInfo(CAInfo_t *info)
877 {
878     OIC_LOG(DEBUG, TAG, "IN");
879
880     if (NULL != info)
881     {
882         OIC_LOG(DEBUG, TAG, "free options");
883         OICFree(info->options);
884
885         OIC_LOG(DEBUG, TAG, "free token");
886         OICFree(info->token);
887
888         OIC_LOG(DEBUG, TAG, "free payload");
889         OICFree(info->payload);
890     }
891
892     OIC_LOG(DEBUG, TAG, "OUT");
893 }
894
895 uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *option, uint32_t buflen)
896 {
897     if (0 == buflen || 0 == len)
898     {
899         OIC_LOG(ERROR, TAG, "len 0");
900         return 0;
901     }
902
903     if (NULL == data || NULL == option)
904     {
905         OIC_LOG(ERROR, TAG, "data/option NULL");
906         return 0;
907     }
908
909     if (buflen <= len)
910     {
911         OIC_LOG(ERROR, TAG, "option buffer too small");
912         return 0;
913     }
914
915     memcpy(option, data, len);
916     option[len] = '\0';
917
918     return len;
919 }
920
921 CAMessageType_t CAGetMessageTypeFromPduBinaryData(const void *pdu, uint32_t size)
922 {
923     if (NULL == pdu)
924     {
925         OIC_LOG(ERROR, TAG, "pdu is null");
926         return CA_MSG_NONCONFIRM;
927     }
928
929     // pdu minimum size is 4 byte.
930     if (size < CA_PDU_MIN_SIZE)
931     {
932         OIC_LOG(ERROR, TAG, "min size");
933         return CA_MSG_NONCONFIRM;
934     }
935
936     coap_hdr_t *hdr = (coap_hdr_t *) pdu;
937
938     return (CAMessageType_t) hdr->type;
939 }
940
941 uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)
942 {
943     if (NULL == pdu)
944     {
945         OIC_LOG(ERROR, TAG, "pdu is null");
946         return 0;
947     }
948
949     // pdu minimum size is 4 byte.
950     if (size < CA_PDU_MIN_SIZE)
951     {
952         OIC_LOG(ERROR, TAG, "min size");
953         return 0;
954     }
955
956     coap_hdr_t *hdr = (coap_hdr_t *) pdu;
957
958     return hdr->id;
959 }
960
961 CAResponseResult_t CAGetCodeFromPduBinaryData(const void *pdu, uint32_t size)
962 {
963     if (NULL == pdu)
964     {
965         OIC_LOG(ERROR, TAG, "pdu is null");
966         return CA_NOT_FOUND;
967     }
968
969     // pdu minimum size is 4 byte.
970     if (size < CA_PDU_MIN_SIZE)
971     {
972         OIC_LOG(ERROR, TAG, "min size");
973         return CA_NOT_FOUND;
974     }
975
976     coap_hdr_t *hdr = (coap_hdr_t *) pdu;
977
978     return (CAResponseResult_t) CA_RESPONSE_CODE(hdr->code);
979 }