From 7a4d2db8f32194a9a2c2e6194dfc2302f00e8b74 Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Wed, 24 Apr 2019 16:26:21 +0100 Subject: [PATCH] Fix RST deleting observer for non-confirmable observe Code works as expected for confirmable observes as the sent pdu is retained for potential re-transmission. For non-confirmable observes, the RST is seen in the response packet but previously had no way of finding the observe/subscription to cancel. Keep the last sent message id in coap_subscription_t (as tid) and when the RST comes in, search for the subscription that has the same message id as the pdu and remove that subscription. include/coap2/subscribe.h: Add in tid to coap_subscription_t (as per coap_pdu_t). src/net.c: Match tid in incoming RST pdu with a subscription. If found, delete the subscription. src/resource.c: Save tid in both pdu and subscription when sending off an observe response. To test code, make the following temporary change to coap-client diff --git a/examples/client.c b/examples/client.c index 4d3e4c7..0020b68 100644 --- a/examples/client.c +++ b/examples/client.c @@ -348,7 +348,8 @@ message_handler(struct coap_context_t *ctx, #endif /* check if this is a response to our original request */ - if (!check_token(received)) { +static int count = 0; + if (!check_token(received) || ++count == 5) { /* drop if this was just some message, or send RST in case of notification */ if (!sent && (received->type == COAP_MESSAGE_CON || received->type == COAP_MESSAGE_NON)) and run (coap-server running on the same host) coap-client -N -s 10 coap://127.0.0.1/time --- include/coap2/subscribe.h | 1 + src/net.c | 14 ++++++++++++++ src/resource.c | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/coap2/subscribe.h b/include/coap2/subscribe.h index 6b661973..ed635a61 100644 --- a/include/coap2/subscribe.h +++ b/include/coap2/subscribe.h @@ -63,6 +63,7 @@ typedef struct coap_subscription_t { * sent (in that case, the resource's partially * dirty flag is set too) */ unsigned int has_block2:1; /**< GET request had Block2 definition */ + uint16_t tid; /**< transaction id, if any, in regular host byte order */ coap_block_t block2; /**< GET request Block2 definition */ size_t token_length; /**< actual length of token */ unsigned char token[8]; /**< token used for subscription */ diff --git a/src/net.c b/src/net.c index f6003fae..74e092cb 100644 --- a/src/net.c +++ b/src/net.c @@ -2227,6 +2227,20 @@ coap_dispatch(coap_context_t *context, coap_session_t *session, if(sent->pdu->type==COAP_MESSAGE_CON && context->nack_handler) context->nack_handler(context, sent->session, sent->pdu, COAP_NACK_RST, sent->id); } + else { + /* Need to check is there is a subscription active and delete it */ + RESOURCES_ITER(context->resources, r) { + coap_subscription_t *obs, *tmp; + LL_FOREACH_SAFE(r->subscribers, obs, tmp) { + if (obs->tid == pdu->tid && obs->session == session) { + coap_binary_t token = { 0, NULL }; + COAP_SET_STR(&token, obs->token_length, obs->token); + coap_delete_observer(r, session, &token); + goto cleanup; + } + } + } + } goto cleanup; case COAP_MESSAGE_NON: /* check for unknown critical options */ diff --git a/src/resource.c b/src/resource.c index 1d8c6a2e..8f143901 100644 --- a/src/resource.c +++ b/src/resource.c @@ -794,7 +794,7 @@ coap_notify_observers(coap_context_t *context, coap_resource_t *r) { token.length = obs->token_length; token.s = obs->token; - response->tid = coap_new_message_id(obs->session); + obs->tid = response->tid = coap_new_message_id(obs->session); if ((r->flags & COAP_RESOURCE_FLAGS_NOTIFY_CON) == 0 && obs->non_cnt < COAP_OBS_MAX_NON) { response->type = COAP_MESSAGE_NON;