|
| 1 | +/* |
| 2 | + * CoAP message deduplication tracking. |
| 3 | + * RFC7252 section 4.2 |
| 4 | + */ |
| 5 | + |
| 6 | +#include <stdbool.h> |
| 7 | + |
| 8 | +#include "message_dedup.h" |
| 9 | +#include <internals.h> |
| 10 | +#include <liblwm2m.h> |
| 11 | + |
| 12 | +void coap_cleanup_message_deduplication_step(coap_msg_dedup_t **message_dedup, const time_t current_time, |
| 13 | + time_t *timeout) { |
| 14 | + LOG("Entering"); |
| 15 | + coap_msg_dedup_t *message_dedup_check = *message_dedup; |
| 16 | + coap_msg_dedup_t *message_dedup_check_prev = *message_dedup; |
| 17 | + while (message_dedup_check != NULL) { |
| 18 | + time_t diff = current_time - message_dedup_check->timestamp; |
| 19 | + if (diff >= EXCHANGE_LIFETIME) { |
| 20 | + LOG_ARG("Message %d deduplication period ended", message_dedup_check->mid); |
| 21 | + if (message_dedup_check_prev != *message_dedup) { |
| 22 | + message_dedup_check_prev->next = message_dedup_check->next; |
| 23 | + } else { |
| 24 | + *message_dedup = message_dedup_check->next; |
| 25 | + message_dedup_check_prev = message_dedup_check->next; |
| 26 | + } |
| 27 | + coap_msg_dedup_t *message_dedup_check_next = message_dedup_check->next; |
| 28 | + lwm2m_free(message_dedup_check); |
| 29 | + message_dedup_check = message_dedup_check_next; |
| 30 | + } else { |
| 31 | + LOG_ARG("Message %d check deduplication", message_dedup_check->mid); |
| 32 | + time_t message_dedup_timeout; |
| 33 | + if ((message_dedup_timeout = (message_dedup_check->timestamp + EXCHANGE_LIFETIME) - current_time) < 0) { |
| 34 | + message_dedup_timeout = 0; |
| 35 | + } |
| 36 | + if (message_dedup_timeout < *timeout) { |
| 37 | + LOG_ARG("Message %d check again in %ds deduplication", message_dedup_check->mid, message_dedup_timeout); |
| 38 | + *timeout = message_dedup_timeout; |
| 39 | + } |
| 40 | + message_dedup_check_prev = message_dedup_check; |
| 41 | + message_dedup_check = message_dedup_check->next; |
| 42 | + } |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +bool coap_check_message_duplication(coap_msg_dedup_t **message_dedup, const uint16_t mid, const void *session) { |
| 47 | + LOG("Entering"); |
| 48 | + coap_msg_dedup_t *message_dedup_check = *message_dedup; |
| 49 | + while (message_dedup_check != NULL) { |
| 50 | + bool is_equal = lwm2m_session_is_equal(message_dedup_check->session, (void *)session, NULL); |
| 51 | + if (message_dedup_check->mid == mid && is_equal) { |
| 52 | + LOG_ARG("Duplicate, ignore mid %d (session: %p)", mid, session); |
| 53 | + return true; |
| 54 | + } |
| 55 | + message_dedup_check = message_dedup_check->next; |
| 56 | + } |
| 57 | + LOG_ARG("Register mid %d (session: %p) for deduplication check", mid, session); |
| 58 | + /* The message was not received in the past. Remember for future checks. */ |
| 59 | + coap_msg_dedup_t *new_message; |
| 60 | + new_message = lwm2m_malloc(sizeof(coap_msg_dedup_t)); |
| 61 | + if (new_message == NULL) { |
| 62 | + /* Memory allocation failed, mark packet as duplicate. Further allocations during packet processing would fail |
| 63 | + * anyway. */ |
| 64 | + return true; |
| 65 | + } |
| 66 | + memset(new_message, 0, sizeof(coap_msg_dedup_t)); |
| 67 | + new_message->mid = mid; |
| 68 | + new_message->session = (void *)session; |
| 69 | + new_message->timestamp = lwm2m_gettime(); |
| 70 | + |
| 71 | + /* Add message id to deduplication list */ |
| 72 | + coap_msg_dedup_t *message_dedup_temp = *message_dedup; |
| 73 | + *message_dedup = new_message; |
| 74 | + (*message_dedup)->next = message_dedup_temp; |
| 75 | + |
| 76 | + return false; |
| 77 | +} |
| 78 | + |
| 79 | +void coap_deduplication_free(lwm2m_context_t *ctx) { |
| 80 | + LOG("Remove and free the whole message deduplication list"); |
| 81 | + while (ctx->message_dedup != NULL) { |
| 82 | + coap_msg_dedup_t *msg_dedup; |
| 83 | + msg_dedup = ctx->message_dedup; |
| 84 | + ctx->message_dedup = ctx->message_dedup->next; |
| 85 | + lwm2m_free(msg_dedup); |
| 86 | + } |
| 87 | +} |
0 commit comments