[coap] rename and clarify response sending methods (#12647)

This commit updates several method names in `CoapBase` to better align
with RFC 7252 terminology and clarify their behavior.

Previously, the term "empty" was used ambiguously to mean either a
message with Code 0.00 (`kCodeEmpty`) or a message that lacked a
payload but contained a response code. For example, `SendEmptyAck()`
sent an ACK (`kTypeAck`) message that actually contained a non-zero
response code (e.g., `kCodeChanged`), which is a "response" message
per the RFC, not an "empty" message.

To address this:

- `SendReset()` and `SendAck()` are removed in favor of using
  `SendEmptyMessage()` directly with `kTypeReset` or `kTypeAck`.
  This restricts the use of "Empty" strictly to Code 0.00 messages.
- `SendHeaderResponse()` is renamed to `SendResponse()` to clarify
  that it dynamically sends a response without a payload.
- `SendEmptyAck()` is renamed to `SendAckResponse()` to indicate it
  sends a piggybacked ACK `kTypeAck` response without a payload.
- `SendNotFound()` is replaced with a direct call to `SendResponse()`
  using `kCodeNotFound`.
- Documentation comments for these methods are updated to explain
  their purpose and requirements clearly.
- Callers across the core modules are updated to use the new method
  names.
This commit is contained in:
Abtin Keshavarzian
2026-03-09 19:49:05 -05:00
committed by GitHub
parent 86bc9435ba
commit b79a6cfc8b
15 changed files with 107 additions and 100 deletions
+2 -2
View File
@@ -420,7 +420,7 @@ exit:
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
if (duaRespCoapCode != Coap::kCodeEmpty)
{
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg, duaRespCoapCode));
IgnoreError(Get<Tmf::Agent>().SendAckResponse(aMsg, duaRespCoapCode));
}
else
#endif
@@ -599,7 +599,7 @@ template <> void Manager::HandleTmf<kUriBackboneAnswer>(Coap::Msg &aMsg)
HandleExtendedBackboneAnswer(dua, meshLocalIid, timeSinceLastTransaction, srcRloc16);
}
SuccessOrExit(error = mBackboneTmfAgent.SendEmptyAck(aMsg));
SuccessOrExit(error = mBackboneTmfAgent.SendAckResponse(aMsg));
exit:
LogInfo("HandleBackboneAnswer: %s", ErrorToString(error));
+32 -20
View File
@@ -416,25 +416,36 @@ Error CoapBase::SendMessageWithResponseHandlerSeparateParams(Message
return SendMessage(aMessage, aMessageInfo, aTxParameters, callbacks);
}
Error CoapBase::SendReset(const Msg &aRxMsg) { return SendEmptyMessage(kTypeReset, aRxMsg); }
Error CoapBase::SendAck(const Msg &aRxMsg) { return SendEmptyMessage(kTypeAck, aRxMsg); }
Error CoapBase::SendEmptyAck(const Msg &aRxMsg, Code aCode)
Error CoapBase::SendAckResponse(const Msg &aRxMsg, Code aCode)
{
return (aRxMsg.IsConfirmable() ? SendHeaderResponse(aCode, aRxMsg) : kErrorInvalidArgs);
return (aRxMsg.IsConfirmable() ? SendResponse(aCode, aRxMsg) : kErrorInvalidArgs);
}
Error CoapBase::SendEmptyAck(const Msg &aRxMsg) { return SendEmptyAck(aRxMsg, kCodeChanged); }
Error CoapBase::SendNotFound(const Msg &aRxMsg) { return SendHeaderResponse(kCodeNotFound, aRxMsg); }
Error CoapBase::SendAckResponse(const Msg &aRxMsg) { return SendAckResponse(aRxMsg, kCodeChanged); }
Error CoapBase::SendEmptyMessage(Type aType, const Msg &aRxMsg)
{
Error error = kErrorNone;
Message *message = nullptr;
VerifyOrExit(aRxMsg.IsConfirmable(), error = kErrorInvalidArgs);
switch (aType)
{
case kTypeConfirmable:
// An empty confirmable message is not used in normal
// operation but only to elicit a Reset response. This is
// used as "CoAP ping" (RFC 7573 section 4.3).
break;
case kTypeAck:
VerifyOrExit(aRxMsg.IsConfirmable(), error = kErrorInvalidArgs);
break;
case kTypeReset:
break;
case kTypeNonConfirmable:
ExitNow(error = kErrorInvalidArgs);
}
VerifyOrExit((message = NewMessage()) != nullptr, error = kErrorNoBufs);
@@ -446,7 +457,7 @@ exit:
return error;
}
Error CoapBase::SendHeaderResponse(Message::Code aCode, const Msg &aRxMsg)
Error CoapBase::SendResponse(Message::Code aCode, const Msg &aRxMsg)
{
Error error = kErrorNone;
Message *message = nullptr;
@@ -503,7 +514,7 @@ void CoapBase::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageIn
if (!aMessageInfo.GetSockAddr().IsMulticast() && rxMsg.IsConfirmable())
{
IgnoreError(SendReset(rxMsg));
IgnoreError(SendEmptyMessage(kTypeReset, rxMsg));
}
}
else if (rxMsg.IsRequest())
@@ -538,7 +549,8 @@ void CoapBase::ProcessReceivedResponse(Msg &aRxMsg)
{
// Successfully parsed a header but no matching request was
// found - reject the message by sending reset.
IgnoreError(SendReset(aRxMsg));
IgnoreError(SendEmptyMessage(kTypeReset, aRxMsg));
}
ExitNow();
@@ -633,8 +645,8 @@ void CoapBase::ProcessReceivedResponse(Msg &aRxMsg)
break;
case kTypeConfirmable:
// Send empty ACK if it is a CON message.
IgnoreError(SendAck(aRxMsg));
// Received a confirmable response, send an Empty Ack message.
IgnoreError(SendEmptyMessage(kTypeAck, aRxMsg));
// Handling of RFC7641 and multicast is below.
@@ -758,7 +770,7 @@ exit:
if (error == kErrorNotFound && !aRxMsg.mMessageInfo.GetSockAddr().IsMulticast())
{
IgnoreError(SendNotFound(aRxMsg));
IgnoreError(SendResponse(kCodeNotFound, aRxMsg));
}
}
@@ -962,15 +974,15 @@ Error CoapBase::ProcessBlockwiseRequest(Msg &aRxMsg, const Message::UriPathStrin
error = kErrorNone;
break;
case kErrorNoBufs:
IgnoreError(SendHeaderResponse(kCodeRequestTooLarge, aRxMsg));
IgnoreError(SendResponse(kCodeRequestTooLarge, aRxMsg));
error = kErrorDrop;
break;
case kErrorNoFrameReceived:
IgnoreError(SendHeaderResponse(kCodeRequestIncomplete, aRxMsg));
IgnoreError(SendResponse(kCodeRequestIncomplete, aRxMsg));
error = kErrorDrop;
break;
default:
IgnoreError(SendHeaderResponse(kCodeInternalError, aRxMsg));
IgnoreError(SendResponse(kCodeInternalError, aRxMsg));
error = kErrorDrop;
break;
}
@@ -981,7 +993,7 @@ Error CoapBase::ProcessBlockwiseRequest(Msg &aRxMsg, const Message::UriPathStrin
{
if ((error = ProcessBlock2Request(aRxMsg, resource)) != kErrorNone)
{
IgnoreError(SendHeaderResponse(kCodeInternalError, aRxMsg));
IgnoreError(SendResponse(kCodeInternalError, aRxMsg));
error = kErrorDrop;
}
}
+53 -61
View File
@@ -591,71 +591,64 @@ public:
Error SendMessage(OwnedPtr<Message> aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* Sends a CoAP reset message.
* Sends an empty CoAP message (using `kCodeEmpty` Code 0.00).
*
* An empty CoAP message has no options and no payload (only a 4-byte header). This is typically used for sending
* Empty Acknowledgments or Resets.
*
* @param[in] aType The CoAP Type of the empty message (e.g., `kTypeAck`, `kTypeReset`).
* @param[in] aRxMsg The received CoAP message to which this message responds (provides Message ID).
*
* @retval kErrorNone Successfully enqueued the CoAP message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP message.
* @retval kErrorInvalidArgs The @p aType is not valid for an empty message (e.g., `kTypeNonConfirmable`),
* or is `kTypeAck` but the @p aRxMsg is not confirmable.
*/
Error SendEmptyMessage(Type aType, const Msg &aRxMsg);
/**
* Sends a CoAP response message without a payload to a given request message.
*
* The response will dynamically be an ACK (`kTypeAck`) or NON (`kTypeNonConfirmable`) message depending on the
* request @p aRxMsg type, containing the specified response code @p aCode and matching token, without any payload.
*
* @param[in] aCode The CoAP response Code.
* @param[in] aRxMsg The received CoAP request message.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRxMsg is not a request, or is neither confirmable nor non-confirmable.
*/
Error SendResponse(Message::Code aCode, const Msg &aRxMsg);
/**
* Sends a CoAP ACK (`kTypeAck`) response without a payload and a given status code.
*
* This method strictly ensures the @p aRxMsg is a confirmable request message. It then sends a piggybacked
* ACK (`kTypeAck`) response containing the provided CoAP @p aCode and matching token without a payload.
*
* @param[in] aRxMsg The received CoAP request message.
* @param[in] aCode The CoAP Code of the ACK response.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRxMsg is not a confirmable request.
*/
Error SendAckResponse(const Msg &aRxMsg, Code aCode);
/**
* Sends a CoAP ACK response without a payload using `kCodeChanged` Code 2.04.
*
* This method strictly ensures the @p aRxMsg is a confirmable request message. It then sends a piggybacked
* ACK (`kTypeAck`) response containing `kCodeChanged` and matching token without a payload.
*
* @param[in] aRxMsg The received CoAP request message.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRxMsg is not of confirmable type.
* @retval kErrorInvalidArgs The @p aRxMsg is not a confirmable request.
*/
Error SendReset(const Msg &aRxMsg);
/**
* Sends header-only CoAP response message.
*
* @param[in] aCode The CoAP code of this response.
* @param[in] aRxMsg The received request message.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type.
*/
Error SendHeaderResponse(Message::Code aCode, const Msg &aRxMsg);
/**
* Sends a CoAP ACK empty message which is used in Separate Response for confirmable requests.
*
* @param[in] aRxMsg `Msg` for the received CoAP request message.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRxMsg header is not of confirmable type.
*/
Error SendAck(const Msg &aRxMsg);
/**
* Sends a CoAP ACK message on which a dummy CoAP response is piggybacked.
*
* @param[in] aRxMsg The received CoAP request Message.
* @param[in] aCode The CoAP code of the dummy CoAP response.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRxMsg header is not of confirmable type.
*/
Error SendEmptyAck(const Msg &aRxMsg, Code aCode);
/**
* Sends a CoAP ACK message on which a dummy CoAP response is piggybacked.
*
* @param[in] aRxMsg The received CoAP request Message.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRxMsg header is not of confirmable type.
*/
Error SendEmptyAck(const Msg &aRxMsg);
/**
* Sends a header-only CoAP message to indicate no resource matched for the request.
*
* @param[in] aRxMsg The received request CoAP Message.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
*/
Error SendNotFound(const Msg &aRxMsg);
Error SendAckResponse(const Msg &aRxMsg);
/**
* Aborts CoAP transactions associated with given handler and context.
@@ -739,7 +732,7 @@ public:
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
*/
Error SendRequestEntityIncomplete(const Msg &aRxMsg) { return SendHeaderResponse(kCodeRequestIncomplete, aRxMsg); }
Error SendRequestEntityIncomplete(const Msg &aRxMsg) { return SendResponse(kCodeRequestIncomplete, aRxMsg); }
#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
protected:
@@ -957,7 +950,6 @@ private:
const Ip6::MessageInfo &aMessageInfo,
const TxParameters *aTxParameters,
const SendCallbacks &aCallbacks);
Error SendEmptyMessage(Type aType, const Msg &aRxMsg);
Error Transmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+4 -1
View File
@@ -685,7 +685,10 @@ Error Manager::CoapDtlsSession::ForwardToLeader(const Coap::Msg &aMsg, Uri aUri)
OT_ASSERT(false);
}
SuccessOrExit(error = SendAck(aMsg));
if (aMsg.IsConfirmable())
{
SuccessOrExit(error = SendEmptyMessage(Coap::kTypeAck, aMsg));
}
forwardContext.Reset(ForwardContext::Allocate(*this, aMsg.mMessage, aUri));
VerifyOrExit(!forwardContext.IsNull(), error = kErrorNoBufs);
+3 -3
View File
@@ -886,7 +886,7 @@ template <> void Commissioner::HandleTmf<kUriDatasetChanged>(Coap::Msg &aMsg)
LogInfo("Received %s", UriToString<kUriDatasetChanged>());
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
SuccessOrExit(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Sent %s ack", UriToString<kUriDatasetChanged>());
@@ -1083,7 +1083,7 @@ template <> void Commissioner::HandleTmf<kUriEnergyReport>(Coap::Msg &aMsg)
mEnergyReportCallback.InvokeIfSet(mask, energyListTlv.GetEnergyList(), energyListTlv.GetEnergyListLength());
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
SuccessOrExit(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Sent %s ack", UriToString<kUriEnergyReport>());
@@ -1137,7 +1137,7 @@ template <> void Commissioner::HandleTmf<kUriPanIdConflict>(Coap::Msg &aMsg)
mPanIdConflictCallback.InvokeIfSet(panId, mask);
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
SuccessOrExit(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Sent %s response", UriToString<kUriPanIdConflict>());
+2 -2
View File
@@ -702,7 +702,7 @@ template <> void AddressResolver::HandleTmf<kUriAddressNotify>(Coap::Msg &aMsg)
LogCacheEntryChange(kEntryUpdated, kReasonReceivedNotification, *entry);
if (Get<Tmf::Agent>().SendEmptyAck(aMsg) == kErrorNone)
if (Get<Tmf::Agent>().SendAckResponse(aMsg) == kErrorNone)
{
LogInfo("Sent %s ack", UriToString<kUriAddressNotify>());
}
@@ -753,7 +753,7 @@ template <> void AddressResolver::HandleTmf<kUriAddressError>(Coap::Msg &aMsg)
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
{
if (Get<Tmf::Agent>().SendEmptyAck(aMsg) == kErrorNone)
if (Get<Tmf::Agent>().SendAckResponse(aMsg) == kErrorNone)
{
LogInfo("Sent %s ack", UriToString<kUriAddressError>());
}
+1 -1
View File
@@ -68,7 +68,7 @@ template <> void AnnounceBeginServer::HandleTmf<kUriAnnounceBegin>(Coap::Msg &aM
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
{
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
SuccessOrExit(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Sent %s response", UriToString<kUriAnnounceBegin>());
}
+1 -1
View File
@@ -574,7 +574,7 @@ template <> void DuaManager::HandleTmf<kUriDuaRegistrationNotify>(Coap::Msg &aMs
VerifyOrExit(aMsg.IsPostRequest(), error = kErrorParse);
if (aMsg.IsConfirmable() && Get<Tmf::Agent>().SendEmptyAck(aMsg) == kErrorNone)
if (aMsg.IsConfirmable() && Get<Tmf::Agent>().SendAckResponse(aMsg) == kErrorNone)
{
LogInfo("Sent %s ack", UriToString<kUriDuaRegistrationNotify>());
}
+1 -1
View File
@@ -89,7 +89,7 @@ template <> void EnergyScanServer::HandleTmf<kUriEnergyScan>(Coap::Msg &aMsg)
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
{
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
SuccessOrExit(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Sent %s ack", UriToString<kUriEnergyScan>());
}
+1 -1
View File
@@ -3648,7 +3648,7 @@ template <> void Mle::HandleTmf<kUriAddressRelease>(Coap::Msg &aMsg)
IgnoreError(mRouterTable.Release(routerId));
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
SuccessOrExit(Get<Tmf::Agent>().SendAckResponse(aMsg));
Log(kMessageSend, kTypeAddressReleaseReply, aMsg.mMessageInfo.GetPeerAddr());
+1 -1
View File
@@ -252,7 +252,7 @@ template <> void Leader::HandleTmf<kUriServerData>(Coap::Msg &aMsg)
}
}
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
SuccessOrExit(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Sent %s ack", UriToString<kUriServerData>());
+3 -3
View File
@@ -563,7 +563,7 @@ template <> void Server::HandleTmf<kUriDiagnosticGetQuery>(Coap::Msg &aMsg)
// DIAG_GET.qry may be sent as a confirmable request.
if (aMsg.IsConfirmable())
{
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg));
IgnoreError(Get<Tmf::Agent>().SendAckResponse(aMsg));
}
#if OPENTHREAD_MTD
@@ -967,7 +967,7 @@ template <> void Server::HandleTmf<kUriDiagnosticReset>(Coap::Msg &aMsg)
}
}
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg));
IgnoreError(Get<Tmf::Agent>().SendAckResponse(aMsg));
exit:
return;
@@ -1092,7 +1092,7 @@ template <> void Client::HandleTmf<kUriDiagnosticGetAnswer>(Coap::Msg &aMsg)
mGetCallback.InvokeIfSet(kErrorNone, &aMsg.mMessage, &aMsg.mMessageInfo);
}
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg));
IgnoreError(Get<Tmf::Agent>().SendAckResponse(aMsg));
exit:
return;
+1 -1
View File
@@ -64,7 +64,7 @@ template <> void PanIdQueryServer::HandleTmf<kUriPanIdQuery>(Coap::Msg &aMsg)
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
{
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
SuccessOrExit(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Sent %s ack", UriToString<kUriPanIdQuery>());
}
+1 -1
View File
@@ -111,7 +111,7 @@ exit:
template <> void Client::HandleTmf<kUriHistoryAnswer>(Coap::Msg &aMsg)
{
VerifyOrExit(aMsg.IsConfirmablePostRequest());
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg));
IgnoreError(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Received %s from %s", ot::UriToString<kUriHistoryAnswer>(),
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
+1 -1
View File
@@ -56,7 +56,7 @@ template <> void Server::HandleTmf<kUriHistoryQuery>(Coap::Msg &aMsg)
if (aMsg.IsConfirmable())
{
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg));
IgnoreError(Get<Tmf::Agent>().SendAckResponse(aMsg));
}
PrepareAndSendAnswers(aMsg.mMessageInfo.GetPeerAddr(), aMsg.mMessage);