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 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
53 // ARM GCC compiler doesnt define srandom function.
54 #if defined(ARDUINO) && !defined(ARDUINO_ARCH_SAM)
55 #define HAVE_SRANDOM 1
56 #endif
57
58 #define TAG "CA"
59
60 #define CA_BUFSIZE (128)
61 #define CA_PDU_MIN_SIZE (4)
62 #define CA_PORT_BUFFER_SIZE (4)
63
64 static const char COAP_URI_HEADER[] = "coap://[::]/";
65
66 static uint32_t SEED = 0;
67
68 CAResult_t CAGetRequestInfoFromPDU(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo,
69                                    char *outUri, uint32_t buflen)
70 {
71     OIC_LOG(DEBUG, TAG, "IN");
72
73     if (NULL == pdu || NULL == outReqInfo || NULL == outUri)
74     {
75         OIC_LOG(ERROR, TAG, "parameter is null");
76         return CA_STATUS_INVALID_PARAM;
77     }
78
79     uint32_t code = CA_NOT_FOUND;
80
81     OIC_LOG_V(DEBUG, TAG, "buffer length : %d", buflen);
82     CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &(outReqInfo->info), outUri, buflen);
83     outReqInfo->method = code;
84     OIC_LOG(DEBUG, TAG, "OUT");
85     return ret;
86 }
87
88 CAResult_t CAGetResponseInfoFromPDU(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo,
89                                     char *outUri, uint32_t buflen)
90 {
91     OIC_LOG(DEBUG, TAG, "IN");
92
93     if (NULL == pdu || NULL == outResInfo || NULL == outUri)
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), outUri, buflen);
101     outResInfo->result = code;
102     OIC_LOG(DEBUG, TAG, "OUT");
103     return ret;
104 }
105
106 CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, CAErrorInfo_t *errorInfo,
107                                  char *uri, uint32_t buflen)
108 {
109     OIC_LOG(DEBUG, TAG, "IN");
110
111     if (!pdu || !errorInfo || !uri)
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, uri, buflen);
119     OIC_LOG(DEBUG, TAG, "OUT");
120     return ret;
121 }
122
123 coap_pdu_t *CAGeneratePDU(const char *uri, 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             if (NULL == uri)
147             {
148                 OIC_LOG(ERROR, TAG, "uri NULL");
149                 return NULL;
150             }
151
152             uint32_t length = strlen(uri);
153             if (CA_MAX_URI_LENGTH < length)
154             {
155                 OIC_LOG(ERROR, TAG, "URI len err");
156                 return NULL;
157             }
158
159             uint32_t uriLength = length + sizeof(COAP_URI_HEADER);
160             char *coapUri = (char *) OICCalloc(1, uriLength);
161             if (NULL == coapUri)
162             {
163                 OIC_LOG(ERROR, TAG, "out of memory");
164                 return NULL;
165             }
166             strcat(coapUri, COAP_URI_HEADER);
167             strcat(coapUri, uri);
168
169             // parsing options in URI
170             CAResult_t res = CAParseURI(coapUri, &optlist);
171             if (CA_STATUS_OK != res)
172             {
173                 if (optlist)
174                 {
175                     coap_delete_list(optlist);
176                 }
177                 OICFree(coapUri);
178                 return NULL;
179             }
180
181             OICFree(coapUri);
182         }
183         // parsing options in HeadOption
184         CAResult_t ret = CAParseHeadOption(code, info, &optlist);
185         if (CA_STATUS_OK != ret)
186         {
187             coap_delete_list(optlist);
188             return NULL;
189         }
190         size_t lenPayload = info.payload ? strlen(info.payload) : 0;
191         pdu = CAGeneratePDUImpl((code_t) code, optlist, info, info.payload, lenPayload);
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 char *payload, size_t payloadSize)
243 {
244     OIC_LOG(DEBUG, TAG, "IN");
245
246     coap_pdu_t *pdu = coap_new_pdu();
247
248     if (NULL == pdu)
249     {
250         OIC_LOG(ERROR, TAG, "malloc failed");
251         return NULL;
252     }
253
254     OIC_LOG_V(DEBUG, TAG, "msgID is %d", info.messageId);
255     uint16_t message_id;
256     if (0 == info.messageId)
257     {
258         /* initialize message id */
259         prng((uint8_t * ) &message_id, sizeof(message_id));
260
261         OIC_LOG_V(DEBUG, TAG, "gen msg id=%d", message_id);
262     }
263     else
264     {
265         /* use saved message id */
266         message_id = info.messageId;
267     }
268     pdu->hdr->id = message_id;
269     OIC_LOG_V(DEBUG, TAG, "messageId in pdu is %d, %d", message_id, pdu->hdr->id);
270
271     pdu->hdr->type = info.type;
272     pdu->hdr->code = COAP_RESPONSE_CODE(code);
273
274     if (info.token && CA_EMPTY != code)
275     {
276         uint32_t tokenLength = info.tokenLength;
277         OIC_LOG_V(DEBUG, TAG, "token info token length: %d, token :", tokenLength);
278         OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *)info.token, tokenLength);
279
280         int32_t ret = coap_add_token(pdu, tokenLength, (unsigned char *) info.token);
281         if (0 == ret)
282         {
283             OIC_LOG(ERROR, TAG, "can't add token");
284         }
285     }
286
287     if (options)
288     {
289         for (coap_list_t *opt = options; opt; opt = opt->next)
290         {
291             OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.",
292                       COAP_OPTION_DATA(*(coap_option *) opt->data));
293             coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
294                             COAP_OPTION_LENGTH(*(coap_option *) opt->data),
295                             COAP_OPTION_DATA(*(coap_option *) opt->data));
296         }
297     }
298
299     if (NULL != payload)
300     {
301         OIC_LOG_V(DEBUG, TAG, "add data, payload:%s", payload);
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                                                     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, COAP_OPTION_URI_PATH,
348                                            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                                                             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
435     OIC_LOG_V(DEBUG, TAG, "parse Head Opt: %d", info.numOptions);
436
437     if (!optlist)
438     {
439         OIC_LOG(ERROR, TAG, "optlist is null");
440         return CA_STATUS_INVALID_PARAM;
441     }
442
443     for (uint32_t i = 0; i < info.numOptions; i++)
444     {
445         if(!(info.options + i))
446         {
447             OIC_LOG(ERROR, TAG, "options is not available");
448             return CA_STATUS_FAILED;
449         }
450
451         uint32_t id = (info.options + i)->optionID;
452         if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
453         {
454             OIC_LOG_V(DEBUG, TAG, "not Header Opt: %d", id);
455         }
456         else
457         {
458             if ((info.options + i)->optionData && (info.options + i)->optionLength > 0)
459             {
460                 OIC_LOG_V(DEBUG, TAG, "Head opt ID: %d", id);
461                 OIC_LOG_V(DEBUG, TAG, "Head opt data: %s", (info.options + i)->optionData);
462                 OIC_LOG_V(DEBUG, TAG, "Head opt length: %d", (info.options + i)->optionLength);
463                 int ret = coap_insert(optlist,
464                                       CACreateNewOptionNode(id, (info.options + i)->optionLength,
465                                                             (info.options + i)->optionData),
466                                       CAOrderOpts);
467                 if (ret <= 0)
468                 {
469                     return CA_STATUS_INVALID_PARAM;
470                 }
471             }
472         }
473     }
474
475     OIC_LOG(DEBUG, TAG, "OUT");
476     return CA_STATUS_OK;
477 }
478
479 coap_list_t *CACreateNewOptionNode(uint16_t key, uint32_t length, const uint8_t *data)
480 {
481     OIC_LOG(DEBUG, TAG, "IN");
482
483     if (!data)
484     {
485         OIC_LOG(ERROR, TAG, "invalid pointer parameter");
486         return NULL;
487     }
488
489     coap_option *option = coap_malloc(sizeof(coap_option) + length + 1);
490     if (!option)
491     {
492         OIC_LOG(ERROR, TAG, "Out of memory");
493         return NULL;
494     }
495     memset(option, 0, sizeof(coap_option) + length + 1);
496
497     COAP_OPTION_KEY(*option) = key;
498     COAP_OPTION_LENGTH(*option) = length;
499     memcpy(COAP_OPTION_DATA(*option), data, length);
500
501     /* we can pass NULL here as delete function since option is released automatically  */
502     coap_list_t *node = coap_new_listnode(option, NULL);
503
504     if (!node)
505     {
506         OIC_LOG(ERROR, TAG, "node is NULL");
507         coap_free(option);
508         return NULL;
509     }
510
511     OIC_LOG(DEBUG, TAG, "OUT");
512     return node;
513 }
514
515 int CAOrderOpts(void *a, void *b)
516 {
517     OIC_LOG(DEBUG, TAG, "IN");
518     if (!a || !b)
519     {
520         return a < b ? -1 : 1;
521     }
522
523     if (COAP_OPTION_KEY(*(coap_option *) a) < COAP_OPTION_KEY(*(coap_option * ) b))
524     {
525         return -1;
526     }
527
528     OIC_LOG(DEBUG, TAG, "OUT");
529     return COAP_OPTION_KEY(*(coap_option *) a) == COAP_OPTION_KEY(*(coap_option * ) b);
530 }
531
532 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
533 {
534     OIC_LOG(DEBUG, TAG, "IN");
535     uint32_t count = 0;
536     coap_opt_t *option;
537
538     while ((option = coap_option_next(&opt_iter)))
539     {
540         if (COAP_OPTION_URI_PATH != opt_iter.type && COAP_OPTION_URI_QUERY != opt_iter.type)
541         {
542             count++;
543         }
544     }
545
546     OIC_LOG(DEBUG, TAG, "OUT");
547     return count;
548 }
549
550 CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo,
551                             char *outUri, uint32_t buflen)
552 {
553     OIC_LOG(DEBUG, TAG, "IN");
554
555     if (!pdu || !outCode || !outInfo || !outUri)
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     if (NULL != pdu->data)
718     {
719         uint32_t payloadLength = strlen((char*) pdu->data);
720         OIC_LOG(DEBUG, TAG, "inside pdu->data");
721         outInfo->payload = (char *) OICMalloc(payloadLength + 1);
722         if (NULL == outInfo->payload)
723         {
724             OIC_LOG(ERROR, TAG, "Out of memory");
725             OICFree(outInfo->options);
726             OICFree(outInfo->token);
727             return CA_MEMORY_ALLOC_FAILED;
728         }
729         memcpy(outInfo->payload, pdu->data, payloadLength);
730         outInfo->payload[payloadLength] = '\0';
731     }
732
733     uint32_t length = strlen(optionResult);
734     OIC_LOG_V(DEBUG, TAG, "URL length:%d,%d,%d", length, buflen, strlen(outUri));
735     if (buflen >= length)
736     {
737         memcpy(outUri, optionResult, length);
738         outUri[length] = '\0';
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 }