1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
26 #include "caprotocolmessage_singlethread.h"
28 #include "oic_malloc.h"
32 #define CA_FLAGS_BLOCK 0x01
33 #define CA_BUFSIZE 128
34 #define CA_COAP_MESSAGE_CON 0
36 #define CA_RESPONSE_CLASS(C) (((C) >> 5)*100)
37 #define CA_RESPONSE_CODE(C) (CA_RESPONSE_CLASS(C) + (C - COAP_RESPONSE_CODE(CA_RESPONSE_CLASS(C))))
39 uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo,
42 OIC_LOG(DEBUG, TAG, "IN");
47 uint32_t code = CA_NOT_FOUND;
48 CAGetRequestPDUInfo(pdu, &code, &(outReqInfo->info), outUri);
49 outReqInfo->method = code;
50 OIC_LOG(DEBUG, TAG, "OUT");
54 uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo,
57 OIC_LOG(DEBUG, TAG, "IN");
61 uint32_t code = CA_NOT_FOUND;
62 CAGetRequestPDUInfo(pdu, &code, &(outResInfo->info), outUri);
63 outResInfo->result = code;
64 OIC_LOG(DEBUG, TAG, "OUT");
68 coap_pdu_t *CAGeneratePdu(const char *uri, const uint32_t code, const CAInfo_t info)
70 OIC_LOG(DEBUG, TAG, "IN");
74 uint32_t coapHeaderLength = 12;
76 coap_list_t *optlist = NULL;
80 if (!(pdu = CACreatePDUforRSTandACK((code_t) code, info)))
91 if (CA_MAX_URI_LENGTH < length)
93 OIC_LOG(DEBUG, TAG, "URI len err");
97 uint32_t uriLength = length + coapHeaderLength + 1;
98 coapUri = (char *) OICMalloc(uriLength);
101 OIC_LOG(ERROR, TAG, "error");
104 memset(coapUri, 0, uriLength);
108 memcpy(coapUri, "coap://[::]/", coapHeaderLength);
109 memcpy(coapUri + coapHeaderLength, uri, length);
111 // parsing options in URI
112 CAParseURI(coapUri, &optlist);
116 // parsing options in HeadOption
117 CAParseHeadOption(code, info, &optlist);
120 if (NULL != info.payload) // payload is include in request / response
122 if (!(pdu = CACreatePDUforRequestWithPayload((code_t) code, optlist, info.payload, info)))
125 else // payload is not include in request / response
127 if (!(pdu = CACreatePDUforRequest((code_t) code, optlist, info)))
131 coap_delete_list(optlist);
134 // pdu print method : coap_show_pdu(pdu);
135 OIC_LOG(DEBUG, TAG, "OUT");
139 coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)
141 OIC_LOG(DEBUG, TAG, "IN");
142 coap_pdu_t *outpdu = coap_new_pdu();
144 coap_pdu_parse((unsigned char *) data, length, outpdu);
145 (*outCode) = (uint32_t) CA_RESPONSE_CODE(outpdu->hdr->code);
146 OIC_LOG(DEBUG, TAG, "OUT");
150 coap_pdu_t *CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *options,
151 const char *payload, const CAInfo_t info)
153 OIC_LOG(DEBUG, TAG, "IN");
158 uint32_t CAFlags = 0;
159 coap_block_t CABlock =
160 { .num = 0, .m = 0, .szx = 6 };
162 if (!(pdu = coap_new_pdu()))
165 unsigned short message_id;
167 if (info.messageId == 0)
169 /* initialize message id */
170 prng((unsigned char * )&message_id, sizeof(unsigned short));
173 OIC_LOG_V(DEBUG, TAG, "gen msg id=%d", message_id);
177 /* use saved message id */
178 message_id = info.messageId;
181 pdu->hdr->type = info.type;
182 pdu->hdr->id = htons(message_id);
183 pdu->hdr->code = COAP_RESPONSE_CODE(code);
187 pdu->hdr->token_length = CA_MAX_TOKEN_LEN;
188 if (!coap_add_token(pdu, CA_MAX_TOKEN_LEN, (unsigned char *) info.token))
190 OIC_LOG(DEBUG, TAG, "cant add token");
193 for (opt = options; opt; opt = opt->next)
195 OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.", COAP_OPTION_DATA(*(coap_option * )opt->data));
196 coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),
197 COAP_OPTION_LENGTH(*(coap_option * )opt->data),
198 COAP_OPTION_DATA(*(coap_option * )opt->data));
203 uint32_t len = strlen(payload);
204 if ((CAFlags & CA_FLAGS_BLOCK) == 0)
206 OIC_LOG_V(DEBUG, TAG, "add data,payload:%s", payload);
207 coap_add_data(pdu, len, (const unsigned char *) payload);
212 OIC_LOG(DEBUG, TAG, "OUT");
216 coap_pdu_t *CACreatePDUforRequest(const code_t code, coap_list_t *options,
219 OIC_LOG(DEBUG, TAG, "IN");
224 if (!(pdu = coap_new_pdu()))
226 OIC_LOG(ERROR, TAG, "error");
230 unsigned short message_id;
232 if (info.messageId == 0)
234 /* initialize message id */
235 prng((unsigned char * )&message_id, sizeof(unsigned short));
238 OIC_LOG_V(DEBUG, TAG, "gen msg id(%d)", message_id);
242 /* use saved message id */
243 message_id = info.messageId;
246 pdu->hdr->type = info.type;
247 pdu->hdr->id = htons(message_id);
248 pdu->hdr->code = COAP_RESPONSE_CODE(code);
250 OIC_LOG_V(DEBUG, TAG, "token info : %s, %d", info.token, strlen(info.token));
251 pdu->hdr->token_length = CA_MAX_TOKEN_LEN;
253 if (!coap_add_token(pdu, CA_MAX_TOKEN_LEN, (unsigned char *) info.token))
255 OIC_LOG(DEBUG, TAG, "cant add data");
258 for (opt = options; opt; opt = opt->next)
260 coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),
261 COAP_OPTION_LENGTH(*(coap_option * )opt->data),
262 COAP_OPTION_DATA(*(coap_option * )opt->data));
264 OIC_LOG(DEBUG, TAG, "OUT");
268 coap_pdu_t *CACreatePDUforRSTandACK(const code_t code, const CAInfo_t info)
270 OIC_LOG(DEBUG, TAG, "IN");
274 if (!(pdu = coap_new_pdu()))
276 OIC_LOG(DEBUG, TAG, "error");
280 unsigned short message_id;
282 if (info.messageId == 0)
284 /* initialize message id */
285 prng((unsigned char * )&message_id, sizeof(unsigned short));
288 OIC_LOG_V(DEBUG, TAG, "msg id(%d)", message_id);
292 /* use saved message id */
293 message_id = info.messageId;
296 pdu->hdr->type = info.type;
297 pdu->hdr->id = htons(message_id);
298 pdu->hdr->code = COAP_RESPONSE_CODE(code);
300 OIC_LOG(DEBUG, TAG, "OUT");
304 void CAParseURI(const char *uriInfo, coap_list_t **optlist)
306 OIC_LOG(DEBUG, TAG, "IN");
308 unsigned char portbuf[2];
309 unsigned char _buf[CA_BUFSIZE];
310 unsigned char *buf = _buf;
315 OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);
317 /* split arg into Uri-* options */
318 coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
320 if (uri.port != COAP_DEFAULT_PORT)
323 CACreateNewOptionNode(COAP_OPTION_URI_PORT,
324 coap_encode_var_bytes(portbuf, uri.port), portbuf),
331 res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
336 CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf),
337 COAP_OPT_VALUE(buf)), CAOrderOpts);
338 buf += COAP_OPT_SIZE(buf);
342 if (uri.query.length)
346 res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
351 CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf),
352 COAP_OPT_VALUE(buf)), CAOrderOpts);
354 buf += COAP_OPT_SIZE(buf);
357 OIC_LOG(DEBUG, TAG, "OUT");
360 void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)
362 OIC_LOG(DEBUG, TAG, "IN");
363 OIC_LOG_V(DEBUG, TAG, "parse Head Opt: %d", info.numOptions);
366 for (i = 0; i < info.numOptions; i++)
368 uint32_t id = info.options[i].optionID;
369 if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
371 OIC_LOG_V(DEBUG, TAG, "not Header Opt: %d", id);
375 OIC_LOG_V(DEBUG, TAG, "Head Opt ID: %d", info.options[i].optionID);
376 OIC_LOG_V(DEBUG, TAG, "Head Opt data: %s", info.options[i].optionData);
377 OIC_LOG_V(DEBUG, TAG, "Head Opt len: %d", info.options[i].optionLength);
380 CACreateNewOptionNode(info.options[i].optionID,
381 info.options[i].optionLength,
382 info.options[i].optionData), CAOrderOpts);
385 OIC_LOG(DEBUG, TAG, "OUT");
388 coap_list_t *CACreateNewOptionNode(const uint16_t key, const uint32_t length,
391 OIC_LOG(DEBUG, TAG, "IN");
395 option = coap_malloc(sizeof(coap_option) + length);
398 OIC_LOG(ERROR, TAG, "error");
401 memset(option, 0, sizeof(coap_option) + length);
403 COAP_OPTION_KEY(*option) = key;
404 COAP_OPTION_LENGTH(*option) = length;
405 memcpy(COAP_OPTION_DATA(*option), data, length);
407 /* we can pass NULL here as delete function since option is released automatically */
408 node = coap_new_listnode(option, NULL);
412 OIC_LOG(DEBUG, TAG, "new_listnode rets NULL");
417 OIC_LOG(DEBUG, TAG, "OUT");
421 int CAOrderOpts(void *a, void *b)
423 OIC_LOG(DEBUG, TAG, "IN");
426 return a < b ? -1 : 1;
429 if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option * )b))
433 OIC_LOG(DEBUG, TAG, "OUT");
434 return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option * )b);
437 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
439 OIC_LOG(DEBUG, TAG, "IN");
443 while ((option = coap_option_next(&opt_iter)))
445 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
454 OIC_LOG(DEBUG, TAG, "OUT");
458 void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo,
461 OIC_LOG(DEBUG, TAG, "IN");
462 char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */
464 coap_opt_iterator_t opt_iter;
466 char optionResult[CA_MAX_URI_LENGTH] =
468 uint32_t count = 0, idx = 0;
469 uint32_t optionLength = 0;
470 uint32_t isfirstsetflag = 0;
472 coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
474 memset(optionResult, 0, sizeof(optionResult));
477 (*outCode) = (uint32_t) CA_RESPONSE_CODE(pdu->hdr->code);
479 // init HeaderOption list
480 count = CAGetOptionCount(opt_iter);
482 memset(outInfo, 0, sizeof(CAInfo_t));
483 outInfo->numOptions = count;
485 outInfo->type = pdu->hdr->type;
488 outInfo->messageId = ntohs(pdu->hdr->id);
492 outInfo->options = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * count);
493 if (outInfo->options == NULL)
495 OIC_LOG(DEBUG, TAG, "error");
498 memset(outInfo->options, 0, sizeof(CAHeaderOption_t) * count);
501 while ((option = coap_option_next(&opt_iter)))
504 if (CAGetOptionData((uint8_t *)(COAP_OPT_VALUE(option)),
505 COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf),
508 OIC_LOG_V(DEBUG, TAG, "COAP URI element : %s", buf);
509 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
511 if (0 == isfirstsetflag)
514 memcpy(optionResult + optionLength, "/", 1);
516 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
517 optionLength += strlen((const char *) buf);
521 if (COAP_OPTION_URI_PATH == opt_iter.type)
523 memcpy(optionResult + optionLength, "/", 1);
526 else if (COAP_OPTION_URI_QUERY == opt_iter.type)
528 memcpy(optionResult + optionLength, "?", 1);
531 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
532 optionLength += strlen((const char *) buf);
539 uint32_t length = (uint32_t) strlen((const char *) buf);
541 if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)
543 outInfo->options[idx].optionID = opt_iter.type;
544 outInfo->options[idx].optionLength = length;
545 outInfo->options[idx].protocolID = CA_COAP_ID;
546 memcpy(outInfo->options[idx].optionData, buf, length);
555 if (pdu->hdr->token_length > 0)
557 OIC_LOG(DEBUG, TAG, "pdu->hdr->token_length>0");
558 outInfo->token = (char *) OICMalloc(CA_MAX_TOKEN_LEN + 1);
559 if (outInfo->token == NULL)
561 OIC_LOG(DEBUG, TAG, "error");
562 OICFree(outInfo->options);
565 memset(outInfo->token, 0, CA_MAX_TOKEN_LEN + 1);
566 memcpy(outInfo->token, pdu->hdr->token, CA_MAX_TOKEN_LEN);
570 if (NULL != pdu->data)
572 OIC_LOG(DEBUG, TAG, "inside pdu->data");
573 outInfo->payload = (char *) OICMalloc(strlen((const char *) pdu->data) + 1);
574 if (outInfo->payload == NULL)
576 OIC_LOG(DEBUG, TAG, "error");
577 OICFree(outInfo->options);
578 OICFree(outInfo->token);
581 memcpy(outInfo->payload, pdu->data, strlen((const char *) pdu->data) + 1);
585 memcpy(outUri, optionResult, strlen(optionResult));
586 OIC_LOG_V(DEBUG, TAG, "made URL:%s\n", optionResult);
587 OIC_LOG(DEBUG, TAG, "OUT");
591 CAResult_t CAGetTokenFromPDU(const coap_hdr_t *pdu_hdr, CAInfo_t *outInfo)
593 OIC_LOG(DEBUG, TAG, "IN");
596 OIC_LOG(DEBUG, TAG, "error");
597 return CA_STATUS_FAILED;
600 if (pdu_hdr->token_length > 0)
602 OIC_LOG(DEBUG, TAG, "toklen > 0");
603 outInfo->token = (char *) OICMalloc(CA_MAX_TOKEN_LEN + 1);
604 if (outInfo->token == NULL)
606 OIC_LOG(DEBUG, TAG, "error");
607 return CA_STATUS_FAILED;
609 memset(outInfo->token, 0, CA_MAX_TOKEN_LEN + 1);
610 memcpy(outInfo->token, pdu_hdr->token, CA_MAX_TOKEN_LEN);
612 OIC_LOG(DEBUG, TAG, "OUT - CAGetTokenFromPDU");
617 CAResult_t CAGenerateTokenInternal(CAToken_t *token)
619 OIC_LOG(DEBUG, TAG, "IN");
622 return CA_STATUS_FAILED;
626 char *temp = (char *) OICMalloc(sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
629 OIC_LOG(DEBUG, TAG, "error");
630 return CA_MEMORY_ALLOC_FAILED;
632 memset(temp, 0, sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
637 for (index = 0; index < CA_MAX_TOKEN_LEN; index++)
639 // use valid characters
640 temp[index] = (rand() % 94 + 33) & 0xFF;
647 OIC_LOG_V(DEBUG, TAG, "gen token(%s)", *token);
648 OIC_LOG(DEBUG, TAG, "OUT");
652 void CADestroyTokenInternal(CAToken_t token)
654 OIC_LOG(DEBUG, TAG, "IN");
657 OIC_LOG_V(DEBUG, TAG, "destroy token(%s)!!", token);
661 OIC_LOG(DEBUG, TAG, "OUT");
664 void CADeinitialize(CAInfo_t *info)
666 OIC_LOG(DEBUG, TAG, "IN");
670 if (NULL != info->options)
672 OIC_LOG(DEBUG, TAG, "free opt");
673 OICFree(info->options);
676 if (NULL != info->token)
678 OIC_LOG(DEBUG, TAG, "free tok");
679 OICFree(info->token);
682 if (NULL != info->payload)
684 OIC_LOG(DEBUG, TAG, "free payld");
685 OICFree(info->payload);
688 OIC_LOG(DEBUG, TAG, "OUT");
691 uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *result,
692 uint32_t buflen, uint32_t encode_always)
694 const unsigned char hex[] = "0123456789ABCDEF";
696 assert(data || len == 0);
698 if (buflen == 0 || len == 0)
712 if (cnt + 4 < buflen)
716 *result++ = hex[(*data & 0xf0) >> 4];
717 *result++ = hex[*data & 0x0f];
732 CAMessageType_t CAGetMessageTypeFromPduBinaryData(const void *pdu, uint32_t size)
734 // pdu minimum size is 4 byte.
736 return CA_MSG_NONCONFIRM;
738 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
740 return (CAMessageType_t) hdr->type;
743 uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)
745 // pdu minimum size is 4 byte.
749 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
751 return ntohs(hdr->id);
754 CAResponseResult_t CAGetCodeFromPduBinaryData(const void *pdu, uint32_t size)
756 // pdu minimum size is 4 byte.
760 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
762 return (CAResponseResult_t) CA_RESPONSE_CODE(hdr->code);