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