pdu.c
Go to the documentation of this file.
/* pdu.c -- CoAP message structure
*
* Copyright (C) 2010--2016 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
* README for terms of use.
*/
#include "coap_internal.h"
#if defined(HAVE_LIMITS_H)
#include <limits.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
void
coap_pdu_clear(coap_pdu_t *pdu, size_t size) {
assert(pdu);
assert(pdu->token);
assert(pdu->max_hdr_size >= COAP_PDU_MAX_UDP_HEADER_SIZE);
if (pdu->alloc_size > size)
pdu->alloc_size = size;
pdu->type = 0;
pdu->code = 0;
pdu->hdr_size = 0;
pdu->token_length = 0;
pdu->tid = 0;
pdu->max_delta = 0;
pdu->max_size = size;
pdu->used_size = 0;
pdu->data = NULL;
}
#ifdef WITH_LWIP
coap_pdu_t *
coap_pdu_from_pbuf( struct pbuf *pbuf )
{
coap_pdu_t *pdu;
if (pbuf == NULL) return NULL;
LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len);
LWIP_ASSERT("coap_read needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1);
pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t) );
if (!pdu) {
pbuf_free(pbuf);
return NULL;
}
pdu->max_hdr_size = COAP_PDU_MAX_UDP_HEADER_SIZE;
pdu->pbuf = pbuf;
pdu->token = (uint8_t *)pbuf->payload + pdu->max_hdr_size;
pdu->alloc_size = pbuf->tot_len - pdu->max_hdr_size;
coap_pdu_clear(pdu, pdu->alloc_size);
return pdu;
}
#endif
coap_pdu_t *
coap_pdu_init(uint8_t type, uint8_t code, uint16_t tid, size_t size) {
coap_pdu_t *pdu;
pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t));
if (!pdu) return NULL;
#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
assert(size <= COAP_MAX_MESSAGE_SIZE_TCP16 + 4);
if (size > COAP_MAX_MESSAGE_SIZE_TCP16 + 4)
return NULL;
pdu->max_hdr_size = COAP_PDU_MAX_UDP_HEADER_SIZE;
#else
pdu->max_hdr_size = COAP_PDU_MAX_TCP_HEADER_SIZE;
#endif
#ifdef WITH_LWIP
pdu->pbuf = pbuf_alloc(PBUF_TRANSPORT, size + pdu->max_hdr_size, PBUF_RAM);
if (pdu->pbuf == NULL) {
coap_free_type(COAP_PDU, pdu);
return NULL;
}
pdu->token = (uint8_t *)pdu->pbuf->payload + pdu->max_hdr_size;
#else /* WITH_LWIP */
uint8_t *buf;
pdu->alloc_size = min(size, 256);
buf = coap_malloc_type(COAP_PDU_BUF, pdu->alloc_size + pdu->max_hdr_size);
if (buf == NULL) {
coap_free_type(COAP_PDU, pdu);
return NULL;
}
pdu->token = buf + pdu->max_hdr_size;
#endif /* WITH_LWIP */
coap_pdu_clear(pdu, size);
pdu->tid = tid;
pdu->type = type;
pdu->code = code;
return pdu;
}
coap_pdu_t *
coap_new_pdu(const struct coap_session_t *session) {
coap_pdu_t *pdu = coap_pdu_init(0, 0, 0, coap_session_max_pdu_size(session));
if (!pdu)
coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n");
return pdu;
}
void
coap_delete_pdu(coap_pdu_t *pdu) {
if (pdu != NULL) {
#ifdef WITH_LWIP
pbuf_free(pdu->pbuf);
#else
if (pdu->token != NULL)
coap_free_type(COAP_PDU_BUF, pdu->token - pdu->max_hdr_size);
#endif
coap_free_type(COAP_PDU, pdu);
}
}
int
coap_pdu_resize(coap_pdu_t *pdu, size_t new_size) {
if (new_size > pdu->alloc_size) {
#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
uint8_t *new_hdr;
size_t offset;
#endif
if (pdu->max_size && new_size > pdu->max_size) {
coap_log(LOG_WARNING, "coap_pdu_resize: pdu too big\n");
return 0;
}
#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
if (pdu->data != NULL) {
assert(pdu->data > pdu->token);
offset = pdu->data - pdu->token;
} else {
offset = 0;
}
new_hdr = (uint8_t*)realloc(pdu->token - pdu->max_hdr_size, new_size + pdu->max_hdr_size);
if (new_hdr == NULL) {
coap_log(LOG_WARNING, "coap_pdu_resize: realloc failed\n");
return 0;
}
pdu->token = new_hdr + pdu->max_hdr_size;
if (offset > 0)
pdu->data = pdu->token + offset;
else
pdu->data = NULL;
#endif
}
pdu->alloc_size = new_size;
return 1;
}
static int
coap_pdu_check_resize(coap_pdu_t *pdu, size_t size) {
if (size > pdu->alloc_size) {
size_t new_size = max(256, pdu->alloc_size * 2);
while (size > new_size)
new_size *= 2;
if (pdu->max_size && new_size > pdu->max_size) {
new_size = pdu->max_size;
if (new_size < size)
return 0;
}
if (!coap_pdu_resize(pdu, new_size))
return 0;
}
return 1;
}
int
coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
/* must allow for pdu == NULL as callers may rely on this */
if (!pdu || len > 8)
return 0;
if (pdu->used_size) {
coap_log(LOG_WARNING,
"coap_add_token: The token must defined first. Token ignored\n");
return 0;
}
if (!coap_pdu_check_resize(pdu, len))
return 0;
pdu->token_length = (uint8_t)len;
if (len)
memcpy(pdu->token, data, len);
pdu->max_delta = 0;
pdu->used_size = len;
pdu->data = NULL;
return 1;
}
/* FIXME: de-duplicate code with coap_add_option_later */
size_t
coap_add_option(coap_pdu_t *pdu, uint16_t type, size_t len, const uint8_t *data) {
size_t optsize;
coap_opt_t *opt;
assert(pdu);
pdu->data = NULL;
if (type < pdu->max_delta) {
coap_log(LOG_WARNING,
"coap_add_option: options are not in correct order\n");
return 0;
}
if (!coap_pdu_check_resize(pdu,
pdu->used_size + coap_opt_encode_size(type - pdu->max_delta, len)))
return 0;
opt = pdu->token + pdu->used_size;
/* encode option and check length */
optsize = coap_opt_encode(opt, pdu->alloc_size - pdu->used_size,
type - pdu->max_delta, data, len);
if (!optsize) {
coap_log(LOG_WARNING, "coap_add_option: cannot add option\n");
/* error */
return 0;
} else {
pdu->max_delta = type;
pdu->used_size += optsize;
}
return optsize;
}
/* FIXME: de-duplicate code with coap_add_option */
uint8_t*
coap_add_option_later(coap_pdu_t *pdu, uint16_t type, size_t len) {
size_t optsize;
coap_opt_t *opt;
assert(pdu);
pdu->data = NULL;
if (type < pdu->max_delta) {
coap_log(LOG_WARNING,
"coap_add_option: options are not in correct order\n");
return NULL;
}
if (!coap_pdu_check_resize(pdu,
pdu->used_size + coap_opt_encode_size(type - pdu->max_delta, len)))
return 0;
opt = pdu->token + pdu->used_size;
/* encode option and check length */
optsize = coap_opt_encode(opt, pdu->alloc_size - pdu->used_size,
type - pdu->max_delta, NULL, len);
if (!optsize) {
coap_log(LOG_WARNING, "coap_add_option: cannot add option\n");
/* error */
return NULL;
} else {
pdu->max_delta = type;
pdu->used_size += (uint16_t)optsize;
}
return opt + optsize - len;
}
int
coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
if (len == 0) {
return 1;
} else {
uint8_t *payload = coap_add_data_after(pdu, len);
if (payload != NULL)
memcpy(payload, data, len);
return payload != NULL;
}
}
uint8_t *
coap_add_data_after(coap_pdu_t *pdu, size_t len) {
assert(pdu);
assert(pdu->data == NULL);
pdu->data = NULL;
if (len == 0)
return NULL;
if (!coap_pdu_resize(pdu, pdu->used_size + len + 1))
return 0;
pdu->token[pdu->used_size++] = COAP_PAYLOAD_START;
pdu->data = pdu->token + pdu->used_size;
pdu->used_size += len;
return pdu->data;
}
int
coap_get_data(const coap_pdu_t *pdu, size_t *len, uint8_t **data) {
assert(pdu);
assert(len);
assert(data);
*data = pdu->data;
if(pdu->data == NULL) {
*len = 0;
return 0;
}
*len = pdu->used_size - (pdu->data - pdu->token);
return 1;
}
#ifndef SHORT_ERROR_RESPONSE
typedef struct {
unsigned char code;
const char *phrase;
} error_desc_t;
/* if you change anything here, make sure, that the longest string does not
* exceed COAP_ERROR_PHRASE_LENGTH. */
error_desc_t coap_error[] = {
{ COAP_RESPONSE_CODE(201), "Created" },
{ COAP_RESPONSE_CODE(202), "Deleted" },
{ COAP_RESPONSE_CODE(203), "Valid" },
{ COAP_RESPONSE_CODE(204), "Changed" },
{ COAP_RESPONSE_CODE(205), "Content" },
{ COAP_RESPONSE_CODE(231), "Continue" },
{ COAP_RESPONSE_CODE(400), "Bad Request" },
{ COAP_RESPONSE_CODE(401), "Unauthorized" },
{ COAP_RESPONSE_CODE(402), "Bad Option" },
{ COAP_RESPONSE_CODE(403), "Forbidden" },
{ COAP_RESPONSE_CODE(404), "Not Found" },
{ COAP_RESPONSE_CODE(405), "Method Not Allowed" },
{ COAP_RESPONSE_CODE(406), "Not Acceptable" },
{ COAP_RESPONSE_CODE(408), "Request Entity Incomplete" },
{ COAP_RESPONSE_CODE(412), "Precondition Failed" },
{ COAP_RESPONSE_CODE(413), "Request Entity Too Large" },
{ COAP_RESPONSE_CODE(415), "Unsupported Content-Format" },
{ COAP_RESPONSE_CODE(500), "Internal Server Error" },
{ COAP_RESPONSE_CODE(501), "Not Implemented" },
{ COAP_RESPONSE_CODE(502), "Bad Gateway" },
{ COAP_RESPONSE_CODE(503), "Service Unavailable" },
{ COAP_RESPONSE_CODE(504), "Gateway Timeout" },
{ COAP_RESPONSE_CODE(505), "Proxying Not Supported" },
{ 0, NULL } /* end marker */
};
const char *
coap_response_phrase(unsigned char code) {
int i;
for (i = 0; coap_error[i].code; ++i) {
if (coap_error[i].code == code)
return coap_error[i].phrase;
}
return NULL;
}
#endif
static size_t
next_option_safe(coap_opt_t **optp, size_t *length) {
coap_option_t option;
size_t optsize;
assert(optp); assert(*optp);
assert(length);
optsize = coap_opt_parse(*optp, *length, &option);
if (optsize) {
assert(optsize <= *length);
*optp += optsize;
*length -= optsize;
}
return optsize;
}
size_t
coap_pdu_parse_header_size(coap_proto_t proto,
const uint8_t *data) {
assert(data);
size_t header_size = 0;
if (proto == COAP_PROTO_TCP || proto==COAP_PROTO_TLS) {
uint8_t len = *data >> 4;
if (len < 13)
header_size = 2;
else if (len==13)
header_size = 3;
else if (len==14)
header_size = 4;
else
header_size = 6;
} else if (proto == COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) {
header_size = 4;
}
return header_size;
}
size_t
coap_pdu_parse_size(coap_proto_t proto,
const uint8_t *data,
size_t length) {
assert(data);
assert(proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS);
assert(coap_pdu_parse_header_size(proto, data) <= length );
size_t size = 0;
if ((proto == COAP_PROTO_TCP || proto==COAP_PROTO_TLS) && length >= 1) {
uint8_t len = *data >> 4;
if (len < 13) {
size = len;
} else if (length >= 2) {
if (len==13) {
size = (size_t)data[1] + COAP_MESSAGE_SIZE_OFFSET_TCP8;
} else if (length >= 3) {
if (len==14) {
size = ((size_t)data[1] << 8) + data[2] + COAP_MESSAGE_SIZE_OFFSET_TCP16;
} else if (length >= 5) {
size = ((size_t)data[1] << 24) + ((size_t)data[2] << 16)
+ ((size_t)data[3] << 8) + data[4] + COAP_MESSAGE_SIZE_OFFSET_TCP32;
}
}
}
size += data[0] & 0x0f;
}
return size;
}
int
coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto) {
uint8_t *hdr = pdu->token - pdu->hdr_size;
if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) {
assert(pdu->hdr_size == 4);
if ((hdr[0] >> 6) != COAP_DEFAULT_VERSION) {
coap_log(LOG_DEBUG, "coap_pdu_parse: UDP version not supported\n");
return 0;
}
pdu->type = (hdr[0] >> 4) & 0x03;
pdu->token_length = hdr[0] & 0x0f;
pdu->code = hdr[1];
pdu->tid = (uint16_t)hdr[2] << 8 | hdr[3];
} else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) {
assert(pdu->hdr_size >= 2 && pdu->hdr_size <= 6);
pdu->type = COAP_MESSAGE_CON;
pdu->token_length = hdr[0] & 0x0f;
pdu->code = hdr[pdu->hdr_size-1];
pdu->tid = 0;
} else {
coap_log(LOG_DEBUG, "coap_pdu_parse: unsupported protocol\n");
return 0;
}
if (pdu->token_length > pdu->alloc_size) {
/* Invalid PDU provided - not wise to assert here though */
coap_log(LOG_DEBUG, "coap_pdu_parse: PDU header token size broken\n");
pdu->token_length = (uint8_t)pdu->alloc_size;
return 0;
}
return 1;
}
int
coap_pdu_parse_opt(coap_pdu_t *pdu) {
/* sanity checks */
if (pdu->code == 0) {
if (pdu->used_size != 0 || pdu->token_length) {
coap_log(LOG_DEBUG, "coap_pdu_parse: empty message is not empty\n");
return 0;
}
}
if (pdu->token_length > pdu->used_size || pdu->token_length > 8) {
coap_log(LOG_DEBUG, "coap_pdu_parse: invalid Token\n");
return 0;
}
if (pdu->code == 0) {
/* empty packet */
pdu->used_size = 0;
pdu->data = NULL;
} else {
/* skip header + token */
coap_opt_t *opt = pdu->token + pdu->token_length;
size_t length = pdu->used_size - pdu->token_length;
while (length > 0 && *opt != COAP_PAYLOAD_START) {
if ( !next_option_safe( &opt, (size_t *)&length ) ) {
coap_log(LOG_DEBUG, "coap_pdu_parse: missing payload start code\n");
return 0;
}
}
if (length > 0) {
assert(*opt == COAP_PAYLOAD_START);
opt++; length--;
if (length == 0) {
coap_log(LOG_DEBUG,
"coap_pdu_parse: message ending in payload start marker\n");
return 0;
}
}
if (length > 0)
pdu->data = (uint8_t*)opt;
else
pdu->data = NULL;
}
return 1;
}
int
coap_pdu_parse(coap_proto_t proto,
const uint8_t *data,
size_t length,
coap_pdu_t *pdu)
{
size_t hdr_size;
if (length == 0)
return 0;
hdr_size = coap_pdu_parse_header_size(proto, data);
if (!hdr_size || hdr_size > length)
return 0;
if (hdr_size > pdu->max_hdr_size)
return 0;
if (!coap_pdu_resize(pdu, length - hdr_size))
return 0;
#ifndef WITH_LWIP
memcpy(pdu->token - hdr_size, data, length);
#endif
pdu->hdr_size = (uint8_t)hdr_size;
pdu->used_size = length - hdr_size;
return coap_pdu_parse_header(pdu, proto) && coap_pdu_parse_opt(pdu);
}
size_t
coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto) {
if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) {
assert(pdu->max_hdr_size >= 4);
if (pdu->max_hdr_size < 4) {
coap_log(LOG_WARNING,
"coap_pdu_encode_header: not enough space for UDP-style header\n");
return 0;
}
pdu->token[-4] = COAP_DEFAULT_VERSION << 6
| pdu->type << 4
| pdu->token_length;
pdu->token[-3] = pdu->code;
pdu->token[-2] = (uint8_t)(pdu->tid >> 8);
pdu->token[-1] = (uint8_t)(pdu->tid);
pdu->hdr_size = 4;
} else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) {
size_t len;
assert(pdu->used_size >= pdu->token_length);
if (pdu->used_size < pdu->token_length) {
coap_log(LOG_WARNING, "coap_pdu_encode_header: corrupted PDU\n");
return 0;
}
len = pdu->used_size - pdu->token_length;
if (len <= COAP_MAX_MESSAGE_SIZE_TCP0) {
assert(pdu->max_hdr_size >= 2);
if (pdu->max_hdr_size < 2) {
coap_log(LOG_WARNING,
"coap_pdu_encode_header: not enough space for TCP0 header\n");
return 0;
}
pdu->token[-2] = (uint8_t)len << 4
| pdu->token_length;
pdu->token[-1] = pdu->code;
pdu->hdr_size = 2;
} else if (len <= COAP_MAX_MESSAGE_SIZE_TCP8) {
assert(pdu->max_hdr_size >= 3);
if (pdu->max_hdr_size < 3) {
coap_log(LOG_WARNING,
"coap_pdu_encode_header: not enough space for TCP8 header\n");
return 0;
}
pdu->token[-3] = 13 << 4 | pdu->token_length;
pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP8);
pdu->token[-1] = pdu->code;
pdu->hdr_size = 3;
} else if (len <= COAP_MAX_MESSAGE_SIZE_TCP16) {
assert(pdu->max_hdr_size >= 4);
if (pdu->max_hdr_size < 4) {
coap_log(LOG_WARNING,
"coap_pdu_encode_header: not enough space for TCP16 header\n");
return 0;
}
pdu->token[-4] = 14 << 4 | pdu->token_length;
pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP16) >> 8);
pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP16);
pdu->token[-1] = pdu->code;
pdu->hdr_size = 4;
} else {
assert(pdu->max_hdr_size >= 6);
if (pdu->max_hdr_size < 6) {
coap_log(LOG_WARNING,
"coap_pdu_encode_header: not enough space for TCP32 header\n");
return 0;
}
pdu->token[-6] = 15 << 4 | pdu->token_length;
pdu->token[-5] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 24);
pdu->token[-4] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 16);
pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 8);
pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP32);
pdu->token[-1] = pdu->code;
pdu->hdr_size = 6;
}
} else {
coap_log(LOG_WARNING, "coap_pdu_encode_header: unsupported protocol\n");
}
return pdu->hdr_size;
}
coap_internal.h
Pulls together all the internal only header files.
coap_session_max_pdu_size
size_t coap_session_max_pdu_size(const coap_session_t *session)
Get maximum acceptable PDU size.
Definition: coap_session.c:187
coap_log
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:129
LOG_CRIT
@ LOG_CRIT
Critical.
Definition: coap_debug.h:50
LOG_WARNING
@ LOG_WARNING
Warning.
Definition: coap_debug.h:52
LOG_DEBUG
@ LOG_DEBUG
Debug.
Definition: coap_debug.h:55
coap_opt_encode
size_t coap_opt_encode(coap_opt_t *opt, size_t maxlen, uint16_t delta, const uint8_t *val, size_t length)
Encodes option with given delta into opt.
Definition: option.c:398
coap_opt_encode_size
size_t coap_opt_encode_size(uint16_t delta, size_t length)
Compute storage bytes needed for an option with given delta and length.
Definition: option.c:377
coap_malloc_type
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
COAP_PDU
@ COAP_PDU
Definition: mem.h:37
COAP_PDU_BUF
@ COAP_PDU_BUF
Definition: mem.h:38
coap_free_type
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
coap_opt_parse
size_t coap_opt_parse(const coap_opt_t *opt, size_t length, coap_option_t *result)
Parses the option pointed to by opt into result.
Definition: option.c:35
coap_opt_t
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
Definition: option.h:25
next_option_safe
static size_t next_option_safe(coap_opt_t **optp, size_t *length)
Advances *optp to next option if still in PDU.
Definition: pdu.c:386
coap_error
error_desc_t coap_error[]
Definition: pdu.c:342
coap_delete_pdu
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition: pdu.c:127
coap_pdu_parse_header
int coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto)
Decode the protocol specific header for the specified PDU.
Definition: pdu.c:460
coap_pdu_parse_header_size
size_t coap_pdu_parse_header_size(coap_proto_t proto, const uint8_t *data)
Interprets data to determine the number of bytes in the header.
Definition: pdu.c:405
coap_get_data
int coap_get_data(const coap_pdu_t *pdu, size_t *len, uint8_t **data)
Retrieves the length and data pointer of specified PDU.
Definition: pdu.c:318
coap_pdu_init
coap_pdu_t * coap_pdu_init(uint8_t type, uint8_t code, uint16_t tid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size.
Definition: pdu.c:79
coap_add_token
int coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds token of length len to pdu.
Definition: pdu.c:191
coap_new_pdu
coap_pdu_t * coap_new_pdu(const struct coap_session_t *session)
Creates a new CoAP PDU.
Definition: pdu.c:119
coap_pdu_clear
void coap_pdu_clear(coap_pdu_t *pdu, size_t size)
Clears any contents from pdu and resets used_size, and data pointers.
Definition: pdu.c:34
coap_add_option
size_t coap_add_option(coap_pdu_t *pdu, uint16_t type, size_t len, const uint8_t *data)
Adds option of given type to pdu that is passed as first parameter.
Definition: pdu.c:215
coap_pdu_parse_opt
int coap_pdu_parse_opt(coap_pdu_t *pdu)
Verify consistency in the given CoAP PDU structure and locate the data.
Definition: pdu.c:492
coap_add_option_later
uint8_t * coap_add_option_later(coap_pdu_t *pdu, uint16_t type, size_t len)
Adds option of given type to pdu that is passed as first parameter, but does not write a value.
Definition: pdu.c:252
coap_add_data_after
uint8_t * coap_add_data_after(coap_pdu_t *pdu, size_t len)
Adds given data to the pdu that is passed as first parameter but does not copyt it.
Definition: pdu.c:300
coap_pdu_encode_header
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto)
Compose the protocol specific header for the specified PDU.
Definition: pdu.c:568
coap_pdu_parse
int coap_pdu_parse(coap_proto_t proto, const uint8_t *data, size_t length, coap_pdu_t *pdu)
Parses data into the CoAP PDU structure given in result.
Definition: pdu.c:543
min
#define min(a, b)
Definition: pdu.c:26
coap_response_phrase
const char * coap_response_phrase(unsigned char code)
Returns a human-readable response phrase for the specified CoAP response code.
Definition: pdu.c:370
coap_pdu_parse_size
size_t coap_pdu_parse_size(coap_proto_t proto, const uint8_t *data, size_t length)
Parses data to extract the message size.
Definition: pdu.c:428
coap_pdu_resize
int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size)
Dynamically grows the size of pdu to new_size.
Definition: pdu.c:140
coap_pdu_check_resize
static int coap_pdu_check_resize(coap_pdu_t *pdu, size_t size)
Definition: pdu.c:174
coap_add_data
int coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds given data to the pdu that is passed as first parameter.
Definition: pdu.c:288
max
#define max(a, b)
Definition: pdu.c:30
COAP_MESSAGE_SIZE_OFFSET_TCP8
#define COAP_MESSAGE_SIZE_OFFSET_TCP8
Definition: pdu.h:36
COAP_PROTO_TCP
#define COAP_PROTO_TCP
Definition: pdu.h:344
COAP_PDU_MAX_UDP_HEADER_SIZE
#define COAP_PDU_MAX_UDP_HEADER_SIZE
Definition: pdu.h:315
COAP_RESPONSE_CODE
#define COAP_RESPONSE_CODE(N)
Definition: pdu.h:132
COAP_PDU_MAX_TCP_HEADER_SIZE
#define COAP_PDU_MAX_TCP_HEADER_SIZE
Definition: pdu.h:316
COAP_PROTO_TLS
#define COAP_PROTO_TLS
Definition: pdu.h:345
COAP_MAX_MESSAGE_SIZE_TCP8
#define COAP_MAX_MESSAGE_SIZE_TCP8
Definition: pdu.h:42
COAP_MAX_MESSAGE_SIZE_TCP0
#define COAP_MAX_MESSAGE_SIZE_TCP0
Definition: pdu.h:41
COAP_MESSAGE_SIZE_OFFSET_TCP16
#define COAP_MESSAGE_SIZE_OFFSET_TCP16
Definition: pdu.h:37
coap_proto_t
uint8_t coap_proto_t
Definition: pdu.h:337
COAP_MESSAGE_SIZE_OFFSET_TCP32
#define COAP_MESSAGE_SIZE_OFFSET_TCP32
Definition: pdu.h:38
COAP_MESSAGE_CON
#define COAP_MESSAGE_CON
Definition: pdu.h:72
COAP_DEFAULT_VERSION
#define COAP_DEFAULT_VERSION
Definition: pdu.h:64
COAP_PROTO_DTLS
#define COAP_PROTO_DTLS
Definition: pdu.h:343
COAP_PAYLOAD_START
#define COAP_PAYLOAD_START
Definition: pdu.h:255
COAP_MAX_MESSAGE_SIZE_TCP16
#define COAP_MAX_MESSAGE_SIZE_TCP16
Definition: pdu.h:43
COAP_PROTO_UDP
#define COAP_PROTO_UDP
Definition: pdu.h:342
coap_option_t
Representation of CoAP options.
Definition: option.h:31
coap_pdu_t
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
Definition: pdu.h:285
coap_pdu_t::max_hdr_size
uint8_t max_hdr_size
space reserved for protocol-specific header
Definition: pdu.h:288
coap_pdu_t::type
uint8_t type
message type
Definition: pdu.h:286
coap_pdu_t::token
uint8_t * token
first byte of token, if any, or options
Definition: pdu.h:296
coap_pdu_t::max_size
size_t max_size
maximum size for token, options and payload, or zero for variable size pdu
Definition: pdu.h:295
coap_pdu_t::tid
uint16_t tid
transaction id, if any, in regular host byte order
Definition: pdu.h:291
coap_pdu_t::code
uint8_t code
request method (value 1–10) or response code (value 40-255)
Definition: pdu.h:287
coap_pdu_t::token_length
uint8_t token_length
length of Token
Definition: pdu.h:290
coap_pdu_t::hdr_size
uint8_t hdr_size
actaul size used for protocol-specific header
Definition: pdu.h:289
coap_pdu_t::data
uint8_t * data
first byte of payload, if any
Definition: pdu.h:297
coap_pdu_t::max_delta
uint16_t max_delta
highest option number
Definition: pdu.h:292
coap_pdu_t::used_size
size_t used_size
used bytes of storage for token, options and payload
Definition: pdu.h:294
coap_pdu_t::alloc_size
size_t alloc_size
allocated storage for token, options and payload
Definition: pdu.h:293
coap_session_t
Definition: coap_session.h:59
error_desc_t
Definition: pdu.c:335
error_desc_t::code
unsigned char code
Definition: pdu.c:336
error_desc_t::phrase
const char * phrase
Definition: pdu.c:337
uint8_t
unsigned char uint8_t
Definition: uthash.h:79