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.h"
28 #include "oic_malloc.h"
32 #define CA_BUFSIZE 128
33 #define CA_PDU_MIN_SIZE 4
35 static const char COAP_HEADER[] = "coap://[::]/";
36 static uint32_t SEED = 0;
38 void CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo, char *outUri,
41 OIC_LOG(DEBUG, TAG, "CAGetRequestInfoFromPdu IN");
48 uint32_t code = CA_NOT_FOUND;
49 CAGetInfoFromPDU(pdu, &code, &(outReqInfo->info), outUri, buflen);
50 outReqInfo->method = code;
51 OIC_LOG(DEBUG, TAG, "CAGetRequestInfoFromPdu OUT");
54 void CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo, char *outUri,
57 OIC_LOG(DEBUG, TAG, "CAGetResponseInfoFromPdu IN");
63 uint32_t code = CA_NOT_FOUND;
64 CAGetInfoFromPDU(pdu, &code, &(outResInfo->info), outUri, buflen);
65 outResInfo->result = code;
66 OIC_LOG(DEBUG, TAG, "CAGetResponseInfoFromPdu OUT");
69 coap_pdu_t *CAGeneratePdu(const char *uri, const uint32_t code, const CAInfo_t info)
71 OIC_LOG(DEBUG, TAG, "CAGeneratePdu IN");
78 uint32_t length = strlen(uri);
79 if (CA_MAX_URI_LENGTH < length)
81 OIC_LOG(ERROR, TAG, "check URI length..");
85 uint32_t uriLength = length + sizeof(COAP_HEADER);
87 coapUri = (char *) OICCalloc(1, uriLength * sizeof(char));
90 OIC_LOG(ERROR, TAG, "CAGeneratePdu, Memory allocation failed !");
94 coap_list_t *optlist = NULL;
97 strcat(coapUri, COAP_HEADER);
100 // parsing options in URI
101 CAParseURI(coapUri, &optlist);
105 // parsing options in HeadOption
106 CAParseHeadOption(code, info, &optlist);
110 if (!(pdu = CAGeneratePduImpl((code_t) code, optlist, info, info.payload)))
116 coap_delete_list(optlist);
118 // pdu print method : coap_show_pdu(pdu);
119 OIC_LOG(DEBUG, TAG, "CAGeneratePdu OUT");
123 coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)
125 OIC_LOG(DEBUG, TAG, "CAParsePDU IN");
126 coap_pdu_t *outpdu = coap_new_pdu();
128 if (0 >= coap_pdu_parse((unsigned char *) data, length, outpdu))
130 OIC_LOG(ERROR, TAG, "coap_pdu_parse failed");
131 coap_delete_pdu(outpdu);
137 (*outCode) = (uint32_t) outpdu->hdr->code;
138 }OIC_LOG(DEBUG, TAG, "CAParsePDU OUT");
142 coap_pdu_t *CAGeneratePduImpl(const code_t code, coap_list_t *options, const CAInfo_t info,
145 OIC_LOG(DEBUG, TAG, "CAGeneratePduImpl IN");
147 coap_pdu_t *pdu = coap_new_pdu();
150 OIC_LOG(ERROR, TAG, "Out of memory");
154 OIC_LOG_V(DEBUG, TAG, "messageId is %d", info.messageId);
155 if (CA_MSG_ACKNOWLEDGE == info.type || CA_MSG_RESET == info.type)
157 pdu->hdr->id = htons(info.messageId);
162 if (info.messageId == 0)
164 /* initialize message id */
165 prng((uint8_t * ) &message_id, sizeof(uint16_t));
167 OIC_LOG_V(DEBUG, TAG, "generate the message id(%d)", message_id);
171 /* use saved message id */
172 message_id = info.messageId;
174 pdu->hdr->id = htons(message_id);
176 pdu->hdr->type = info.type;
177 pdu->hdr->code = COAP_RESPONSE_CODE(code);
181 uint32_t tokenLength = strlen(info.token);
182 OIC_LOG_V(DEBUG, TAG, "token info : %s, %d", info.token, tokenLength);
184 int32_t ret = coap_add_token(pdu, tokenLength, (uint8_t *) info.token);
187 OIC_LOG(DEBUG, TAG, "cannot add token to request");
194 for (opt = options; opt; opt = opt->next)
196 OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.",
197 COAP_OPTION_DATA(*(coap_option *) opt->data));
198 coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * ) opt->data),
199 COAP_OPTION_LENGTH(*(coap_option * ) opt->data),
200 COAP_OPTION_DATA(*(coap_option * ) opt->data));
206 uint32_t len = strlen(payload);
207 OIC_LOG_V(DEBUG, TAG, "coap_add_data, payload: %s", payload);
208 coap_add_data(pdu, len, (const uint8_t *) payload);
211 OIC_LOG(DEBUG, TAG, "CAGeneratePduImpl OUT");
215 void CAParseURI(const char *uriInfo, coap_list_t **optlist)
217 OIC_LOG(DEBUG, TAG, "CAParseURI IN");OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);
219 /* split arg into Uri-* options */
221 coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
223 unsigned char portbuf[2];
224 if (uri.port != COAP_DEFAULT_PORT)
228 CACreateNewOptionNode(COAP_OPTION_URI_PORT,
229 coap_encode_var_bytes(portbuf, uri.port), portbuf),
233 unsigned char uriBuffer[CA_BUFSIZE] =
235 unsigned char *pBuf = uriBuffer;
242 res = coap_split_path(uri.path.s, uri.path.length, pBuf, &buflen);
246 uint32_t prevIdx = 0;
251 CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(pBuf),
252 COAP_OPT_VALUE(pBuf)),
255 uint32_t optSize = COAP_OPT_SIZE(pBuf);
256 uint32_t nextIdx = prevIdx + optSize;
257 if (nextIdx < buflen)
266 if (uri.query.length)
270 res = coap_split_query(uri.query.s, uri.query.length, pBuf, &buflen);
274 uint32_t prevIdx = 0;
279 CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(pBuf),
280 COAP_OPT_VALUE(pBuf)),
283 uint32_t optSize = COAP_OPT_SIZE(pBuf);
284 uint32_t nextIdx = prevIdx + optSize;
285 if (nextIdx < buflen)
294 OIC_LOG(DEBUG, TAG, "CAParseURI OUT");
297 void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)
299 OIC_LOG(DEBUG, TAG, "CAParseHeadOption IN");
301 OIC_LOG_V(DEBUG, TAG, "start parse Head Option : %d", info.numOptions);
304 for (i = 0; i < info.numOptions; i++)
306 uint32_t id = info.options[i].optionID;
307 if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
309 OIC_LOG_V(DEBUG, TAG, "it is not Header Option : %d", id);
313 OIC_LOG_V(DEBUG, TAG, "Head Option ID: %d", info.options[i].optionID);
315 OIC_LOG_V(DEBUG, TAG, "Head Option data: %s", info.options[i].optionData);
317 OIC_LOG_V(DEBUG, TAG, "Head Option length: %d", info.options[i].optionLength);
321 CACreateNewOptionNode(info.options[i].optionID, info.options[i].optionLength,
322 info.options[i].optionData),
327 OIC_LOG(DEBUG, TAG, "CAParseHeadOption OUT");
330 coap_list_t *CACreateNewOptionNode(const uint16_t key, const uint32_t length, const uint8_t *data)
332 OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode IN");
333 coap_option *option = coap_malloc(sizeof(coap_option) + length + 1);
336 OIC_LOG(DEBUG, TAG, "Out of memory");
339 memset(option, 0, sizeof(coap_option) + length + 1);
341 COAP_OPTION_KEY(*option) = key;
342 COAP_OPTION_LENGTH(*option) = length;
343 memcpy(COAP_OPTION_DATA(*option), data, length);
345 /* we can pass NULL here as delete function since option is released automatically */
346 coap_list_t *node = coap_new_listnode(option, NULL);
350 OIC_LOG(DEBUG, TAG, "coap_new_listnode returns NULL");
355 OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode OUT");
359 int CAOrderOpts(void *a, void *b)
361 OIC_LOG(DEBUG, TAG, "CAOrderOpts IN");
364 return a < b ? -1 : 1;
367 if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option * )b))
372 OIC_LOG(DEBUG, TAG, "CAOrderOpts OUT");
373 return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option * )b);
376 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
378 OIC_LOG(DEBUG, TAG, "CAGetOptionCount IN");
382 while ((option = coap_option_next(&opt_iter)))
384 if (COAP_OPTION_URI_PATH != opt_iter.type && COAP_OPTION_URI_QUERY != opt_iter.type)
390 OIC_LOG(DEBUG, TAG, "CAGetOptionCount OUT");
394 void CAGetInfoFromPDU(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo, char *outUri,
397 OIC_LOG(DEBUG, TAG, "CAGetInfoFromPDU IN");
399 coap_opt_iterator_t opt_iter;
400 coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
405 (*outCode) = (uint32_t) CA_RESPONSE_CODE(pdu->hdr->code);
408 // init HeaderOption list
409 uint32_t count = CAGetOptionCount(opt_iter);
413 OIC_LOG(ERROR, TAG, "outInfo is null");
416 memset(outInfo, 0, sizeof(*outInfo));
417 outInfo->numOptions = count;
419 outInfo->type = pdu->hdr->type;
422 outInfo->messageId = ntohs(pdu->hdr->id);
426 outInfo->options = (CAHeaderOption_t *) OICCalloc(count, sizeof(CAHeaderOption_t));
427 if (outInfo->options == NULL)
429 OIC_LOG(DEBUG, TAG, "CAGetInfoFromPDU, Memory allocation failed !");
434 char buf[COAP_MAX_PDU_SIZE] =
437 char optionResult[CA_MAX_URI_LENGTH] =
440 uint32_t optionLength = 0;
441 bool isfirstsetflag = false;
442 bool isQueryBeingProcessed = false;
444 while ((option = coap_option_next(&opt_iter)))
446 if (CAGetOptionData((uint8_t *) (COAP_OPT_VALUE(option)), COAP_OPT_LENGTH(option),
447 (uint8_t *) buf, sizeof(buf)))
449 OIC_LOG_V(DEBUG, TAG, "COAP URI element : %s", buf);
450 uint32_t bufLength = strlen(buf);
451 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
453 if (false == isfirstsetflag)
455 isfirstsetflag = true;
456 optionResult[optionLength] = '/';
458 memcpy(optionResult + optionLength, buf, bufLength);
459 optionLength += bufLength;
463 if (COAP_OPTION_URI_PATH == opt_iter.type)
465 optionResult[optionLength] = '/';
468 else if (COAP_OPTION_URI_QUERY == opt_iter.type)
470 if(false == isQueryBeingProcessed)
472 optionResult[optionLength] = '?';
474 isQueryBeingProcessed = true;
478 optionResult[optionLength] = '&';
482 memcpy(optionResult + optionLength, buf, bufLength);
483 optionLength += bufLength;
490 uint32_t length = bufLength;
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, "inside pdu->hdr->token_length");
509 outInfo->token = (char *) OICMalloc(pdu->hdr->token_length + 1);
510 if (outInfo->token == NULL)
512 OIC_LOG(DEBUG, TAG, "CAGetInfoFromPDU, Memory allocation failed !");
513 OICFree(outInfo->options);
516 memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length);
517 outInfo->token[pdu->hdr->token_length] = '\0';
521 if (NULL != pdu->data)
523 uint32_t payloadLength = strlen((char*) pdu->data);
524 OIC_LOG(DEBUG, TAG, "inside pdu->data");
525 outInfo->payload = (char *) OICMalloc(payloadLength + 1);
526 if (outInfo->payload == NULL)
528 OIC_LOG(DEBUG, TAG, "CAGetInfoFromPDU, Memory allocation failed !");
529 OICFree(outInfo->options);
530 OICFree(outInfo->token);
533 memcpy(outInfo->payload, pdu->data, payloadLength);
534 outInfo->payload[payloadLength] = '\0';
537 uint32_t length = strlen(optionResult);
538 OIC_LOG_V(DEBUG, TAG, "made URL length: %d, %d, %d...\n", length, buflen, strlen(outUri));
539 if (buflen >= length)
541 memcpy(outUri, optionResult, length);
542 outUri[length] = '\0';
543 OIC_LOG_V(DEBUG, TAG, "made URL : %s, %s\n", optionResult, outUri);
544 }OIC_LOG(DEBUG, TAG, "CAGetInfoFromPDU OUT");
547 CAResult_t CAGenerateTokenInternal(CAToken_t *token)
549 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal IN");
552 return CA_STATUS_FAILED;
556 char *temp = (char *) OICCalloc(1, (CA_MAX_TOKEN_LEN + 1) * sizeof(char));
559 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal, Memory allocation failed !");
560 return CA_MEMORY_ALLOC_FAILED;
568 OIC_LOG(DEBUG, TAG, "Failed to Create Seed!");
571 return CA_STATUS_FAILED;
578 for (index = 0; index < CA_MAX_TOKEN_LEN; index++)
580 // use valid characters
581 temp[index] = (random() % 94 + 33) & 0xFF;
588 OIC_LOG_V(DEBUG, TAG, "generate the token(%s)!!", *token);
590 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal OUT");
594 void CADestroyTokenInternal(CAToken_t token)
596 OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal IN");
599 OIC_LOG_V(DEBUG, TAG, "destroy the token(%s)!!", token);
605 OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal OUT");
608 void CADestroyInfo(CAInfo_t *info)
610 OIC_LOG(DEBUG, TAG, "CADestroyInfo IN");
614 if (NULL != info->options)
616 OIC_LOG(DEBUG, TAG, "free options in CAInfo");
617 OICFree(info->options);
620 if (NULL != info->token)
622 OIC_LOG(DEBUG, TAG, "free token in CAInfo");
623 OICFree(info->token);
626 if (NULL != info->payload)
628 OIC_LOG(DEBUG, TAG, "free payload in CAInfo");
629 OICFree(info->payload);
633 OIC_LOG(DEBUG, TAG, "OUT");
636 uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *option, uint32_t buflen)
638 assert(data || 0 == len);
640 if (0 == buflen || 0 == len)
642 OIC_LOG(ERROR, TAG, "buflen or len is not available");
648 OIC_LOG(ERROR, TAG, "data not available");
654 OIC_LOG(ERROR, TAG, "option pointer is null");
661 if (cnt == buflen - 1)
676 CAMessageType_t CAGetMessageTypeFromPduBinaryData(const void *pdu, uint32_t size)
678 // pdu minimum size is 4 byte.
679 if (size < CA_PDU_MIN_SIZE)
681 return CA_MSG_NONCONFIRM;
684 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
687 return CA_MSG_NONCONFIRM;
690 return (CAMessageType_t) hdr->type;
693 uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)
695 // pdu minimum size is 4 byte.
696 if (size < CA_PDU_MIN_SIZE)
701 coap_hdr_t *hdr = (coap_hdr_t *) pdu;
707 return ntohs(hdr->id);