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