58 #define LOG_MODULE "coap" 59 #define LOG_LEVEL LOG_LEVEL_COAP 64 static uint16_t current_mid = 0;
66 coap_status_t coap_status_code = NO_ERROR;
67 const char *coap_error_message =
"";
72 coap_log_2(uint16_t value)
81 return result ? result - 1 : result;
85 coap_parse_int_option(uint8_t *bytes,
size_t length)
98 coap_option_nibble(
unsigned int value)
102 }
else if(value <= 0xFF + 13) {
110 coap_set_option_header(
unsigned int delta,
size_t length, uint8_t *buffer)
114 buffer[0] = coap_option_nibble(delta) << 4 | coap_option_nibble(length);
117 buffer[++written] = ((delta - 269) >> 8) & 0xff;
118 buffer[++written] = (delta - 269) & 0xff;
119 }
else if(delta > 12) {
120 buffer[++written] = (delta - 13);
124 buffer[++written] = ((length - 269) >> 8) & 0xff;
125 buffer[++written] = (length - 269) & 0xff;
126 }
else if(length > 12) {
127 buffer[++written] = (length - 13);
130 LOG_DBG(
"WRITTEN %zu B opt header\n", 1 + written);
136 coap_serialize_int_option(
unsigned int number,
unsigned int current_number,
137 uint8_t *buffer, uint32_t value)
141 if(0xFF000000 & value) {
144 if(0xFFFF0000 & value) {
147 if(0xFFFFFF00 & value) {
150 if(0xFFFFFFFF & value) {
153 LOG_DBG(
"OPTION %u (delta %u, len %zu)\n", number, number - current_number,
156 i = coap_set_option_header(number - current_number, i, buffer);
158 if(0xFF000000 & value) {
159 buffer[i++] = (uint8_t)(value >> 24);
161 if(0xFFFF0000 & value) {
162 buffer[i++] = (uint8_t)(value >> 16);
164 if(0xFFFFFF00 & value) {
165 buffer[i++] = (uint8_t)(value >> 8);
167 if(0xFFFFFFFF & value) {
168 buffer[i++] = (uint8_t)(value);
174 coap_serialize_array_option(
unsigned int number,
unsigned int current_number,
175 uint8_t *buffer, uint8_t *array,
size_t length,
180 LOG_DBG(
"ARRAY type %u, len %zu, full [", number, length);
181 LOG_DBG_COAP_STRING((
const char *)array, length);
184 if(split_char !=
'\0') {
186 uint8_t *part_start = array;
187 uint8_t *part_end = NULL;
190 for(j = 0; j <= length + 1; ++j) {
191 LOG_DBG(
"STEP %u/%zu (%c)\n", j, length, array[j]);
192 if(array[j] == split_char || j == length) {
193 part_end = array + j;
194 temp_length = part_end - part_start;
196 i += coap_set_option_header(number - current_number, temp_length,
198 memcpy(&buffer[i], part_start, temp_length);
201 LOG_DBG(
"OPTION type %u, delta %u, len %zu, part [", number,
202 number - current_number, i);
203 LOG_DBG_COAP_STRING((
const char *)part_start, temp_length);
206 current_number = number;
207 part_start = array + j;
211 i += coap_set_option_header(number - current_number, length, &buffer[i]);
212 memcpy(&buffer[i], array, length);
215 LOG_DBG(
"OPTION type %u, delta %u, len %zu\n", number,
216 number - current_number, length);
223 coap_merge_multi_option(
char **dst,
size_t *dst_len, uint8_t *option,
224 size_t option_len,
char separator)
229 (*dst)[*dst_len] = separator;
233 memmove((*dst) + (*dst_len), option, option_len);
235 *dst_len += option_len;
238 *dst = (
char *)option;
239 *dst_len = option_len;
244 coap_get_variable(
const char *buffer,
size_t length,
const char *name,
247 const char *
start = NULL;
248 const char *end = NULL;
249 const char *value_end = NULL;
255 name_len = strlen(name);
256 end = buffer + length;
258 for(start = buffer; start + name_len < end; ++
start) {
259 if((start == buffer || start[-1] ==
'&') && start[name_len] ==
'=' 260 && strncmp(name, start, name_len) == 0) {
263 start += name_len + 1;
266 value_end = (
const char *)memchr(start,
'&', end - start);
267 if(value_end == NULL) {
272 return value_end -
start;
281 coap_init_connection(
void)
284 current_mid = rand();
290 return ++current_mid;
294 coap_init_message(coap_message_t *coap_pkt, coap_message_type_t type,
295 uint8_t code, uint16_t mid)
298 memset(coap_pkt, 0,
sizeof(coap_message_t));
300 coap_pkt->type = type;
301 coap_pkt->code = code;
306 coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer)
309 unsigned int current_number = 0;
312 coap_pkt->buffer = buffer;
313 coap_pkt->version = 1;
315 LOG_DBG(
"-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer);
318 coap_pkt->buffer[0] = 0x00;
319 coap_pkt->buffer[0] |= COAP_HEADER_VERSION_MASK
320 & (coap_pkt->version) << COAP_HEADER_VERSION_POSITION;
321 coap_pkt->buffer[0] |= COAP_HEADER_TYPE_MASK
322 & (coap_pkt->type) << COAP_HEADER_TYPE_POSITION;
323 coap_pkt->buffer[0] |= COAP_HEADER_TOKEN_LEN_MASK
324 & (coap_pkt->token_len) << COAP_HEADER_TOKEN_LEN_POSITION;
325 coap_pkt->buffer[1] = coap_pkt->code;
326 coap_pkt->buffer[2] = (uint8_t)((coap_pkt->mid) >> 8);
327 coap_pkt->buffer[3] = (uint8_t)(coap_pkt->mid);
330 if(!coap_pkt->code) {
331 LOG_DBG_(
"-Done serializing empty message at %p-\n", coap_pkt->buffer);
336 LOG_DBG_(
"Token (len %u)", coap_pkt->token_len);
337 option = coap_pkt->buffer + COAP_HEADER_LEN;
338 for(current_number = 0; current_number < coap_pkt->token_len;
340 LOG_DBG_(
" %02X", coap_pkt->token[current_number]);
341 *option = coap_pkt->token[current_number];
349 LOG_DBG(
"-Serializing options at %p-\n", option);
352 COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match,
"If-Match");
353 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_HOST, uri_host,
'\0',
355 COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_ETAG, etag,
"ETag");
356 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_IF_NONE_MATCH,
361 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_OBSERVE, observe,
"Observe");
362 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_URI_PORT, uri_port,
"Uri-Port");
363 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_PATH, location_path,
'/',
365 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path,
'/',
367 LOG_DBG(
"Serialize content format: %d\n", coap_pkt->content_format);
368 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format,
370 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age,
"Max-Age");
371 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_QUERY, uri_query,
'&',
373 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_ACCEPT,
accept,
"Accept");
374 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_QUERY, location_query,
375 '&',
"Location-Query");
376 COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK2, block2,
"Block2");
377 COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK1, block1,
"Block1");
378 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE2, size2,
"Size2");
379 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_URI, proxy_uri,
'\0',
381 COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_SCHEME, proxy_scheme,
'\0',
383 COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1,
"Size1");
385 LOG_DBG(
"-Done serializing at %p----\n", option);
388 if((option - coap_pkt->buffer) <= COAP_MAX_HEADER_SIZE) {
390 if(coap_pkt->payload_len) {
394 memmove(option, coap_pkt->payload, coap_pkt->payload_len);
397 coap_pkt->buffer = NULL;
398 coap_error_message =
"Serialized header exceeds COAP_MAX_HEADER_SIZE";
402 LOG_DBG(
"-Done %u B (header len %u, payload len %u)-\n",
403 (
unsigned int)(coap_pkt->payload_len + option - buffer),
404 (
unsigned int)(option - buffer),
405 (
unsigned int)coap_pkt->payload_len);
407 LOG_DBG(
"Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n",
408 coap_pkt->buffer[0], coap_pkt->buffer[1], coap_pkt->buffer[2],
409 coap_pkt->buffer[3], coap_pkt->buffer[4], coap_pkt->buffer[5],
410 coap_pkt->buffer[6], coap_pkt->buffer[7]);
412 return (option - buffer) + coap_pkt->payload_len;
416 coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len)
419 memset(coap_pkt, 0,
sizeof(coap_message_t));
422 coap_pkt->buffer = data;
425 coap_pkt->version = (COAP_HEADER_VERSION_MASK & coap_pkt->buffer[0])
426 >> COAP_HEADER_VERSION_POSITION;
427 coap_pkt->type = (COAP_HEADER_TYPE_MASK & coap_pkt->buffer[0])
428 >> COAP_HEADER_TYPE_POSITION;
429 coap_pkt->token_len = (COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->buffer[0])
430 >> COAP_HEADER_TOKEN_LEN_POSITION;
431 coap_pkt->code = coap_pkt->buffer[1];
432 coap_pkt->mid = coap_pkt->buffer[2] << 8 | coap_pkt->buffer[3];
434 if(coap_pkt->version != 1) {
435 coap_error_message =
"CoAP version must be 1";
436 return BAD_REQUEST_4_00;
439 if(coap_pkt->token_len > COAP_TOKEN_LEN) {
440 coap_error_message =
"Token Length must not be more than 8";
441 return BAD_REQUEST_4_00;
444 uint8_t *current_option = data + COAP_HEADER_LEN;
446 memcpy(coap_pkt->token, current_option, coap_pkt->token_len);
447 LOG_DBG(
"Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
448 coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1],
449 coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4],
450 coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7]
454 memset(coap_pkt->options, 0,
sizeof(coap_pkt->options));
455 current_option += coap_pkt->token_len;
457 unsigned int option_number = 0;
458 unsigned int option_delta = 0;
459 size_t option_length = 0;
461 while(current_option < data + data_len) {
463 if((current_option[0] & 0xF0) == 0xF0) {
464 coap_pkt->payload = ++current_option;
465 coap_pkt->payload_len = data_len - (coap_pkt->payload - data);
468 if(coap_pkt->payload_len > COAP_MAX_CHUNK_SIZE) {
469 coap_pkt->payload_len = COAP_MAX_CHUNK_SIZE;
472 coap_pkt->payload[coap_pkt->payload_len] =
'\0';
477 option_delta = current_option[0] >> 4;
478 option_length = current_option[0] & 0x0F;
481 if(option_delta == 13) {
482 option_delta += current_option[0];
484 }
else if(option_delta == 14) {
486 option_delta += current_option[0] << 8;
488 option_delta += current_option[0];
492 if(option_length == 13) {
493 option_length += current_option[0];
495 }
else if(option_length == 14) {
496 option_length += 255;
497 option_length += current_option[0] << 8;
499 option_length += current_option[0];
503 if(current_option + option_length > data + data_len) {
505 LOG_WARN(
"BAD REQUEST: options outside data message: %u > %u\n",
506 (
unsigned)(current_option + option_length - data), data_len);
507 return BAD_REQUEST_4_00;
510 option_number += option_delta;
512 if(option_number > COAP_OPTION_SIZE1) {
514 LOG_WARN(
"BAD REQUEST: option number too large: %u\n", option_number);
515 return BAD_REQUEST_4_00;
518 LOG_DBG(
"OPTION %u (delta %u, len %zu): ", option_number, option_delta,
521 coap_set_option(coap_pkt, option_number);
523 switch(option_number) {
524 case COAP_OPTION_CONTENT_FORMAT:
525 coap_pkt->content_format = coap_parse_int_option(current_option,
527 LOG_DBG_(
"Content-Format [%u]\n", coap_pkt->content_format);
529 case COAP_OPTION_MAX_AGE:
530 coap_pkt->max_age = coap_parse_int_option(current_option,
532 LOG_DBG_(
"Max-Age [%"PRIu32
"]\n", coap_pkt->max_age);
534 case COAP_OPTION_ETAG:
535 coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
536 memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len);
537 LOG_DBG_(
"ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
538 coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1],
539 coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4],
540 coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7]
543 case COAP_OPTION_ACCEPT:
544 coap_pkt->accept = coap_parse_int_option(current_option, option_length);
545 LOG_DBG_(
"Accept [%u]\n", coap_pkt->accept);
547 case COAP_OPTION_IF_MATCH:
549 coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length);
550 memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len);
551 LOG_DBG_(
"If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
552 coap_pkt->if_match_len, coap_pkt->if_match[0],
553 coap_pkt->if_match[1], coap_pkt->if_match[2],
554 coap_pkt->if_match[3], coap_pkt->if_match[4],
555 coap_pkt->if_match[5], coap_pkt->if_match[6],
556 coap_pkt->if_match[7]
559 case COAP_OPTION_IF_NONE_MATCH:
560 coap_pkt->if_none_match = 1;
561 LOG_DBG_(
"If-None-Match\n");
564 case COAP_OPTION_PROXY_URI:
565 #if COAP_PROXY_OPTION_PROCESSING 566 coap_pkt->proxy_uri = (
char *)current_option;
567 coap_pkt->proxy_uri_len = option_length;
569 LOG_DBG_(
"Proxy-Uri NOT IMPLEMENTED [");
570 LOG_DBG_COAP_STRING(coap_pkt->proxy_uri, coap_pkt->proxy_uri_len);
573 coap_error_message =
"This is a constrained server (Contiki)";
574 return PROXYING_NOT_SUPPORTED_5_05;
576 case COAP_OPTION_PROXY_SCHEME:
577 #if COAP_PROXY_OPTION_PROCESSING 578 coap_pkt->proxy_scheme = (
char *)current_option;
579 coap_pkt->proxy_scheme_len = option_length;
581 LOG_DBG_(
"Proxy-Scheme NOT IMPLEMENTED [");
582 LOG_DBG_COAP_STRING(coap_pkt->proxy_scheme, coap_pkt->proxy_scheme_len);
584 coap_error_message =
"This is a constrained server (Contiki)";
585 return PROXYING_NOT_SUPPORTED_5_05;
588 case COAP_OPTION_URI_HOST:
589 coap_pkt->uri_host = (
char *)current_option;
590 coap_pkt->uri_host_len = option_length;
591 LOG_DBG_(
"Uri-Host [");
592 LOG_DBG_COAP_STRING(coap_pkt->uri_host, coap_pkt->uri_host_len);
595 case COAP_OPTION_URI_PORT:
596 coap_pkt->uri_port = coap_parse_int_option(current_option,
598 LOG_DBG_(
"Uri-Port [%u]\n", coap_pkt->uri_port);
600 case COAP_OPTION_URI_PATH:
602 coap_merge_multi_option((
char **)&(coap_pkt->uri_path),
603 &(coap_pkt->uri_path_len), current_option,
605 LOG_DBG_(
"Uri-Path [");
606 LOG_DBG_COAP_STRING(coap_pkt->uri_path, coap_pkt->uri_path_len);
609 case COAP_OPTION_URI_QUERY:
611 coap_merge_multi_option((
char **)&(coap_pkt->uri_query),
612 &(coap_pkt->uri_query_len), current_option,
614 LOG_DBG_(
"Uri-Query[");
615 LOG_DBG_COAP_STRING(coap_pkt->uri_query, coap_pkt->uri_query_len);
619 case COAP_OPTION_LOCATION_PATH:
621 coap_merge_multi_option((
char **)&(coap_pkt->location_path),
622 &(coap_pkt->location_path_len), current_option,
625 LOG_DBG_(
"Location-Path [");
626 LOG_DBG_COAP_STRING(coap_pkt->location_path, coap_pkt->location_path_len);
629 case COAP_OPTION_LOCATION_QUERY:
631 coap_merge_multi_option((
char **)&(coap_pkt->location_query),
632 &(coap_pkt->location_query_len), current_option,
634 LOG_DBG_(
"Location-Query [");
635 LOG_DBG_COAP_STRING(coap_pkt->location_query, coap_pkt->location_query_len);
639 case COAP_OPTION_OBSERVE:
640 coap_pkt->observe = coap_parse_int_option(current_option,
642 LOG_DBG_(
"Observe [%"PRId32
"]\n", coap_pkt->observe);
644 case COAP_OPTION_BLOCK2:
645 coap_pkt->block2_num = coap_parse_int_option(current_option,
647 coap_pkt->block2_more = (coap_pkt->block2_num & 0x08) >> 3;
648 coap_pkt->block2_size = 16 << (coap_pkt->block2_num & 0x07);
649 coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)
650 << (coap_pkt->block2_num & 0x07);
651 coap_pkt->block2_num >>= 4;
652 LOG_DBG_(
"Block2 [%lu%s (%u B/blk)]\n",
653 (
unsigned long)coap_pkt->block2_num,
654 coap_pkt->block2_more ?
"+" :
"", coap_pkt->block2_size);
656 case COAP_OPTION_BLOCK1:
657 coap_pkt->block1_num = coap_parse_int_option(current_option,
659 coap_pkt->block1_more = (coap_pkt->block1_num & 0x08) >> 3;
660 coap_pkt->block1_size = 16 << (coap_pkt->block1_num & 0x07);
661 coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)
662 << (coap_pkt->block1_num & 0x07);
663 coap_pkt->block1_num >>= 4;
664 LOG_DBG_(
"Block1 [%lu%s (%u B/blk)]\n",
665 (
unsigned long)coap_pkt->block1_num,
666 coap_pkt->block1_more ?
"+" :
"", coap_pkt->block1_size);
668 case COAP_OPTION_SIZE2:
669 coap_pkt->size2 = coap_parse_int_option(current_option, option_length);
670 LOG_DBG_(
"Size2 [%"PRIu32
"]\n", coap_pkt->size2);
672 case COAP_OPTION_SIZE1:
673 coap_pkt->size1 = coap_parse_int_option(current_option, option_length);
674 LOG_DBG_(
"Size1 [%"PRIu32
"]\n", coap_pkt->size1);
677 LOG_DBG_(
"unknown (%u)\n", option_number);
679 if(option_number & 1) {
680 coap_error_message =
"Unsupported critical option";
681 return BAD_OPTION_4_02;
685 current_option += option_length;
687 LOG_DBG(
"-Done parsing-------\n");
695 coap_get_query_variable(coap_message_t *coap_pkt,
696 const char *name,
const char **output)
698 if(coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) {
699 return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len,
705 coap_get_post_variable(coap_message_t *coap_pkt,
706 const char *name,
const char **output)
708 if(coap_pkt->payload_len) {
709 return coap_get_variable((
const char *)coap_pkt->payload,
710 coap_pkt->payload_len, name, output);
716 coap_set_status_code(coap_message_t *message,
unsigned int code)
719 message->code = (uint8_t)code;
727 coap_set_token(coap_message_t *coap_pkt,
const uint8_t *token,
size_t token_len)
729 coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len);
730 memcpy(coap_pkt->token, token, coap_pkt->token_len);
732 return coap_pkt->token_len;
738 coap_get_header_content_format(coap_message_t *coap_pkt,
unsigned int *format)
740 if(!coap_is_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) {
743 *format = coap_pkt->content_format;
747 coap_set_header_content_format(coap_message_t *coap_pkt,
unsigned int format)
749 coap_pkt->content_format = format;
750 coap_set_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT);
755 coap_get_header_accept(coap_message_t *coap_pkt,
unsigned int *
accept)
757 if(!coap_is_option(coap_pkt, COAP_OPTION_ACCEPT)) {
760 *accept = coap_pkt->accept;
764 coap_set_header_accept(coap_message_t *coap_pkt,
unsigned int accept)
766 coap_pkt->accept =
accept;
767 coap_set_option(coap_pkt, COAP_OPTION_ACCEPT);
772 coap_get_header_max_age(coap_message_t *coap_pkt, uint32_t *age)
774 if(!coap_is_option(coap_pkt, COAP_OPTION_MAX_AGE)) {
775 *age = COAP_DEFAULT_MAX_AGE;
777 *age = coap_pkt->max_age;
781 coap_set_header_max_age(coap_message_t *coap_pkt, uint32_t age)
783 coap_pkt->max_age = age;
784 coap_set_option(coap_pkt, COAP_OPTION_MAX_AGE);
789 coap_get_header_etag(coap_message_t *coap_pkt,
const uint8_t **etag)
791 if(!coap_is_option(coap_pkt, COAP_OPTION_ETAG)) {
794 *etag = coap_pkt->etag;
795 return coap_pkt->etag_len;
798 coap_set_header_etag(coap_message_t *coap_pkt,
const uint8_t *etag,
size_t etag_len)
800 coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len);
801 memcpy(coap_pkt->etag, etag, coap_pkt->etag_len);
803 coap_set_option(coap_pkt, COAP_OPTION_ETAG);
804 return coap_pkt->etag_len;
809 coap_get_header_if_match(coap_message_t *coap_pkt,
const uint8_t **etag)
811 if(!coap_is_option(coap_pkt, COAP_OPTION_IF_MATCH)) {
814 *etag = coap_pkt->if_match;
815 return coap_pkt->if_match_len;
818 coap_set_header_if_match(coap_message_t *coap_pkt,
const uint8_t *etag,
size_t etag_len)
820 coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len);
821 memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len);
823 coap_set_option(coap_pkt, COAP_OPTION_IF_MATCH);
824 return coap_pkt->if_match_len;
828 coap_get_header_if_none_match(coap_message_t *message)
830 return coap_is_option(message, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0;
833 coap_set_header_if_none_match(coap_message_t *message)
835 coap_set_option(message, COAP_OPTION_IF_NONE_MATCH);
840 coap_get_header_proxy_uri(coap_message_t *coap_pkt,
const char **uri)
842 if(!coap_is_option(coap_pkt, COAP_OPTION_PROXY_URI)) {
845 *uri = coap_pkt->proxy_uri;
846 return coap_pkt->proxy_uri_len;
849 coap_set_header_proxy_uri(coap_message_t *coap_pkt,
const char *uri)
853 coap_pkt->proxy_uri = uri;
854 coap_pkt->proxy_uri_len = strlen(uri);
856 coap_set_option(coap_pkt, COAP_OPTION_PROXY_URI);
857 return coap_pkt->proxy_uri_len;
861 coap_get_header_uri_host(coap_message_t *coap_pkt,
const char **host)
863 if(!coap_is_option(coap_pkt, COAP_OPTION_URI_HOST)) {
866 *host = coap_pkt->uri_host;
867 return coap_pkt->uri_host_len;
870 coap_set_header_uri_host(coap_message_t *coap_pkt,
const char *host)
872 coap_pkt->uri_host = host;
873 coap_pkt->uri_host_len = strlen(host);
875 coap_set_option(coap_pkt, COAP_OPTION_URI_HOST);
876 return coap_pkt->uri_host_len;
880 coap_get_header_uri_path(coap_message_t *coap_pkt,
const char **path)
882 if(!coap_is_option(coap_pkt, COAP_OPTION_URI_PATH)) {
885 *path = coap_pkt->uri_path;
886 return coap_pkt->uri_path_len;
889 coap_set_header_uri_path(coap_message_t *coap_pkt,
const char *path)
891 while(path[0] ==
'/') {
895 coap_pkt->uri_path = path;
896 coap_pkt->uri_path_len = strlen(path);
898 coap_set_option(coap_pkt, COAP_OPTION_URI_PATH);
899 return coap_pkt->uri_path_len;
903 coap_get_header_uri_query(coap_message_t *coap_pkt,
const char **query)
905 if(!coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) {
908 *query = coap_pkt->uri_query;
909 return coap_pkt->uri_query_len;
912 coap_set_header_uri_query(coap_message_t *coap_pkt,
const char *query)
914 while(query[0] ==
'?') {
918 coap_pkt->uri_query = query;
919 coap_pkt->uri_query_len = strlen(query);
921 coap_set_option(coap_pkt, COAP_OPTION_URI_QUERY);
922 return coap_pkt->uri_query_len;
926 coap_get_header_location_path(coap_message_t *coap_pkt,
const char **path)
928 if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_PATH)) {
931 *path = coap_pkt->location_path;
932 return coap_pkt->location_path_len;
935 coap_set_header_location_path(coap_message_t *coap_pkt,
const char *path)
939 while(path[0] ==
'/') {
943 if((query = strchr(path,
'?'))) {
944 coap_set_header_location_query(coap_pkt, query + 1);
945 coap_pkt->location_path_len = query - path;
947 coap_pkt->location_path_len = strlen(path);
948 } coap_pkt->location_path = path;
950 if(coap_pkt->location_path_len > 0) {
951 coap_set_option(coap_pkt, COAP_OPTION_LOCATION_PATH);
953 return coap_pkt->location_path_len;
957 coap_get_header_location_query(coap_message_t *coap_pkt,
const char **query)
959 if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_QUERY)) {
962 *query = coap_pkt->location_query;
963 return coap_pkt->location_query_len;
966 coap_set_header_location_query(coap_message_t *coap_pkt,
const char *query)
968 while(query[0] ==
'?') {
972 coap_pkt->location_query = query;
973 coap_pkt->location_query_len = strlen(query);
975 coap_set_option(coap_pkt, COAP_OPTION_LOCATION_QUERY);
976 return coap_pkt->location_query_len;
980 coap_get_header_observe(coap_message_t *coap_pkt, uint32_t *observe)
982 if(!coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) {
985 *observe = coap_pkt->observe;
989 coap_set_header_observe(coap_message_t *coap_pkt, uint32_t observe)
991 coap_pkt->observe = observe;
992 coap_set_option(coap_pkt, COAP_OPTION_OBSERVE);
997 coap_get_header_block2(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more,
998 uint16_t *size, uint32_t *offset)
1000 if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK2)) {
1005 *num = coap_pkt->block2_num;
1008 *more = coap_pkt->block2_more;
1011 *size = coap_pkt->block2_size;
1013 if(offset != NULL) {
1014 *offset = coap_pkt->block2_offset;
1019 coap_set_header_block2(coap_message_t *coap_pkt, uint32_t num, uint8_t more,
1028 if(num > 0x0FFFFF) {
1031 coap_pkt->block2_num = num;
1032 coap_pkt->block2_more = more ? 1 : 0;
1033 coap_pkt->block2_size = size;
1035 coap_set_option(coap_pkt, COAP_OPTION_BLOCK2);
1040 coap_get_header_block1(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more,
1041 uint16_t *size, uint32_t *offset)
1043 if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK1)) {
1048 *num = coap_pkt->block1_num;
1051 *more = coap_pkt->block1_more;
1054 *size = coap_pkt->block1_size;
1056 if(offset != NULL) {
1057 *offset = coap_pkt->block1_offset;
1062 coap_set_header_block1(coap_message_t *coap_pkt, uint32_t num, uint8_t more,
1071 if(num > 0x0FFFFF) {
1074 coap_pkt->block1_num = num;
1075 coap_pkt->block1_more = more;
1076 coap_pkt->block1_size = size;
1078 coap_set_option(coap_pkt, COAP_OPTION_BLOCK1);
1083 coap_get_header_size2(coap_message_t *coap_pkt, uint32_t *size)
1085 if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE2)) {
1088 *size = coap_pkt->size2;
1092 coap_set_header_size2(coap_message_t *coap_pkt, uint32_t size)
1094 coap_pkt->size2 = size;
1095 coap_set_option(coap_pkt, COAP_OPTION_SIZE2);
1100 coap_get_header_size1(coap_message_t *coap_pkt, uint32_t *size)
1102 if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE1)) {
1105 *size = coap_pkt->size1;
1109 coap_set_header_size1(coap_message_t *coap_pkt, uint32_t size)
1111 coap_pkt->size1 = size;
1112 coap_set_option(coap_pkt, COAP_OPTION_SIZE1);
1117 coap_get_payload(coap_message_t *coap_pkt,
const uint8_t **payload)
1119 if(payload != NULL) {
1120 *payload = coap_pkt->payload;
1122 return coap_pkt->payload != NULL ? coap_pkt->payload_len : 0;
1125 coap_set_payload(coap_message_t *coap_pkt,
const void *payload,
size_t length)
1127 coap_pkt->payload = (uint8_t *)payload;
1128 coap_pkt->payload_len = MIN(COAP_MAX_CHUNK_SIZE, length);
1130 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.