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_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
40 uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo,
\r
43 OIC_LOG(DEBUG, TAG, "CAGetRequestInfoFromPdu IN");
\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
55 uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo,
\r
58 OIC_LOG(DEBUG, TAG, "CAGetResponseInfoFromPdu IN");
\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
69 coap_pdu_t *CAGeneratePdu(const char *uri, const uint32_t code, const CAInfo_t info)
\r
71 OIC_LOG(DEBUG, TAG, "CAGeneratePdu IN");
\r
74 char *coapUri = NULL;
\r
75 uint32_t coapHeaderLength = 12;
\r
77 coap_list_t *optlist = NULL;
\r
82 length = strlen(uri);
\r
83 if (CA_MAX_URI_LENGTH < length)
\r
85 OIC_LOG(DEBUG, TAG, "check URI length..");
\r
89 coapUri = (char *) OICMalloc(length + coapHeaderLength + 1);
\r
90 if (coapUri == NULL)
\r
92 OIC_LOG(DEBUG, TAG, "CAGeneratePdu, Memory allocation failed !");
\r
95 memset(coapUri, 0, length + coapHeaderLength + 1);
\r
97 if (NULL != coapUri)
\r
99 memcpy(coapUri, "coap://[::]/", coapHeaderLength);
\r
100 memcpy(coapUri + coapHeaderLength, uri, length);
\r
102 // parsing options in URI
\r
103 CAParseURI(coapUri, &optlist);
\r
105 // parsing options in HeadOption
\r
106 CAParseHeadOption(code, info, &optlist);
\r
111 if (NULL != info.payload) // payload is include in request / response
\r
113 if (!(pdu = CACreatePDUforRequestWithPayload((code_t) code, optlist, info.payload, info)))
\r
116 else // payload is not include in request / response
\r
118 if (!(pdu = CACreatePDUforRequest((code_t) code, optlist, info)))
\r
122 // pdu print method : coap_show_pdu(pdu);
\r
123 OIC_LOG(DEBUG, TAG, "CAGeneratePdu OUT");
\r
127 coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)
\r
129 OIC_LOG(DEBUG, TAG, "CAParsePDU IN");
\r
130 coap_pdu_t *outpdu = coap_new_pdu();
\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
138 coap_pdu_t *CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *options,
\r
139 const char *payload, const CAInfo_t info)
\r
141 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload IN");
\r
146 uint32_t CAFlags = 0;
\r
147 coap_block_t CABlock =
\r
148 { .num = 0, .m = 0, .szx = 6 };
\r
150 if (!(pdu = coap_new_pdu()))
\r
153 unsigned short message_id;
\r
155 if (info.messageId == 0)
\r
157 /* initialize message id */
\r
158 prng((unsigned char * )&message_id, sizeof(unsigned short));
\r
161 OIC_LOG_V(DEBUG, TAG, "generate the message id(%d)", message_id);
\r
165 /* use saved message id */
\r
166 message_id = info.messageId;
\r
169 pdu->hdr->type = info.type;
\r
170 pdu->hdr->id = htons(message_id);
\r
171 pdu->hdr->code = code;
\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
178 OIC_LOG(DEBUG, TAG, "cannot add token to request");
\r
181 for (opt = options; opt; opt = opt->next)
\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
189 if (NULL != payload)
\r
191 uint32_t len = strlen(payload);
\r
192 if ((CAFlags & CA_FLAGS_BLOCK) == 0)
\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
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
203 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload OUT");
\r
207 coap_pdu_t *CACreatePDUforRequest(const code_t code, coap_list_t *options,
\r
208 const CAInfo_t info)
\r
210 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest IN");
\r
215 if (!(pdu = coap_new_pdu()))
\r
217 OIC_LOG(DEBUG, TAG, "Out of memory");
\r
221 unsigned short message_id;
\r
223 if (info.messageId == 0)
\r
225 /* initialize message id */
\r
226 prng((unsigned char * )&message_id, sizeof(unsigned short));
\r
229 OIC_LOG_V(DEBUG, TAG, "generate the message id(%d)", message_id);
\r
233 /* use saved message id */
\r
234 message_id = info.messageId;
\r
237 pdu->hdr->type = info.type;
\r
238 pdu->hdr->id = htons(message_id);
\r
239 pdu->hdr->code = code;
\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
244 if (!coap_add_token(pdu, CA_MAX_TOKEN_LEN, (unsigned char *) info.token))
\r
246 OIC_LOG(DEBUG, TAG, "cannot add token to request");
\r
249 for (opt = options; opt; opt = opt->next)
\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
255 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest OUT");
\r
259 void CAParseURI(const char *uriInfo, coap_list_t **optlist)
\r
261 OIC_LOG(DEBUG, TAG, "CAParseURI IN");
\r
263 unsigned char portbuf[2];
\r
264 unsigned char _buf[CA_BUFSIZE];
\r
265 unsigned char *buf = _buf;
\r
270 OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);
\r
272 /* split arg into Uri-* options */
\r
273 coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
\r
275 if (uri.port != COAP_DEFAULT_PORT)
\r
277 coap_insert(optlist,
\r
278 CACreateNewOptionNode(COAP_OPTION_URI_PORT,
\r
279 coap_encode_var_bytes(portbuf, uri.port), portbuf),
\r
283 if (uri.path.length)
\r
285 buflen = CA_BUFSIZE;
\r
286 res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
\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
297 if (uri.query.length)
\r
299 buflen = CA_BUFSIZE;
\r
301 res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
\r
305 coap_insert(optlist,
\r
306 CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf),
\r
307 COAP_OPT_VALUE(buf)), CAOrderOpts);
\r
309 buf += COAP_OPT_SIZE(buf);
\r
312 OIC_LOG(DEBUG, TAG, "CAParseURI OUT");
\r
315 void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)
\r
317 OIC_LOG(DEBUG, TAG, "CAParseHeadOption IN");
\r
318 OIC_LOG_V(DEBUG, TAG, "start parse Head Option : %d", info.numOptions);
\r
321 for (i = 0; i < info.numOptions; i++)
\r
323 uint32_t id = info.options[i].optionID;
\r
324 if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
\r
326 OIC_LOG_V(DEBUG, TAG, "it is not Header Option : %d", id);
\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
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
340 OIC_LOG(DEBUG, TAG, "CAParseHeadOption OUT");
\r
343 coap_list_t *CACreateNewOptionNode(const uint16_t key, const uint32_t length,
\r
344 const uint8_t *data)
\r
346 OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode IN");
\r
347 coap_option *option;
\r
350 option = coap_malloc(sizeof(coap_option) + length);
\r
353 OIC_LOG(DEBUG, TAG, "Out of memory");
\r
356 memset(option, 0, sizeof(coap_option) + length);
\r
358 COAP_OPTION_KEY(*option) = key;
\r
359 COAP_OPTION_LENGTH(*option) = length;
\r
360 memcpy(COAP_OPTION_DATA(*option), data, length);
\r
362 /* we can pass NULL here as delete function since option is released automatically */
\r
363 node = coap_new_listnode(option, NULL);
\r
367 OIC_LOG(DEBUG, TAG, "coap_new_listnode returns NULL");
\r
371 //coap_free(option);
\r
372 OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode OUT");
\r
376 int CAOrderOpts(void *a, void *b)
\r
378 OIC_LOG(DEBUG, TAG, "CAOrderOpts IN");
\r
381 return a < b ? -1 : 1;
\r
384 if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option * )b))
\r
388 OIC_LOG(DEBUG, TAG, "CAOrderOpts OUT");
\r
389 return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option * )b);
\r
392 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
\r
394 OIC_LOG(DEBUG, TAG, "CAGetOptionCount IN");
\r
395 uint32_t count = 0;
\r
396 coap_opt_t *option;
\r
398 while ((option = coap_option_next(&opt_iter)))
\r
400 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
\r
409 OIC_LOG(DEBUG, TAG, "CAGetOptionCount OUT");
\r
413 void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo,
\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
423 uint32_t count = 0, idx = 0;
\r
424 uint32_t optionLength = 0;
\r
425 uint32_t isfirstsetflag = 0;
\r
427 coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
\r
429 memset(optionResult, 0, sizeof(optionResult));
\r
432 (*outCode) = (uint32_t) pdu->hdr->code;
\r
434 // init HeaderOption list
\r
435 count = CAGetOptionCount(opt_iter);
\r
437 memset(outInfo, 0, sizeof(CAInfo_t));
\r
438 outInfo->numOptions = count;
\r
440 outInfo->type = pdu->hdr->type;
\r
443 outInfo->messageId = ntohs(pdu->hdr->id);
\r
447 outInfo->options = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * count);
\r
448 if (outInfo->options == NULL)
\r
450 OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");
\r
453 memset(outInfo->options, 0, sizeof(CAHeaderOption_t) * count);
\r
456 while ((option = coap_option_next(&opt_iter)))
\r
459 if (CAGetOptionData((uint8_t *)(COAP_OPT_VALUE(option)),
\r
460 COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf),
\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
466 if (0 == isfirstsetflag)
\r
468 isfirstsetflag = 1;
\r
469 memcpy(optionResult + optionLength, "/", 1);
\r
471 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
\r
472 optionLength += strlen((const char *) buf);
\r
476 if (COAP_OPTION_URI_PATH == opt_iter.type)
\r
478 memcpy(optionResult + optionLength, "/", 1);
\r
481 else if (COAP_OPTION_URI_QUERY == opt_iter.type)
\r
483 memcpy(optionResult + optionLength, "?", 1);
\r
486 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
\r
487 optionLength += strlen((const char *) buf);
\r
494 uint32_t length = (uint32_t) strlen((const char *) buf);
\r
496 if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)
\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
510 if (pdu->hdr->token_length > 0)
\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
516 OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");
\r
517 OICFree(outInfo->options);
\r
520 memcpy(outInfo->token, pdu->hdr->token, CA_MAX_TOKEN_LEN);
\r
523 // set payload data
\r
524 if (NULL != pdu->data)
\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
530 OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo, Memory allocation failed !");
\r
531 OICFree(outInfo->options);
\r
532 OICFree(outInfo->token);
\r
535 memcpy(outInfo->payload, pdu->data, strlen((const char *) pdu->data) + 1);
\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
545 CAResult_t CAGenerateTokenInternal(CAToken_t *token)
\r
547 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal IN");
\r
550 return CA_STATUS_FAILED;
\r
553 // memory allocation
\r
554 char *temp = (char *) OICMalloc(sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
\r
557 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal, Memory allocation failed !");
\r
558 return CA_MEMORY_ALLOC_FAILED;
\r
560 memset(temp, 0, sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
\r
566 for (index = 0; index < CA_MAX_TOKEN_LEN; index++)
\r
568 // use valid characters
\r
569 temp[index] = (rand() % 94 + 33) & 0xFF;
\r
572 temp[index] = '\0';
\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
581 void CADestroyTokenInternal(CAToken_t token)
\r
583 OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal IN");
\r
586 OIC_LOG_V(DEBUG, TAG, "destroy the token(%s)!!", token);
\r
590 OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal OUT");
\r
593 void CADeinitialize(CAInfo_t *info)
\r
595 OIC_LOG(DEBUG, TAG, "CADeinitialize IN");
\r
599 if (NULL != info->options)
\r
601 OIC_LOG(DEBUG, TAG, "free options in CAInfo");
\r
602 OICFree(info->options);
\r
605 if (NULL != info->token)
\r
607 OIC_LOG(DEBUG, TAG, "free token in CAInfo");
\r
608 OICFree(info->token);
\r
611 if (NULL != info->payload)
\r
613 OIC_LOG(DEBUG, TAG, "free payload in CAInfo");
\r
614 OICFree(info->payload);
\r
617 OIC_LOG(DEBUG, TAG, "CADeinitialize OUT");
\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
623 const unsigned char hex[] = "0123456789ABCDEF";
\r
625 assert(data || len == 0);
\r
627 if (buflen == 0 || len == 0)
\r
637 if (!encode_always)
\r
646 if (cnt + 4 < buflen)
\r
650 *result++ = hex[(*data & 0xf0) >> 4];
\r
651 *result++ = hex[*data & 0x0f];
\r
666 CAMessageType_t CAGetMessageTypeFromPduBinaryData(const void *pdu, uint32_t size)
\r
668 // pdu minimum size is 4 byte.
\r
670 return CA_MSG_NONCONFIRM;
\r
672 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
\r
674 return (CAMessageType_t) hdr->type;
\r
677 uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)
\r
679 // pdu minimum size is 4 byte.
\r
683 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
\r
685 return ntohs(hdr->id);
\r