52 #include "lib/random.h" 59 #define LOG_MODULE "coap" 60 #define LOG_LEVEL LOG_LEVEL_COAP 65 static uint16_t current_mid = 0;
67 coap_status_t coap_status_code = NO_ERROR;
68 const char *coap_error_message =
"";
73 coap_log_2(uint16_t value)
82 return result ? result - 1 : result;
86 coap_parse_int_option(uint8_t *bytes,
size_t length)
99 coap_option_nibble(
unsigned int value)
103 }
else if(value <= 0xFF + 13) {
111 coap_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);
137 coap_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);
175 coap_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);
224 coap_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;
245 coap_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;
259 for(start = buffer; start + name_len < end; ++
start) {
260 if((start == buffer || start[-1] ==
'&') && start[name_len] ==
'=' 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;
282 coap_init_connection(
void)
291 return ++current_mid;
295 coap_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;
307 coap_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;
417 coap_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;
602 LOG_DBG_(
"Proxy-Uri NOT IMPLEMENTED [");
603 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;
614 LOG_DBG_(
"Proxy-Scheme NOT IMPLEMENTED [");
615 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");
728 coap_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,
738 coap_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);
749 coap_set_status_code(coap_message_t *message,
unsigned int code)
752 message->code = (uint8_t)code;
760 coap_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;
771 coap_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;
780 coap_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);
788 coap_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;
797 coap_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);
805 coap_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;
814 coap_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);
822 coap_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;
831 coap_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;
842 coap_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;
851 coap_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;
861 coap_get_header_if_none_match(coap_message_t *message)
863 return coap_is_option(message, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0;
866 coap_set_header_if_none_match(coap_message_t *message)
868 coap_set_option(message, COAP_OPTION_IF_NONE_MATCH);
873 coap_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;
882 coap_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;
894 coap_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;
903 coap_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;
913 coap_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;
922 coap_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;
936 coap_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;
945 coap_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;
959 coap_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;
968 coap_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;
990 coap_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;
999 coap_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;
1013 coap_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;
1022 coap_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);
1030 coap_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;
1052 coap_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);
1073 coap_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;
1095 coap_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);
1116 coap_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;
1125 coap_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);
1133 coap_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;
1142 coap_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);
1150 coap_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;
1158 coap_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;
static uint8_t accept(uint8_t in)
static uint8_t output(const linkaddr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
static void start(void)
Start measurement.
CoAP module for reliable transport
An implementation of the Constrained Application Protocol (RFC 7252).
Default definitions of C compiler quirk work-arounds.
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.