diff --git a/sys/include/net/gcoap.h b/sys/include/net/gcoap.h index ebac4e16d4264c071ed4d9b5cfee70f60ba3301c..47c25c65fd41693d9620c18f7dba114a1371a151 100644 --- a/sys/include/net/gcoap.h +++ b/sys/include/net/gcoap.h @@ -209,7 +209,10 @@ #ifndef NET_GCOAP_H #define NET_GCOAP_H +#include <stdint.h> +#include <stdatomic.h> #include "net/sock/udp.h" +#include "mutex.h" #include "nanocoap.h" #include "xtimer.h" @@ -437,12 +440,13 @@ typedef struct { * @brief Container for the state of gcoap itself */ typedef struct { + mutex_t lock; /**< Shares state attributes safely */ gcoap_listener_t *listeners; /**< List of registered listeners */ gcoap_request_memo_t open_reqs[GCOAP_REQ_WAITING_MAX]; /**< Storage for open requests; if first byte of an entry is zero, the entry is available */ - uint16_t last_message_id; /**< Last message ID used */ + atomic_uint next_message_id; /**< Next message ID to use */ sock_udp_ep_t observers[GCOAP_OBS_CLIENTS_MAX]; /**< Observe clients; allows reuse for observe memos */ diff --git a/sys/net/application_layer/coap/gcoap.c b/sys/net/application_layer/coap/gcoap.c index cd933dbe2cfad939fe12b7b4b9ade34f0954b96a..0bfb0c376bdc9a52af9e70b671ddf425cd45f115 100644 --- a/sys/net/application_layer/coap/gcoap.c +++ b/sys/net/application_layer/coap/gcoap.c @@ -585,12 +585,13 @@ kernel_pid_t gcoap_init(void) _pid = thread_create(_msg_stack, sizeof(_msg_stack), THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, _event_loop, NULL, "coap"); + mutex_init(&_coap_state.lock); /* Blank lists so we know if an entry is available. */ memset(&_coap_state.open_reqs[0], 0, sizeof(_coap_state.open_reqs)); memset(&_coap_state.observers[0], 0, sizeof(_coap_state.observers)); memset(&_coap_state.observe_memos[0], 0, sizeof(_coap_state.observe_memos)); /* randomize initial value */ - _coap_state.last_message_id = random_uint32() & 0xFFFF; + atomic_init(&_coap_state.next_message_id, (unsigned)random_uint32()); return _pid; } @@ -609,7 +610,6 @@ void gcoap_register_listener(gcoap_listener_t *listener) int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code, char *path) { - ssize_t hdrlen; (void)len; pdu->hdr = (coap_hdr_t *)buf; @@ -624,11 +624,13 @@ int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code, &rand, (GCOAP_TOKENLEN - i >= 4) ? 4 : GCOAP_TOKENLEN - i); } - hdrlen = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, &token[0], GCOAP_TOKENLEN, - code, ++_coap_state.last_message_id); + uint16_t msgid = (uint16_t)atomic_fetch_add(&_coap_state.next_message_id, 1); + ssize_t hdrlen = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, &token[0], GCOAP_TOKENLEN, + code, msgid); #else - hdrlen = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, NULL, GCOAP_TOKENLEN, - code, ++_coap_state.last_message_id); + uint16_t msgid = (uint16_t)atomic_fetch_add(&_coap_state.next_message_id, 1); + ssize_t hdrlen = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, NULL, GCOAP_TOKENLEN, + code, msgid); #endif if (hdrlen > 0) { @@ -682,6 +684,7 @@ size_t gcoap_req_send2(const uint8_t *buf, size_t len, assert(resp_handler != NULL); /* Find empty slot in list of open requests. */ + mutex_lock(&_coap_state.lock); for (int i = 0; i < GCOAP_REQ_WAITING_MAX; i++) { if (_coap_state.open_reqs[i].state == GCOAP_MEMO_UNUSED) { memo = &_coap_state.open_reqs[i]; @@ -689,6 +692,8 @@ size_t gcoap_req_send2(const uint8_t *buf, size_t len, break; } } + mutex_unlock(&_coap_state.lock); + if (memo) { memcpy(&memo->hdr_buf[0], buf, GCOAP_HEADER_MAXLEN); memo->resp_handler = resp_handler; @@ -742,7 +747,6 @@ int gcoap_resp_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code) int gcoap_obs_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, const coap_resource_t *resource) { - ssize_t hdrlen; gcoap_observe_memo_t *memo = NULL; _find_obs_memo_resource(&memo, resource); @@ -751,10 +755,11 @@ int gcoap_obs_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, return GCOAP_OBS_INIT_UNUSED; } - pdu->hdr = (coap_hdr_t *)buf; - hdrlen = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, &memo->token[0], - memo->token_len, COAP_CODE_CONTENT, - ++_coap_state.last_message_id); + pdu->hdr = (coap_hdr_t *)buf; + uint16_t msgid = (uint16_t)atomic_fetch_add(&_coap_state.next_message_id, 1); + ssize_t hdrlen = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, &memo->token[0], + memo->token_len, COAP_CODE_CONTENT, msgid); + if (hdrlen > 0) { uint32_t now = xtimer_now_usec(); pdu->observe_value = (now >> GCOAP_OBS_TICK_EXPONENT) & 0xFFFFFF;