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_MAX_TOKEN_LEN (8)
33 #define CA_FLAGS_BLOCK 0x01
34 #define CA_BUFSIZE 128
35 #define CA_COAP_MESSAGE_CON 0
41 #endif //#ifdef __ARDUINO__
43 uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo, char *outUri)
45 OIC_LOG(DEBUG, TAG, "CAGetRequestInfoFromPdu IN");
49 uint32_t code = CA_NOT_FOUND;
50 CAGetRequestPDUInfo(pdu, &code, &(outReqInfo->info), outUri);
51 outReqInfo->method = code;
52 OIC_LOG(DEBUG, TAG, "CAGetRequestInfoFromPdu OUT");
56 uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo, char *outUri)
58 OIC_LOG(DEBUG, TAG, "CAGetResponseInfoFromPdu IN");
62 uint32_t code = CA_NOT_FOUND;
63 CAGetRequestPDUInfo(pdu, &code, &(outResInfo->info), outUri);
64 outResInfo->result = code;
65 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");
75 uint32_t coapHeaderLength = 12;
77 coap_list_t *optlist = NULL;
83 if (CA_MAX_URI_LENGTH < length)
85 OIC_LOG(DEBUG, TAG, "check URI length..");
89 coapUri = (char *) OICMalloc(length + coapHeaderLength + 1);
90 memset(coapUri, 0, length + coapHeaderLength + 1);
94 memcpy(coapUri, "coap://[::]/", coapHeaderLength);
95 memcpy(coapUri + coapHeaderLength, uri, length);
97 // parsing options in URI
98 CAParseURI(coapUri, &optlist);
100 // parsing options in HeadOption
101 CAParseHeadOption(code, info, &optlist);
106 if (NULL != info.payload) // payload is include in request / response
108 if (!(pdu = CACreatePDUforRequestWithPayload((code_t) code, optlist, info.payload, info)))
111 else // payload is not include in request / response
113 if (!(pdu = CACreatePDUforRequest((code_t) code, optlist, info)))
117 // pdu print method : coap_show_pdu(pdu);
118 OIC_LOG(DEBUG, TAG, "CAGeneratePdu OUT");
122 coap_pdu_t *CAParsePDU(const char *data, uint32_t *outCode)
124 OIC_LOG(DEBUG, TAG, "CAParsePDU IN");
125 coap_pdu_t *outpdu = coap_new_pdu();
126 coap_pdu_parse((unsigned char *) data, strlen(data), outpdu);
127 (*outCode) = (uint32_t) outpdu->hdr->code;
128 OIC_LOG(DEBUG, TAG, "CAParsePDU OUT");
132 coap_pdu_t *CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *options,
133 const char* payload, const CAInfo_t info)
135 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload IN");
140 uint32_t CAFlags = 0;
141 coap_block_t CABlock =
142 { .num = 0, .m = 0, .szx = 6 };
144 if (!(pdu = coap_new_pdu()))
147 /* initialize message id */
148 unsigned short message_id;
149 prng((unsigned char * )&message_id, sizeof(unsigned short));
151 pdu->hdr->type = CA_COAP_MESSAGE_CON;
153 pdu->hdr->id = htons(message_id);
154 pdu->hdr->code = code;
156 pdu->hdr->token_length = strlen(info.token);
157 if (!coap_add_token(pdu, strlen(info.token),(unsigned char*)info.token))
159 OIC_LOG(DEBUG, TAG, "cannot add token to request");
162 for (opt = options; opt; opt = opt->next)
164 coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),
165 COAP_OPTION_LENGTH(*(coap_option * )opt->data),
166 COAP_OPTION_DATA(*(coap_option * )opt->data));
171 uint32_t len = strlen(payload);
172 if ((CAFlags & CA_FLAGS_BLOCK) == 0)
174 OIC_LOG_V(DEBUG, TAG, "coap_add_data, payload: %s", payload);
175 coap_add_data(pdu, len, (const unsigned char *) payload);
179 OIC_LOG_V(DEBUG, TAG, "coap_add_block, payload: %s", payload);
180 coap_add_block(pdu, len, (const unsigned char *) payload, CABlock.num, CABlock.szx);
183 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload OUT");
187 coap_pdu_t* CACreatePDUforRequest(const code_t code, coap_list_t *options, const CAInfo_t info)
189 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest IN");
194 if (!(pdu = coap_new_pdu()))
196 OIC_LOG(DEBUG, TAG, "Out of memory");
200 /* initialize message id */
201 unsigned short message_id;
202 prng((unsigned char * )&message_id, sizeof(unsigned short));
204 pdu->hdr->type = CA_COAP_MESSAGE_CON;
206 pdu->hdr->id = htons(message_id);
207 pdu->hdr->code = code;
209 OIC_LOG_V(DEBUG, TAG, "token info : %s, %d", info.token, strlen(info.token));
210 pdu->hdr->token_length = strlen(info.token);
211 if (!coap_add_token(pdu, strlen(info.token),(unsigned char*) info.token))
213 OIC_LOG(DEBUG, TAG, "cannot add token to request");
216 for (opt = options; opt; opt = opt->next)
218 coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option * )opt->data),
219 COAP_OPTION_LENGTH(*(coap_option * )opt->data),
220 COAP_OPTION_DATA(*(coap_option * )opt->data));
222 OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest OUT");
226 void CAParseURI(const char *uriInfo, coap_list_t **optlist)
228 OIC_LOG(DEBUG, TAG, "CAParseURI IN");
230 unsigned char portbuf[2];
231 unsigned char _buf[CA_BUFSIZE];
232 unsigned char *buf = _buf;
237 OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);
239 /* split arg into Uri-* options */
240 coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
242 if (uri.port != COAP_DEFAULT_PORT)
245 CACreateNewOptionNode(COAP_OPTION_URI_PORT,
246 coap_encode_var_bytes(portbuf, uri.port), portbuf), CAOrderOpts);
252 res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
257 CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf),
258 COAP_OPT_VALUE(buf)), CAOrderOpts);
259 buf += COAP_OPT_SIZE(buf);
263 if (uri.query.length)
267 res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
272 CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf),
273 COAP_OPT_VALUE(buf)), CAOrderOpts);
275 buf += COAP_OPT_SIZE(buf);
278 OIC_LOG(DEBUG, TAG, "CAParseURI OUT");
281 void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)
283 OIC_LOG(DEBUG, TAG, "CAParseHeadOption IN");
284 OIC_LOG_V(DEBUG, TAG, "start parse Head Option : %d", info.numOptions);
287 for (i = 0; i < info.numOptions; i++)
289 uint32_t id = info.options[i].optionID;
290 if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
292 OIC_LOG_V(DEBUG, TAG, "it is not Header Option : %d", id);
296 OIC_LOG_V(DEBUG, TAG, "Head Option ID: %d", info.options[i].optionID);
297 OIC_LOG_V(DEBUG, TAG, "Head Option data: %s", info.options[i].optionData);
298 OIC_LOG_V(DEBUG, TAG, "Head Option length: %d", info.options[i].optionLength);
301 CACreateNewOptionNode(info.options[i].optionID, info.options[i].optionLength,
302 info.options[i].optionData), CAOrderOpts);
305 OIC_LOG(DEBUG, TAG, "CAParseHeadOption OUT");
308 coap_list_t *CACreateNewOptionNode(const uint16_t key, const uint32_t length, const uint8_t *data)
310 OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode IN");
314 option = coap_malloc(sizeof(coap_option) + length);
317 OIC_LOG(DEBUG, TAG, "Out of memory");
320 memset(option, 0, sizeof(coap_option)+length);
322 COAP_OPTION_KEY(*option) = key;
323 COAP_OPTION_LENGTH(*option) = length;
324 memcpy(COAP_OPTION_DATA(*option), data, length);
326 /* we can pass NULL here as delete function since option is released automatically */
327 node = coap_new_listnode(option, NULL);
331 OIC_LOG(DEBUG, TAG, "coap_new_listnode returns NULL");
336 OIC_LOG(DEBUG, TAG, "CACreateNewOptionNode OUT");
340 int CAOrderOpts(void *a, void *b)
342 OIC_LOG(DEBUG, TAG, "CAOrderOpts IN");
345 return a < b ? -1 : 1;
348 if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option * )b))
352 OIC_LOG(DEBUG, TAG, "CAOrderOpts OUT");
353 return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option * )b);
356 uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
358 OIC_LOG(DEBUG, TAG, "CAGetOptionCount IN");
362 while ((option = coap_option_next(&opt_iter)))
364 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
371 OIC_LOG(DEBUG, TAG, "CAGetOptionCount OUT");
375 void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo, char *outUri)
377 OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo IN");
378 char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */
380 coap_opt_iterator_t opt_iter;
382 char optionResult[CA_MAX_URI_LENGTH] =
384 uint32_t count = 0, idx = 0;
385 uint32_t optionLength = 0;
386 uint32_t isfirstsetflag = 0;
388 coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
390 memset(optionResult, 0, sizeof(optionResult));
393 (*outCode) = (uint32_t) pdu->hdr->code;
395 // init HeaderOption list
396 count = CAGetOptionCount(opt_iter);
398 memset(outInfo, 0, sizeof(CAInfo_t));
399 outInfo->numOptions = count;
402 outInfo->options = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * count);
403 memset(outInfo->options, 0, sizeof(CAHeaderOption_t) * count);
406 while ((option = coap_option_next(&opt_iter)))
409 if (CAGetOptionData((uint8_t*)(COAP_OPT_VALUE(option)), COAP_OPT_LENGTH(option), (uint8_t*)buf, sizeof(buf),
412 if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
414 if (0 == isfirstsetflag)
417 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
418 optionLength += strlen((const char *) buf);
423 if (COAP_OPTION_URI_PATH == opt_iter.type)
425 memcpy(optionResult + optionLength, "/", 1);
428 else if (COAP_OPTION_URI_QUERY == opt_iter.type)
430 memcpy(optionResult + optionLength, "?", 1);
433 memcpy(optionResult + optionLength, buf, strlen((const char *) buf));
434 optionLength += strlen((const char *) buf);
440 uint32_t length = (uint32_t) strlen((const char *) buf);
442 if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)
444 outInfo->options[idx].optionID = opt_iter.type;
445 outInfo->options[idx].optionLength = length;
446 outInfo->options[idx].protocolID = CA_COAP_ID;
447 memcpy(outInfo->options[idx].optionData, buf, length);
456 if (pdu->hdr->token_length > 0)
458 OIC_LOG(DEBUG, TAG, "inside pdu->hdr->token_length");
459 outInfo->token = (char *) OICMalloc(pdu->hdr->token_length);
460 memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length);
464 if (NULL != pdu->data)
466 OIC_LOG(DEBUG, TAG, "inside pdu->data");
467 outInfo->payload = (char *) OICMalloc(strlen((const char *) pdu->data) + 1);
468 memcpy(outInfo->payload, pdu->data, strlen((const char *) pdu->data) + 1);
471 OIC_LOG_V(DEBUG, TAG, "made URL : %s\n", optionResult);
473 memcpy(outUri, optionResult, strlen(optionResult));
474 OIC_LOG(DEBUG, TAG, "CAGetRequestPDUInfo OUT");
477 CAResult_t CAGenerateTokenInternal(CAToken_t *token)
479 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal IN");
482 return CA_STATUS_FAILED;
486 char *temp = (char *) OICMalloc(sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
490 return CA_MEMORY_ALLOC_FAILED;
492 memset(temp, 0, sizeof(char) * (CA_MAX_TOKEN_LEN + 1));
499 #endif //#ifndef __ARDUINO__
500 for (index = 0; index < CA_MAX_TOKEN_LEN; index++)
502 // use valid characters
503 temp[index] = (rand() % 94 + 33) & 0xFF;
510 OIC_LOG_V(DEBUG, TAG, "generate the token(%s)!!", *token);
511 OIC_LOG(DEBUG, TAG, "CAGenerateTokenInternal OUT");
515 void CADestroyTokenInternal(CAToken_t token)
517 OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal IN");
520 OIC_LOG_V(DEBUG, TAG, "destroy the token(%s)!!", token);
524 OIC_LOG(DEBUG, TAG, "CADestroyTokenInternal OUT");
527 void CADeinitialize(CAInfo_t *info)
529 OIC_LOG(DEBUG, TAG, "CADeinitialize IN");
533 if (NULL != info->options)
535 OIC_LOG(DEBUG, TAG, "free options in CAInfo");
536 OICFree(info->options);
539 if (NULL != info->token)
541 OIC_LOG(DEBUG, TAG, "free token in CAInfo");
542 OICFree(info->token);
545 if (NULL != info->payload)
547 OIC_LOG(DEBUG, TAG, "free payload in CAInfo");
548 OICFree(info->payload);
551 OIC_LOG(DEBUG, TAG, "CADeinitialize OUT");
554 uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *result,
555 uint32_t buflen, uint32_t encode_always)
557 const unsigned char hex[] = "0123456789ABCDEF";
559 assert(data || len == 0);
561 if (buflen == 0 || len == 0)
575 if (cnt + 4 < buflen)
579 *result++ = hex[(*data & 0xf0) >> 4];
580 *result++ = hex[*data & 0x0f];