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