52215491ed662623e8f3430bf4bcd255597adbca
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / caprotocolmessage.c
1 /******************************************************************\r
2  *\r
3  * Copyright 2014 Samsung Electronics All Rights Reserved.\r
4  *\r
5  *\r
6  *\r
7  * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * you may not use this file except in compliance with the License.\r
9  * You may obtain a copy of the License at\r
10  *\r
11  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * Unless required by applicable law or agreed to in writing, software\r
14  * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * See the License for the specific language governing permissions and\r
17  * limitations under the License.\r
18  *\r
19  ******************************************************************/\r
20 \r
21 #include <stdio.h>\r
22 #include <stdlib.h>\r
23 #include <string.h>\r
24 #include <time.h>\r
25 \r
26 #include "caprotocolmessage.h"\r
27 #include "logger.h"\r
28 #include "oic_malloc.h"\r
29 \r
30 #define TAG "CA"\r
31 \r
32 #define CA_MAX_TOKEN_LEN   (8)\r
33 #define CA_FLAGS_BLOCK 0x01\r
34 #define CA_BUFSIZE 128\r
35 #define CA_COAP_MESSAGE_CON 0\r
36 \r
37 static int32_t SEED = 0;\r
38 \r
39 uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo,\r
40                                  char *outUri)\r
41 {\r
42     OIC_LOG(DEBUG, TAG, "CAGetRequestInfoFromPdu IN");\r
43 \r
44     if (NULL == pdu)\r
45         return 0;\r
46 \r
47     uint32_t code = CA_NOT_FOUND;\r
48     CAGetRequestPDUInfo(pdu, &code, &(outReqInfo->info), outUri);\r
49     outReqInfo->method = code;\r
50     OIC_LOG(DEBUG, TAG, "CAGetRequestInfoFromPdu OUT");\r
51     return 1;\r
52 }\r
53 \r
54 uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo,\r
55                                   char *outUri)\r
56 {\r
57     OIC_LOG(DEBUG, TAG, "CAGetResponseInfoFromPdu IN");\r
58     if (NULL == pdu)\r
59         return 0;\r
60 \r
61     uint32_t code = CA_NOT_FOUND;\r
62     CAGetRequestPDUInfo(pdu, &code, &(outResInfo->info), outUri);\r
63     outResInfo->result = code;\r
64     OIC_LOG(DEBUG, TAG, "CAGetResponseInfoFromPdu OUT");\r
65     return 1;\r
66 }\r
67 \r
68 coap_pdu_t *CAGeneratePdu(const char *uri, const uint32_t code, const CAInfo_t info)\r
69 {\r
70     OIC_LOG(DEBUG, TAG, "CAGeneratePdu IN");\r
71 \r
72     coap_pdu_t *pdu;\r
73     char *coapUri = NULL;\r
74     uint32_t coapHeaderLength = 12;\r
75     uint32_t length;\r
76     coap_list_t *optlist = NULL;\r
77 \r
78     if (NULL == uri)\r
79         return NULL;\r
80 \r
81     length = strlen(uri);\r
82     if (CA_MAX_URI_LENGTH < length)\r
83     {\r
84         OIC_LOG(DEBUG, TAG, "check URI length..");\r
85         return NULL;\r
86     }\r
87 \r
88     uint32_t uriLength = length + coapHeaderLength + 1;\r
89     coapUri = (char *) OICMalloc(uriLength);\r
90     if (NULL == coapUri)\r
91     {\r
92         OIC_LOG(DEBUG, TAG, "CAGeneratePdu, Memory allocation failed !");\r
93         return NULL;\r
94     }\r
95     memset(coapUri, 0, uriLength);\r
96 \r
97     if (NULL != coapUri)\r
98     {\r
99         strcat(coapUri, "coap://[::]/");\r
100         strcat(coapUri, uri);\r
101 \r
102         // parsing options in URI\r
103         CAParseURI(coapUri, &optlist);\r
104         OICFree(coapUri);\r
105         coapUri = NULL;\r
106 \r
107         // parsing options in HeadOption\r
108         CAParseHeadOption(code, info, &optlist);\r
109     }\r
110 \r
111     if (NULL != info.payload) // payload is include in request / response\r
112     {\r
113         if (!(pdu = CACreatePDUforRequestWithPayload((code_t) code, optlist, info.payload, info)))\r
114             return NULL;\r
115     }\r
116     else // payload is not include in request / response\r
117     {\r
118         if (!(pdu = CACreatePDUforRequest((code_t) code, optlist, info)))\r
119             return NULL;\r
120     }\r
121 \r
122     // free option list\r
123     coap_delete_list(optlist);\r
124 \r
125     // pdu print method : coap_show_pdu(pdu);\r
126     OIC_LOG(DEBUG, TAG, "CAGeneratePdu OUT");\r
127     return pdu;\r
128 }\r
129 \r
130 coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)\r
131 {\r
132     OIC_LOG(DEBUG, TAG, "CAParsePDU IN");\r
133     coap_pdu_t *outpdu = coap_new_pdu();\r
134 \r
135     coap_pdu_parse((unsigned char *) data, length, outpdu);\r
136     (*outCode) = (uint32_t) outpdu->hdr->code;\r
137     OIC_LOG(DEBUG, TAG, "CAParsePDU OUT");\r
138     return outpdu;\r
139 }\r
140 \r
141 coap_pdu_t *CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *options,\r
142         const char *payload, const CAInfo_t info)\r
143 {\r
144     OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload IN");\r
145 \r
146     coap_pdu_t *pdu;\r
147     coap_list_t *opt;\r
148 \r
149     uint32_t CAFlags = 0;\r
150     coap_block_t CABlock =\r
151     { .num = 0, .m = 0, .szx = 6 };\r
152 \r
153     if (!(pdu = coap_new_pdu()))\r
154         return NULL;\r
155 \r
156     unsigned short message_id;\r
157 \r
158     if (info.messageId == 0)\r
159     {\r
160         /* initialize message id */\r
161         prng((unsigned char * )&message_id, sizeof(unsigned short));\r
162         ++message_id;\r
163 \r
164         OIC_LOG_V(DEBUG, TAG, "generate the message id(%d)", message_id);\r
165     }\r
166     else\r
167     {\r
168         /* use saved message id */\r
169         message_id = info.messageId;\r
170     }\r
171 \r
172     pdu->hdr->type = info.type;\r
173     pdu->hdr->id = htons(message_id);\r
174     pdu->hdr->code = code;\r
175 \r
176     if (info.token)\r
177     {\r
178         pdu->hdr->token_length = CA_MAX_TOKEN_LEN;\r
179         if (!coap_add_token(pdu, CA_MAX_TOKEN_LEN, (unsigned char *) info.token))\r
180         {\r
181             OIC_LOG(DEBUG, TAG, "cannot add token to request");\r
182         }\r
183     }\r
184     for (opt = options; opt; opt = opt->next)\r
185     {\r
186         OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.", COAP_OPTION_DATA(*(coap_option * )opt->data));\r
187         coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),\r
188                         COAP_OPTION_LENGTH(*(coap_option * )opt->data),\r
189                         COAP_OPTION_DATA(*(coap_option * )opt->data));\r
190     }\r
191 \r
192     if (NULL != payload)\r
193     {\r
194         uint32_t len = strlen(payload);\r
195         if ((CAFlags & CA_FLAGS_BLOCK) == 0)\r
196         {\r
197             OIC_LOG_V(DEBUG, TAG, "coap_add_data, payload: %s", payload);\r
198             coap_add_data(pdu, len, (const unsigned char *) payload);\r
199         }\r
200         else\r
201         {\r
202             OIC_LOG_V(DEBUG, TAG, "coap_add_block, payload: %s", payload);\r
203             coap_add_block(pdu, len, (const unsigned char *) payload, CABlock.num, CABlock.szx);\r
204         }\r
205     }\r
206     OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload OUT");\r
207     return pdu;\r
208 }\r
209 \r
210 coap_pdu_t *CACreatePDUforRequest(const code_t code, coap_list_t *options,\r
211                                   const CAInfo_t info)\r
212 {\r
213     OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest IN");\r
214 \r
215     coap_pdu_t *pdu;\r
216     coap_list_t *opt;\r
217 \r
218     if (!(pdu = coap_new_pdu()))\r
219     {\r
220         OIC_LOG(DEBUG, TAG, "Out of memory");\r
221         return NULL;\r
222     }\r
223 \r
224     unsigned short message_id;\r
225 \r
226     if (info.messageId == 0)\r
227     {\r
228         /* initialize message id */\r
229         prng((unsigned char * )&message_id, sizeof(unsigned short));\r
230         ++message_id;\r
231 \r
232         OIC_LOG_V(DEBUG, TAG, "generate the message id(%d)", message_id);\r
233     }\r
234     else\r
235     {\r
236         /* use saved message id */\r
237         message_id = info.messageId;\r
238     }\r
239 \r
240     pdu->hdr->type = info.type;\r
241     pdu->hdr->id = htons(message_id);\r
242     pdu->hdr->code = code;\r
243 \r
244     OIC_LOG_V(DEBUG, TAG, "token info : %s, %d", info.token, strlen(info.token));\r
245     pdu->hdr->token_length = CA_MAX_TOKEN_LEN;\r
246 \r
247     if (!coap_add_token(pdu, CA_MAX_TOKEN_LEN, (unsigned char *) info.token))\r
248     {\r
249         OIC_LOG(DEBUG, TAG, "cannot add token to request");\r
250     }\r
251 \r
252     for (opt = options; opt; opt = opt->next)\r
253     {\r
254         coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),\r
255                         COAP_OPTION_LENGTH(*(coap_option * )opt->data),\r
256                         COAP_OPTION_DATA(*(coap_option * )opt->data));\r
257     }\r
258     OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest OUT");\r
259     return pdu;\r
260 }\r
261 \r
262 void CAParseURI(const char *uriInfo, coap_list_t **optlist)\r
263 {\r
264     OIC_LOG(DEBUG, TAG, "CAParseURI IN");\r
265 \r
266     unsigned char portbuf[2];\r
267     unsigned char _buf[CA_BUFSIZE];\r
268     unsigned char *buf = _buf;\r
269     coap_uri_t uri;\r
270     size_t buflen;\r
271     uint32_t res;\r
272 \r
273     OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);\r
274 \r
275     /* split arg into Uri-* options */\r
276     coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);\r
277 \r
278     if (uri.port != COAP_DEFAULT_PORT)\r
279     {\r
280         coap_insert(optlist,\r
281                     CACreateNewOptionNode(COAP_OPTION_URI_PORT,\r
282                                           coap_encode_var_bytes(portbuf, uri.port), portbuf),\r
283                     CAOrderOpts);\r
284     }\r
285 \r
286     if (uri.path.length)\r
287     {\r
288         buflen = CA_BUFSIZE;\r
289         res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);\r
290 \r
291         while (res--)\r
292         {\r
293             coap_insert(optlist,\r
294                         CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf),\r
295                                               COAP_OPT_VALUE(buf)), CAOrderOpts);\r
296             buf += COAP_OPT_SIZE(buf);\r
297         }\r
298     }\r
299 \r
300     if (uri.query.length)\r
301     {\r
302         buflen = CA_BUFSIZE;\r
303         buf = _buf;\r
304         res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);\r
305 \r
306         while (res--)\r
307         {\r
308             coap_insert(optlist,\r
309                         CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf),\r
310                                               COAP_OPT_VALUE(buf)), CAOrderOpts);\r
311 \r
312             buf += COAP_OPT_SIZE(buf);\r
313         }\r
314     }\r
315     OIC_LOG(DEBUG, TAG, "CAParseURI OUT");\r
316 }\r
317 \r
318 void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)\r
319 {\r
320     OIC_LOG(DEBUG, TAG, "CAParseHeadOption IN");\r
321     OIC_LOG_V(DEBUG, TAG, "start parse Head Option : %d", info.numOptions);\r
322 \r
323     uint32_t i;\r
324     for (i = 0; i < info.numOptions; i++)\r
325     {\r
326         uint32_t id = info.options[i].optionID;\r
327         if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)\r
328         {\r
329             OIC_LOG_V(DEBUG, TAG, "it is not Header Option : %d", id);\r
330         }\r
331         else\r
332         {\r
333             OIC_LOG_V(DEBUG, TAG, "Head Option ID: %d", info.options[i].optionID);\r
334             OIC_LOG_V(DEBUG, TAG, "Head Option data: %s", info.options[i].optionData);\r
335             OIC_LOG_V(DEBUG, TAG, "Head Option length: %d", info.options[i].optionLength);\r
336 \r
337             coap_insert(optlist,\r
338                         CACreateNewOptionNode(info.options[i].optionID,\r
339                                               info.options[i].optionLength,\r
340                                               info.options[i].optionData), CAOrderOpts);\r
341         }\r
342     }\r
343     OIC_LOG(DEBUG, TAG, "CAParseHeadOption OUT");\r
344 }\r
345 \r
346 coap_list_t *CACreateNewOptionNode(const uint16_t key, const uint32_t length,\r
347                                    const uint8_t *data)\r
348 {\r
349     OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode IN");\r
350     coap_option *option;\r
351     coap_list_t *node;\r
352 \r
353     option = coap_malloc(sizeof(coap_option) + length + 1);\r
354     if (!option)\r
355     {\r
356         OIC_LOG(DEBUG, TAG, "Out of memory");\r
357         return NULL;\r
358     }\r
359     memset(option, 0, sizeof(coap_option) + length + 1);\r
360 \r
361     COAP_OPTION_KEY(*option) = key;\r
362     COAP_OPTION_LENGTH(*option) = length;\r
363     memcpy(COAP_OPTION_DATA(*option), data, length);\r
364 \r
365     /* we can pass NULL here as delete function since option is released automatically  */\r
366     node = coap_new_listnode(option, NULL);\r
367 \r
368     if (!node)\r
369     {\r
370         OIC_LOG(DEBUG, TAG, "coap_new_listnode returns NULL");\r
371         coap_free(option);\r
372         return NULL;\r
373     }\r
374     //coap_free(option);\r
375     OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode OUT");\r
376     return node;\r
377 }\r
378 \r
379 int CAOrderOpts(void *a, void *b)\r
380 {\r
381     OIC_LOG(DEBUG, TAG, "CAOrderOpts IN");\r
382     if (!a || !b)\r
383     {\r
384         return a < b ? -1 : 1;\r
385     }\r
386 \r
387     if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option * )b))\r
388     {\r
389         return -1;\r
390     }\r
391     OIC_LOG(DEBUG, TAG, "CAOrderOpts OUT");\r
392     return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option * )b);\r
393 }\r
394 \r
395 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)\r
396 {\r
397     OIC_LOG(DEBUG, TAG, "CAGetOptionCount IN");\r
398     uint32_t count = 0;\r
399     coap_opt_t *option;\r
400 \r
401     while ((option = coap_option_next(&opt_iter)))\r
402     {\r
403         if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)\r
404         {\r
405 \r
406         }\r
407         else\r
408         {\r
409             count++;\r
410         }\r
411     }\r
412     OIC_LOG(DEBUG, TAG, "CAGetOptionCount OUT");\r
413     return count;\r
414 }\r
415 \r
416 void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo,\r
417                          char *outUri)\r
418 {\r
419     OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo IN");\r
420     char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */\r
421     uint32_t encode = 0;\r
422     coap_opt_iterator_t opt_iter;\r
423     coap_opt_t *option;\r
424     char optionResult[CA_MAX_URI_LENGTH] =\r
425     { 0, };\r
426     uint32_t count = 0, idx = 0;\r
427     uint32_t optionLength = 0;\r
428     uint32_t isfirstsetflag = 0;\r
429 \r
430     coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);\r
431 \r
432     memset(optionResult, 0, sizeof(optionResult));\r
433 \r
434     // set code\r
435     (*outCode) = (uint32_t) pdu->hdr->code;\r
436 \r
437     // init HeaderOption list\r
438     count = CAGetOptionCount(opt_iter);\r
439 \r
440     memset(outInfo, 0, sizeof(CAInfo_t));\r
441     outInfo->numOptions = count;\r
442     // set type\r
443     outInfo->type = pdu->hdr->type;\r
444 \r
445     // set message id\r
446     outInfo->messageId = ntohs(pdu->hdr->id);\r
447 \r
448     if (count > 0)\r
449     {\r
450         outInfo->options = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * count);\r
451         if (outInfo->options == NULL)\r
452         {\r
453             OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");\r
454             return;\r
455         }\r
456         memset(outInfo->options, 0, sizeof(CAHeaderOption_t) * count);\r
457     }\r
458 \r
459     while ((option = coap_option_next(&opt_iter)))\r
460     {\r
461 \r
462         if (CAGetOptionData((uint8_t *)(COAP_OPT_VALUE(option)),\r
463                             COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf),\r
464                             encode))\r
465         {\r
466             OIC_LOG_V(DEBUG, TAG, "COAP URI element : %s", buf);\r
467             if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)\r
468             {\r
469                 if (0 == isfirstsetflag)\r
470                 {\r
471                     isfirstsetflag = 1;\r
472                     memcpy(optionResult + optionLength, "/", 1);\r
473                     optionLength++;\r
474                     memcpy(optionResult + optionLength, buf, strlen((const char *) buf));\r
475                     optionLength += strlen((const char *) buf);\r
476                 }\r
477                 else\r
478                 {\r
479                     if (COAP_OPTION_URI_PATH == opt_iter.type)\r
480                     {\r
481                         memcpy(optionResult + optionLength, "/", 1);\r
482                         optionLength++;\r
483                     }\r
484                     else if (COAP_OPTION_URI_QUERY == opt_iter.type)\r
485                     {\r
486                         memcpy(optionResult + optionLength, "?", 1);\r
487                         optionLength++;\r
488                     }\r
489                     memcpy(optionResult + optionLength, buf, strlen((const char *) buf));\r
490                     optionLength += strlen((const char *) buf);\r
491                 }\r
492             }\r
493             else\r
494             {\r
495                 if (idx < count)\r
496                 {\r
497                     uint32_t length = (uint32_t) strlen((const char *) buf);\r
498 \r
499                     if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)\r
500                     {\r
501                         outInfo->options[idx].optionID = opt_iter.type;\r
502                         outInfo->options[idx].optionLength = length;\r
503                         outInfo->options[idx].protocolID = CA_COAP_ID;\r
504                         memcpy(outInfo->options[idx].optionData, buf, length);\r
505                         idx++;\r
506                     }\r
507                 }\r
508             }\r
509         }\r
510     }\r
511 \r
512     // set token data\r
513     if (pdu->hdr->token_length > 0)\r
514     {\r
515         OIC_LOG(DEBUG, TAG, "inside pdu->hdr->token_length");\r
516         outInfo->token = (char *) OICMalloc(CA_MAX_TOKEN_LEN + 1);\r
517         if (outInfo->token == NULL)\r
518         {\r
519             OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");\r
520             OICFree(outInfo->options);\r
521             return;\r
522         }\r
523         memset(outInfo->token, 0, CA_MAX_TOKEN_LEN + 1);\r
524         memcpy(outInfo->token, pdu->hdr->token, CA_MAX_TOKEN_LEN);\r
525     }\r
526 \r
527     // set payload data\r
528     if (NULL != pdu->data)\r
529     {\r
530         OIC_LOG(DEBUG, TAG, "inside pdu->data");\r
531         outInfo->payload = (char *) OICMalloc(strlen((const char *) pdu->data) + 1);\r
532         if (outInfo->payload == NULL)\r
533         {\r
534             OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");\r
535             OICFree(outInfo->options);\r
536             OICFree(outInfo->token);\r
537             return;\r
538         }\r
539         memcpy(outInfo->payload, pdu->data, strlen((const char *) pdu->data) + 1);\r
540     }\r
541 \r
542 \r
543     memcpy(outUri, optionResult, strlen(optionResult));\r
544     OIC_LOG_V(DEBUG, TAG, "made URL : %s\n", optionResult);\r
545     OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo OUT");\r
546 \r
547 }\r
548 \r
549 CAResult_t CAGenerateTokenInternal(CAToken_t *token)\r
550 {\r
551     OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal IN");\r
552     if (token == NULL)\r
553     {\r
554         return CA_STATUS_FAILED;\r
555     }\r
556 \r
557     // memory allocation\r
558     char *temp = (char *) OICMalloc(sizeof(char) * (CA_MAX_TOKEN_LEN + 1));\r
559     if (temp == NULL)\r
560     {\r
561         OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal, Memory allocation failed !");\r
562         return CA_MEMORY_ALLOC_FAILED;\r
563     }\r
564     memset(temp, 0, sizeof(char) * (CA_MAX_TOKEN_LEN + 1));\r
565 \r
566     if (SEED == 0)\r
567     {\r
568         SEED = time(NULL);\r
569         if (SEED == -1)\r
570         {\r
571             OIC_LOG(DEBUG, TAG, "Failed to Create Seed!");\r
572             SEED = 0;\r
573             OICFree(temp);\r
574             return CA_STATUS_FAILED;\r
575         }\r
576         srand(SEED);\r
577     }\r
578 \r
579     // set random byte\r
580     uint32_t index;\r
581     for (index = 0; index < CA_MAX_TOKEN_LEN; index++)\r
582     {\r
583         // use valid characters\r
584         temp[index] = (rand() % 94 + 33) & 0xFF;\r
585     }\r
586 \r
587     temp[index] = '\0';\r
588     // save token\r
589     *token = temp;\r
590 \r
591     OIC_LOG_V(DEBUG, TAG, "generate the token(%s)!!", *token);\r
592     OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal OUT");\r
593     return CA_STATUS_OK;\r
594 }\r
595 \r
596 void CADestroyTokenInternal(CAToken_t token)\r
597 {\r
598     OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal IN");\r
599     if (token != NULL)\r
600     {\r
601         OIC_LOG_V(DEBUG, TAG, "destroy the token(%s)!!", token);\r
602 \r
603         OICFree(token);\r
604     }\r
605     OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal OUT");\r
606 }\r
607 \r
608 void CADeinitialize(CAInfo_t *info)\r
609 {\r
610     OIC_LOG(DEBUG, TAG, "CADeinitialize IN");\r
611 \r
612     if (NULL != info)\r
613     {\r
614         if (NULL != info->options)\r
615         {\r
616             OIC_LOG(DEBUG, TAG, "free options in CAInfo");\r
617             OICFree(info->options);\r
618         }\r
619 \r
620         if (NULL != info->token)\r
621         {\r
622             OIC_LOG(DEBUG, TAG, "free token in CAInfo");\r
623             OICFree(info->token);\r
624         }\r
625 \r
626         if (NULL != info->payload)\r
627         {\r
628             OIC_LOG(DEBUG, TAG, "free payload in CAInfo");\r
629             OICFree(info->payload);\r
630         }\r
631     }\r
632     OIC_LOG(DEBUG, TAG, "CADeinitialize OUT");\r
633 }\r
634 \r
635 uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *result,\r
636                          uint32_t buflen, uint32_t encode_always)\r
637 {\r
638     const unsigned char hex[] = "0123456789ABCDEF";\r
639     uint32_t cnt = 0;\r
640     assert(data || len == 0);\r
641 \r
642     if (buflen == 0 || len == 0)\r
643         return 0;\r
644 \r
645     if (data == NULL)\r
646     {\r
647         return 0;\r
648     }\r
649 \r
650     while (len)\r
651     {\r
652         if (!encode_always)\r
653         {\r
654             if (cnt == buflen)\r
655                 break;\r
656             *result++ = *data;\r
657             ++cnt;\r
658         }\r
659         else\r
660         {\r
661             if (cnt + 4 < buflen)\r
662             {\r
663                 *result++ = '\\';\r
664                 *result++ = 'x';\r
665                 *result++ = hex[(*data & 0xf0) >> 4];\r
666                 *result++ = hex[*data & 0x0f];\r
667                 cnt += 4;\r
668             }\r
669             else\r
670                 break;\r
671         }\r
672 \r
673         ++data;\r
674         --len;\r
675     }\r
676 \r
677     *result = '\0';\r
678     return cnt;\r
679 }\r
680 \r
681 CAMessageType_t CAGetMessageTypeFromPduBinaryData(const void *pdu, uint32_t size)\r
682 {\r
683     // pdu minimum size is 4 byte.\r
684     if (size < 4)\r
685         return CA_MSG_NONCONFIRM;\r
686 \r
687     coap_hdr_t *hdr = (coap_hdr_t *) pdu;\r
688 \r
689     return (CAMessageType_t) hdr->type;\r
690 }\r
691 \r
692 uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)\r
693 {\r
694     // pdu minimum size is 4 byte.\r
695     if (size < 4)\r
696         return 0;\r
697 \r
698     coap_hdr_t *hdr = (coap_hdr_t *) pdu;\r
699 \r
700     return ntohs(hdr->id);\r
701 }\r