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