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