1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

nanocoap: implement extended tokens (RFC 8974)

This commit is contained in:
Benjamin Valentin 2023-04-19 17:51:06 +02:00 committed by Benjamin Valentin
parent 812c216f0c
commit 660c77e2c3
2 changed files with 86 additions and 7 deletions

View File

@ -91,6 +91,7 @@
#include "byteorder.h"
#include "iolist.h"
#include "net/coap.h"
#include "modules.h"
#else
#include "coap.h"
#include <arpa/inet.h>
@ -494,15 +495,37 @@ static inline unsigned coap_get_id(const coap_pkt_t *pkt)
/**
* @brief Get a message's token length [in byte]
*
* If the `nanocoap_token_ext` module is enabled, this will include
* the extended token length.
*
* @param[in] pkt CoAP packet
*
* @returns length of token in the given message (0-8 byte)
*/
static inline unsigned coap_get_token_len(const coap_pkt_t *pkt)
{
return (pkt->hdr->ver_t_tkl & 0xf);
uint8_t tkl = pkt->hdr->ver_t_tkl & 0xf;
if (!IS_USED(MODULE_NANOCOAP_TOKEN_EXT)) {
return tkl;
}
void *ext = pkt->hdr + 1;
switch (tkl) {
case 13:
return tkl + *(uint8_t *)ext;
case 14:
return tkl + 255 + byteorder_bebuftohs(ext);
case 15:
assert(0);
/* fall-through */
default:
return tkl;
}
}
static inline uint8_t *coap_hdr_data_ptr(const coap_hdr_t *hdr);
/**
* @brief Get pointer to a message's token
*
@ -512,7 +535,7 @@ static inline unsigned coap_get_token_len(const coap_pkt_t *pkt)
*/
static inline void *coap_get_token(const coap_pkt_t *pkt)
{
return (uint8_t*)pkt->hdr + sizeof(coap_hdr_t);
return coap_hdr_data_ptr(pkt->hdr);
}
/**
@ -568,6 +591,35 @@ static inline unsigned coap_get_ver(const coap_pkt_t *pkt)
return (pkt->hdr->ver_t_tkl & 0x60) >> 6;
}
/**
* @brief Get the size of the extended Token length field
* (RFC 8974)
*
* @note This requires the `nanocoap_token_ext` module to be enabled
*
* @param[in] hdr CoAP header
*
* @returns number of bytes used for extended token length
*/
static inline uint8_t coap_hdr_tkl_ext_len(const coap_hdr_t *hdr)
{
if (!IS_USED(MODULE_NANOCOAP_TOKEN_EXT)) {
return 0;
}
switch (hdr->ver_t_tkl & 0xf) {
case 13:
return 1;
case 14:
return 2;
case 15:
assert(0);
/* fall-through */
default:
return 0;
}
}
/**
* @brief Get the start of data after the header
*
@ -577,7 +629,7 @@ static inline unsigned coap_get_ver(const coap_pkt_t *pkt)
*/
static inline uint8_t *coap_hdr_data_ptr(const coap_hdr_t *hdr)
{
return ((uint8_t *)hdr) + sizeof(coap_hdr_t);
return ((uint8_t *)hdr) + sizeof(coap_hdr_t) + coap_hdr_tkl_ext_len(hdr);
}
/**

View File

@ -80,7 +80,13 @@ int coap_parse(coap_pkt_t *pkt, uint8_t *buf, size_t len)
return -EBADMSG;
}
if (coap_get_token_len(pkt) > COAP_TOKEN_LENGTH_MAX) {
if (IS_USED(MODULE_NANOCOAP_TOKEN_EXT)) {
if ((pkt->hdr->ver_t_tkl & 0xf) == 15) {
DEBUG("nanocoap: token length is reserved value 15,"
"invalid for extended token length field.\n");
return -EBADMSG;
}
} else if (coap_get_token_len(pkt) > COAP_TOKEN_LENGTH_MAX) {
DEBUG("nanocoap: token length invalid\n");
return -EBADMSG;
}
@ -555,18 +561,39 @@ ssize_t coap_build_reply(coap_pkt_t *pkt, unsigned code,
ssize_t coap_build_hdr(coap_hdr_t *hdr, unsigned type, uint8_t *token, size_t token_len, unsigned code, uint16_t id)
{
assert(!(type & ~0x3));
assert(!(token_len & ~0x1f));
uint16_t tkl_ext;
uint8_t tkl_ext_len, tkl;
if (token_len > 268 && IS_USED(MODULE_NANOCOAP_TOKEN_EXT)) {
tkl_ext_len = 2;
tkl_ext = htons(token_len - 269); /* 269 = 255 + 14 */
tkl = 14;
}
else if (token_len > 12 && IS_USED(MODULE_NANOCOAP_TOKEN_EXT)) {
tkl_ext_len = 1;
tkl_ext = token_len - 13;
tkl = 13;
}
else {
tkl = token_len;
tkl_ext_len = 0;
}
memset(hdr, 0, sizeof(coap_hdr_t));
hdr->ver_t_tkl = (COAP_V1 << 6) | (type << 4) | token_len;
hdr->ver_t_tkl = (COAP_V1 << 6) | (type << 4) | tkl;
hdr->code = code;
hdr->id = htons(id);
if (tkl_ext_len) {
memcpy(hdr + 1, &tkl_ext, tkl_ext_len);
}
if (token_len) {
memcpy(coap_hdr_data_ptr(hdr), token, token_len);
}
return sizeof(coap_hdr_t) + token_len;
return sizeof(coap_hdr_t) + token_len + tkl_ext_len;
}
void coap_pkt_init(coap_pkt_t *pkt, uint8_t *buf, size_t len, size_t header_len)