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