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