fedc0de4e54f25dbfc3008696d8eae01f4de7f56
[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 files from the arduino platform do not provide these conversions:
34 #ifdef ARDUINO
35 #define htons(x) ( ((x)<< 8 & 0xFF00) | ((x)>> 8 & 0x00FF) )
36 #define ntohs(x) htons(x)
37 #else
38 #define HAVE_TIME_H 1
39 #endif
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <stdbool.h>
45 #ifdef HAVE_TIME_H
46 #include <time.h>
47 #endif
48
49 #include "caprotocolmessage.h"
50 #include "logger.h"
51 #include "oic_malloc.h"
52 #include "oic_string.h"
53
54 // ARM GCC compiler doesnt define srandom function.
55 #if defined(ARDUINO) && !defined(ARDUINO_ARCH_SAM)
56 #define HAVE_SRANDOM 1
57 #endif
58
59 #define TAG "CA"
60
61 #define CA_BUFSIZE (128)
62 #define CA_PDU_MIN_SIZE (4)
63 #define CA_PORT_BUFFER_SIZE (4)
64
65 static const char COAP_URI_HEADER[] = "coap://[::]/";
66
67 static uint32_t SEED = 0;
68
69 CAResult_t CAGetRequestInfoFromPDU(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo,
70                                    char *outUri, uint32_t buflen)
71 {
72     OIC_LOG(DEBUG, TAG, "IN");
73
74     if (NULL == pdu || NULL == outReqInfo || NULL == outUri)
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
82     OIC_LOG_V(DEBUG, TAG, "buffer length : %d", buflen);
83     CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &(outReqInfo->info), outUri, buflen);
84     outReqInfo->method = code;
85     OIC_LOG(DEBUG, TAG, "OUT");
86     return ret;
87 }
88
89 CAResult_t CAGetResponseInfoFromPDU(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo,
90                                     char *outUri, uint32_t buflen)
91 {
92     OIC_LOG(DEBUG, TAG, "IN");
93
94     if (NULL == pdu || NULL == outResInfo || NULL == outUri)
95     {
96         OIC_LOG(ERROR, TAG, "parameter is null");
97         return CA_STATUS_INVALID_PARAM;
98     }
99
100     uint32_t code = CA_NOT_FOUND;
101     CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &(outResInfo->info), outUri, buflen);
102     outResInfo->result = code;
103     OIC_LOG(DEBUG, TAG, "OUT");
104     return ret;
105 }
106
107 CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, CAErrorInfo_t *errorInfo,
108                                  char *uri, uint32_t buflen)
109 {
110     OIC_LOG(DEBUG, TAG, "IN");
111
112     if (!pdu || !errorInfo || !uri)
113     {
114         OIC_LOG(ERROR, TAG, "parameter is null");
115         return CA_STATUS_INVALID_PARAM;
116     }
117
118     uint32_t code = 0;
119     CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &errorInfo->info, uri, buflen);
120     OIC_LOG(DEBUG, TAG, "OUT");
121     return ret;
122 }
123
124 coap_pdu_t *CAGeneratePDU(const char *uri, uint32_t code, const CAInfo_t info)
125 {
126     OIC_LOG(DEBUG, TAG, "IN");
127
128     coap_pdu_t *pdu = NULL;
129
130     // RESET have to use only 4byte (empty message)
131     // and ACKNOWLEDGE can use empty message when code is empty.
132     if (CA_MSG_RESET == info.type || (CA_EMPTY == code && CA_MSG_ACKNOWLEDGE == info.type))
133     {
134         OIC_LOG(DEBUG, TAG, "code is empty");
135         if (!(pdu = CAGeneratePDUImpl((code_t) code, NULL, info, NULL, 0)))
136         {
137             OIC_LOG(ERROR, TAG, "pdu NULL");
138             return NULL;
139         }
140     }
141     else
142     {
143         coap_list_t *optlist = NULL;
144
145         if (CA_MSG_ACKNOWLEDGE != info.type)
146         {
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
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         OIC_LOG_V(DEBUG, TAG, "add data, payload:%s", payload);
303         coap_add_data(pdu, payloadSize, (const unsigned char *) payload);
304     }
305
306     OIC_LOG(DEBUG, TAG, "OUT");
307     return pdu;
308 }
309
310 CAResult_t CAParseURI(const char *uriInfo, coap_list_t **optlist)
311 {
312     OIC_LOG(DEBUG, TAG, "IN");
313
314     if (NULL == uriInfo)
315     {
316         OIC_LOG(ERROR, TAG, "uriInfo is null");
317         return CA_STATUS_INVALID_PARAM;
318     }
319
320     OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);
321
322     if (NULL == optlist)
323     {
324         OIC_LOG(ERROR, TAG, "optlist is null");
325         return CA_STATUS_INVALID_PARAM;
326     }
327
328     /* split arg into Uri-* options */
329     coap_uri_t uri;
330     coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
331
332     if (uri.port != COAP_DEFAULT_PORT)
333     {
334         unsigned char portbuf[CA_PORT_BUFFER_SIZE] = { 0 };
335         int ret = coap_insert(optlist,
336                               CACreateNewOptionNode(COAP_OPTION_URI_PORT,
337                                                     coap_encode_var_bytes(portbuf, uri.port),
338                                                     portbuf),
339                               CAOrderOpts);
340         if (ret <= 0)
341         {
342             return CA_STATUS_INVALID_PARAM;
343         }
344     }
345
346     if (uri.path.s && uri.path.length)
347     {
348         CAResult_t ret = CAParseUriPartial(uri.path.s, uri.path.length, COAP_OPTION_URI_PATH,
349                                            optlist);
350         if (CA_STATUS_OK != ret)
351         {
352             OIC_LOG(ERROR, TAG, "CAParseUriPartial failed(uri path)");
353             return ret;
354         }
355     }
356
357     if (uri.query.s && uri.query.length)
358     {
359         CAResult_t ret = CAParseUriPartial(uri.query.s, uri.query.length, COAP_OPTION_URI_QUERY,
360                                            optlist);
361         if (CA_STATUS_OK != ret)
362         {
363             OIC_LOG(ERROR, TAG, "CAParseUriPartial failed(uri query)");
364             return ret;
365         }
366     }
367
368     OIC_LOG(DEBUG, TAG, "OUT");
369     return CA_STATUS_OK;
370 }
371
372 CAResult_t CAParseUriPartial(const unsigned char *str, size_t length, int target,
373                              coap_list_t **optlist)
374 {
375     if (!optlist)
376     {
377         OIC_LOG(ERROR, TAG, "optlist is null");
378         return CA_STATUS_INVALID_PARAM;
379     }
380
381     if ((target != COAP_OPTION_URI_PATH) && (target != COAP_OPTION_URI_QUERY))
382     {
383         // should never occur. Log just in case.
384         OIC_LOG(DEBUG, TAG, "Unexpected URI component.");
385         return CA_NOT_SUPPORTED;
386     }
387     else if (str && length)
388     {
389         unsigned char uriBuffer[CA_BUFSIZE] = { 0 };
390         unsigned char *pBuf = uriBuffer;
391         size_t buflen = sizeof(uriBuffer);
392         int res = (target == COAP_OPTION_URI_PATH) ? coap_split_path(str, length, pBuf, &buflen) :
393                                                      coap_split_query(str, length, pBuf, &buflen);
394
395         if (res > 0)
396         {
397             size_t prevIdx = 0;
398             while (res--)
399             {
400                 int ret = coap_insert(optlist,
401                                       CACreateNewOptionNode(target, COAP_OPT_LENGTH(pBuf),
402                                                             COAP_OPT_VALUE(pBuf)),
403                                       CAOrderOpts);
404                 if (ret <= 0)
405                 {
406                     return CA_STATUS_INVALID_PARAM;
407                 }
408
409                 size_t optSize = COAP_OPT_SIZE(pBuf);
410                 if ((prevIdx + optSize) < buflen)
411                 {
412                     pBuf += optSize;
413                     prevIdx += optSize;
414                 }
415             }
416         }
417         else
418         {
419             OIC_LOG_V(ERROR, TAG, "Problem parsing URI : %d for %d", res, target);
420             return CA_STATUS_FAILED;
421         }
422     }
423     else
424     {
425         OIC_LOG(ERROR, TAG, "str or length is not available");
426         return CA_STATUS_FAILED;
427     }
428
429     return CA_STATUS_OK;
430 }
431
432 CAResult_t CAParseHeadOption(uint32_t code, const CAInfo_t info, coap_list_t **optlist)
433 {
434     OIC_LOG(DEBUG, TAG, "IN");
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 uint8_t *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                             char *outUri, uint32_t buflen)
553 {
554     OIC_LOG(DEBUG, TAG, "IN");
555
556     if (!pdu || !outCode || !outInfo || !outUri)
557     {
558         OIC_LOG(ERROR, TAG, "NULL pointer param");
559         return CA_STATUS_INVALID_PARAM;
560     }
561
562     coap_opt_iterator_t opt_iter;
563     coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
564
565     if (outCode)
566     {
567         (*outCode) = (uint32_t) CA_RESPONSE_CODE(pdu->hdr->code);
568     }
569
570     // init HeaderOption list
571     uint32_t count = CAGetOptionCount(opt_iter);
572     memset(outInfo, 0, sizeof(*outInfo));
573
574     outInfo->numOptions = count;
575
576     // set type
577     outInfo->type = pdu->hdr->type;
578
579     // set message id
580     outInfo->messageId = pdu->hdr->id;
581
582     if (count > 0)
583     {
584         outInfo->options = (CAHeaderOption_t *) OICCalloc(count, sizeof(CAHeaderOption_t));
585         if (NULL == outInfo->options)
586         {
587             OIC_LOG(ERROR, TAG, "Out of memory");
588             return CA_MEMORY_ALLOC_FAILED;
589         }
590     }
591
592     coap_opt_t *option;
593     char optionResult[CA_MAX_URI_LENGTH] = {0};
594     uint32_t idx = 0;
595     uint32_t optionLength = 0;
596     bool isfirstsetflag = false;
597     bool isQueryBeingProcessed = false;
598
599     while ((option = coap_option_next(&opt_iter)))
600     {
601         char buf[COAP_MAX_PDU_SIZE] = {0};
602         if (CAGetOptionData((uint8_t *)(COAP_OPT_VALUE(option)),
603                             COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf)))
604         {
605             OIC_LOG_V(DEBUG, TAG, "COAP URI element : %s", buf);
606             uint32_t bufLength = strlen(buf);
607             if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
608             {
609                 if (false == isfirstsetflag)
610                 {
611                     isfirstsetflag = true;
612                     optionResult[optionLength] = '/';
613                     optionLength++;
614                     // Make sure there is enough room in the optionResult buffer
615                     if ((optionLength + bufLength) < sizeof(optionResult))
616                     {
617                         memcpy(&optionResult[optionLength], buf, bufLength);
618                         optionLength += bufLength;
619                     }
620                     else
621                     {
622                         goto exit;
623                     }
624                 }
625                 else
626                 {
627                     if (COAP_OPTION_URI_PATH == opt_iter.type)
628                     {
629                         // Make sure there is enough room in the optionResult buffer
630                         if (optionLength < sizeof(optionResult))
631                         {
632                             optionResult[optionLength] = '/';
633                             optionLength++;
634                         }
635                         else
636                         {
637                             goto exit;
638                         }
639                     }
640                     else if (COAP_OPTION_URI_QUERY == opt_iter.type)
641                     {
642                         if (false == isQueryBeingProcessed)
643                         {
644                             // Make sure there is enough room in the optionResult buffer
645                             if (optionLength < sizeof(optionResult))
646                             {
647                                 optionResult[optionLength] = '?';
648                                 optionLength++;
649                                 isQueryBeingProcessed = true;
650                             }
651                             else
652                             {
653                                 goto exit;
654                             }
655                         }
656                         else
657                         {
658                             // Make sure there is enough room in the optionResult buffer
659                             if (optionLength < sizeof(optionResult))
660                             {
661                                 optionResult[optionLength] = ';';
662                                 optionLength++;
663                             }
664                             else
665                             {
666                                 goto exit;
667                             }
668                         }
669                     }
670                     // Make sure there is enough room in the optionResult buffer
671                     if ((optionLength + bufLength) < sizeof(optionResult))
672                     {
673                         memcpy(&optionResult[optionLength], buf, bufLength);
674                         optionLength += bufLength;
675                     }
676                     else
677                     {
678                         goto exit;
679                     }
680                 }
681             }
682             else
683             {
684                 if (idx < count)
685                 {
686                     uint32_t length = bufLength;
687
688                     if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)
689                     {
690                         outInfo->options[idx].optionID = opt_iter.type;
691                         outInfo->options[idx].optionLength = length;
692                         outInfo->options[idx].protocolID = CA_COAP_ID;
693                         memcpy(outInfo->options[idx].optionData, buf, length);
694                         idx++;
695                     }
696                 }
697             }
698         }
699     }
700
701     // set token data
702     if (pdu->hdr->token_length > 0)
703     {
704         OIC_LOG_V(DEBUG, TAG, "inside token length : %d", pdu->hdr->token_length);
705         outInfo->token = (char *) OICMalloc(pdu->hdr->token_length);
706         if (NULL == outInfo->token)
707         {
708             OIC_LOG(ERROR, TAG, "Out of memory");
709             OICFree(outInfo->options);
710             return CA_MEMORY_ALLOC_FAILED;
711         }
712         memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length);
713     }
714
715     outInfo->tokenLength = pdu->hdr->token_length;
716
717     // set payload data
718     if (NULL != pdu->data)
719     {
720         uint32_t payloadLength = strlen((char*) pdu->data);
721         OIC_LOG(DEBUG, TAG, "inside pdu->data");
722         outInfo->payload = (char *) OICMalloc(payloadLength + 1);
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, payloadLength);
731         outInfo->payload[payloadLength] = '\0';
732     }
733
734     uint32_t length = strlen(optionResult);
735     OIC_LOG_V(DEBUG, TAG, "URL length:%d,%d,%d", length, buflen, strlen(outUri));
736     if (buflen >= length)
737     {
738         memcpy(outUri, optionResult, length);
739 #ifdef ARDUINO
740         OIC_LOG_V(DEBUG, TAG, "made URL:%s\n", optionResult);
741 #else
742         OIC_LOG_V(DEBUG, TAG, "made URL : %s, %s", optionResult, outUri);
743 #endif
744     }
745     OIC_LOG(DEBUG, TAG, "OUT");
746     return CA_STATUS_OK;
747
748 exit:
749     OIC_LOG(ERROR, TAG, "buffer too small");
750     OICFree(outInfo->options);
751     return CA_STATUS_FAILED;
752 }
753
754 CAResult_t CAGetTokenFromPDU(const coap_hdr_t *pdu_hdr, CAInfo_t *outInfo)
755 {
756     OIC_LOG(DEBUG, TAG, "IN");
757     if (NULL == pdu_hdr)
758     {
759         OIC_LOG(ERROR, TAG, "pdu_hdr is null");
760         return CA_STATUS_INVALID_PARAM;
761     }
762
763     if (NULL == outInfo)
764     {
765         OIC_LOG(ERROR, TAG, "outInfo is null");
766         return CA_STATUS_INVALID_PARAM;
767     }
768
769     // set token data
770     if (pdu_hdr->token_length > 0)
771     {
772         OIC_LOG_V(DEBUG, TAG, "token len:%d", pdu_hdr->token_length);
773         outInfo->token = (char *) OICMalloc(pdu_hdr->token_length);
774         if (NULL == outInfo->token)
775         {
776             OIC_LOG(ERROR, TAG, "out of memory");
777             return CA_MEMORY_ALLOC_FAILED;
778         }
779         memcpy(outInfo->token, pdu_hdr->token, pdu_hdr->token_length);
780     }
781
782     outInfo->tokenLength = pdu_hdr->token_length;
783
784     OIC_LOG(DEBUG, TAG, "OUT");
785
786     return CA_STATUS_OK;
787 }
788
789 CAResult_t CAGenerateTokenInternal(CAToken_t *token, uint8_t tokenLength)
790 {
791     OIC_LOG(DEBUG, TAG, "IN");
792
793     if (!token)
794     {
795         OIC_LOG(ERROR, TAG, "invalid token pointer");
796         return CA_STATUS_INVALID_PARAM;
797     }
798
799     if ((tokenLength > CA_MAX_TOKEN_LEN) || (0 == tokenLength))
800     {
801         OIC_LOG(ERROR, TAG, "invalid token length");
802         return CA_STATUS_INVALID_PARAM;
803     }
804
805     if (SEED == 0)
806     {
807 #ifdef ARDUINO
808         SEED = now();
809 #else
810         SEED = time(NULL);
811 #endif
812         if (SEED == -1)
813         {
814             OIC_LOG(ERROR, TAG, "seed is not made");
815             SEED = 0;
816             return CA_STATUS_FAILED;
817         }
818 #if HAVE_SRANDOM
819         srandom(SEED);
820 #else
821         srand(SEED);
822 #endif
823     }
824
825     // memory allocation
826     char *temp = (char *) OICCalloc(tokenLength, sizeof(char));
827     if (NULL == temp)
828     {
829         OIC_LOG(ERROR, TAG, "Out of memory");
830         return CA_MEMORY_ALLOC_FAILED;
831     }
832
833     // set random byte
834     for (uint8_t index = 0; index < tokenLength; index++)
835     {
836         // use valid characters
837 #ifdef ARDUINO
838         temp[index] = rand() & 0x00FF;
839 #else
840         temp[index] = random() & 0x00FF;
841 #endif
842     }
843
844     // save token
845     *token = temp;
846
847     OIC_LOG_V(DEBUG, TAG, "token len:%d, token:", tokenLength);
848     OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *)(*token), tokenLength);
849
850     OIC_LOG(DEBUG, TAG, "OUT");
851     return CA_STATUS_OK;
852 }
853
854 void CADestroyTokenInternal(CAToken_t token)
855 {
856     OIC_LOG(DEBUG, TAG, "IN");
857     OICFree(token);
858     OIC_LOG(DEBUG, TAG, "OUT");
859 }
860
861 void CADestroyInfo(CAInfo_t *info)
862 {
863     OIC_LOG(DEBUG, TAG, "IN");
864
865     if (NULL != info)
866     {
867         OIC_LOG(DEBUG, TAG, "free options");
868         OICFree(info->options);
869
870         OIC_LOG(DEBUG, TAG, "free token");
871         OICFree(info->token);
872
873         OIC_LOG(DEBUG, TAG, "free payload");
874         OICFree(info->payload);
875     }
876
877     OIC_LOG(DEBUG, TAG, "OUT");
878 }
879
880 uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *option, uint32_t buflen)
881 {
882     if (0 == buflen || 0 == len)
883     {
884         OIC_LOG(ERROR, TAG, "len 0");
885         return 0;
886     }
887
888     if (NULL == data || NULL == option)
889     {
890         OIC_LOG(ERROR, TAG, "data/option NULL");
891         return 0;
892     }
893
894     if (buflen <= len)
895     {
896         OIC_LOG(ERROR, TAG, "option buffer too small");
897         return 0;
898     }
899
900     memcpy(option, data, len);
901     option[len] = '\0';
902
903     return len;
904 }
905
906 CAMessageType_t CAGetMessageTypeFromPduBinaryData(const void *pdu, uint32_t size)
907 {
908     if (NULL == pdu)
909     {
910         OIC_LOG(ERROR, TAG, "pdu is null");
911         return CA_MSG_NONCONFIRM;
912     }
913
914     // pdu minimum size is 4 byte.
915     if (size < CA_PDU_MIN_SIZE)
916     {
917         OIC_LOG(ERROR, TAG, "min size");
918         return CA_MSG_NONCONFIRM;
919     }
920
921     coap_hdr_t *hdr = (coap_hdr_t *) pdu;
922
923     return (CAMessageType_t) hdr->type;
924 }
925
926 uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)
927 {
928     if (NULL == pdu)
929     {
930         OIC_LOG(ERROR, TAG, "pdu is null");
931         return 0;
932     }
933
934     // pdu minimum size is 4 byte.
935     if (size < CA_PDU_MIN_SIZE)
936     {
937         OIC_LOG(ERROR, TAG, "min size");
938         return 0;
939     }
940
941     coap_hdr_t *hdr = (coap_hdr_t *) pdu;
942
943     return hdr->id;
944 }
945
946 CAResponseResult_t CAGetCodeFromPduBinaryData(const void *pdu, uint32_t size)
947 {
948     if (NULL == pdu)
949     {
950         OIC_LOG(ERROR, TAG, "pdu is null");
951         return CA_NOT_FOUND;
952     }
953
954     // pdu minimum size is 4 byte.
955     if (size < CA_PDU_MIN_SIZE)
956     {
957         OIC_LOG(ERROR, TAG, "min size");
958         return CA_NOT_FOUND;
959     }
960
961     coap_hdr_t *hdr = (coap_hdr_t *) pdu;
962
963     return (CAResponseResult_t) CA_RESPONSE_CODE(hdr->code);
964 }