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