52#include "lib/random.h"
59#define LOG_MODULE "coap"
60#define LOG_LEVEL LOG_LEVEL_COAP
65static uint16_t current_mid = 0;
67coap_status_t coap_status_code = NO_ERROR;
68const char *coap_error_message =
"";
73coap_log_2(uint16_t value)
82 return result ? result - 1 : result;
86coap_parse_int_option(
const uint8_t *bytes,
size_t length)
99coap_option_nibble(
unsigned int value)
103 }
else if(value <= 0xFF + 13) {
111coap_set_option_header(
unsigned int delta,
size_t length, uint8_t *buffer)
115 buffer[0] = coap_option_nibble(delta) << 4 | coap_option_nibble(length);
118 buffer[++written] = ((delta - 269) >> 8) & 0xff;
119 buffer[++written] = (delta - 269) & 0xff;
120 }
else if(delta > 12) {
121 buffer[++written] = (delta - 13);
125 buffer[++written] = ((length - 269) >> 8) & 0xff;
126 buffer[++written] = (length - 269) & 0xff;
127 }
else if(length > 12) {
128 buffer[++written] = (length - 13);
131 LOG_DBG(
"WRITTEN %zu B opt header\n", 1 + written);
137coap_serialize_int_option(
unsigned int number,
unsigned int current_number,
138 uint8_t *buffer, uint32_t value)
142 if(0xFF000000 & value) {
145 if(0xFFFF0000 & value) {
148 if(0xFFFFFF00 & value) {
151 if(0xFFFFFFFF & value) {
154 LOG_DBG(
"OPTION %u (delta %u, len %zu)\n", number, number - current_number,
157 i = coap_set_option_header(number - current_number, i, buffer);
159 if(0xFF000000 & value) {
160 buffer[i++] = (uint8_t)(value >> 24);
162 if(0xFFFF0000 & value) {
163 buffer[i++] = (uint8_t)(value >> 16);
165 if(0xFFFFFF00 & value) {
166 buffer[i++] = (uint8_t)(value >> 8);
168 if(0xFFFFFFFF & value) {
169 buffer[i++] = (uint8_t)(value);
175coap_serialize_array_option(
unsigned int number,
unsigned int current_number,
176 uint8_t *buffer, uint8_t *array,
size_t length,
181 LOG_DBG(
"ARRAY type %u, len %zu, full [", number, length);
182 LOG_DBG_COAP_STRING((
const char *)array, length);
185 if(split_char !=
'\0') {
187 uint8_t *part_start = array;
188 uint8_t *part_end = NULL;
191 for(j = 0; j <= length + 1; ++j) {
192 LOG_DBG(
"STEP %u/%zu (%c)\n", j, length, array[j]);
193 if(array[j] == split_char || j == length) {
194 part_end = array + j;
195 temp_length = part_end - part_start;
197 i += coap_set_option_header(number - current_number, temp_length,
199 memcpy(&buffer[i], part_start, temp_length);
202 LOG_DBG(
"OPTION type %u, delta %u, len %zu, part [", number,
203 number - current_number, i);
204 LOG_DBG_COAP_STRING((
const char *)part_start, temp_length);
207 current_number = number;
208 part_start = array + j;
212 i += coap_set_option_header(number - current_number, length, &buffer[i]);
213 memcpy(&buffer[i], array, length);
216 LOG_DBG(
"OPTION type %u, delta %u, len %zu\n", number,
217 number - current_number, length);
224coap_merge_multi_option(
char **dst,
size_t *dst_len, uint8_t *option,
225 size_t option_len,
char separator)
230 (*dst)[*dst_len] = separator;
234 memmove((*dst) + (*dst_len), option, option_len);
236 *dst_len += option_len;
239 *dst = (
char *)option;
240 *dst_len = option_len;
245coap_get_variable(
const char *buffer,
size_t length,
const char *name,
248 const char *
start = NULL;
249 const char *end = NULL;
250 const char *value_end = NULL;
256 name_len = strlen(name);
257 end = buffer + length;
261 && strncmp(name,
start, name_len) == 0) {
264 start += name_len + 1;
267 value_end = (
const char *)memchr(
start,
'&', end -
start);
268 if(value_end == NULL) {
273 return value_end -
start;
282coap_init_connection(
void)
291 return ++current_mid;
295coap_init_message(coap_message_t *coap_pkt, coap_message_type_t type,
296 uint8_t code, uint16_t mid)
299 memset(coap_pkt, 0,
sizeof(coap_message_t));
301 coap_pkt->type = type;
302 coap_pkt->code = code;
307coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer)
310 unsigned int current_number = 0;
313 coap_pkt->buffer = buffer;
314 coap_pkt->version = 1;
316 LOG_DBG(
"-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer);
319 coap_pkt->buffer[0] = 0x00;
320 coap_pkt->buffer[0] |= COAP_HEADER_VERSION_MASK
321 & (coap_pkt->version) << COAP_HEADER_VERSION_POSITION;
322 coap_pkt->buffer[0] |= COAP_HEADER_TYPE_MASK
323 & (coap_pkt->type) << COAP_HEADER_TYPE_POSITION;
324 coap_pkt->buffer[0] |= COAP_HEADER_TOKEN_LEN_MASK
325 & (coap_pkt->token_len) << COAP_HEADER_TOKEN_LEN_POSITION;
326 coap_pkt->buffer[1] = coap_pkt->code;
327 coap_pkt->buffer[2] = (uint8_t)((coap_pkt->mid) >> 8);
328 coap_pkt->buffer[3] = (uint8_t)(coap_pkt->mid);
331 if(!coap_pkt->code) {
332 LOG_DBG_(
"-Done serializing empty message at %p-\n", coap_pkt->buffer);
337 LOG_DBG_(
"Token (len %u)", coap_pkt->token_len);
338 option = coap_pkt->buffer + COAP_HEADER_LEN;
339 for(current_number = 0; current_number < coap_pkt->token_len;
341 LOG_DBG_(
" %02X", coap_pkt->token[current_number]);
342 *option = coap_pkt->token[current_number];
350 LOG_DBG(
"-Serializing options at %p-\n", option);
353 COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match,
"If-Match");
354 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_HOST, uri_host,
'\0',
356 COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_ETAG, etag,
"ETag");
357 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_IF_NONE_MATCH,
362 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_OBSERVE, observe,
"Observe");
363 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_URI_PORT, uri_port,
"Uri-Port");
364 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_PATH, location_path,
'/',
366 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path,
'/',
368 LOG_DBG(
"Serialize content format: %d\n", coap_pkt->content_format);
369 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format,
371 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age,
"Max-Age");
372 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_QUERY, uri_query,
'&',
374 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_ACCEPT,
accept,
"Accept");
375 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_QUERY, location_query,
376 '&',
"Location-Query");
377 COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK2, block2,
"Block2");
378 COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK1, block1,
"Block1");
379 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE2, size2,
"Size2");
380 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_URI, proxy_uri,
'\0',
382 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_SCHEME, proxy_scheme,
'\0',
384 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1,
"Size1");
386 LOG_DBG(
"-Done serializing at %p----\n", option);
389 if((option - coap_pkt->buffer) <= COAP_MAX_HEADER_SIZE) {
391 if(coap_pkt->payload_len) {
395 memmove(option, coap_pkt->payload, coap_pkt->payload_len);
398 coap_pkt->buffer = NULL;
399 coap_error_message =
"Serialized header exceeds COAP_MAX_HEADER_SIZE";
403 LOG_DBG(
"-Done %u B (header len %u, payload len %u)-\n",
404 (
unsigned int)(coap_pkt->payload_len + option - buffer),
405 (
unsigned int)(option - buffer),
406 (
unsigned int)coap_pkt->payload_len);
408 LOG_DBG(
"Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n",
409 coap_pkt->buffer[0], coap_pkt->buffer[1], coap_pkt->buffer[2],
410 coap_pkt->buffer[3], coap_pkt->buffer[4], coap_pkt->buffer[5],
411 coap_pkt->buffer[6], coap_pkt->buffer[7]);
413 return (option - buffer) + coap_pkt->payload_len;
417coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len)
419 if(data_len < COAP_HEADER_LEN) {
421 LOG_WARN(
"BAD REQUEST: message too short\n");
422 return BAD_REQUEST_4_00;
426 memset(coap_pkt, 0,
sizeof(coap_message_t));
429 coap_pkt->buffer = data;
432 coap_pkt->version = (COAP_HEADER_VERSION_MASK & coap_pkt->buffer[0])
433 >> COAP_HEADER_VERSION_POSITION;
434 coap_pkt->type = (COAP_HEADER_TYPE_MASK & coap_pkt->buffer[0])
435 >> COAP_HEADER_TYPE_POSITION;
436 coap_pkt->token_len = (COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->buffer[0])
437 >> COAP_HEADER_TOKEN_LEN_POSITION;
438 coap_pkt->code = coap_pkt->buffer[1];
439 coap_pkt->mid = coap_pkt->buffer[2] << 8 | coap_pkt->buffer[3];
441 if(coap_pkt->version != 1) {
442 coap_error_message =
"CoAP version must be 1";
443 return BAD_REQUEST_4_00;
446 if(coap_pkt->token_len > COAP_TOKEN_LEN) {
447 coap_error_message =
"Token Length must not be more than 8";
448 return BAD_REQUEST_4_00;
451 uint8_t *current_option = data + COAP_HEADER_LEN;
452 if(current_option + coap_pkt->token_len > data + data_len) {
454 LOG_WARN(
"BAD REQUEST: token outside message buffer");
455 return BAD_REQUEST_4_00;
458 memcpy(coap_pkt->token, current_option, coap_pkt->token_len);
459 LOG_DBG(
"Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
460 coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1],
461 coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4],
462 coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7]
466 memset(coap_pkt->options, 0,
sizeof(coap_pkt->options));
467 current_option += coap_pkt->token_len;
469 unsigned int option_number = 0;
470 unsigned int option_delta = 0;
471 size_t option_length = 0;
473 while(current_option < data + data_len) {
475 if((current_option[0] & 0xF0) == 0xF0) {
476 coap_pkt->payload = ++current_option;
477 coap_pkt->payload_len = data_len - (coap_pkt->payload - data);
480 if(coap_pkt->payload_len > COAP_MAX_CHUNK_SIZE) {
481 coap_pkt->payload_len = COAP_MAX_CHUNK_SIZE;
484 coap_pkt->payload[coap_pkt->payload_len] =
'\0';
489 option_delta = current_option[0] >> 4;
490 option_length = current_option[0] & 0x0F;
492 if(current_option >= data + data_len) {
494 LOG_WARN(
"BAD REQUEST: option delta outside message buffer\n");
495 return BAD_REQUEST_4_00;
498 if(option_delta == 13) {
499 option_delta += current_option[0];
501 }
else if(option_delta == 14) {
503 option_delta += current_option[0] << 8;
505 if(current_option >= data + data_len) {
507 LOG_WARN(
"BAD REQUEST: option delta outside message buffer\n");
508 return BAD_REQUEST_4_00;
510 option_delta += current_option[0];
514 if(current_option >= data + data_len) {
516 LOG_WARN(
"BAD REQUEST: option delta outside message buffer\n");
517 return BAD_REQUEST_4_00;
520 if(option_length == 13) {
521 option_length += current_option[0];
523 }
else if(option_length == 14) {
524 option_length += 255;
525 option_length += current_option[0] << 8;
527 if(current_option >= data + data_len) {
529 LOG_WARN(
"BAD REQUEST: option length outside message buffer\n");
530 return BAD_REQUEST_4_00;
532 option_length += current_option[0];
536 if(current_option + option_length > data + data_len) {
538 LOG_WARN(
"BAD REQUEST: options outside data message: %u > %u\n",
539 (
unsigned)(current_option + option_length - data), data_len);
540 return BAD_REQUEST_4_00;
543 option_number += option_delta;
545 if(option_number > COAP_OPTION_SIZE1) {
547 LOG_WARN(
"BAD REQUEST: option number too large: %u\n", option_number);
548 return BAD_REQUEST_4_00;
551 LOG_DBG(
"OPTION %u (delta %u, len %zu): ", option_number, option_delta,
554 coap_set_option(coap_pkt, option_number);
556 switch(option_number) {
557 case COAP_OPTION_CONTENT_FORMAT:
558 coap_pkt->content_format = coap_parse_int_option(current_option,
560 LOG_DBG_(
"Content-Format [%u]\n", coap_pkt->content_format);
562 case COAP_OPTION_MAX_AGE:
563 coap_pkt->max_age = coap_parse_int_option(current_option,
565 LOG_DBG_(
"Max-Age [%"PRIu32
"]\n", coap_pkt->max_age);
567 case COAP_OPTION_ETAG:
568 coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
569 memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len);
570 LOG_DBG_(
"ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
571 coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1],
572 coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4],
573 coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7]
576 case COAP_OPTION_ACCEPT:
577 coap_pkt->accept = coap_parse_int_option(current_option, option_length);
578 LOG_DBG_(
"Accept [%u]\n", coap_pkt->accept);
580 case COAP_OPTION_IF_MATCH:
582 coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length);
583 memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len);
584 LOG_DBG_(
"If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
585 coap_pkt->if_match_len, coap_pkt->if_match[0],
586 coap_pkt->if_match[1], coap_pkt->if_match[2],
587 coap_pkt->if_match[3], coap_pkt->if_match[4],
588 coap_pkt->if_match[5], coap_pkt->if_match[6],
589 coap_pkt->if_match[7]
592 case COAP_OPTION_IF_NONE_MATCH:
593 coap_pkt->if_none_match = 1;
594 LOG_DBG_(
"If-None-Match\n");
597 case COAP_OPTION_PROXY_URI:
598#if COAP_PROXY_OPTION_PROCESSING
599 coap_pkt->proxy_uri = (
char *)current_option;
600 coap_pkt->proxy_uri_len = option_length;
601 LOG_DBG_(
"Proxy-Uri NOT IMPLEMENTED [");
602 LOG_DBG_COAP_STRING(coap_pkt->proxy_uri, coap_pkt->proxy_uri_len);
606 coap_error_message =
"This is a constrained server (Contiki)";
607 return PROXYING_NOT_SUPPORTED_5_05;
609 case COAP_OPTION_PROXY_SCHEME:
610#if COAP_PROXY_OPTION_PROCESSING
611 coap_pkt->proxy_scheme = (
char *)current_option;
612 coap_pkt->proxy_scheme_len = option_length;
613 LOG_DBG_(
"Proxy-Scheme NOT IMPLEMENTED [");
614 LOG_DBG_COAP_STRING(coap_pkt->proxy_scheme, coap_pkt->proxy_scheme_len);
617 coap_error_message =
"This is a constrained server (Contiki)";
618 return PROXYING_NOT_SUPPORTED_5_05;
621 case COAP_OPTION_URI_HOST:
622 coap_pkt->uri_host = (
char *)current_option;
623 coap_pkt->uri_host_len = option_length;
624 LOG_DBG_(
"Uri-Host [");
625 LOG_DBG_COAP_STRING(coap_pkt->uri_host, coap_pkt->uri_host_len);
628 case COAP_OPTION_URI_PORT:
629 coap_pkt->uri_port = coap_parse_int_option(current_option,
631 LOG_DBG_(
"Uri-Port [%u]\n", coap_pkt->uri_port);
633 case COAP_OPTION_URI_PATH:
635 coap_merge_multi_option((
char **)&(coap_pkt->uri_path),
636 &(coap_pkt->uri_path_len), current_option,
638 LOG_DBG_(
"Uri-Path [");
639 LOG_DBG_COAP_STRING(coap_pkt->uri_path, coap_pkt->uri_path_len);
642 case COAP_OPTION_URI_QUERY:
644 coap_merge_multi_option((
char **)&(coap_pkt->uri_query),
645 &(coap_pkt->uri_query_len), current_option,
647 LOG_DBG_(
"Uri-Query[");
648 LOG_DBG_COAP_STRING(coap_pkt->uri_query, coap_pkt->uri_query_len);
652 case COAP_OPTION_LOCATION_PATH:
654 coap_merge_multi_option((
char **)&(coap_pkt->location_path),
655 &(coap_pkt->location_path_len), current_option,
658 LOG_DBG_(
"Location-Path [");
659 LOG_DBG_COAP_STRING(coap_pkt->location_path, coap_pkt->location_path_len);
662 case COAP_OPTION_LOCATION_QUERY:
664 coap_merge_multi_option((
char **)&(coap_pkt->location_query),
665 &(coap_pkt->location_query_len), current_option,
667 LOG_DBG_(
"Location-Query [");
668 LOG_DBG_COAP_STRING(coap_pkt->location_query, coap_pkt->location_query_len);
672 case COAP_OPTION_OBSERVE:
673 coap_pkt->observe = coap_parse_int_option(current_option,
675 LOG_DBG_(
"Observe [%"PRId32
"]\n", coap_pkt->observe);
677 case COAP_OPTION_BLOCK2:
678 coap_pkt->block2_num = coap_parse_int_option(current_option,
680 coap_pkt->block2_more = (coap_pkt->block2_num & 0x08) >> 3;
681 coap_pkt->block2_size = 16 << (coap_pkt->block2_num & 0x07);
682 coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)
683 << (coap_pkt->block2_num & 0x07);
684 coap_pkt->block2_num >>= 4;
685 LOG_DBG_(
"Block2 [%lu%s (%u B/blk)]\n",
686 (
unsigned long)coap_pkt->block2_num,
687 coap_pkt->block2_more ?
"+" :
"", coap_pkt->block2_size);
689 case COAP_OPTION_BLOCK1:
690 coap_pkt->block1_num = coap_parse_int_option(current_option,
692 coap_pkt->block1_more = (coap_pkt->block1_num & 0x08) >> 3;
693 coap_pkt->block1_size = 16 << (coap_pkt->block1_num & 0x07);
694 coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)
695 << (coap_pkt->block1_num & 0x07);
696 coap_pkt->block1_num >>= 4;
697 LOG_DBG_(
"Block1 [%lu%s (%u B/blk)]\n",
698 (
unsigned long)coap_pkt->block1_num,
699 coap_pkt->block1_more ?
"+" :
"", coap_pkt->block1_size);
701 case COAP_OPTION_SIZE2:
702 coap_pkt->size2 = coap_parse_int_option(current_option, option_length);
703 LOG_DBG_(
"Size2 [%"PRIu32
"]\n", coap_pkt->size2);
705 case COAP_OPTION_SIZE1:
706 coap_pkt->size1 = coap_parse_int_option(current_option, option_length);
707 LOG_DBG_(
"Size1 [%"PRIu32
"]\n", coap_pkt->size1);
710 LOG_DBG_(
"unknown (%u)\n", option_number);
712 if(option_number & 1) {
713 coap_error_message =
"Unsupported critical option";
714 return BAD_OPTION_4_02;
718 current_option += option_length;
720 LOG_DBG(
"-Done parsing-------\n");
728coap_get_query_variable(coap_message_t *coap_pkt,
729 const char *name,
const char **output)
731 if(coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) {
732 return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len,
738coap_get_post_variable(coap_message_t *coap_pkt,
739 const char *name,
const char **output)
741 if(coap_pkt->payload_len) {
742 return coap_get_variable((
const char *)coap_pkt->payload,
743 coap_pkt->payload_len, name, output);
749coap_set_status_code(coap_message_t *message,
unsigned int code)
752 message->code = (uint8_t)code;
760coap_set_token(coap_message_t *coap_pkt,
const uint8_t *token,
size_t token_len)
762 coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len);
763 memcpy(coap_pkt->token, token, coap_pkt->token_len);
765 return coap_pkt->token_len;
771coap_get_header_content_format(coap_message_t *coap_pkt,
unsigned int *format)
773 if(!coap_is_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) {
776 *format = coap_pkt->content_format;
780coap_set_header_content_format(coap_message_t *coap_pkt,
unsigned int format)
782 coap_pkt->content_format = format;
783 coap_set_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT);
788coap_get_header_accept(coap_message_t *coap_pkt,
unsigned int *
accept)
790 if(!coap_is_option(coap_pkt, COAP_OPTION_ACCEPT)) {
793 *
accept = coap_pkt->accept;
797coap_set_header_accept(coap_message_t *coap_pkt,
unsigned int accept)
799 coap_pkt->accept =
accept;
800 coap_set_option(coap_pkt, COAP_OPTION_ACCEPT);
805coap_get_header_max_age(coap_message_t *coap_pkt, uint32_t *age)
807 if(!coap_is_option(coap_pkt, COAP_OPTION_MAX_AGE)) {
808 *age = COAP_DEFAULT_MAX_AGE;
810 *age = coap_pkt->max_age;
814coap_set_header_max_age(coap_message_t *coap_pkt, uint32_t age)
816 coap_pkt->max_age = age;
817 coap_set_option(coap_pkt, COAP_OPTION_MAX_AGE);
822coap_get_header_etag(coap_message_t *coap_pkt,
const uint8_t **etag)
824 if(!coap_is_option(coap_pkt, COAP_OPTION_ETAG)) {
827 *etag = coap_pkt->etag;
828 return coap_pkt->etag_len;
831coap_set_header_etag(coap_message_t *coap_pkt,
const uint8_t *etag,
size_t etag_len)
833 coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len);
834 memcpy(coap_pkt->etag, etag, coap_pkt->etag_len);
836 coap_set_option(coap_pkt, COAP_OPTION_ETAG);
837 return coap_pkt->etag_len;
842coap_get_header_if_match(coap_message_t *coap_pkt,
const uint8_t **etag)
844 if(!coap_is_option(coap_pkt, COAP_OPTION_IF_MATCH)) {
847 *etag = coap_pkt->if_match;
848 return coap_pkt->if_match_len;
851coap_set_header_if_match(coap_message_t *coap_pkt,
const uint8_t *etag,
size_t etag_len)
853 coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len);
854 memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len);
856 coap_set_option(coap_pkt, COAP_OPTION_IF_MATCH);
857 return coap_pkt->if_match_len;
861coap_get_header_if_none_match(coap_message_t *message)
863 return coap_is_option(message, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0;
866coap_set_header_if_none_match(coap_message_t *message)
868 coap_set_option(message, COAP_OPTION_IF_NONE_MATCH);
873coap_get_header_proxy_uri(coap_message_t *coap_pkt,
const char **uri)
875 if(!coap_is_option(coap_pkt, COAP_OPTION_PROXY_URI)) {
878 *uri = coap_pkt->proxy_uri;
879 return coap_pkt->proxy_uri_len;
882coap_set_header_proxy_uri(coap_message_t *coap_pkt,
const char *uri)
886 coap_pkt->proxy_uri = uri;
887 coap_pkt->proxy_uri_len = strlen(uri);
889 coap_set_option(coap_pkt, COAP_OPTION_PROXY_URI);
890 return coap_pkt->proxy_uri_len;
894coap_get_header_uri_host(coap_message_t *coap_pkt,
const char **host)
896 if(!coap_is_option(coap_pkt, COAP_OPTION_URI_HOST)) {
899 *host = coap_pkt->uri_host;
900 return coap_pkt->uri_host_len;
903coap_set_header_uri_host(coap_message_t *coap_pkt,
const char *host)
905 coap_pkt->uri_host = host;
906 coap_pkt->uri_host_len = strlen(host);
908 coap_set_option(coap_pkt, COAP_OPTION_URI_HOST);
909 return coap_pkt->uri_host_len;
913coap_get_header_uri_path(coap_message_t *coap_pkt,
const char **path)
915 if(!coap_is_option(coap_pkt, COAP_OPTION_URI_PATH)) {
918 *path = coap_pkt->uri_path;
919 return coap_pkt->uri_path_len;
922coap_set_header_uri_path(coap_message_t *coap_pkt,
const char *path)
924 while(path[0] ==
'/') {
928 coap_pkt->uri_path = path;
929 coap_pkt->uri_path_len = strlen(path);
931 coap_set_option(coap_pkt, COAP_OPTION_URI_PATH);
932 return coap_pkt->uri_path_len;
936coap_get_header_uri_query(coap_message_t *coap_pkt,
const char **query)
938 if(!coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) {
941 *query = coap_pkt->uri_query;
942 return coap_pkt->uri_query_len;
945coap_set_header_uri_query(coap_message_t *coap_pkt,
const char *query)
947 while(query[0] ==
'?') {
951 coap_pkt->uri_query = query;
952 coap_pkt->uri_query_len = strlen(query);
954 coap_set_option(coap_pkt, COAP_OPTION_URI_QUERY);
955 return coap_pkt->uri_query_len;
959coap_get_header_location_path(coap_message_t *coap_pkt,
const char **path)
961 if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_PATH)) {
964 *path = coap_pkt->location_path;
965 return coap_pkt->location_path_len;
968coap_set_header_location_path(coap_message_t *coap_pkt,
const char *path)
972 while(path[0] ==
'/') {
976 if((query = strchr(path,
'?'))) {
977 coap_set_header_location_query(coap_pkt, query + 1);
978 coap_pkt->location_path_len = query - path;
980 coap_pkt->location_path_len = strlen(path);
981 } coap_pkt->location_path = path;
983 if(coap_pkt->location_path_len > 0) {
984 coap_set_option(coap_pkt, COAP_OPTION_LOCATION_PATH);
986 return coap_pkt->location_path_len;
990coap_get_header_location_query(coap_message_t *coap_pkt,
const char **query)
992 if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_QUERY)) {
995 *query = coap_pkt->location_query;
996 return coap_pkt->location_query_len;
999coap_set_header_location_query(coap_message_t *coap_pkt,
const char *query)
1001 while(query[0] ==
'?') {
1005 coap_pkt->location_query = query;
1006 coap_pkt->location_query_len = strlen(query);
1008 coap_set_option(coap_pkt, COAP_OPTION_LOCATION_QUERY);
1009 return coap_pkt->location_query_len;
1013coap_get_header_observe(coap_message_t *coap_pkt, uint32_t *observe)
1015 if(!coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) {
1018 *observe = coap_pkt->observe;
1022coap_set_header_observe(coap_message_t *coap_pkt, uint32_t observe)
1024 coap_pkt->observe = observe;
1025 coap_set_option(coap_pkt, COAP_OPTION_OBSERVE);
1030coap_get_header_block2(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more,
1031 uint16_t *size, uint32_t *offset)
1033 if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK2)) {
1038 *num = coap_pkt->block2_num;
1041 *more = coap_pkt->block2_more;
1044 *size = coap_pkt->block2_size;
1046 if(offset != NULL) {
1047 *offset = coap_pkt->block2_offset;
1052coap_set_header_block2(coap_message_t *coap_pkt, uint32_t num, uint8_t more,
1061 if(num > 0x0FFFFF) {
1064 coap_pkt->block2_num = num;
1065 coap_pkt->block2_more = more ? 1 : 0;
1066 coap_pkt->block2_size = size;
1068 coap_set_option(coap_pkt, COAP_OPTION_BLOCK2);
1073coap_get_header_block1(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more,
1074 uint16_t *size, uint32_t *offset)
1076 if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK1)) {
1081 *num = coap_pkt->block1_num;
1084 *more = coap_pkt->block1_more;
1087 *size = coap_pkt->block1_size;
1089 if(offset != NULL) {
1090 *offset = coap_pkt->block1_offset;
1095coap_set_header_block1(coap_message_t *coap_pkt, uint32_t num, uint8_t more,
1104 if(num > 0x0FFFFF) {
1107 coap_pkt->block1_num = num;
1108 coap_pkt->block1_more = more;
1109 coap_pkt->block1_size = size;
1111 coap_set_option(coap_pkt, COAP_OPTION_BLOCK1);
1116coap_get_header_size2(coap_message_t *coap_pkt, uint32_t *size)
1118 if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE2)) {
1121 *size = coap_pkt->size2;
1125coap_set_header_size2(coap_message_t *coap_pkt, uint32_t size)
1127 coap_pkt->size2 = size;
1128 coap_set_option(coap_pkt, COAP_OPTION_SIZE2);
1133coap_get_header_size1(coap_message_t *coap_pkt, uint32_t *size)
1135 if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE1)) {
1138 *size = coap_pkt->size1;
1142coap_set_header_size1(coap_message_t *coap_pkt, uint32_t size)
1144 coap_pkt->size1 = size;
1145 coap_set_option(coap_pkt, COAP_OPTION_SIZE1);
1150coap_get_payload(coap_message_t *coap_pkt,
const uint8_t **payload)
1152 if(payload != NULL) {
1153 *payload = coap_pkt->payload;
1155 return coap_pkt->payload != NULL ? coap_pkt->payload_len : 0;
1158coap_set_payload(coap_message_t *coap_pkt,
const void *payload,
size_t length)
1160 coap_pkt->payload = (uint8_t *)payload;
1161 coap_pkt->payload_len = MIN(COAP_MAX_CHUNK_SIZE, length);
1163 return coap_pkt->payload_len;
Default definitions of C compiler quirk work-arounds.
CoAP module for reliable transport.
An implementation of the Constrained Application Protocol (RFC 7252).
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
static uint8_t accept(uint8_t in)
static void start(void)
Start measurement.