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_MAX_TOKEN_LEN (8)
33 #define CA_FLAGS_BLOCK 0x01
34 #define CA_BUFSIZE 128
35 #define CA_COAP_MESSAGE_CON 0
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;
82 if (CA_MAX_URI_LENGTH < length)
84 OIC_LOG(DEBUG, TAG, "URI len err");
88 coapUri = (char *) OICMalloc(length + coapHeaderLength + 1);
91 OIC_LOG(ERROR, TAG, "error");
94 memset(coapUri, 0, length + coapHeaderLength + 1);
98 memcpy(coapUri, "coap://[::]/", coapHeaderLength);
99 memcpy(coapUri + coapHeaderLength, uri, length);
101 // parsing options in URI
102 CAParseURI(coapUri, &optlist);
104 // parsing options in HeadOption
105 CAParseHeadOption(code, info, &optlist);
110 if (NULL != info.payload) // payload is include in request / response
112 if (!(pdu = CACreatePDUforRequestWithPayload((code_t) code, optlist, info.payload, info)))
115 else // payload is not include in request / response
117 if (!(pdu = CACreatePDUforRequest((code_t) code, optlist, info)))
121 // pdu print method : coap_show_pdu(pdu);
122 OIC_LOG(DEBUG, TAG, "OUT");
126 coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)
128 OIC_LOG(DEBUG, TAG, "IN");
129 coap_pdu_t *outpdu = coap_new_pdu();
131 coap_pdu_parse((unsigned char *) data, length, outpdu);
132 (*outCode) = (uint32_t) outpdu->hdr->code;
133 OIC_LOG(DEBUG, TAG, "OUT");
137 coap_pdu_t *CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *options,
138 const char *payload, const CAInfo_t info)
140 OIC_LOG(DEBUG, TAG, "IN");
145 uint32_t CAFlags = 0;
146 coap_block_t CABlock =
147 { .num = 0, .m = 0, .szx = 6 };
149 if (!(pdu = coap_new_pdu()))
152 unsigned short message_id;
154 if (info.messageId == 0)
156 /* initialize message id */
157 prng((unsigned char * )&message_id, sizeof(unsigned short));
160 OIC_LOG_V(DEBUG, TAG, "gen msg id=%d", message_id);
164 /* use saved message id */
165 message_id = info.messageId;
168 pdu->hdr->type = info.type;
169 pdu->hdr->id = htons(message_id);
170 pdu->hdr->code = code;
174 pdu->hdr->token_length = CA_MAX_TOKEN_LEN;
175 if (!coap_add_token(pdu, CA_MAX_TOKEN_LEN, (unsigned char *) info.token))
177 OIC_LOG(DEBUG, TAG, "cant add token");
180 for (opt = options; opt; opt = opt->next)
182 OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.", COAP_OPTION_DATA(*(coap_option * )opt->data));
183 coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),
184 COAP_OPTION_LENGTH(*(coap_option * )opt->data),
185 COAP_OPTION_DATA(*(coap_option * )opt->data));
190 uint32_t len = strlen(payload);
191 if ((CAFlags & CA_FLAGS_BLOCK) == 0)
193 OIC_LOG_V(DEBUG, TAG, "add data,payload:%s", payload);
194 coap_add_data(pdu, len, (const unsigned char *) payload);
199 OIC_LOG(DEBUG, TAG, "OUT");
203 coap_pdu_t *CACreatePDUforRequest(const code_t code, coap_list_t *options,
206 OIC_LOG(DEBUG, TAG, "IN");
211 if (!(pdu = coap_new_pdu()))
213 OIC_LOG(ERROR, TAG, "error");
217 unsigned short message_id;
219 if (info.messageId == 0)
221 /* initialize message id */
222 prng((unsigned char * )&message_id, sizeof(unsigned short));
225 OIC_LOG_V(DEBUG, TAG, "gen msg id(%d)", message_id);
229 /* use saved message id */
230 message_id = info.messageId;
233 pdu->hdr->type = info.type;
234 pdu->hdr->id = htons(message_id);
235 pdu->hdr->code = code;
237 OIC_LOG_V(DEBUG, TAG, "token info : %s, %d", info.token, strlen(info.token));
238 pdu->hdr->token_length = CA_MAX_TOKEN_LEN;
240 if (!coap_add_token(pdu, CA_MAX_TOKEN_LEN, (unsigned char *) info.token))
242 OIC_LOG(DEBUG, TAG, "cant add data");
245 for (opt = options; opt; opt = opt->next)
247 coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),
248 COAP_OPTION_LENGTH(*(coap_option * )opt->data),
249 COAP_OPTION_DATA(*(coap_option * )opt->data));
251 OIC_LOG(DEBUG, TAG, "OUT");
255 void CAParseURI(const char *uriInfo, coap_list_t **optlist)
257 OIC_LOG(DEBUG, TAG, "IN");
259 unsigned char portbuf[2];
260 unsigned char _buf[CA_BUFSIZE];
261 unsigned char *buf = _buf;
266 OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);
268 /* split arg into Uri-* options */
269 coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
271 if (uri.port != COAP_DEFAULT_PORT)
274 CACreateNewOptionNode(COAP_OPTION_URI_PORT,
275 coap_encode_var_bytes(portbuf, uri.port), portbuf),
282 res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
287 CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf),
288 COAP_OPT_VALUE(buf)), CAOrderOpts);
289 buf += COAP_OPT_SIZE(buf);
293 if (uri.query.length)
297 res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
302 CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf),
303 COAP_OPT_VALUE(buf)), CAOrderOpts);
305 buf += COAP_OPT_SIZE(buf);
308 OIC_LOG(DEBUG, TAG, "OUT");
311 void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)
313 OIC_LOG(DEBUG, TAG, "IN");
314 OIC_LOG_V(DEBUG, TAG, "parse Head Opt: %d", info.numOptions);
317 for (i = 0; i < info.numOptions; i++)
319 uint32_t id = info.options[i].optionID;
320 if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
322 OIC_LOG_V(DEBUG, TAG, "not Header Opt: %d", id);
326 OIC_LOG_V(DEBUG, TAG, "Head Opt ID: %d", info.options[i].optionID);
327 OIC_LOG_V(DEBUG, TAG, "Head Opt data: %s", info.options[i].optionData);
328 OIC_LOG_V(DEBUG, TAG, "Head Opt len: %d", info.options[i].optionLength);
331 CACreateNewOptionNode(info.options[i].optionID,
332 info.options[i].optionLength,
333 info.options[i].optionData), CAOrderOpts);
336 OIC_LOG(DEBUG, TAG, "OUT");
339 coap_list_t *CACreateNewOptionNode(const uint16_t key, const uint32_t length,
342 OIC_LOG(DEBUG, TAG, "IN");
346 option = coap_malloc(sizeof(coap_option) + length);
349 OIC_LOG(ERROR, TAG, "error");
352 memset(option, 0, sizeof(coap_option) + length);
354 COAP_OPTION_KEY(*option) = key;
355 COAP_OPTION_LENGTH(*option) = length;
356 memcpy(COAP_OPTION_DATA(*option), data, length);
358 /* we can pass NULL here as delete function since option is released automatically */
359 node = coap_new_listnode(option, NULL);
363 OIC_LOG(DEBUG, TAG, "new_listnode rets NULL");
368 OIC_LOG(DEBUG, TAG, "OUT");
372 int CAOrderOpts(void *a, void *b)
374 OIC_LOG(DEBUG, TAG, "IN");
377 return a < b ? -1 : 1;
380 if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option * )b))
384 OIC_LOG(DEBUG, TAG, "OUT");
385 return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option * )b);
388 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
390 OIC_LOG(DEBUG, TAG, "IN");
394 while ((option = coap_option_next(&opt_iter)))
396 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
405 OIC_LOG(DEBUG, TAG, "OUT");
409 void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo,
412 OIC_LOG(DEBUG, TAG, "IN");
413 char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */
415 coap_opt_iterator_t opt_iter;
417 char optionResult[CA_MAX_URI_LENGTH] =
419 uint32_t count = 0, idx = 0;
420 uint32_t optionLength = 0;
421 uint32_t isfirstsetflag = 0;
423 coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
425 memset(optionResult, 0, sizeof(optionResult));
428 (*outCode) = (uint32_t) pdu->hdr->code;
430 // init HeaderOption list
431 count = CAGetOptionCount(opt_iter);
433 memset(outInfo, 0, sizeof(CAInfo_t));
434 outInfo->numOptions = count;
436 outInfo->type = pdu->hdr->type;
439 outInfo->messageId = ntohs(pdu->hdr->id);
443 outInfo->options = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * count);
444 if (outInfo->options == NULL)
446 OIC_LOG(DEBUG, TAG, "error");
449 memset(outInfo->options, 0, sizeof(CAHeaderOption_t) * count);
452 while ((option = coap_option_next(&opt_iter)))
455 if (CAGetOptionData((uint8_t *)(COAP_OPT_VALUE(option)),
456 COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf),
459 OIC_LOG_V(DEBUG, TAG, "COAP URI element : %s", buf);
460 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
462 if (0 == isfirstsetflag)
465 memcpy(optionResult + optionLength, "/", 1);
467 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
468 optionLength += strlen((const char *) buf);
472 if (COAP_OPTION_URI_PATH == opt_iter.type)
474 memcpy(optionResult + optionLength, "/", 1);
477 else if (COAP_OPTION_URI_QUERY == opt_iter.type)
479 memcpy(optionResult + optionLength, "?", 1);
482 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
483 optionLength += strlen((const char *) buf);
490 uint32_t length = (uint32_t) strlen((const char *) buf);
492 if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)
494 outInfo->options[idx].optionID = opt_iter.type;
495 outInfo->options[idx].optionLength = length;
496 outInfo->options[idx].protocolID = CA_COAP_ID;
497 memcpy(outInfo->options[idx].optionData, buf, length);
506 if (pdu->hdr->token_length > 0)
508 OIC_LOG(DEBUG, TAG, "pdu->hdr->token_length>0");
509 outInfo->token = (char *) OICMalloc(CA_MAX_TOKEN_LEN);
510 if (outInfo->token == NULL)
512 OIC_LOG(DEBUG, TAG, "error");
513 OICFree(outInfo->options);
516 memcpy(outInfo->token, pdu->hdr->token, CA_MAX_TOKEN_LEN);
520 if (NULL != pdu->data)
522 OIC_LOG(DEBUG, TAG, "inside pdu->data");
523 outInfo->payload = (char *) OICMalloc(strlen((const char *) pdu->data) + 1);
524 if (outInfo->payload == NULL)
526 OIC_LOG(DEBUG, TAG, "error");
527 OICFree(outInfo->options);
528 OICFree(outInfo->token);
531 memcpy(outInfo->payload, pdu->data, strlen((const char *) pdu->data) + 1);
535 memcpy(outUri, optionResult, strlen(optionResult));
536 OIC_LOG_V(DEBUG, TAG, "made URL:%s\n", optionResult);
537 OIC_LOG(DEBUG, TAG, "OUT");
541 CAResult_t CAGenerateTokenInternal(CAToken_t *token)
543 OIC_LOG(DEBUG, TAG, "IN");
546 return CA_STATUS_FAILED;
550 char *temp = (char *) OICMalloc(sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
553 OIC_LOG(DEBUG, TAG, "error");
554 return CA_MEMORY_ALLOC_FAILED;
556 memset(temp, 0, sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
561 for (index = 0; index < CA_MAX_TOKEN_LEN; index++)
563 // use valid characters
564 temp[index] = (rand() % 94 + 33) & 0xFF;
571 OIC_LOG_V(DEBUG, TAG, "gen token(%s)", *token);
572 OIC_LOG(DEBUG, TAG, "OUT");
576 void CADestroyTokenInternal(CAToken_t token)
578 OIC_LOG(DEBUG, TAG, "IN");
581 OIC_LOG_V(DEBUG, TAG, "destroy token(%s)!!", token);
585 OIC_LOG(DEBUG, TAG, "OUT");
588 void CADeinitialize(CAInfo_t *info)
590 OIC_LOG(DEBUG, TAG, "IN");
594 if (NULL != info->options)
596 OIC_LOG(DEBUG, TAG, "free opt");
597 OICFree(info->options);
600 if (NULL != info->token)
602 OIC_LOG(DEBUG, TAG, "free tok");
603 OICFree(info->token);
606 if (NULL != info->payload)
608 OIC_LOG(DEBUG, TAG, "free payld");
609 OICFree(info->payload);
612 OIC_LOG(DEBUG, TAG, "OUT");
615 uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *result,
616 uint32_t buflen, uint32_t encode_always)
618 const unsigned char hex[] = "0123456789ABCDEF";
620 assert(data || len == 0);
622 if (buflen == 0 || len == 0)
636 if (cnt + 4 < buflen)
640 *result++ = hex[(*data & 0xf0) >> 4];
641 *result++ = hex[*data & 0x0f];
656 CAMessageType_t CAGetMessageTypeFromPduBinaryData(const void *pdu, uint32_t size)
658 // pdu minimum size is 4 byte.
660 return CA_MSG_NONCONFIRM;
662 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
664 return (CAMessageType_t) hdr->type;
667 uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)
669 // pdu minimum size is 4 byte.
673 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
675 return ntohs(hdr->id);