diff --git a/include/coap2/resource.h b/include/coap2/resource.h index dc0a0abd..77d15ec3 100644 --- a/include/coap2/resource.h +++ b/include/coap2/resource.h @@ -62,15 +62,26 @@ typedef struct coap_attr_t { /** * Notifications will be sent non-confirmable by default. RFC 7641 Section 4.5 * https://tools.ietf.org/html/rfc7641#section-4.5 + * Libcoap will always send every fifth packet as confirmable. */ #define COAP_RESOURCE_FLAGS_NOTIFY_NON 0x0 /** - * Notifications will be sent confirmable by default. RFC 7641 Section 4.5 + * Notifications will be sent confirmable. RFC 7641 Section 4.5 * https://tools.ietf.org/html/rfc7641#section-4.5 */ #define COAP_RESOURCE_FLAGS_NOTIFY_CON 0x2 +/** + * Notifications will always be sent non-confirmable. This is in + * violation of RFC 7641 Section 4.5 + * https://tools.ietf.org/html/rfc7641#section-4.5 + * but required by the DOTS signal channel protocol which needs to operate in + * lossy DDoS attack environments. + * https://tools.ietf.org/html/draft-ietf-dots-signal-channel-41#section-4.4.2.1 + */ +#define COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS 0x4 + typedef struct coap_resource_t { unsigned int dirty:1; /**< set to 1 if resource has changed */ unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet diff --git a/man/coap_observe.txt.in b/man/coap_observe.txt.in index f0a1b3db..c507177e 100644 --- a/man/coap_observe.txt.in +++ b/man/coap_observe.txt.in @@ -94,13 +94,19 @@ manage the deletion of the resource at the appropriate time. *NOTE:* The type (confirmable or non-confirmable) of the triggered observe GET response is determined not by the initial GET request, but independently -by the server as per RFC 7641 3.5. Transmission. This is controlled by the -flags (one of COAP_RESOURCE_FLAGS_NOTIFY_NON or COAP_RESOURCE_FLAGS_NOTIFY_CON) +by the server as per https://tools.ietf.org/html/rfc7641#section-3.5. +This is controlled by the flags (one of COAP_RESOURCE_FLAGS_NOTIFY_NON, +COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS or COAP_RESOURCE_FLAGS_NOTIFY_CON) used when creating the resource using *coap_resource_init*(3). -Furthermore, the server must send at least one "observe" response as -confirmable, when generally sending non-confirmable, every 24 hours. -libcoap handles this by sending every fifth (COAP_OBS_MAX_NON) response as a -confirmable response for detection that the client is still responding. + +*NOTE:* Furthermore, the server must send at least one "observe" response as +confirmable, when generally sending non-confirmable, at least every 24 hours +as per https://tools.ietf.org/html/rfc7641#section-4.5. +Libcoap automatically handles this by sending every fifth (COAP_OBS_MAX_NON) +response as a confirmable response for detection that the client is still +responding unless if COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS is set, which is a +RFC7641 violation, where non-confirmable "observe" responses are always sent +as required by some higher layer protocols. The *coap_resource_notify_observers*() function needs to be called whenever the server application determines that there has been a change to the state of diff --git a/man/coap_resource.txt.in b/man/coap_resource.txt.in index 6a509b2e..4dd6cd4a 100644 --- a/man/coap_resource.txt.in +++ b/man/coap_resource.txt.in @@ -84,7 +84,13 @@ _flags_ can be one of the following definitions or'ed together. [horizontal] *COAP_RESOURCE_FLAGS_NOTIFY_NON*:: Set the notification message type to non-confirmable for any trigggered -"observe" responses. +"observe" responses with type set to confirmable every 5 packets as required by +https://tools.ietf.org/html/rfc7641#section-4.5. +//- +*COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS*:: +Set the notification message type to always non-confirmable for any trigggered +"observe" responses. This should only be used if a upper layer protocol +requires it. //- *COAP_RESOURCE_FLAGS_NOTIFY_CON*:: Set the notification message type to confirmable for any trigggered @@ -120,7 +126,8 @@ _context_ and frees their storage. The *coap_resource_set_mode*() changes the notification message type of _resource_ to the given _mode_ which must be one of -COAP_RESOURCE_FLAGS_NOTIFY_NON or COAP_RESOURCE_FLAGS_NOTIFY_CON. +COAP_RESOURCE_FLAGS_NOTIFY_NON, COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS or +COAP_RESOURCE_FLAGS_NOTIFY_CON. The *coap_resource_set_userdata*() function allows a pointer to user _data_ to be associated with a _resource_ that can accessed in any callback that diff --git a/src/resource.c b/src/resource.c index e9792b58..323f1a61 100644 --- a/src/resource.c +++ b/src/resource.c @@ -793,8 +793,9 @@ coap_notify_observers(coap_context_t *context, coap_resource_t *r) { token.s = obs->token; 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) { + if ((r->flags & COAP_RESOURCE_FLAGS_NOTIFY_CON) == 0 && + ((r->flags & COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS) || + obs->non_cnt < COAP_OBS_MAX_NON)) { response->type = COAP_MESSAGE_NON; } else { response->type = COAP_MESSAGE_CON; @@ -805,7 +806,8 @@ coap_notify_observers(coap_context_t *context, coap_resource_t *r) { /* TODO: do not send response and remove observer when * COAP_RESPONSE_CLASS(response->hdr->code) > 2 */ - if (response->type == COAP_MESSAGE_CON) { + if (response->type == COAP_MESSAGE_CON || + (r->flags & COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS)) { obs->non_cnt = 0; } else { obs->non_cnt++;