coap_net.c: Do not send an Empty message as a separate response

A request handler that leaves the response code unset asks for no
response to be sent.  That is honoured for a piggybacked ACK (the token
gets stripped, so an empty ACK goes out) and for a non-confirmable or
reliable response (dropped in no_response()), but not for a separate
response set up with coap_register_async().

There the response is turned into a CON, and a 0.00 CON was put on the
wire.  An Empty message is a ping (RFC 7252 4.2), not a response, and the
PDU still carries the request's token, which RFC 7252 4.1 does not allow.
Being confirmable, it was then retransmitted up to MAX_RETRANSMIT times,
usually at a client port that had long gone away.

Drop it like the other two cases, delete it without logging it as a
dropped response since the application asked for this, and document in
coap_handler(3) that a separate response is not sent either.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michiel De WitteandClaude Opus 5 authored and Jon Shallow committed 2026-09-02 15:22:26 +01:00
1 parent 05e9a9caf4
commit 5e86d78e6d
2 files changed
+12 -4

No files matched your search

+2 -1
View File
@@ -118,7 +118,8 @@ This _handler_ must not call *coap_send*(3) to send _response_pdu_.
_response_pdu_ gets sent on return from _handler_, assuming the response
code has been updated. If the response code was not updated, then an empty
ACK packet will get sent for CON type requests or nothing for NON type
requests.
requests. Nothing gets sent for a separate response (*coap_async*(3)), as
an Empty message is only valid as an ACK or a RST.
*NOTE:* Any data associated with _incoming_pdu_ is no longer be available after
exiting this function as _incoming_pdu_ is deleted. In particular
+10 -3
View File
@@ -3573,8 +3573,9 @@ enum respond_t { RESPONSE_DEFAULT, RESPONSE_DROP, RESPONSE_SEND };
* change it to an empty ACK and @c RESPONSE_SEND so the client does not keep
* on retrying.
*
* Checks if the response code is 0.00 and if either the session is reliable or
* non-confirmable, @c RESPONSE_DROP is also returned.
* Checks if the response code is 0.00 and if the response is confirmable,
* non-confirmable, or the session is reliable, @c RESPONSE_DROP is also
* returned. An Empty confirmable message is a ping, not a response.
*
* Multicast response checking is also carried out.
*
@@ -3673,8 +3674,13 @@ no_response(coap_pdu_t *request, coap_pdu_t *response,
}
} else if (COAP_PDU_IS_EMPTY(response) &&
(response->type == COAP_MESSAGE_NON ||
response->type == COAP_MESSAGE_CON ||
COAP_PROTO_RELIABLE(session->proto))) {
/* response is 0.00, and this is reliable or non-confirmable */
/* Response is 0.00, and this is reliable, non-confirmable, or a separate
* (confirmable) response. An Empty CON is a ping (RFC 7252 4.2), not a
* response, and the PDU still has the request's token attached, which
* RFC 7252 4.1 does not allow. A CON would then get retransmitted up to
* MAX_RETRANSMIT times. */
return RESPONSE_DROP;
}
@@ -4352,6 +4358,7 @@ skip_handler:
}
} else if (COAP_PDU_IS_EMPTY(response) &&
(response->type == COAP_MESSAGE_NON ||
response->type == COAP_MESSAGE_CON ||
COAP_PROTO_RELIABLE(session->proto))) {
coap_delete_pdu_lkd(response);
} else {