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