diff --git a/src/core/backbone_router/bbr_manager.cpp b/src/core/backbone_router/bbr_manager.cpp index 791286c6a..025a9c58a 100644 --- a/src/core/backbone_router/bbr_manager.cpp +++ b/src/core/backbone_router/bbr_manager.cpp @@ -420,7 +420,7 @@ exit: #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE if (duaRespCoapCode != Coap::kCodeEmpty) { - IgnoreError(Get().SendEmptyAck(aMsg, duaRespCoapCode)); + IgnoreError(Get().SendAckResponse(aMsg, duaRespCoapCode)); } else #endif @@ -599,7 +599,7 @@ template <> void Manager::HandleTmf(Coap::Msg &aMsg) HandleExtendedBackboneAnswer(dua, meshLocalIid, timeSinceLastTransaction, srcRloc16); } - SuccessOrExit(error = mBackboneTmfAgent.SendEmptyAck(aMsg)); + SuccessOrExit(error = mBackboneTmfAgent.SendAckResponse(aMsg)); exit: LogInfo("HandleBackboneAnswer: %s", ErrorToString(error)); diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index 935bc95d5..fe6fcec03 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -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; } } diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index 02bb379e0..7501913af 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -591,71 +591,64 @@ public: Error SendMessage(OwnedPtr 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 diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 4c6bd754b..7bbb82d58 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -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); diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index f0722a280..84259b4e2 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -886,7 +886,7 @@ template <> void Commissioner::HandleTmf(Coap::Msg &aMsg) LogInfo("Received %s", UriToString()); - SuccessOrExit(Get().SendEmptyAck(aMsg)); + SuccessOrExit(Get().SendAckResponse(aMsg)); LogInfo("Sent %s ack", UriToString()); @@ -1083,7 +1083,7 @@ template <> void Commissioner::HandleTmf(Coap::Msg &aMsg) mEnergyReportCallback.InvokeIfSet(mask, energyListTlv.GetEnergyList(), energyListTlv.GetEnergyListLength()); - SuccessOrExit(Get().SendEmptyAck(aMsg)); + SuccessOrExit(Get().SendAckResponse(aMsg)); LogInfo("Sent %s ack", UriToString()); @@ -1137,7 +1137,7 @@ template <> void Commissioner::HandleTmf(Coap::Msg &aMsg) mPanIdConflictCallback.InvokeIfSet(panId, mask); - SuccessOrExit(Get().SendEmptyAck(aMsg)); + SuccessOrExit(Get().SendAckResponse(aMsg)); LogInfo("Sent %s response", UriToString()); diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp index a11480f89..2732eff23 100644 --- a/src/core/thread/address_resolver.cpp +++ b/src/core/thread/address_resolver.cpp @@ -702,7 +702,7 @@ template <> void AddressResolver::HandleTmf(Coap::Msg &aMsg) LogCacheEntryChange(kEntryUpdated, kReasonReceivedNotification, *entry); - if (Get().SendEmptyAck(aMsg) == kErrorNone) + if (Get().SendAckResponse(aMsg) == kErrorNone) { LogInfo("Sent %s ack", UriToString()); } @@ -753,7 +753,7 @@ template <> void AddressResolver::HandleTmf(Coap::Msg &aMsg) if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast()) { - if (Get().SendEmptyAck(aMsg) == kErrorNone) + if (Get().SendAckResponse(aMsg) == kErrorNone) { LogInfo("Sent %s ack", UriToString()); } diff --git a/src/core/thread/announce_begin_server.cpp b/src/core/thread/announce_begin_server.cpp index 52bb560c4..6535bc1dd 100644 --- a/src/core/thread/announce_begin_server.cpp +++ b/src/core/thread/announce_begin_server.cpp @@ -68,7 +68,7 @@ template <> void AnnounceBeginServer::HandleTmf(Coap::Msg &aM if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast()) { - SuccessOrExit(Get().SendEmptyAck(aMsg)); + SuccessOrExit(Get().SendAckResponse(aMsg)); LogInfo("Sent %s response", UriToString()); } diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp index 5962b894d..9013e784d 100644 --- a/src/core/thread/dua_manager.cpp +++ b/src/core/thread/dua_manager.cpp @@ -574,7 +574,7 @@ template <> void DuaManager::HandleTmf(Coap::Msg &aMs VerifyOrExit(aMsg.IsPostRequest(), error = kErrorParse); - if (aMsg.IsConfirmable() && Get().SendEmptyAck(aMsg) == kErrorNone) + if (aMsg.IsConfirmable() && Get().SendAckResponse(aMsg) == kErrorNone) { LogInfo("Sent %s ack", UriToString()); } diff --git a/src/core/thread/energy_scan_server.cpp b/src/core/thread/energy_scan_server.cpp index 05d209277..b4439fdc6 100644 --- a/src/core/thread/energy_scan_server.cpp +++ b/src/core/thread/energy_scan_server.cpp @@ -89,7 +89,7 @@ template <> void EnergyScanServer::HandleTmf(Coap::Msg &aMsg) if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast()) { - SuccessOrExit(Get().SendEmptyAck(aMsg)); + SuccessOrExit(Get().SendAckResponse(aMsg)); LogInfo("Sent %s ack", UriToString()); } diff --git a/src/core/thread/mle_ftd.cpp b/src/core/thread/mle_ftd.cpp index 4f49bdbe8..acb37847e 100644 --- a/src/core/thread/mle_ftd.cpp +++ b/src/core/thread/mle_ftd.cpp @@ -3648,7 +3648,7 @@ template <> void Mle::HandleTmf(Coap::Msg &aMsg) IgnoreError(mRouterTable.Release(routerId)); - SuccessOrExit(Get().SendEmptyAck(aMsg)); + SuccessOrExit(Get().SendAckResponse(aMsg)); Log(kMessageSend, kTypeAddressReleaseReply, aMsg.mMessageInfo.GetPeerAddr()); diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index 075fde64a..2629d18bb 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -252,7 +252,7 @@ template <> void Leader::HandleTmf(Coap::Msg &aMsg) } } - SuccessOrExit(Get().SendEmptyAck(aMsg)); + SuccessOrExit(Get().SendAckResponse(aMsg)); LogInfo("Sent %s ack", UriToString()); diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp index db37bc7b5..334c701f9 100644 --- a/src/core/thread/network_diagnostic.cpp +++ b/src/core/thread/network_diagnostic.cpp @@ -563,7 +563,7 @@ template <> void Server::HandleTmf(Coap::Msg &aMsg) // DIAG_GET.qry may be sent as a confirmable request. if (aMsg.IsConfirmable()) { - IgnoreError(Get().SendEmptyAck(aMsg)); + IgnoreError(Get().SendAckResponse(aMsg)); } #if OPENTHREAD_MTD @@ -967,7 +967,7 @@ template <> void Server::HandleTmf(Coap::Msg &aMsg) } } - IgnoreError(Get().SendEmptyAck(aMsg)); + IgnoreError(Get().SendAckResponse(aMsg)); exit: return; @@ -1092,7 +1092,7 @@ template <> void Client::HandleTmf(Coap::Msg &aMsg) mGetCallback.InvokeIfSet(kErrorNone, &aMsg.mMessage, &aMsg.mMessageInfo); } - IgnoreError(Get().SendEmptyAck(aMsg)); + IgnoreError(Get().SendAckResponse(aMsg)); exit: return; diff --git a/src/core/thread/panid_query_server.cpp b/src/core/thread/panid_query_server.cpp index 93aa45c68..10acbf3a5 100644 --- a/src/core/thread/panid_query_server.cpp +++ b/src/core/thread/panid_query_server.cpp @@ -64,7 +64,7 @@ template <> void PanIdQueryServer::HandleTmf(Coap::Msg &aMsg) if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast()) { - SuccessOrExit(Get().SendEmptyAck(aMsg)); + SuccessOrExit(Get().SendAckResponse(aMsg)); LogInfo("Sent %s ack", UriToString()); } diff --git a/src/core/utils/history_tracker_client.cpp b/src/core/utils/history_tracker_client.cpp index 1686ebe03..0e2e70261 100644 --- a/src/core/utils/history_tracker_client.cpp +++ b/src/core/utils/history_tracker_client.cpp @@ -111,7 +111,7 @@ exit: template <> void Client::HandleTmf(Coap::Msg &aMsg) { VerifyOrExit(aMsg.IsConfirmablePostRequest()); - IgnoreError(Get().SendEmptyAck(aMsg)); + IgnoreError(Get().SendAckResponse(aMsg)); LogInfo("Received %s from %s", ot::UriToString(), aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString()); diff --git a/src/core/utils/history_tracker_server.cpp b/src/core/utils/history_tracker_server.cpp index 879e72d8f..b2bd78674 100644 --- a/src/core/utils/history_tracker_server.cpp +++ b/src/core/utils/history_tracker_server.cpp @@ -56,7 +56,7 @@ template <> void Server::HandleTmf(Coap::Msg &aMsg) if (aMsg.IsConfirmable()) { - IgnoreError(Get().SendEmptyAck(aMsg)); + IgnoreError(Get().SendAckResponse(aMsg)); } PrepareAndSendAnswers(aMsg.mMessageInfo.GetPeerAddr(), aMsg.mMessage);