Skip to content

Commit

Permalink
RFC8974: Add in support for Extended Tokens
Browse files Browse the repository at this point in the history
Add in new function coap_context_set_max_token_size() to define
the maximum supported token size.

Track changes to PDU to support extended tokens.

Update documentation.
  • Loading branch information
mrdeep1 committed Nov 26, 2022
1 parent c9f40d7 commit 334d320
Show file tree
Hide file tree
Showing 30 changed files with 715 additions and 217 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ The following RFCs are supported

* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option

* RFC8974: Extended Tokens and Stateless Clients in the Constrained Application Protocol (CoAP)

* RFC9175: CoAP: Echo, Request-Tag, and Token Processing

There is (D)TLS support for the following libraries
Expand Down
2 changes: 2 additions & 0 deletions doc/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ The following RFCs are supported

* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option

* RFC8974: Extended Tokens and Stateless Clients in the Constrained Application Protocol (CoAP)

* RFC9175: CoAP: Echo, Request-Tag, and Token Processing

There is (D)TLS support for the following libraries
Expand Down
34 changes: 23 additions & 11 deletions examples/coap-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ strndup(const char* s1, size_t n) {

int flags = 0;

static unsigned char _token_data[8];
coap_binary_t base_token = { 0, _token_data };
static unsigned char _token_data[24]; /* With support for RFC8974 */
coap_binary_t the_token = { 0, _token_data };

typedef struct {
coap_binary_t *token;
Expand Down Expand Up @@ -268,11 +268,19 @@ coap_new_request(coap_context_t *ctx,

/*
* Create unique token for this request for handling unsolicited /
* delayed responses
* delayed responses.
* Note that only up to 8 bytes are returned
*/
coap_session_new_token(session, &tokenlen, token);
track_new_token(tokenlen, token);
if (!coap_add_token(pdu, tokenlen, token)) {
if (the_token.length > COAP_TOKEN_DEFAULT_MAX) {
coap_session_new_token(session, &tokenlen, token);
/* Update the last part 8 bytes of the large token */
memcpy(&the_token.s[the_token.length - tokenlen], token, tokenlen);
}
else {
coap_session_new_token(session, &the_token.length, the_token.s);
}
track_new_token(the_token.length, the_token.s);
if (!coap_add_token(pdu, the_token.length, the_token.s)) {
coap_log(LOG_DEBUG, "cannot add token to request\n");
}

Expand Down Expand Up @@ -565,7 +573,7 @@ usage(const char *program, const char *version) {
"\t \t\tdefine how to connect to a CoAP proxy (automatically adds\n"
"\t \t\tProxy-Uri option to request) to forward the request to.\n"
"\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n"
"\t-T token\tDefine the initial starting token\n"
"\t-T token\tDefine the initial starting token (up to 24 characters)\n"
"\t-U \t\tNever include Uri-Host or Uri-Port options\n"
"\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n"
"\t \t\tlibrary logging\n"
Expand Down Expand Up @@ -856,9 +864,9 @@ cmdline_proxy(char *arg) {

static inline void
cmdline_token(char *arg) {
base_token.length = min(sizeof(_token_data), strlen(arg));
if (base_token.length > 0) {
memcpy((char *)base_token.s, arg, base_token.length);
the_token.length = min(sizeof(_token_data), strlen(arg));
if (the_token.length > 0) {
memcpy((char *)the_token.s, arg, the_token.length);
}
}

Expand Down Expand Up @@ -1700,6 +1708,9 @@ main(int argc, char **argv) {
dst.size = res;
dst.addr.sin.sin_port = htons( port );

if (the_token.length > COAP_TOKEN_DEFAULT_MAX)
coap_context_set_max_token_size(ctx, the_token.length);

session = get_session(
ctx,
node_str[0] ? node_str : NULL, port_str,
Expand All @@ -1723,8 +1734,9 @@ main(int argc, char **argv) {
* Prime the base token value, which coap_session_new_token() will increment
* every time it is called to get an unique token.
* [Option '-T token' is used to seed a different value]
* Note that only the first 8 bytes of the token are used as the prime.
*/
coap_session_init_token(session, base_token.length, base_token.s);
coap_session_init_token(session, the_token.length, the_token.s);

/* add Uri-Host if server address differs from uri.host */

Expand Down
33 changes: 28 additions & 5 deletions examples/coap-rd.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static uint8_t key[MAX_KEY];
static ssize_t key_length = 0;
static int key_defined = 0;
static const char *hint = "CoAP";
static size_t extended_token_size = COAP_TOKEN_DEFAULT_MAX;

#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
Expand Down Expand Up @@ -583,7 +584,7 @@ usage(const char *program, const char *version) {
fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer)));
fprintf(stderr, "\n"
"Usage: %s [-g group] [-G group_if] [-p port] [-v num] [-A address]\n"
"\t [-V num]\n"
"\t [-T max_token_size] [-V num]\n"
"\t [[-h hint] [-k key]]\n"
"\t [[-c certfile] [-C cafile] [-n] [-R trust_casfile]]\n"
"General Options\n"
Expand All @@ -596,6 +597,7 @@ usage(const char *program, const char *version) {
"\t-v num \t\tVerbosity level (default 4, maximum is 8) for general\n"
"\t \t\tCoAP logging\n"
"\t-A address\tInterface address to bind to\n"
"\t-T max_token_length\tSet the maximum token length (8-65804)\n"
"\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n"
"\t \t\tlibrary logging\n"
"PSK Options (if supported by underlying (D)TLS library)\n"
Expand Down Expand Up @@ -775,6 +777,20 @@ get_context(const char *node, const char *port) {
return ctx;
}

static int
cmdline_read_extended_token_size(char *arg) {
extended_token_size = strtoul(arg, NULL, 0);
if (extended_token_size < COAP_TOKEN_DEFAULT_MAX) {
coap_log(LOG_ERR, "Extended Token Length must be 8 or greater\n");
return 0;
}
else if (extended_token_size > COAP_TOKEN_EXT_MAX) {
coap_log(LOG_ERR, "Extended Token Length must be 65804 or less\n");
return 0;
}
return 1;
}

int
main(int argc, char **argv) {
coap_context_t *ctx;
Expand All @@ -790,7 +806,7 @@ main(int argc, char **argv) {
struct sigaction sa;
#endif

while ((opt = getopt(argc, argv, "A:c:C:g:G:h:k:n:R:p:v:V:")) != -1) {
while ((opt = getopt(argc, argv, "A:c:C:g:G:h:k:n:R:p:v:T:V:")) != -1) {
switch (opt) {
case 'A' :
strncpy(addr_str, optarg, NI_MAXHOST-1);
Expand Down Expand Up @@ -826,13 +842,18 @@ main(int argc, char **argv) {
case 'n':
verify_peer_cert = 0;
break;
case 'R' :
root_ca_file = optarg;
break;
case 'p' :
strncpy(port_str, optarg, NI_MAXSERV-1);
port_str[NI_MAXSERV - 1] = '\0';
break;
case 'R' :
root_ca_file = optarg;
break;
case 'T':
if (!cmdline_read_extended_token_size(optarg)) {
exit(1);
}
break;
case 'v' :
log_level = strtol(optarg, NULL, 10);
break;
Expand All @@ -857,6 +878,8 @@ main(int argc, char **argv) {
coap_join_mcast_group_intf(ctx, group, group_if);

init_resources(ctx);
if (extended_token_size > COAP_TOKEN_DEFAULT_MAX)
coap_context_set_max_token_size(ctx, extended_token_size);

#ifdef _WIN32
signal(SIGINT, handle_sigint);
Expand Down
30 changes: 26 additions & 4 deletions examples/coap-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ static int support_dynamic = 0;
static uint32_t block_mode = COAP_BLOCK_USE_LIBCOAP;
static int echo_back = 0;
static uint32_t csm_max_message_size = 0;
static size_t extended_token_size = COAP_TOKEN_DEFAULT_MAX;

static coap_dtls_pki_t *
setup_pki(coap_context_t *ctx, coap_dtls_role_t role, char *sni);
Expand Down Expand Up @@ -2137,7 +2138,8 @@ usage( const char *program, const char *version) {
fprintf(stderr, "\n"
"Usage: %s [-d max] [-e] [-g group] [-G group_if] [-l loss] [-p port]\n"
"\t\t[-r] [-v num] [-A address] [-L value] [-N]\n"
"\t\t[-P scheme://address[:port],[name1[,name2..]]] [-V num] [-X size]\n"
"\t\t[-P scheme://address[:port],[name1[,name2..]]]\n"
"\t\t[-T max_token_size] [-V num] [-X size]\n"
"\t\t[[-h hint] [-i match_identity_file] [-k key]\n"
"\t\t[-s match_psk_sni_file] [-u user]]\n"
"\t\t[[-c certfile] [-j keyfile] [-m] [-n] [-C cafile]\n"
Expand Down Expand Up @@ -2188,6 +2190,7 @@ usage( const char *program, const char *version) {
"\t \t\tdefined before the leading , (comma) of the first name,\n"
"\t \t\tthen the ongoing connection will be a direct connection.\n"
"\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n"
"\t-T max_token_length\tSet the maximum token length (8-65804)\n"
"\t-V num \t\tVerbosity level (default 3, maximum is 7) for (D)TLS\n"
"\t \t\tlibrary logging\n"
"\t-X size\t\tMaximum message size to use for TCP based connections\n"
Expand Down Expand Up @@ -2584,6 +2587,20 @@ cmdline_read_pki_sni_check(char *arg) {
return valid_pki_snis.count > 0;
}

static int
cmdline_read_extended_token_size(char *arg) {
extended_token_size = strtoul(arg, NULL, 0);
if (extended_token_size < COAP_TOKEN_DEFAULT_MAX) {
coap_log(LOG_ERR, "Extended Token Length must be 8 or greater\n");
return 0;
}
else if (extended_token_size > COAP_TOKEN_EXT_MAX) {
coap_log(LOG_ERR, "Extended Token Length must be 65804 or less\n");
return 0;
}
return 1;
}

int
main(int argc, char **argv) {
coap_context_t *ctx;
Expand Down Expand Up @@ -2614,7 +2631,7 @@ main(int argc, char **argv) {

clock_offset = time(NULL);

while ((opt = getopt(argc, argv, "c:d:eg:G:h:i:j:J:k:l:mnp:rs:u:v:A:C:L:M:NP:R:S:V:X:")) != -1) {
while ((opt = getopt(argc, argv, "c:d:eg:G:h:i:j:J:k:l:mnp:rs:u:v:A:C:L:M:NP:R:S:T:V:X:")) != -1) {
switch (opt) {
case 'A' :
strncpy(addr_str, optarg, NI_MAXHOST-1);
Expand Down Expand Up @@ -2714,13 +2731,16 @@ main(int argc, char **argv) {
break;
case 's':
if (!cmdline_read_psk_sni_check(optarg)) {
usage(argv[0], LIBCOAP_PACKAGE_VERSION);
exit(1);
}
break;
case 'S':
if (!cmdline_read_pki_sni_check(optarg)) {
usage(argv[0], LIBCOAP_PACKAGE_VERSION);
exit(1);
}
break;
case 'T':
if (!cmdline_read_extended_token_size(optarg)) {
exit(1);
}
break;
Expand Down Expand Up @@ -2775,6 +2795,8 @@ main(int argc, char **argv) {
coap_context_set_block_mode(ctx, block_mode);
if (csm_max_message_size)
coap_context_set_csm_max_message_size(ctx, csm_max_message_size);
if (extended_token_size > COAP_TOKEN_DEFAULT_MAX)
coap_context_set_max_token_size(ctx, extended_token_size);

/* Define the options to ignore when setting up cache-keys */
coap_cache_ignore_options(ctx, cache_ignore_options,
Expand Down
2 changes: 0 additions & 2 deletions include/coap3/coap_block_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,6 @@ struct coap_lg_srcv_t {
coap_resource_t *resource; /**< associated resource */
coap_str_const_t *uri_path; /** set to uri_path if unknown resource */
coap_rblock_t rec_blocks; /** < list of received blocks */
uint8_t last_token[8]; /**< last used token */
size_t last_token_length; /**< length of token */
coap_mid_t last_mid; /**< Last received mid for this set of packets */
coap_tick_t last_used; /**< Last time data sent or 0 */
uint16_t block_option; /**< Block option in use */
Expand Down
5 changes: 2 additions & 3 deletions include/coap3/coap_net_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ struct coap_context_t {
when creating a cache-key */
#endif /* COAP_SERVER_SUPPORT */
void *app; /**< application-specific data */
uint32_t max_token_size; /**< Largest token size supported RFC8974 */
#ifdef COAP_EPOLL_SUPPORT
int epfd; /**< External FD for epoll */
int eptimerfd; /**< Internal FD for timeout */
Expand Down Expand Up @@ -271,12 +272,10 @@ coap_wait_ack( coap_context_t *context, coap_session_t *session,
* @param context The context in use.
* @param session Session of the messages to remove.
* @param token Message token.
* @param token_length Actual length of @p token.
*/
void coap_cancel_all_messages(coap_context_t *context,
coap_session_t *session,
const uint8_t *token,
size_t token_length);
coap_bin_const_t *token);

/**
* Cancels all outstanding messages for session @p session.
Expand Down
13 changes: 11 additions & 2 deletions include/coap3/coap_pdu_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
#define COAP_MAX_MESSAGE_SIZE_TCP16 (COAP_MESSAGE_SIZE_OFFSET_TCP32-1) /* 65804 */
#define COAP_MAX_MESSAGE_SIZE_TCP32 (COAP_MESSAGE_SIZE_OFFSET_TCP32+0xFFFFFFFF)

/* Extended Token constants */
#define COAP_TOKEN_EXT_1B_TKL 13
#define COAP_TOKEN_EXT_2B_TKL 14
#define COAP_TOKEN_EXT_1B_BIAS 13
#define COAP_TOKEN_EXT_2B_BIAS 269 /* 13 + 256 */

#ifndef COAP_DEBUG_BUF_SIZE
#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
#define COAP_DEBUG_BUF_SIZE 128
Expand Down Expand Up @@ -112,16 +118,19 @@ struct coap_pdu_t {
uint8_t max_hdr_size; /**< space reserved for protocol-specific header */
uint8_t hdr_size; /**< actual size used for protocol-specific
header (0 until header is encoded) */
uint8_t token_length; /**< length of Token */
uint8_t crit_opt; /**< Set if unknown critical option for proxy */
uint16_t max_opt; /**< highest option number in PDU */
uint32_t token_length; /**< length of Token space (includes leading
extended bytes */
coap_bin_const_t actual_token; /**< Actual token in pdu */
size_t alloc_size; /**< allocated storage for token, options and
payload */
size_t used_size; /**< used bytes of storage for token, options and
payload */
size_t max_size; /**< maximum size for token, options and payload,
or zero for variable size pdu */
uint8_t *token; /**< first byte of token, if any, or options */
uint8_t *token; /**< first byte of token (or extended length bytes
prefix), if any, or options */
uint8_t *data; /**< first byte of payload, if any */
#ifdef WITH_LWIP
struct pbuf *pbuf; /**< lwIP PBUF. The package data will always reside
Expand Down
16 changes: 15 additions & 1 deletion include/coap3/coap_session_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ struct coap_addr_hash_t {
coap_proto_t proto; /**< CoAP protocol */
};

/**
* coap_ext_token_check_t values
*/
typedef enum coap_ext_token_check_t {
COAP_EXT_T_NOT_CHECKED = 0, /**< Not checked */
COAP_EXT_T_CHECKED, /**< Token size valid */
COAP_EXT_T_CHECKING, /**< Token size check request sent */
} coap_ext_token_check_t;

/**
* Abstraction of virtual session that can be attached to coap_context_t
* (client) or coap_endpoint_t (server).
Expand Down Expand Up @@ -139,6 +148,7 @@ struct coap_session_t {
unsigned int dtls_timeout_count; /**< dtls setup retry counter */
int dtls_event; /**< Tracking any (D)TLS events on this
sesison */
uint32_t tx_rtag; /**< Next Request-Tag number to use */
uint8_t csm_bert_rem_support; /**< CSM TCP BERT blocks supported (remote) */
uint8_t csm_bert_loc_support; /**< CSM TCP BERT blocks supported (local) */
uint8_t block_mode; /**< Zero or more COAP_BLOCK_ or'd options */
Expand All @@ -147,7 +157,11 @@ struct coap_session_t {
uint8_t delay_recursive; /**< Set if in coap_client_delay_first() */
uint8_t no_observe_cancel; /**< Set if do not cancel observe on session
close */
uint32_t tx_rtag; /**< Next Request-Tag number to use */
volatile uint8_t max_token_checked; /**< Check for max token size
coap_ext_token_check_t */
uint16_t max_token_mid; /**< mid used for checking ext token
support */
uint32_t max_token_size; /**< Largest token size supported RFC8974 */
uint64_t tx_token; /**< Next token number to use */
coap_bin_const_t *last_token; /** last token used to make a request */
coap_bin_const_t *echo; /**< Echo value to send with next request */
Expand Down
Loading

0 comments on commit 334d320

Please sign in to comment.