1 /******************************************************************
\r
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
\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
11 * http://www.apache.org/licenses/LICENSE-2.0
\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
19 ******************************************************************/
\r
26 #include "caprotocolmessage.h"
\r
28 #include "oic_malloc.h"
\r
32 #define CA_FLAGS_BLOCK 0x01
\r
33 #define CA_BUFSIZE 128
\r
34 #define CA_COAP_MESSAGE_CON 0
\r
36 static int32_t SEED = 0;
\r
38 uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo,
\r
41 OIC_LOG(DEBUG, TAG, "CAGetRequestInfoFromPdu IN");
\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
53 uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo,
\r
56 OIC_LOG(DEBUG, TAG, "CAGetResponseInfoFromPdu IN");
\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
67 coap_pdu_t *CAGeneratePdu(const char *uri, const uint32_t code, const CAInfo_t info)
\r
69 OIC_LOG(DEBUG, TAG, "CAGeneratePdu IN");
\r
72 char *coapUri = NULL;
\r
73 uint32_t coapHeaderLength = 12;
\r
75 coap_list_t *optlist = NULL;
\r
80 length = strlen(uri);
\r
81 if (CA_MAX_URI_LENGTH < length)
\r
83 OIC_LOG(DEBUG, TAG, "check URI length..");
\r
87 uint32_t uriLength = length + coapHeaderLength + 1;
\r
88 coapUri = (char *) OICMalloc(uriLength);
\r
89 if (NULL == coapUri)
\r
91 OIC_LOG(DEBUG, TAG, "CAGeneratePdu, Memory allocation failed !");
\r
94 memset(coapUri, 0, uriLength);
\r
96 if (NULL != coapUri)
\r
98 strcat(coapUri, "coap://[::]/");
\r
99 strcat(coapUri, uri);
\r
101 // parsing options in URI
\r
102 CAParseURI(coapUri, &optlist);
\r
106 // parsing options in HeadOption
\r
107 CAParseHeadOption(code, info, &optlist);
\r
110 if (NULL != info.payload) // payload is include in request / response
\r
112 if (!(pdu = CACreatePDUforRequestWithPayload((code_t) code, optlist, info.payload, info)))
\r
115 else // payload is not include in request / response
\r
117 if (!(pdu = CACreatePDUforRequest((code_t) code, optlist, info)))
\r
121 // free option list
\r
122 coap_delete_list(optlist);
\r
124 // pdu print method : coap_show_pdu(pdu);
\r
125 OIC_LOG(DEBUG, TAG, "CAGeneratePdu OUT");
\r
129 coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)
\r
131 OIC_LOG(DEBUG, TAG, "CAParsePDU IN");
\r
132 coap_pdu_t *outpdu = coap_new_pdu();
\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
140 coap_pdu_t *CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *options,
\r
141 const char *payload, const CAInfo_t info)
\r
143 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload IN");
\r
148 uint32_t CAFlags = 0;
\r
149 coap_block_t CABlock =
\r
150 { .num = 0, .m = 0, .szx = 6 };
\r
152 if (!(pdu = coap_new_pdu()))
\r
155 unsigned short message_id;
\r
157 if (info.messageId == 0)
\r
159 /* initialize message id */
\r
160 prng((unsigned char * )&message_id, sizeof(unsigned short));
\r
163 OIC_LOG_V(DEBUG, TAG, "generate the message id(%d)", message_id);
\r
167 /* use saved message id */
\r
168 message_id = info.messageId;
\r
171 pdu->hdr->type = info.type;
\r
172 pdu->hdr->id = htons(message_id);
\r
173 pdu->hdr->code = code;
\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
180 OIC_LOG(DEBUG, TAG, "cannot add token to request");
\r
183 for (opt = options; opt; opt = opt->next)
\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
191 if (NULL != payload)
\r
193 uint32_t len = strlen(payload);
\r
194 if ((CAFlags & CA_FLAGS_BLOCK) == 0)
\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
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
205 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload OUT");
\r
209 coap_pdu_t *CACreatePDUforRequest(const code_t code, coap_list_t *options,
\r
210 const CAInfo_t info)
\r
212 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest IN");
\r
217 if (!(pdu = coap_new_pdu()))
\r
219 OIC_LOG(DEBUG, TAG, "Out of memory");
\r
223 unsigned short message_id;
\r
225 if (info.messageId == 0)
\r
227 /* initialize message id */
\r
228 prng((unsigned char * )&message_id, sizeof(unsigned short));
\r
231 OIC_LOG_V(DEBUG, TAG, "generate the message id(%d)", message_id);
\r
235 /* use saved message id */
\r
236 message_id = info.messageId;
\r
239 pdu->hdr->type = info.type;
\r
240 pdu->hdr->id = htons(message_id);
\r
241 pdu->hdr->code = code;
\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
246 if (!coap_add_token(pdu, CA_MAX_TOKEN_LEN, (unsigned char *) info.token))
\r
248 OIC_LOG(DEBUG, TAG, "cannot add token to request");
\r
251 for (opt = options; opt; opt = opt->next)
\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
257 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest OUT");
\r
261 void CAParseURI(const char *uriInfo, coap_list_t **optlist)
\r
263 OIC_LOG(DEBUG, TAG, "CAParseURI IN");
\r
265 unsigned char portbuf[2];
\r
266 unsigned char _buf[CA_BUFSIZE];
\r
267 unsigned char *buf = _buf;
\r
272 OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);
\r
274 /* split arg into Uri-* options */
\r
275 coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
\r
277 if (uri.port != COAP_DEFAULT_PORT)
\r
279 coap_insert(optlist,
\r
280 CACreateNewOptionNode(COAP_OPTION_URI_PORT,
\r
281 coap_encode_var_bytes(portbuf, uri.port), portbuf),
\r
285 if (uri.path.length)
\r
287 buflen = CA_BUFSIZE;
\r
288 res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
\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
299 if (uri.query.length)
\r
301 buflen = CA_BUFSIZE;
\r
303 res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
\r
307 coap_insert(optlist,
\r
308 CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf),
\r
309 COAP_OPT_VALUE(buf)), CAOrderOpts);
\r
311 buf += COAP_OPT_SIZE(buf);
\r
314 OIC_LOG(DEBUG, TAG, "CAParseURI OUT");
\r
317 void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)
\r
319 OIC_LOG(DEBUG, TAG, "CAParseHeadOption IN");
\r
320 OIC_LOG_V(DEBUG, TAG, "start parse Head Option : %d", info.numOptions);
\r
323 for (i = 0; i < info.numOptions; i++)
\r
325 uint32_t id = info.options[i].optionID;
\r
326 if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
\r
328 OIC_LOG_V(DEBUG, TAG, "it is not Header Option : %d", id);
\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
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
342 OIC_LOG(DEBUG, TAG, "CAParseHeadOption OUT");
\r
345 coap_list_t *CACreateNewOptionNode(const uint16_t key, const uint32_t length,
\r
346 const uint8_t *data)
\r
348 OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode IN");
\r
349 coap_option *option;
\r
352 option = coap_malloc(sizeof(coap_option) + length + 1);
\r
355 OIC_LOG(DEBUG, TAG, "Out of memory");
\r
358 memset(option, 0, sizeof(coap_option) + length + 1);
\r
360 COAP_OPTION_KEY(*option) = key;
\r
361 COAP_OPTION_LENGTH(*option) = length;
\r
362 memcpy(COAP_OPTION_DATA(*option), data, length);
\r
364 /* we can pass NULL here as delete function since option is released automatically */
\r
365 node = coap_new_listnode(option, NULL);
\r
369 OIC_LOG(DEBUG, TAG, "coap_new_listnode returns NULL");
\r
373 //coap_free(option);
\r
374 OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode OUT");
\r
378 int CAOrderOpts(void *a, void *b)
\r
380 OIC_LOG(DEBUG, TAG, "CAOrderOpts IN");
\r
383 return a < b ? -1 : 1;
\r
386 if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option * )b))
\r
390 OIC_LOG(DEBUG, TAG, "CAOrderOpts OUT");
\r
391 return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option * )b);
\r
394 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
\r
396 OIC_LOG(DEBUG, TAG, "CAGetOptionCount IN");
\r
397 uint32_t count = 0;
\r
398 coap_opt_t *option;
\r
400 while ((option = coap_option_next(&opt_iter)))
\r
402 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
\r
411 OIC_LOG(DEBUG, TAG, "CAGetOptionCount OUT");
\r
415 void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo,
\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
425 uint32_t count = 0, idx = 0;
\r
426 uint32_t optionLength = 0;
\r
427 uint32_t isfirstsetflag = 0;
\r
429 coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
\r
431 memset(optionResult, 0, sizeof(optionResult));
\r
434 (*outCode) = (uint32_t) pdu->hdr->code;
\r
436 // init HeaderOption list
\r
437 count = CAGetOptionCount(opt_iter);
\r
439 memset(outInfo, 0, sizeof(CAInfo_t));
\r
440 outInfo->numOptions = count;
\r
442 outInfo->type = pdu->hdr->type;
\r
445 outInfo->messageId = ntohs(pdu->hdr->id);
\r
449 outInfo->options = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * count);
\r
450 if (outInfo->options == NULL)
\r
452 OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");
\r
455 memset(outInfo->options, 0, sizeof(CAHeaderOption_t) * count);
\r
458 while ((option = coap_option_next(&opt_iter)))
\r
461 if (CAGetOptionData((uint8_t *)(COAP_OPT_VALUE(option)),
\r
462 COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf),
\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
468 if (0 == isfirstsetflag)
\r
470 isfirstsetflag = 1;
\r
471 memcpy(optionResult + optionLength, "/", 1);
\r
473 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
\r
474 optionLength += strlen((const char *) buf);
\r
478 if (COAP_OPTION_URI_PATH == opt_iter.type)
\r
480 memcpy(optionResult + optionLength, "/", 1);
\r
483 else if (COAP_OPTION_URI_QUERY == opt_iter.type)
\r
485 memcpy(optionResult + optionLength, "?", 1);
\r
488 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
\r
489 optionLength += strlen((const char *) buf);
\r
496 uint32_t length = (uint32_t) strlen((const char *) buf);
\r
498 if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)
\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
512 if (pdu->hdr->token_length > 0)
\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
518 OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");
\r
519 OICFree(outInfo->options);
\r
522 memset(outInfo->token, 0, CA_MAX_TOKEN_LEN + 1);
\r
523 memcpy(outInfo->token, pdu->hdr->token, CA_MAX_TOKEN_LEN);
\r
526 // set payload data
\r
527 if (NULL != pdu->data)
\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
533 OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");
\r
534 OICFree(outInfo->options);
\r
535 OICFree(outInfo->token);
\r
538 memcpy(outInfo->payload, pdu->data, strlen((const char *) pdu->data) + 1);
\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
548 CAResult_t CAGenerateTokenInternal(CAToken_t *token)
\r
550 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal IN");
\r
553 return CA_STATUS_FAILED;
\r
556 // memory allocation
\r
557 char *temp = (char *) OICMalloc(sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
\r
560 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal, Memory allocation failed !");
\r
561 return CA_MEMORY_ALLOC_FAILED;
\r
563 memset(temp, 0, sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
\r
570 OIC_LOG(DEBUG, TAG, "Failed to Create Seed!");
\r
573 return CA_STATUS_FAILED;
\r
580 for (index = 0; index < CA_MAX_TOKEN_LEN; index++)
\r
582 // use valid characters
\r
583 temp[index] = (rand() % 94 + 33) & 0xFF;
\r
586 temp[index] = '\0';
\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
595 void CADestroyTokenInternal(CAToken_t token)
\r
597 OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal IN");
\r
600 OIC_LOG_V(DEBUG, TAG, "destroy the token(%s)!!", token);
\r
604 OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal OUT");
\r
607 void CADeinitialize(CAInfo_t *info)
\r
609 OIC_LOG(DEBUG, TAG, "CADeinitialize IN");
\r
613 if (NULL != info->options)
\r
615 OIC_LOG(DEBUG, TAG, "free options in CAInfo");
\r
616 OICFree(info->options);
\r
619 if (NULL != info->token)
\r
621 OIC_LOG(DEBUG, TAG, "free token in CAInfo");
\r
622 OICFree(info->token);
\r
625 if (NULL != info->payload)
\r
627 OIC_LOG(DEBUG, TAG, "free payload in CAInfo");
\r
628 OICFree(info->payload);
\r
631 OIC_LOG(DEBUG, TAG, "CADeinitialize OUT");
\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
637 const unsigned char hex[] = "0123456789ABCDEF";
\r
639 assert(data || len == 0);
\r
641 if (buflen == 0 || len == 0)
\r
651 if (!encode_always)
\r
660 if (cnt + 4 < buflen)
\r
664 *result++ = hex[(*data & 0xf0) >> 4];
\r
665 *result++ = hex[*data & 0x0f];
\r
680 CAMessageType_t CAGetMessageTypeFromPduBinaryData(const void *pdu, uint32_t size)
\r
682 // pdu minimum size is 4 byte.
\r
684 return CA_MSG_NONCONFIRM;
\r
686 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
\r
688 return (CAMessageType_t) hdr->type;
\r
691 uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)
\r
693 // pdu minimum size is 4 byte.
\r
697 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
\r
699 return ntohs(hdr->id);
\r