mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
[coap] simplify Coap::Message implementation (#12313)
This change simplifies the `Coap::Message` implementation and removes the fragile `HelpData` struct which was used to cache header information within reserved portion of message. The `Coap::Msg` class is updated to hold the parsed CoAP header information (type, code, message ID, token). It now inherits from a new `HeaderInfo` class which contains the parsed fields. This change helps to simplify many of the call sites which previously had to parse the header information themselves. The key changes are: - The `HelpData` struct is removed from `Coap::Message`. - `Coap::Msg` is updated to track parsed header info in `HeaderInfo`. - `otCoapMessageInit()` and `otCoapMessageInitResponse()` now return an `otError`. - Methods are renamed to harmonize their names. - A new unit test `test_coap_message.cpp` is added to verify the `Coap::Message` implementation.
This commit is contained in:
committed by
GitHub
parent
3b676fb6f3
commit
5cae26e22b
+19
-12
@@ -312,26 +312,33 @@ typedef struct otCoapTxParameters
|
||||
// `otCoapMessage*` APIs - Constructing or parsing a CoAP message.
|
||||
|
||||
/**
|
||||
* Initializes the CoAP header.
|
||||
* Initializes a CoAP message.
|
||||
*
|
||||
* @param[in,out] aMessage A pointer to the CoAP message to initialize.
|
||||
* @param[in] aType CoAP message type.
|
||||
* @param[in] aCode CoAP message code.
|
||||
* This function initializes the CoAP header, erasing any previously written content in the message. The Message ID is
|
||||
* set to zero, and the token is empty (zero-length).
|
||||
*
|
||||
* @param[in,out] aMessage A pointer to the CoAP message to initialize.
|
||||
* @param[in] aType The CoAP Type.
|
||||
* @param[in] aCode The CoAP Code.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully initialized the message.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient message buffers available to write the CoAP header.
|
||||
*/
|
||||
void otCoapMessageInit(otMessage *aMessage, otCoapType aType, otCoapCode aCode);
|
||||
otError otCoapMessageInit(otMessage *aMessage, otCoapType aType, otCoapCode aCode);
|
||||
|
||||
/**
|
||||
* Initializes a response message.
|
||||
* Initializes a CoAP message as a response to a request.
|
||||
*
|
||||
* @note Both message ID and token are set according to @p aRequest.
|
||||
* This function initializes the CoAP header, erasing any previously written content in the message. The Message ID and
|
||||
* Token are copied from the request message.
|
||||
*
|
||||
* @param[in,out] aResponse A pointer to the CoAP response message.
|
||||
* @param[in] aRequest A pointer to the CoAP request message.
|
||||
* @param[in] aType CoAP message type.
|
||||
* @param[in] aCode CoAP message code.
|
||||
* @param[in,out] aResponse A pointer to the CoAP response message to initialize.
|
||||
* @param[in] aRequest A pointer to the CoAP request message.
|
||||
* @param[in] aType The CoAP Type for the response.
|
||||
* @param[in] aCode The CoAP Code for the response.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully initialized the response message.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient message buffers available to initialize the response message.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient message buffers available to write the CoAP header.
|
||||
*/
|
||||
otError otCoapMessageInitResponse(otMessage *aResponse, const otMessage *aRequest, otCoapType aType, otCoapCode aCode);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (573)
|
||||
#define OPENTHREAD_API_VERSION (574)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -89,7 +89,7 @@ otError Coap::CancelResourceSubscription(bool aSendCancelMessage)
|
||||
message = otCoapNewMessage(GetInstancePtr(), nullptr);
|
||||
VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
otCoapMessageInit(message, OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_GET);
|
||||
SuccessOrExit(error = otCoapMessageInit(message, OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_GET));
|
||||
|
||||
SuccessOrExit(error = otCoapMessageWriteToken(message, &mRequestToken));
|
||||
SuccessOrExit(error = otCoapMessageAppendObserveOption(message, 1));
|
||||
@@ -268,9 +268,10 @@ template <> otError Coap::Process<Cmd("set")>(Arg aArgs[])
|
||||
notificationMessage = otCoapNewMessage(GetInstancePtr(), nullptr);
|
||||
VerifyOrExit(notificationMessage != nullptr, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
otCoapMessageInit(notificationMessage,
|
||||
(isConNotification ? OT_COAP_TYPE_CONFIRMABLE : OT_COAP_TYPE_NON_CONFIRMABLE),
|
||||
OT_COAP_CODE_CONTENT);
|
||||
SuccessOrExit(
|
||||
error = otCoapMessageInit(notificationMessage,
|
||||
(isConNotification ? OT_COAP_TYPE_CONFIRMABLE : OT_COAP_TYPE_NON_CONFIRMABLE),
|
||||
OT_COAP_CODE_CONTENT));
|
||||
|
||||
SuccessOrExit(error = otCoapMessageWriteToken(notificationMessage, &mSubscriberToken));
|
||||
SuccessOrExit(error = otCoapMessageAppendObserveOption(notificationMessage, mObserveSerial++));
|
||||
@@ -704,7 +705,7 @@ otError Coap::ProcessRequest(Arg aArgs[], otCoapCode aCoapCode)
|
||||
message = otCoapNewMessage(GetInstancePtr(), nullptr);
|
||||
VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
otCoapMessageInit(message, coapType, aCoapCode);
|
||||
SuccessOrExit(error = otCoapMessageInit(message, coapType, aCoapCode));
|
||||
otCoapMessageGenerateToken(message, OT_COAP_DEFAULT_TOKEN_LENGTH);
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
|
||||
|
||||
@@ -525,7 +525,7 @@ otError CoapSecure::ProcessRequest(Arg aArgs[], otCoapCode aCoapCode)
|
||||
message = otCoapNewMessage(GetInstancePtr(), nullptr);
|
||||
VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
otCoapMessageInit(message, coapType, aCoapCode);
|
||||
SuccessOrExit(error = otCoapMessageInit(message, coapType, aCoapCode));
|
||||
otCoapMessageGenerateToken(message, OT_COAP_DEFAULT_TOKEN_LENGTH);
|
||||
SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, coapUri));
|
||||
|
||||
|
||||
@@ -44,20 +44,14 @@ otMessage *otCoapNewMessage(otInstance *aInstance, const otMessageSettings *aSet
|
||||
return AsCoreType(aInstance).Get<Coap::ApplicationCoap>().NewMessage(Message::Settings::From(aSettings));
|
||||
}
|
||||
|
||||
void otCoapMessageInit(otMessage *aMessage, otCoapType aType, otCoapCode aCode)
|
||||
otError otCoapMessageInit(otMessage *aMessage, otCoapType aType, otCoapCode aCode)
|
||||
{
|
||||
AsCoapMessage(aMessage).Init(MapEnum(aType), MapEnum(aCode));
|
||||
return AsCoapMessage(aMessage).Init(MapEnum(aType), MapEnum(aCode));
|
||||
}
|
||||
|
||||
otError otCoapMessageInitResponse(otMessage *aResponse, const otMessage *aRequest, otCoapType aType, otCoapCode aCode)
|
||||
{
|
||||
Coap::Message &response = AsCoapMessage(aResponse);
|
||||
const Coap::Message &request = AsCoapMessage(aRequest);
|
||||
|
||||
response.Init(MapEnum(aType), MapEnum(aCode));
|
||||
response.SetMessageId(request.GetMessageId());
|
||||
|
||||
return response.WriteTokenFromMessage(request);
|
||||
return AsCoapMessage(aResponse).InitAsResponse(MapEnum(aType), MapEnum(aCode), AsCoapMessage(aRequest));
|
||||
}
|
||||
|
||||
otError otCoapMessageWriteToken(otMessage *aMessage, const otCoapToken *aToken)
|
||||
@@ -151,23 +145,23 @@ otError otCoapMessageAppendUriQueryOption(otMessage *aMessage, const char *aUriQ
|
||||
return AsCoapMessage(aMessage).AppendUriQueryOption(aUriQuery);
|
||||
}
|
||||
|
||||
otError otCoapMessageSetPayloadMarker(otMessage *aMessage) { return AsCoapMessage(aMessage).SetPayloadMarker(); }
|
||||
otError otCoapMessageSetPayloadMarker(otMessage *aMessage) { return AsCoapMessage(aMessage).AppendPayloadMarker(); }
|
||||
|
||||
otCoapType otCoapMessageGetType(const otMessage *aMessage)
|
||||
{
|
||||
return static_cast<otCoapType>(AsCoapMessage(aMessage).GetType());
|
||||
return static_cast<otCoapType>(AsCoapMessage(aMessage).ReadType());
|
||||
}
|
||||
|
||||
otCoapCode otCoapMessageGetCode(const otMessage *aMessage)
|
||||
{
|
||||
return static_cast<otCoapCode>(AsCoapMessage(aMessage).GetCode());
|
||||
return static_cast<otCoapCode>(AsCoapMessage(aMessage).ReadCode());
|
||||
}
|
||||
|
||||
void otCoapMessageSetCode(otMessage *aMessage, otCoapCode aCode) { AsCoapMessage(aMessage).SetCode(MapEnum(aCode)); }
|
||||
void otCoapMessageSetCode(otMessage *aMessage, otCoapCode aCode) { AsCoapMessage(aMessage).WriteCode(MapEnum(aCode)); }
|
||||
|
||||
const char *otCoapMessageCodeToString(const otMessage *aMessage) { return AsCoapMessage(aMessage).CodeToString(); }
|
||||
|
||||
uint16_t otCoapMessageGetMessageId(const otMessage *aMessage) { return AsCoapMessage(aMessage).GetMessageId(); }
|
||||
uint16_t otCoapMessageGetMessageId(const otMessage *aMessage) { return AsCoapMessage(aMessage).ReadMessageId(); }
|
||||
|
||||
otError otCoapMessageReadToken(const otMessage *aMessage, otCoapToken *aToken)
|
||||
{
|
||||
|
||||
@@ -149,7 +149,7 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Msg &aMsg)
|
||||
bool hasCommissionerSessionIdTlv = false;
|
||||
bool processTimeoutTlv = false;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest(), error = kErrorParse);
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest(), error = kErrorParse);
|
||||
|
||||
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
// Required by Test Specification 5.10.22 DUA-TC-26, only for certification purpose
|
||||
@@ -366,7 +366,7 @@ void Manager::HandleDuaRegistration(const Coap::Msg &aMsg)
|
||||
#endif
|
||||
|
||||
VerifyOrExit(aMsg.mMessageInfo.GetPeerAddr().GetIid().IsRoutingLocator(), error = kErrorDrop);
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest(), error = kErrorParse);
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest(), error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, target));
|
||||
SuccessOrExit(error = Tlv::Find<ThreadMeshLocalEidTlv>(aMsg.mMessage, meshLocalIid));
|
||||
@@ -542,7 +542,7 @@ template <> void Manager::HandleTmf<kUriBackboneQuery>(Coap::Msg &aMsg)
|
||||
VerifyOrExit(aMsg.mMessageInfo.IsHostInterface(), error = kErrorDrop);
|
||||
|
||||
VerifyOrExit(Get<Local>().IsPrimary(), error = kErrorInvalidState);
|
||||
VerifyOrExit(aMsg.mMessage.IsNonConfirmablePostRequest(), error = kErrorParse);
|
||||
VerifyOrExit(aMsg.IsNonConfirmablePostRequest(), error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, dua));
|
||||
|
||||
@@ -574,9 +574,9 @@ template <> void Manager::HandleTmf<kUriBackboneAnswer>(Coap::Msg &aMsg)
|
||||
VerifyOrExit(aMsg.mMessageInfo.IsHostInterface(), error = kErrorDrop);
|
||||
|
||||
VerifyOrExit(Get<Local>().IsPrimary(), error = kErrorInvalidState);
|
||||
VerifyOrExit(aMsg.mMessage.IsPostRequest(), error = kErrorParse);
|
||||
VerifyOrExit(aMsg.IsPostRequest(), error = kErrorParse);
|
||||
|
||||
proactive = !aMsg.mMessage.IsConfirmable();
|
||||
proactive = !aMsg.IsConfirmable();
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, dua));
|
||||
SuccessOrExit(error = Tlv::Find<ThreadMeshLocalEidTlv>(aMsg.mMessage, meshLocalIid));
|
||||
@@ -637,7 +637,7 @@ Error Manager::SendBackboneAnswer(const Ip6::Address &aDstAddr,
|
||||
|
||||
SuccessOrExit(error = message->Init(proactive ? Coap::kTypeNonConfirmable : Coap::kTypeConfirmable, Coap::kCodePost,
|
||||
kUriBackboneAnswer));
|
||||
SuccessOrExit(error = message->SetPayloadMarker());
|
||||
SuccessOrExit(error = message->AppendPayloadMarker());
|
||||
|
||||
SuccessOrExit(error = Tlv::Append<ThreadTargetTlv>(*message, aDua));
|
||||
|
||||
|
||||
+138
-70
@@ -40,6 +40,81 @@ namespace Coap {
|
||||
|
||||
RegisterLogModule("Coap");
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Msg
|
||||
|
||||
Error Msg::ParseHeaderAndOptions(PayloadMarkerMode aPayloadMarkerMode)
|
||||
{
|
||||
// Parses and validates CoAP headers and options. Assumes
|
||||
// `GetHeaderOffset()` points to the header start.
|
||||
// `aPayloadMarkerMode` determines behavior regarding "payload
|
||||
// marker". Either rejects the message if payload marker is present
|
||||
// with no payload (used on a received message), or removes the
|
||||
// payload marker in such a situation (used on a message to be
|
||||
// sent). Upon completion, `GetOffset()` is updated to the start of
|
||||
// the payload.
|
||||
|
||||
Error error;
|
||||
Option::Iterator iterator;
|
||||
uint16_t payloadOffset;
|
||||
bool emptyPayload;
|
||||
|
||||
SuccessOrExit(error = mMessage.ParseHeaderInfo(*this));
|
||||
|
||||
SuccessOrExit(error = iterator.Init(mMessage));
|
||||
|
||||
while (!iterator.IsDone())
|
||||
{
|
||||
SuccessOrExit(error = iterator.Advance());
|
||||
}
|
||||
|
||||
payloadOffset = iterator.GetPayloadMessageOffset();
|
||||
emptyPayload = (payloadOffset == mMessage.GetLength());
|
||||
|
||||
if (iterator.HasPayloadMarker())
|
||||
{
|
||||
switch (aPayloadMarkerMode)
|
||||
{
|
||||
case kRejectIfNoPayloadWithPayloadMarker:
|
||||
VerifyOrExit(!emptyPayload, error = kErrorParse);
|
||||
break;
|
||||
|
||||
case kRemovePayloadMarkerIfNoPayload:
|
||||
if (emptyPayload)
|
||||
{
|
||||
mMessage.RemoveFooter(sizeof(uint8_t));
|
||||
payloadOffset--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mMessage.SetOffset(payloadOffset);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint16_t Msg::GetHeaderSize(void) const
|
||||
{
|
||||
// Determines the size of the CoAP header including the token
|
||||
// but excluding any appended Options.
|
||||
|
||||
return sizeof(Message::Header) + GetToken().GetLength();
|
||||
}
|
||||
|
||||
void Msg::UpdateType(Type aType)
|
||||
{
|
||||
mType = aType;
|
||||
mMessage.WriteType(aType);
|
||||
}
|
||||
|
||||
void Msg::UpdateMessageId(uint16_t aMessageId)
|
||||
{
|
||||
mMessageId = aMessageId;
|
||||
mMessage.WriteMessageId(aMessageId);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// CoapBase
|
||||
|
||||
@@ -137,7 +212,7 @@ Message *CoapBase::InitMessage(Message *aMessage, Type aType, Uri aUri)
|
||||
VerifyOrExit(aMessage != nullptr);
|
||||
|
||||
SuccessOrExit(error = aMessage->Init(aType, kCodePost, aUri));
|
||||
SuccessOrExit(error = aMessage->SetPayloadMarker());
|
||||
SuccessOrExit(error = aMessage->AppendPayloadMarker());
|
||||
|
||||
exit:
|
||||
FreeAndNullMessageOnError(aMessage, error);
|
||||
@@ -150,8 +225,8 @@ Message *CoapBase::InitResponse(Message *aMessage, const Message &aRequest)
|
||||
|
||||
VerifyOrExit(aMessage != nullptr);
|
||||
|
||||
SuccessOrExit(error = aMessage->SetDefaultResponseHeader(aRequest));
|
||||
SuccessOrExit(error = aMessage->SetPayloadMarker());
|
||||
SuccessOrExit(error = aMessage->InitAsResponse(kTypeAck, kCodeChanged, aRequest));
|
||||
SuccessOrExit(error = aMessage->AppendPayloadMarker());
|
||||
|
||||
exit:
|
||||
FreeAndNullMessageOnError(aMessage, error);
|
||||
@@ -199,46 +274,46 @@ Error CoapBase::SendMessage(Message &aMessage,
|
||||
Msg txMsg(aMessage, aMessageInfo);
|
||||
Metadata metadata;
|
||||
|
||||
SuccessOrExit(error = txMsg.ParseHeaderAndOptions(Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
if (aTxParameters == nullptr)
|
||||
{
|
||||
aTxParameters = &TxParameters::GetDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = aTxParameters->ValidateFor(txMsg.mMessage));
|
||||
SuccessOrExit(error = aTxParameters->ValidateFor(txMsg));
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
|
||||
metadata.mBlockwiseReceiveHook = aReceiveHook;
|
||||
metadata.mBlockwiseTransmitHook = aTransmitHook;
|
||||
|
||||
SuccessOrExit(error = ProcessBlockwiseSend(txMsg.mMessage, aTransmitHook, aContext));
|
||||
SuccessOrExit(error = ProcessBlockwiseSend(txMsg, aTransmitHook, aContext));
|
||||
#endif
|
||||
|
||||
switch (txMsg.mMessage.GetType())
|
||||
switch (txMsg.GetType())
|
||||
{
|
||||
case kTypeAck:
|
||||
mResponseCache.Add(txMsg, aTxParameters->CalculateExchangeLifetime());
|
||||
break;
|
||||
case kTypeReset:
|
||||
OT_ASSERT(txMsg.mMessage.GetCode() == kCodeEmpty);
|
||||
OT_ASSERT(txMsg.GetCode() == kCodeEmpty);
|
||||
break;
|
||||
default:
|
||||
txMsg.mMessage.SetMessageId(mMessageId++);
|
||||
txMsg.UpdateMessageId(mMessageId++);
|
||||
break;
|
||||
}
|
||||
|
||||
txMsg.mMessage.Finish();
|
||||
|
||||
if (txMsg.mMessage.IsConfirmable())
|
||||
if (txMsg.IsConfirmable())
|
||||
{
|
||||
copyLength = txMsg.mMessage.GetLength();
|
||||
}
|
||||
else if (txMsg.mMessage.IsNonConfirmable() && (aHandler != nullptr))
|
||||
else if (txMsg.IsNonConfirmable() && (aHandler != nullptr))
|
||||
{
|
||||
// As we do not retransmit non confirmable messages, create a
|
||||
// copy of header only, for token information.
|
||||
copyLength = txMsg.mMessage.GetOptionStart();
|
||||
copyLength = txMsg.GetHeaderSize();
|
||||
}
|
||||
|
||||
if (copyLength > 0)
|
||||
@@ -248,7 +323,8 @@ Error CoapBase::SendMessage(Message &aMessage,
|
||||
bool shouldObserve = false;
|
||||
|
||||
SuccessOrExit(error = ProcessObserveSend(txMsg, shouldObserve));
|
||||
metadata.mObserve = shouldObserve;
|
||||
metadata.mObserve = shouldObserve;
|
||||
metadata.mIsRequest = txMsg.IsRequest();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -261,7 +337,7 @@ Error CoapBase::SendMessage(Message &aMessage,
|
||||
metadata.mRetransmissionsRemaining = aTxParameters->mMaxRetransmit;
|
||||
metadata.mRetransmissionTimeout = aTxParameters->CalculateInitialRetransmissionTimeout();
|
||||
metadata.mAcknowledged = false;
|
||||
metadata.mConfirmable = txMsg.mMessage.IsConfirmable();
|
||||
metadata.mConfirmable = txMsg.IsConfirmable();
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
metadata.mHopLimit = txMsg.mMessageInfo.GetHopLimit();
|
||||
metadata.mIsHostInterface = txMsg.mMessageInfo.IsHostInterface();
|
||||
@@ -339,7 +415,7 @@ Error CoapBase::SendAck(const Msg &aRxMsg) { return SendEmptyMessage(kTypeAck, a
|
||||
|
||||
Error CoapBase::SendEmptyAck(const Msg &aRxMsg, Code aCode)
|
||||
{
|
||||
return (aRxMsg.mMessage.IsConfirmable() ? SendHeaderResponse(aCode, aRxMsg) : kErrorInvalidArgs);
|
||||
return (aRxMsg.IsConfirmable() ? SendHeaderResponse(aCode, aRxMsg) : kErrorInvalidArgs);
|
||||
}
|
||||
|
||||
Error CoapBase::SendEmptyAck(const Msg &aRxMsg) { return SendEmptyAck(aRxMsg, kCodeChanged); }
|
||||
@@ -351,14 +427,11 @@ Error CoapBase::SendEmptyMessage(Type aType, const Msg &aRxMsg)
|
||||
Error error = kErrorNone;
|
||||
Message *message = nullptr;
|
||||
|
||||
VerifyOrExit(aRxMsg.mMessage.IsConfirmable(), error = kErrorInvalidArgs);
|
||||
VerifyOrExit(aRxMsg.IsConfirmable(), error = kErrorInvalidArgs);
|
||||
|
||||
VerifyOrExit((message = NewMessage()) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
message->Init(aType, kCodeEmpty);
|
||||
message->SetMessageId(aRxMsg.mMessage.GetMessageId());
|
||||
|
||||
message->Finish();
|
||||
SuccessOrExit(error = message->Init(aType, kCodeEmpty, aRxMsg.GetMessageId()));
|
||||
SuccessOrExit(error = Send(*message, aRxMsg.mMessageInfo));
|
||||
|
||||
exit:
|
||||
@@ -371,18 +444,17 @@ Error CoapBase::SendHeaderResponse(Message::Code aCode, const Msg &aRxMsg)
|
||||
Error error = kErrorNone;
|
||||
Message *message = nullptr;
|
||||
|
||||
VerifyOrExit(aRxMsg.mMessage.IsRequest(), error = kErrorInvalidArgs);
|
||||
VerifyOrExit(aRxMsg.IsRequest(), error = kErrorInvalidArgs);
|
||||
VerifyOrExit((message = NewMessage()) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
switch (aRxMsg.mMessage.GetType())
|
||||
switch (aRxMsg.GetType())
|
||||
{
|
||||
case kTypeConfirmable:
|
||||
message->Init(kTypeAck, aCode);
|
||||
message->SetMessageId(aRxMsg.mMessage.GetMessageId());
|
||||
SuccessOrExit(error = message->Init(kTypeAck, aCode, aRxMsg.GetMessageId()));
|
||||
break;
|
||||
|
||||
case kTypeNonConfirmable:
|
||||
message->Init(kTypeNonConfirmable, aCode);
|
||||
SuccessOrExit(error = message->Init(kTypeNonConfirmable, aCode));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -408,7 +480,7 @@ void CoapBase::ScheduleRetransmissionTimer(void)
|
||||
metadata.ReadFrom(message);
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
|
||||
if (IsObserveSubscription(message, metadata))
|
||||
if (IsObserveSubscription(metadata))
|
||||
{
|
||||
// This is an RFC7641 subscription which is already acknowledged.
|
||||
// We do not time it out, so skip it when determining the next
|
||||
@@ -441,7 +513,7 @@ void CoapBase::HandleRetransmissionTimer(void)
|
||||
if (now >= metadata.mNextTimerShot)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
|
||||
if (IsObserveSubscription(message, metadata))
|
||||
if (IsObserveSubscription(metadata))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -570,11 +642,11 @@ Message *CoapBase::FindRelatedRequest(const Msg &aMsg, Metadata &aMetadata)
|
||||
aMetadata.mDestinationPort == aMsg.mMessageInfo.GetPeerPort()) ||
|
||||
aMetadata.mDestinationAddress.IsMulticast() || aMetadata.mDestinationAddress.GetIid().IsAnycastLocator()))
|
||||
{
|
||||
switch (aMsg.mMessage.GetType())
|
||||
switch (aMsg.GetType())
|
||||
{
|
||||
case kTypeReset:
|
||||
case kTypeAck:
|
||||
if (aMsg.mMessage.GetMessageId() == message.GetMessageId())
|
||||
if (aMsg.GetMessageId() == message.ReadMessageId())
|
||||
{
|
||||
request = &message;
|
||||
ExitNow();
|
||||
@@ -603,16 +675,18 @@ void CoapBase::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
{
|
||||
Msg rxMsg(AsCoapMessage(&aMessage), aMessageInfo);
|
||||
|
||||
if (rxMsg.mMessage.ParseHeader() != kErrorNone)
|
||||
rxMsg.mMessage.SetHeaderOffset(rxMsg.mMessage.GetOffset());
|
||||
|
||||
if (rxMsg.ParseHeaderAndOptions(Msg::kRejectIfNoPayloadWithPayloadMarker) != kErrorNone)
|
||||
{
|
||||
LogDebg("Failed to parse CoAP header");
|
||||
|
||||
if (!aMessageInfo.GetSockAddr().IsMulticast() && rxMsg.mMessage.IsConfirmable())
|
||||
if (!aMessageInfo.GetSockAddr().IsMulticast() && rxMsg.IsConfirmable())
|
||||
{
|
||||
IgnoreError(SendReset(rxMsg));
|
||||
}
|
||||
}
|
||||
else if (rxMsg.mMessage.IsRequest())
|
||||
else if (rxMsg.IsRequest())
|
||||
{
|
||||
ProcessReceivedRequest(rxMsg);
|
||||
}
|
||||
@@ -643,7 +717,7 @@ void CoapBase::ProcessReceivedResponse(Msg &aRxMsg)
|
||||
// response, and we have a response handler; then we're dealing
|
||||
// with RFC7641 rules here. If there is no response handler, then
|
||||
// we're wasting our time!
|
||||
if (metadata.mObserve && request->IsRequest() && (metadata.mResponseHandler != nullptr))
|
||||
if (metadata.mObserve && metadata.mIsRequest && (metadata.mResponseHandler != nullptr))
|
||||
{
|
||||
Option::Iterator iterator;
|
||||
|
||||
@@ -652,10 +726,10 @@ void CoapBase::ProcessReceivedResponse(Msg &aRxMsg)
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (aRxMsg.mMessage.GetType())
|
||||
switch (aRxMsg.GetType())
|
||||
{
|
||||
case kTypeReset:
|
||||
if (aRxMsg.mMessage.IsEmpty())
|
||||
if (aRxMsg.IsEmpty())
|
||||
{
|
||||
FinalizeCoapTransaction(*request, metadata, nullptr, kErrorAbort);
|
||||
}
|
||||
@@ -664,12 +738,12 @@ void CoapBase::ProcessReceivedResponse(Msg &aRxMsg)
|
||||
break;
|
||||
|
||||
case kTypeAck:
|
||||
if (aRxMsg.mMessage.IsEmpty())
|
||||
if (aRxMsg.IsEmpty())
|
||||
{
|
||||
// Empty acknowledgment.
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
|
||||
if (metadata.mObserve && !request->IsRequest())
|
||||
if (metadata.mObserve && !metadata.mIsRequest)
|
||||
{
|
||||
// This is the ACK to our RFC7641 CON notification.
|
||||
// There will be no "separate" response so pass it back
|
||||
@@ -697,7 +771,7 @@ void CoapBase::ProcessReceivedResponse(Msg &aRxMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (aRxMsg.mMessage.IsResponse() && aRxMsg.mMessage.HasSameTokenAs(*request))
|
||||
else if (aRxMsg.IsResponse() && aRxMsg.mMessage.HasSameTokenAs(*request))
|
||||
{
|
||||
// Piggybacked response.
|
||||
|
||||
@@ -777,7 +851,7 @@ exit:
|
||||
{
|
||||
bool didHandle = InvokeResponseFallback(aRxMsg);
|
||||
|
||||
if (!didHandle && aRxMsg.mMessage.RequireResetOnError())
|
||||
if (!didHandle && aRxMsg.RequireResetOnError())
|
||||
{
|
||||
// Successfully parsed a header but no matching request was
|
||||
// found - reject the message by sending reset.
|
||||
@@ -893,10 +967,10 @@ Error CoapBase::SendMessage(Message &aMessage,
|
||||
return SendMessage(aMessage, aMessageInfo, aTxParameters, aHandler, aContext, nullptr, nullptr);
|
||||
}
|
||||
|
||||
Error CoapBase::ProcessBlockwiseSend(Message &aMessage, BlockwiseTransmitHook aTransmitHook, void *aContext)
|
||||
Error CoapBase::ProcessBlockwiseSend(Msg &aMsg, BlockwiseTransmitHook aTransmitHook, void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint8_t type = aMessage.GetType();
|
||||
uint8_t type = aMsg.GetType();
|
||||
bool moreBlocks = false;
|
||||
uint16_t blockSize;
|
||||
uint8_t buf[kMaxBlockSize];
|
||||
@@ -906,7 +980,7 @@ Error CoapBase::ProcessBlockwiseSend(Message &aMessage, BlockwiseTransmitHook aT
|
||||
|
||||
VerifyOrExit(aTransmitHook != nullptr);
|
||||
|
||||
SuccessOrExit(aMessage.ReadBlockOptionValues(type == kTypeAck ? kOptionBlock2 : kOptionBlock1, blockInfo));
|
||||
SuccessOrExit(aMsg.mMessage.ReadBlockOptionValues(type == kTypeAck ? kOptionBlock2 : kOptionBlock1, blockInfo));
|
||||
|
||||
VerifyOrExit(blockInfo.mBlockNumber == 0);
|
||||
|
||||
@@ -914,17 +988,17 @@ Error CoapBase::ProcessBlockwiseSend(Message &aMessage, BlockwiseTransmitHook aT
|
||||
VerifyOrExit(blockSize <= kMaxBlockSize, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = aTransmitHook(aContext, buf, 0, &blockSize, &moreBlocks));
|
||||
SuccessOrExit(error = aMessage.AppendBytes(buf, blockSize));
|
||||
SuccessOrExit(error = aMsg.mMessage.AppendBytes(buf, blockSize));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case kTypeAck:
|
||||
SuccessOrExit(error = CacheLastBlockResponse(&aMessage));
|
||||
SuccessOrExit(error = CacheLastBlockResponse(&aMsg.mMessage));
|
||||
break;
|
||||
|
||||
case kTypeNonConfirmable:
|
||||
// Block-Wise messages always have to be confirmable
|
||||
aMessage.SetType(kTypeConfirmable);
|
||||
aMsg.UpdateType(kTypeConfirmable);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -980,31 +1054,29 @@ Error CoapBase::ProcessBlockwiseResponse(Msg &aRxMsg, Message &aRequest, const M
|
||||
FinalizeCoapTransaction(aRequest, aMetadata, &aRxMsg, kErrorNone);
|
||||
break;
|
||||
case 1: // Block1 option
|
||||
if (aRxMsg.mMessage.GetCode() == kCodeContinue && aMetadata.mBlockwiseTransmitHook != nullptr)
|
||||
if (aRxMsg.GetCode() == kCodeContinue && aMetadata.mBlockwiseTransmitHook != nullptr)
|
||||
{
|
||||
error = SendNextBlock1Request(aRequest, aRxMsg, aMetadata);
|
||||
}
|
||||
|
||||
if (aRxMsg.mMessage.GetCode() != kCodeContinue || aMetadata.mBlockwiseTransmitHook == nullptr ||
|
||||
error != kErrorNone)
|
||||
if (aRxMsg.GetCode() != kCodeContinue || aMetadata.mBlockwiseTransmitHook == nullptr || error != kErrorNone)
|
||||
{
|
||||
FinalizeCoapTransaction(aRequest, aMetadata, &aRxMsg, error);
|
||||
}
|
||||
break;
|
||||
case 2: // Block2 option
|
||||
if (aRxMsg.mMessage.GetCode() < kCodeBadRequest && aMetadata.mBlockwiseReceiveHook != nullptr)
|
||||
if (aRxMsg.GetCode() < kCodeBadRequest && aMetadata.mBlockwiseReceiveHook != nullptr)
|
||||
{
|
||||
error = SendNextBlock2Request(aRequest, aRxMsg, aMetadata, totalTransferSize, false);
|
||||
}
|
||||
|
||||
if (aRxMsg.mMessage.GetCode() >= kCodeBadRequest || aMetadata.mBlockwiseReceiveHook == nullptr ||
|
||||
error != kErrorNone)
|
||||
if (aRxMsg.GetCode() >= kCodeBadRequest || aMetadata.mBlockwiseReceiveHook == nullptr || error != kErrorNone)
|
||||
{
|
||||
FinalizeCoapTransaction(aRequest, aMetadata, &aRxMsg, error);
|
||||
}
|
||||
break;
|
||||
case 3: // Block1 & Block2 option
|
||||
if (aRxMsg.mMessage.GetCode() < kCodeBadRequest && aMetadata.mBlockwiseReceiveHook != nullptr)
|
||||
if (aRxMsg.GetCode() < kCodeBadRequest && aMetadata.mBlockwiseReceiveHook != nullptr)
|
||||
{
|
||||
error = SendNextBlock2Request(aRequest, aRxMsg, aMetadata, totalTransferSize, true);
|
||||
}
|
||||
@@ -1162,12 +1234,12 @@ Error CoapBase::PrepareNextBlockRequest(uint16_t aBlockOptionNumber,
|
||||
Message &aRequest,
|
||||
const BlockInfo &aBlockInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error;
|
||||
bool isOptionSet = false;
|
||||
Option::Iterator iterator;
|
||||
Metadata metadata;
|
||||
|
||||
aRequest.Init(kTypeConfirmable, static_cast<ot::Coap::Code>(aRequestOld.GetCode()));
|
||||
SuccessOrExit(error = aRequest.Init(kTypeConfirmable, static_cast<ot::Coap::Code>(aRequestOld.ReadCode())));
|
||||
|
||||
metadata.ReadFrom(aRequestOld);
|
||||
metadata.RemoveFrom(aRequestOld);
|
||||
@@ -1253,7 +1325,7 @@ Error CoapBase::SendNextBlock1Request(Message &aRequest, Msg &aRxMsg, const Meta
|
||||
|
||||
SuccessOrExit(error = PrepareNextBlockRequest(kOptionBlock1, aRequest, *request, requestBlockInfo));
|
||||
|
||||
SuccessOrExit(error = request->SetPayloadMarker());
|
||||
SuccessOrExit(error = request->AppendPayloadMarker());
|
||||
|
||||
SuccessOrExit(error = request->AppendBytes(buf, blockSize));
|
||||
|
||||
@@ -1352,8 +1424,7 @@ Error CoapBase::ProcessBlock1Request(Msg &aRxMsg, const ResourceBlockWise &aReso
|
||||
{
|
||||
// Set up next response
|
||||
VerifyOrExit((response = NewMessage()) != nullptr, error = kErrorFailed);
|
||||
response->Init(kTypeAck, kCodeContinue);
|
||||
response->SetMessageId(aRxMsg.mMessage.GetMessageId());
|
||||
SuccessOrExit(error = response->Init(kTypeAck, kCodeContinue, aRxMsg.GetMessageId()));
|
||||
SuccessOrExit(error = response->WriteTokenFromMessage(aRxMsg.mMessage));
|
||||
|
||||
SuccessOrExit(error = response->AppendBlockOption(kOptionBlock1, msgBlockInfo));
|
||||
@@ -1405,9 +1476,8 @@ Error CoapBase::ProcessBlock2Request(Msg &aRxMsg, const ResourceBlockWise &aReso
|
||||
}
|
||||
|
||||
VerifyOrExit((response = NewMessage()) != nullptr, error = kErrorNoBufs);
|
||||
response->Init(kTypeAck, kCodeContent);
|
||||
response->SetMessageId(aRxMsg.mMessage.GetMessageId());
|
||||
|
||||
SuccessOrExit(error = response->Init(kTypeAck, kCodeContent, aRxMsg.GetMessageId()));
|
||||
SuccessOrExit(error = response->WriteTokenFromMessage(aRxMsg.mMessage));
|
||||
|
||||
responseBlockInfo.mMoreBlocks = false;
|
||||
@@ -1448,7 +1518,7 @@ Error CoapBase::ProcessBlock2Request(Msg &aRxMsg, const ResourceBlockWise &aReso
|
||||
SuccessOrExit(error = iterator.Advance());
|
||||
}
|
||||
|
||||
SuccessOrExit(error = response->SetPayloadMarker());
|
||||
SuccessOrExit(error = response->AppendPayloadMarker());
|
||||
SuccessOrExit(error = response->AppendBytes(buf, blockSize));
|
||||
|
||||
if (responseBlockInfo.mMoreBlocks)
|
||||
@@ -1512,7 +1582,7 @@ Error CoapBase::ProcessObserveSend(Msg &aTxMsg, bool &aShouldObserve)
|
||||
// Special case, if we're sending a GET with Observe=1, that is a
|
||||
// cancellation.
|
||||
|
||||
if (aShouldObserve && aTxMsg.mMessage.IsGetRequest())
|
||||
if (aShouldObserve && aTxMsg.IsGetRequest())
|
||||
{
|
||||
uint64_t value = 0;
|
||||
|
||||
@@ -1540,12 +1610,12 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool CoapBase::IsObserveSubscription(const Message &aMessage, const Metadata &aMetadata)
|
||||
bool CoapBase::IsObserveSubscription(const Metadata &aMetadata)
|
||||
{
|
||||
// Indicate whether the message is an RFC7641 subscription which
|
||||
// is already acknowledged.
|
||||
|
||||
return aMessage.IsRequest() && aMetadata.mObserve && aMetadata.mAcknowledged;
|
||||
return aMetadata.mIsRequest && aMetadata.mObserve && aMetadata.mAcknowledged;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
|
||||
@@ -1588,8 +1658,6 @@ Error CoapBase::ResponseCache::SendCachedResponse(const Msg &aRxMsg, CoapBase &a
|
||||
response = match->Clone(match->GetLength() - sizeof(ResponseMetadata));
|
||||
VerifyOrExit(response != nullptr, error = kErrorNoBufs);
|
||||
|
||||
response->Finish();
|
||||
|
||||
error = aCoapBase.Send(*response, aRxMsg.mMessageInfo);
|
||||
|
||||
exit:
|
||||
@@ -1600,11 +1668,11 @@ exit:
|
||||
const Message *CoapBase::ResponseCache::FindMatching(const Msg &aRxMsg) const
|
||||
{
|
||||
const Message *match = nullptr;
|
||||
uint16_t requestMsgId = aRxMsg.mMessage.GetMessageId();
|
||||
uint16_t requestMsgId = aRxMsg.GetMessageId();
|
||||
|
||||
for (const Message &response : mResponses)
|
||||
{
|
||||
if (response.GetMessageId() == requestMsgId)
|
||||
if (response.ReadMessageId() == requestMsgId)
|
||||
{
|
||||
ResponseMetadata metadata;
|
||||
|
||||
@@ -1745,7 +1813,7 @@ const TxParameters &TxParameters::GetDefault(void)
|
||||
return AsCoreType(&kDefaultTxParameters);
|
||||
}
|
||||
|
||||
Error TxParameters::ValidateFor(const Message &aMessage) const
|
||||
Error TxParameters::ValidateFor(const Msg &aMsg) const
|
||||
{
|
||||
Error error = kErrorInvalidArgs;
|
||||
uint32_t duration;
|
||||
@@ -1754,7 +1822,7 @@ Error TxParameters::ValidateFor(const Message &aMessage) const
|
||||
if (mAckTimeout == 0)
|
||||
{
|
||||
// Fire and forget is only allowed for non-confirmable messages.
|
||||
VerifyOrExit(aMessage.IsNonConfirmable());
|
||||
VerifyOrExit(aMsg.IsNonConfirmable());
|
||||
error = kErrorNone;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
+34
-18
@@ -55,6 +55,8 @@
|
||||
|
||||
namespace ot {
|
||||
|
||||
class UnitTester;
|
||||
|
||||
namespace Coap {
|
||||
|
||||
/**
|
||||
@@ -63,6 +65,7 @@ namespace Coap {
|
||||
* @{
|
||||
*/
|
||||
|
||||
class Msg;
|
||||
class CoapBase;
|
||||
|
||||
/**
|
||||
@@ -112,7 +115,7 @@ private:
|
||||
static constexpr uint8_t kMaxRetransmit = OT_COAP_MAX_RETRANSMIT;
|
||||
static constexpr uint32_t kMinAckTimeout = OT_COAP_MIN_ACK_TIMEOUT;
|
||||
|
||||
Error ValidateFor(const Message &aMessage) const;
|
||||
Error ValidateFor(const Msg &aMsg) const;
|
||||
uint32_t CalculateInitialRetransmissionTimeout(void) const;
|
||||
uint32_t CalculateExchangeLifetime(void) const;
|
||||
uint32_t CalculateMaxTransmitWait(void) const;
|
||||
@@ -122,11 +125,12 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a CoAP message and its associated `Ip6::MessageInfo`.
|
||||
* Represents a CoAP message and its associated `Ip6::MessageInfo` along with parse CoAP Header information.
|
||||
*/
|
||||
class Msg
|
||||
class Msg : public HeaderInfo
|
||||
{
|
||||
friend class CoapBase;
|
||||
friend class ot::UnitTester;
|
||||
|
||||
public:
|
||||
Message &mMessage; ///< The CoAP message.
|
||||
@@ -138,6 +142,17 @@ private:
|
||||
, mMessageInfo(aMessageInfo)
|
||||
{
|
||||
}
|
||||
|
||||
enum PayloadMarkerMode : uint8_t
|
||||
{
|
||||
kRejectIfNoPayloadWithPayloadMarker,
|
||||
kRemovePayloadMarkerIfNoPayload,
|
||||
};
|
||||
|
||||
Error ParseHeaderAndOptions(PayloadMarkerMode aPayloadMarkerMode);
|
||||
uint16_t GetHeaderSize(void) const;
|
||||
void UpdateType(Type aType);
|
||||
void UpdateMessageId(uint16_t aMessageId);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -342,9 +357,9 @@ public:
|
||||
* Allocates and initializes a new CoAP Confirmable Post message with Network Control priority level.
|
||||
*
|
||||
* The CoAP header is initialized as `kTypeConfirmable` and `kCodePost` with a given URI path and a randomly
|
||||
* generated token (of default length). This method also sets the payload marker (`SetPayloadMarker()` on message.
|
||||
* Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and
|
||||
* remove the payload marker when there is no payload.
|
||||
* generated token (of default length). This method also sets the payload marker (`AppendPayloadMarker()` on
|
||||
* message. Even if message has no payload, calling `AppendPayloadMarker()` is harmless, since `SendMessage()` will
|
||||
* check and remove the payload marker when there is no payload.
|
||||
*
|
||||
* @param[in] aUri The URI.
|
||||
*
|
||||
@@ -356,8 +371,8 @@ public:
|
||||
* Allocates and initializes a new CoAP Confirmable Post message with normal priority level.
|
||||
*
|
||||
* The CoAP header is initialized as `kTypeConfirmable` and `kCodePost` with a given URI and a randomly
|
||||
* generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`).
|
||||
* Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and
|
||||
* generated token (of default length). This method also sets the payload marker (calling `AppendPayloadMarker()`).
|
||||
* Even if message has no payload, calling `AppendPayloadMarker()` is harmless, since `SendMessage()` will check and
|
||||
* remove the payload marker when there is no payload.
|
||||
*
|
||||
* @param[in] aUri The URI.
|
||||
@@ -371,8 +386,8 @@ public:
|
||||
* level.
|
||||
*
|
||||
* The CoAP header is initialized as `kTypeNonConfirmable` and `kCodePost` with a given URI and a randomly
|
||||
* generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`).
|
||||
* Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and
|
||||
* generated token (of default length). This method also sets the payload marker (calling `AppendPayloadMarker()`).
|
||||
* Even if message has no payload, calling `AppendPayloadMarker()` is harmless, since `SendMessage()` will check and
|
||||
* remove the payload marker when there is no payload.
|
||||
*
|
||||
* @param[in] aUri The URI.
|
||||
@@ -385,8 +400,8 @@ public:
|
||||
* Allocates and initializes a new CoAP Non-confirmable Post message with normal priority level.
|
||||
*
|
||||
* The CoAP header is initialized as `kTypeNonConfirmable` and `kCodePost` with a given URI and a randomly
|
||||
* generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`).
|
||||
* Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and
|
||||
* generated token (of default length). This method also sets the payload marker (calling `AppendPayloadMarker()`).
|
||||
* Even if message has no payload, calling `AppendPayloadMarker()` is harmless, since `SendMessage()` will check and
|
||||
* remove the payload marker when there is no payload.
|
||||
*
|
||||
* @param[in] aUri The URI.
|
||||
@@ -400,8 +415,8 @@ public:
|
||||
* given request message.
|
||||
*
|
||||
* The CoAP header is initialized as `kTypeAck` with `kCodeChanged`. The token and message ID is copied from
|
||||
* @p aRequest. This method also sets the payload marker (calling `SetPayloadMarker()`). Even if message has
|
||||
* no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and remove the payload
|
||||
* @p aRequest. This method also sets the payload marker (calling `AppendPayloadMarker()`). Even if message has
|
||||
* no payload, calling `AppendPayloadMarker()` is harmless, since `SendMessage()` will check and remove the payload
|
||||
* marker when there is no payload.
|
||||
*
|
||||
* @returns A pointer to the message or `nullptr` if failed to allocate message.
|
||||
@@ -413,8 +428,8 @@ public:
|
||||
* request message.
|
||||
*
|
||||
* The CoAP header is initialized as `kTypeAck` with `kCodeChanged`. The token and message ID is copied from
|
||||
* @p aRequest. This method also sets the payload marker (calling `SetPayloadMarker()`). Even if message has
|
||||
* no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and remove the payload
|
||||
* @p aRequest. This method also sets the payload marker (calling `AppendPayloadMarker()`). Even if message has
|
||||
* no payload, calling `AppendPayloadMarker()` is harmless, since `SendMessage()` will check and remove the payload
|
||||
* marker when there is no payload.
|
||||
*
|
||||
* @returns A pointer to the message or `nullptr` if failed to allocate message.
|
||||
@@ -754,6 +769,7 @@ private:
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
|
||||
bool mObserve : 1; // Information that this request involves Observations.
|
||||
bool mIsRequest : 1;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
|
||||
BlockwiseReceiveHook mBlockwiseReceiveHook; // Function pointer called on Block2 response reception.
|
||||
@@ -810,7 +826,7 @@ private:
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
|
||||
|
||||
Error ProcessBlockwiseSend(Message &aMessage, BlockwiseTransmitHook aTransmitHook, void *aContext);
|
||||
Error ProcessBlockwiseSend(Msg &aMsg, BlockwiseTransmitHook aTransmitHook, void *aContext);
|
||||
Error ProcessBlockwiseResponse(Msg &aRxMsg, Message &aRequest, const Metadata &aMetadata);
|
||||
Error ProcessBlockwiseRequest(Msg &aRxMsg, Message::UriPathStringBuffer &aUriPath, bool &aDidHandle);
|
||||
void FreeLastBlockResponse(void);
|
||||
@@ -835,7 +851,7 @@ private:
|
||||
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
|
||||
Error ProcessObserveSend(Msg &aTxMsg, bool &aShouldObserve);
|
||||
|
||||
static bool IsObserveSubscription(const Message &aMessage, const Metadata &aMetadata);
|
||||
static bool IsObserveSubscription(const Metadata &aMetadata);
|
||||
#endif
|
||||
|
||||
MessageQueue mPendingRequests;
|
||||
|
||||
+280
-145
@@ -86,31 +86,44 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// `HeaderInfo`
|
||||
|
||||
bool HeaderInfo::IsRequest(void) const { return IsValueInRange<uint8_t>(mCode, kCodeGet, kCodeDelete); }
|
||||
|
||||
bool HeaderInfo::IsConfirmablePostRequest(void) const { return IsConfirmable() && IsPostRequest(); }
|
||||
|
||||
bool HeaderInfo::IsNonConfirmablePostRequest(void) const { return IsNonConfirmable() && IsPostRequest(); }
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// `Message`
|
||||
|
||||
void Message::Init(void)
|
||||
Error Message::Init(Type aType, Code aCode) { return Init(aType, aCode, 0); }
|
||||
|
||||
Error Message::Init(Type aType, Code aCode, uint16_t aMessageId)
|
||||
{
|
||||
GetHelpData().Clear();
|
||||
SetVersion(Header::kVersion1);
|
||||
Header header;
|
||||
|
||||
// Erase any previously written content in the message.
|
||||
IgnoreError(SetLength(0));
|
||||
|
||||
SetOffset(0);
|
||||
GetHelpData().mHeaderLength = kMinHeaderLength;
|
||||
SetHeaderOffset(0);
|
||||
|
||||
IgnoreError(SetLength(GetHelpData().mHeaderLength));
|
||||
}
|
||||
header.Clear();
|
||||
header.SetVersion(Header::kVersion1);
|
||||
header.SetType(aType);
|
||||
header.SetCode(aCode);
|
||||
header.SetMessageId(aMessageId);
|
||||
|
||||
void Message::Init(Type aType, Code aCode)
|
||||
{
|
||||
Init();
|
||||
SetType(aType);
|
||||
SetCode(aCode);
|
||||
return Append(header);
|
||||
}
|
||||
|
||||
Error Message::Init(Type aType, Code aCode, Uri aUri)
|
||||
{
|
||||
Error error;
|
||||
|
||||
Init(aType, aCode);
|
||||
SuccessOrExit(error = Init(aType, aCode));
|
||||
SuccessOrExit(error = WriteRandomToken(Token::kDefaultLength));
|
||||
SuccessOrExit(error = AppendUriPathOptions(PathForUri(aUri)));
|
||||
|
||||
@@ -123,23 +136,120 @@ Error Message::InitAsPost(const Ip6::Address &aDestination, Uri aUri)
|
||||
return Init(aDestination.IsMulticast() ? kTypeNonConfirmable : kTypeConfirmable, kCodePost, aUri);
|
||||
}
|
||||
|
||||
bool Message::IsConfirmablePostRequest(void) const { return IsConfirmable() && IsPostRequest(); }
|
||||
|
||||
bool Message::IsNonConfirmablePostRequest(void) const { return IsNonConfirmable() && IsPostRequest(); }
|
||||
|
||||
void Message::Finish(void)
|
||||
Error Message::InitAsResponse(Type aType, Code aCode, const Message &aRequest)
|
||||
{
|
||||
// If the payload marker is set but the message contains no
|
||||
// payload, we remove the payload marker from the message. Note
|
||||
// that the presence of a marker followed by a zero-length payload
|
||||
// will be processed as a message format error on the receiver.
|
||||
Error error;
|
||||
|
||||
if (GetHelpData().mPayloadMarkerSet && (GetHelpData().mHeaderLength == GetLength()))
|
||||
{
|
||||
RemoveFooter(sizeof(uint8_t));
|
||||
}
|
||||
SuccessOrExit(error = Init(aType, aCode, aRequest.ReadMessageId()));
|
||||
error = WriteTokenFromMessage(aRequest);
|
||||
|
||||
WriteBytes(0, &GetHelpData().mHeader, GetOptionStart());
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Message::ReadHeader(Header &aHeader) const
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Read(GetHeaderOffset(), aHeader));
|
||||
VerifyOrExit(aHeader.GetVersion() == Header::kVersion1, error = kErrorParse);
|
||||
VerifyOrExit(aHeader.GetTokenLength() <= Token::kMaxLength, error = kErrorParse);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Message::WriteHeader(const Header &aHeader) { Write(GetHeaderOffset(), aHeader); }
|
||||
|
||||
Error Message::ParseHeaderInfo(HeaderInfo &aInfo) const
|
||||
{
|
||||
Error error;
|
||||
Header header;
|
||||
|
||||
aInfo.Clear();
|
||||
|
||||
SuccessOrExit(error = ReadHeader(header));
|
||||
|
||||
aInfo.mType = header.GetType();
|
||||
aInfo.mCode = header.GetCode();
|
||||
aInfo.mMessageId = header.GetMessageId();
|
||||
|
||||
error = ReadToken(header, aInfo.mToken);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t Message::ReadType(void) const
|
||||
{
|
||||
uint8_t type = 0;
|
||||
Header header;
|
||||
|
||||
SuccessOrExit(ReadHeader(header));
|
||||
type = header.GetType();
|
||||
|
||||
exit:
|
||||
return type;
|
||||
}
|
||||
|
||||
void Message::WriteType(Type aType)
|
||||
{
|
||||
Header header;
|
||||
|
||||
SuccessOrExit(ReadHeader(header));
|
||||
header.SetType(aType);
|
||||
WriteHeader(header);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t Message::ReadCode(void) const
|
||||
{
|
||||
uint8_t code = 0;
|
||||
Header header;
|
||||
|
||||
SuccessOrExit(ReadHeader(header));
|
||||
code = header.GetCode();
|
||||
|
||||
exit:
|
||||
return code;
|
||||
}
|
||||
|
||||
void Message::WriteCode(Code aCode)
|
||||
{
|
||||
Header header;
|
||||
|
||||
SuccessOrExit(ReadHeader(header));
|
||||
header.SetCode(aCode);
|
||||
WriteHeader(header);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t Message::ReadMessageId(void) const
|
||||
{
|
||||
uint16_t messageId = 0;
|
||||
Header header;
|
||||
|
||||
SuccessOrExit(ReadHeader(header));
|
||||
messageId = header.GetMessageId();
|
||||
|
||||
exit:
|
||||
return messageId;
|
||||
}
|
||||
|
||||
void Message::WriteMessageId(uint16_t aMessageId)
|
||||
{
|
||||
Header header;
|
||||
|
||||
SuccessOrExit(ReadHeader(header));
|
||||
header.SetMessageId(aMessageId);
|
||||
WriteHeader(header);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t Message::WriteExtendedOptionField(uint16_t aValue, uint8_t *&aBuffer)
|
||||
@@ -186,18 +296,34 @@ uint8_t Message::WriteExtendedOptionField(uint16_t aValue, uint8_t *&aBuffer)
|
||||
|
||||
Error Message::AppendOptionHeader(uint16_t aNumber, uint16_t aLength)
|
||||
{
|
||||
/*
|
||||
* Appends a CoAP Option header field (Option Delta/Length) per RFC 7252.
|
||||
*/
|
||||
// Appends a CoAP Option header field (Option Delta/Length) per RFC 7252.
|
||||
|
||||
Error error = kErrorNone;
|
||||
uint16_t delta;
|
||||
uint8_t header[kMaxOptionHeaderSize];
|
||||
uint16_t headerLength;
|
||||
uint8_t *cur;
|
||||
Error error;
|
||||
Option::Iterator iterator;
|
||||
uint16_t lastNumber;
|
||||
uint16_t delta;
|
||||
uint8_t header[kMaxOptionHeaderSize];
|
||||
uint16_t headerLength;
|
||||
uint8_t *cur;
|
||||
|
||||
VerifyOrExit(aNumber >= GetHelpData().mOptionLast, error = kErrorInvalidArgs);
|
||||
delta = aNumber - GetHelpData().mOptionLast;
|
||||
// Parses the already appended options in the message
|
||||
// to determine the last option number. Also ensures
|
||||
// that "payload marker" is not appended.
|
||||
|
||||
SuccessOrExit(error = iterator.Init(*this));
|
||||
|
||||
lastNumber = 0;
|
||||
|
||||
while (!iterator.IsDone())
|
||||
{
|
||||
lastNumber = iterator.GetOption()->GetNumber();
|
||||
SuccessOrExit(error = iterator.Advance());
|
||||
}
|
||||
|
||||
VerifyOrExit(!iterator.HasPayloadMarker(), error = kErrorParse);
|
||||
|
||||
VerifyOrExit(aNumber >= lastNumber, error = kErrorInvalidArgs);
|
||||
delta = aNumber - lastNumber;
|
||||
|
||||
cur = &header[1];
|
||||
|
||||
@@ -206,12 +332,8 @@ Error Message::AppendOptionHeader(uint16_t aNumber, uint16_t aLength)
|
||||
|
||||
headerLength = static_cast<uint16_t>(cur - header);
|
||||
|
||||
VerifyOrExit(static_cast<uint32_t>(GetLength()) + headerLength + aLength < kMaxHeaderLength, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = AppendBytes(header, headerLength));
|
||||
|
||||
GetHelpData().mOptionLast = aNumber;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -223,8 +345,6 @@ Error Message::AppendOption(uint16_t aNumber, uint16_t aLength, const void *aVal
|
||||
SuccessOrExit(error = AppendOptionHeader(aNumber, aLength));
|
||||
SuccessOrExit(error = AppendBytes(aValue, aLength));
|
||||
|
||||
GetHelpData().mHeaderLength = GetLength();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -236,8 +356,6 @@ Error Message::AppendOptionFromMessage(uint16_t aNumber, uint16_t aLength, const
|
||||
SuccessOrExit(error = AppendOptionHeader(aNumber, aLength));
|
||||
SuccessOrExit(error = AppendBytesFromMessage(aMessage, aOffset, aLength));
|
||||
|
||||
GetHelpData().mHeaderLength = GetLength();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -407,38 +525,12 @@ exit:
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
|
||||
|
||||
Error Message::SetPayloadMarker(void)
|
||||
Error Message::AppendPayloadMarker(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint8_t marker = kPayloadMarker;
|
||||
|
||||
VerifyOrExit(GetLength() < kMaxHeaderLength, error = kErrorNoBufs);
|
||||
SuccessOrExit(error = Append(marker));
|
||||
GetHelpData().mPayloadMarkerSet = true;
|
||||
GetHelpData().mHeaderLength = GetLength();
|
||||
|
||||
// Set offset to the start of payload.
|
||||
SetOffset(GetHelpData().mHeaderLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Message::ParseHeader(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t offset = GetOffset();
|
||||
Error error;
|
||||
uint8_t marker = kPayloadMarker;
|
||||
Option::Iterator iterator;
|
||||
|
||||
OT_ASSERT(GetReserved() >=
|
||||
sizeof(HelpData) + static_cast<size_t>((reinterpret_cast<uint8_t *>(&GetHelpData()) - GetFirstData())));
|
||||
|
||||
GetHelpData().Clear();
|
||||
|
||||
GetHelpData().mHeaderOffset = offset;
|
||||
|
||||
SuccessOrExit(error = GetHelpData().mHeader.ParseFrom(*this));
|
||||
|
||||
SuccessOrExit(error = iterator.Init(*this));
|
||||
|
||||
while (!iterator.IsDone())
|
||||
@@ -446,8 +538,51 @@ Error Message::ParseHeader(void)
|
||||
SuccessOrExit(error = iterator.Advance());
|
||||
}
|
||||
|
||||
GetHelpData().mHeaderLength = iterator.GetPayloadMessageOffset() - GetHelpData().mHeaderOffset;
|
||||
MoveOffset(GetHelpData().mHeaderLength);
|
||||
VerifyOrExit(!iterator.HasPayloadMarker());
|
||||
|
||||
SuccessOrExit(error = Append(marker));
|
||||
|
||||
SetOffset(GetLength());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint16_t Message::DetermineTokenOffset(void) const
|
||||
{
|
||||
uint16_t offset;
|
||||
|
||||
if (CanAddSafely<uint16_t>(GetHeaderOffset(), sizeof(Header)))
|
||||
{
|
||||
offset = GetHeaderOffset() + sizeof(Header);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetToUintMax(offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
Error Message::DetermineOptionStartOffset(uint16_t &aOffset) const
|
||||
{
|
||||
Error error;
|
||||
uint8_t tokenLength;
|
||||
uint16_t offset;
|
||||
|
||||
SuccessOrExit(error = ReadTokenLength(tokenLength));
|
||||
offset = DetermineTokenOffset();
|
||||
|
||||
if (CanAddSafely<uint16_t>(offset, tokenLength))
|
||||
{
|
||||
offset += tokenLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetToUintMax(offset);
|
||||
}
|
||||
|
||||
aOffset = offset;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -455,10 +590,11 @@ exit:
|
||||
|
||||
Error Message::ReadTokenLength(uint8_t &aLength) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
Header header;
|
||||
|
||||
VerifyOrExit(GetHelpData().mHeader.IsValid(), error = kErrorParse);
|
||||
aLength = GetHelpData().mHeader.GetTokenLength();
|
||||
SuccessOrExit(error = ReadHeader(header));
|
||||
aLength = header.GetTokenLength();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -466,16 +602,51 @@ exit:
|
||||
|
||||
Error Message::ReadToken(Token &aToken) const
|
||||
{
|
||||
return aToken.SetToken(GetHelpData().mHeader.GetToken(), GetHelpData().mHeader.GetTokenLength());
|
||||
Error error;
|
||||
Header header;
|
||||
|
||||
SuccessOrExit(error = ReadHeader(header));
|
||||
error = ReadToken(header, aToken);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Message::ReadToken(const Header &aHeader, Token &aToken) const
|
||||
{
|
||||
aToken.mLength = aHeader.GetTokenLength();
|
||||
|
||||
return Read(DetermineTokenOffset(), aToken.m8, aToken.mLength);
|
||||
}
|
||||
|
||||
Error Message::WriteToken(const Token &aToken)
|
||||
{
|
||||
Error error;
|
||||
Error error;
|
||||
Header header;
|
||||
uint16_t tokenOffset = DetermineTokenOffset();
|
||||
|
||||
SuccessOrExit(error = GetHelpData().mHeader.SetToken(aToken));
|
||||
GetHelpData().mHeaderLength += aToken.GetLength();
|
||||
error = SetLength(GetHelpData().mHeaderLength);
|
||||
VerifyOrExit(aToken.IsValid(), error = kErrorInvalidArgs);
|
||||
|
||||
SuccessOrExit(error = ReadHeader(header));
|
||||
|
||||
if (tokenOffset == GetLength())
|
||||
{
|
||||
// A token has not been written yet, so grow the message to make
|
||||
// space for it.
|
||||
|
||||
SuccessOrExit(error = IncreaseLength(aToken.GetLength()));
|
||||
|
||||
header.SetTokenLength(aToken.GetLength());
|
||||
WriteHeader(header);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a token was previously written, we only allow it to be
|
||||
// overwritten by a new token of the same length.
|
||||
|
||||
VerifyOrExit(header.GetTokenLength() == aToken.GetLength(), error = kErrorInvalidArgs);
|
||||
}
|
||||
|
||||
WriteBytes(tokenOffset, aToken.GetBytes(), aToken.GetLength());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -519,22 +690,13 @@ exit:
|
||||
return hasSame;
|
||||
}
|
||||
|
||||
Error Message::SetDefaultResponseHeader(const Message &aRequest)
|
||||
{
|
||||
Init(kTypeAck, kCodeChanged);
|
||||
|
||||
SetMessageId(aRequest.GetMessageId());
|
||||
|
||||
return WriteTokenFromMessage(aRequest);
|
||||
}
|
||||
|
||||
Message *Message::Clone(uint16_t aLength) const
|
||||
{
|
||||
Message *message = static_cast<Message *>(ot::Message::Clone(aLength));
|
||||
|
||||
VerifyOrExit(message != nullptr);
|
||||
|
||||
message->GetHelpData() = GetHelpData();
|
||||
message->SetHeaderOffset(GetHeaderOffset());
|
||||
|
||||
exit:
|
||||
return message;
|
||||
@@ -576,45 +738,10 @@ const char *Message::CodeToString(void) const
|
||||
|
||||
static_assert(Stringify::IsSorted(kCodeTable), "kCodeTable is not sorted");
|
||||
|
||||
return Stringify::Lookup(GetCode(), kCodeTable, "Unknown");
|
||||
return Stringify::Lookup(ReadCode(), kCodeTable, "Unknown");
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// `Message::Header`
|
||||
|
||||
bool Message::Header::IsValid(void) const
|
||||
{
|
||||
return (GetVersion() == kVersion1) && (GetTokenLength() <= Token::kMaxLength);
|
||||
}
|
||||
|
||||
Error Message::Header::ParseFrom(const Message &aMessage)
|
||||
{
|
||||
Error error;
|
||||
uint16_t offset = aMessage.GetOffset();
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(offset, this, kMinSize));
|
||||
VerifyOrExit(IsValid(), error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(offset + kMinSize, mToken, GetTokenLength()));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Message::Header::SetToken(const Token &aToken)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(aToken.IsValid(), error = kErrorInvalidArgs);
|
||||
|
||||
SetTokenLength(aToken.mLength);
|
||||
memcpy(mToken, aToken.GetBytes(), aToken.GetLength());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// `Message::Iterator`
|
||||
|
||||
@@ -627,23 +754,30 @@ Message::ConstIterator MessageQueue::begin(void) const { return Message::ConstIt
|
||||
|
||||
Error Option::Iterator::Init(const Message &aMessage)
|
||||
{
|
||||
Error error = kErrorParse;
|
||||
uint32_t offset = static_cast<uint32_t>(aMessage.GetHelpData().mHeaderOffset) + aMessage.GetOptionStart();
|
||||
Error error;
|
||||
uint16_t offset;
|
||||
|
||||
SuccessOrExit(error = aMessage.DetermineOptionStartOffset(offset));
|
||||
|
||||
// Note that the case where `offset == aMessage.GetLength())` is
|
||||
// valid and indicates an empty payload (no CoAP Option and no
|
||||
// Payload Marker).
|
||||
|
||||
VerifyOrExit(offset <= aMessage.GetLength(), MarkAsParseErrored());
|
||||
VerifyOrExit(offset <= aMessage.GetLength(), error = kErrorParse);
|
||||
|
||||
mOption.mNumber = 0;
|
||||
mOption.mLength = 0;
|
||||
mMessage = &aMessage;
|
||||
mNextOptionOffset = static_cast<uint16_t>(offset);
|
||||
mNextOptionOffset = offset;
|
||||
|
||||
error = Advance();
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
MarkAsDone();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -658,22 +792,23 @@ Error Option::Iterator::Advance(void)
|
||||
|
||||
error = Read(sizeof(uint8_t), &headerByte);
|
||||
|
||||
if ((error != kErrorNone) || (headerByte == Message::kPayloadMarker))
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
// Reached the end without seeing the payload marker.
|
||||
|
||||
MarkAsDone();
|
||||
SetHasPayloadMarker(false);
|
||||
ExitNow(error = kErrorNone);
|
||||
}
|
||||
|
||||
if (headerByte == Message::kPayloadMarker)
|
||||
{
|
||||
// Payload Marker indicates end of options and start of payload.
|
||||
// Absence of a Payload Marker indicates a zero-length payload.
|
||||
|
||||
MarkAsDone();
|
||||
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
// The presence of a marker followed by a zero-length payload
|
||||
// MUST be processed as a message format error.
|
||||
|
||||
VerifyOrExit(mNextOptionOffset < GetMessage().GetLength(), error = kErrorParse);
|
||||
}
|
||||
|
||||
ExitNow(error = kErrorNone);
|
||||
SetHasPayloadMarker(true);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
optionDelta = (headerByte & Message::kOptionDeltaMask) >> Message::kOptionDeltaOffset;
|
||||
@@ -691,7 +826,7 @@ Error Option::Iterator::Advance(void)
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
MarkAsParseErrored();
|
||||
MarkAsDone();
|
||||
}
|
||||
|
||||
return error;
|
||||
|
||||
+284
-283
@@ -69,8 +69,10 @@ namespace Coap {
|
||||
* @{
|
||||
*/
|
||||
|
||||
class Msg;
|
||||
class Message;
|
||||
class Option;
|
||||
class CoapBase;
|
||||
|
||||
/**
|
||||
* CoAP Type values.
|
||||
@@ -263,18 +265,177 @@ private:
|
||||
Error GenerateRandom(uint8_t aLength);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents information from a parsed CoAP Header in a CoAP message.
|
||||
*/
|
||||
class HeaderInfo : public Clearable<HeaderInfo>
|
||||
{
|
||||
friend class Message;
|
||||
friend class Msg;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the Type value.
|
||||
*
|
||||
* @returns The Type value.
|
||||
*/
|
||||
uint8_t GetType(void) const { return mType; }
|
||||
|
||||
/**
|
||||
* Returns the Code value.
|
||||
*
|
||||
* @returns The Code value.
|
||||
*/
|
||||
uint8_t GetCode(void) const { return mCode; }
|
||||
|
||||
/**
|
||||
* Returns the Message ID value.
|
||||
*
|
||||
* @returns The Message ID value.
|
||||
*/
|
||||
uint16_t GetMessageId(void) const { return mMessageId; }
|
||||
|
||||
/**
|
||||
* Returns the Token.
|
||||
*
|
||||
* @returns The Token.
|
||||
*/
|
||||
const Token &GetToken(void) const { return mToken; }
|
||||
|
||||
/**
|
||||
* Checks if a header is an empty message header (`kCodeEmpty`).
|
||||
*
|
||||
* @retval TRUE Message is an empty message header.
|
||||
* @retval FALSE Message is not an empty message header.
|
||||
*/
|
||||
bool IsEmpty(void) const { return (mCode == kCodeEmpty); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a request header.
|
||||
*
|
||||
* @retval TRUE Message is a request header.
|
||||
* @retval FALSE Message is not a request header.
|
||||
*/
|
||||
bool IsRequest(void) const;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the CoAP code in header is "Get" request.
|
||||
*
|
||||
* @retval TRUE Message is a Get request.
|
||||
* @retval FALSE Message is not a Get request.
|
||||
*/
|
||||
bool IsGetRequest(void) const { return (mCode == kCodeGet); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the CoAP code in header is "Post" request.
|
||||
*
|
||||
* @retval TRUE Message is a Post request.
|
||||
* @retval FALSE Message is not a Post request.
|
||||
*/
|
||||
bool IsPostRequest(void) const { return (mCode == kCodePost); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the CoAP code in header is "Put" request.
|
||||
*
|
||||
* @retval TRUE Message is a Put request.
|
||||
* @retval FALSE Message is not a Put request.
|
||||
*/
|
||||
bool IsPutRequest(void) const { return (mCode == kCodePut); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the CoAP code in header is "Delete" request.
|
||||
*
|
||||
* @retval TRUE Message is a Delete request.
|
||||
* @retval FALSE Message is not a Delete request.
|
||||
*/
|
||||
bool IsDeleteRequest(void) const { return (mCode == kCodeDelete); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a response header.
|
||||
*
|
||||
* @retval TRUE Message is a response header.
|
||||
* @retval FALSE Message is not a response header.
|
||||
*/
|
||||
bool IsResponse(void) const { return mCode >= kCodeResponseMin; }
|
||||
|
||||
/**
|
||||
* Checks if a header is a CON message header.
|
||||
*
|
||||
* @retval TRUE Message is a CON message header.
|
||||
* @retval FALSE Message is not is a CON message header.
|
||||
*/
|
||||
bool IsConfirmable(void) const { return (GetType() == kTypeConfirmable); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a NON message header.
|
||||
*
|
||||
* @retval TRUE Message is a NON message header.
|
||||
* @retval FALSE Message is not is a NON message header.
|
||||
*/
|
||||
bool IsNonConfirmable(void) const { return (mType == kTypeNonConfirmable); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a ACK message header.
|
||||
*
|
||||
* @retval TRUE Message is a ACK message header.
|
||||
* @retval FALSE Message is not is a ACK message header.
|
||||
*/
|
||||
bool IsAck(void) const { return (mType == kTypeAck); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a RST message header.
|
||||
*
|
||||
* @retval TRUE Message is a RST message header.
|
||||
* @retval FALSE Message is not is a RST message header.
|
||||
*/
|
||||
bool IsReset(void) const { return (mType == kTypeReset); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the header is a confirmable Post request (`kTypeConfirmable` with`kCodePost`).
|
||||
*
|
||||
* @retval TRUE Message is a confirmable Post request.
|
||||
* @retval FALSE Message is not a confirmable Post request.
|
||||
*/
|
||||
bool IsConfirmablePostRequest(void) const;
|
||||
|
||||
/**
|
||||
* Indicates whether the message is a non-confirmable Post request (`kTypeNonConfirmable` with `kCodePost`).
|
||||
*
|
||||
* @retval TRUE Message is a non-confirmable Post request.
|
||||
* @retval FALSE Message is not a non-confirmable Post request.
|
||||
*/
|
||||
bool IsNonConfirmablePostRequest(void) const;
|
||||
|
||||
/**
|
||||
* Checks if the message requires a reset response if an error during low level CoAP processing occurred.
|
||||
*
|
||||
* A reset message is expected to be sent for NON and CON messages if the message can not be processed or a
|
||||
* duplicated message has been received.
|
||||
*
|
||||
* @retval TRUE Expect to respond with CoAP reset message on error.
|
||||
* @retval FALSE No CoAP reset message should be sent on error.
|
||||
*/
|
||||
bool RequireResetOnError(void) { return IsConfirmable() || IsNonConfirmable(); }
|
||||
|
||||
private:
|
||||
uint8_t mType;
|
||||
uint8_t mCode;
|
||||
uint16_t mMessageId;
|
||||
Token mToken;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements CoAP message generation and parsing.
|
||||
*/
|
||||
class Message : public ot::Message
|
||||
{
|
||||
friend class Msg;
|
||||
friend class Option;
|
||||
friend class MessageQueue;
|
||||
friend class CoapBase;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kDefaultTokenLength = OT_COAP_DEFAULT_TOKEN_LENGTH; ///< Default token length.
|
||||
static constexpr uint8_t kMaxReceivedUriPath = 32; ///< Max URI path length on rx msgs.
|
||||
static constexpr uint8_t kMaxTokenLength = OT_COAP_MAX_TOKEN_LENGTH; ///< Maximum token length.
|
||||
static constexpr uint8_t kMaxReceivedUriPath = 32; ///< Max URI path length on rx msgs.
|
||||
|
||||
typedef ot::Coap::Type Type; ///< CoAP Type.
|
||||
typedef ot::Coap::Code Code; ///< CoAP Code.
|
||||
@@ -282,91 +443,121 @@ public:
|
||||
typedef char UriPathStringBuffer[kMaxReceivedUriPath + 1]; ///< Buffer to store a received URI Path string.
|
||||
|
||||
/**
|
||||
* Initializes the CoAP header.
|
||||
* Initializes the CoAP message with a given Type and Code.
|
||||
*
|
||||
* This method erases any previously written content in the message. The Message ID is set to zero, and the token
|
||||
* is empty (zero-length).
|
||||
*
|
||||
* @param[in] aType The CoAP Type value.
|
||||
* @param[in] aCode The CoAP Code value.
|
||||
*
|
||||
* @retval kErrorNone Successfully initialized the message.
|
||||
* @retval kErrorNoBufs Could not grow the message to write the CoAP header.
|
||||
*/
|
||||
void Init(void);
|
||||
Error Init(Type aType, Code aCode);
|
||||
|
||||
/**
|
||||
* Initializes the CoAP header with specific Type and Code.
|
||||
* Initializes the CoAP message with a given Type, Code, and Message ID.
|
||||
*
|
||||
* @param[in] aType The Type value.
|
||||
* @param[in] aCode The Code value.
|
||||
* This method erases any previously written content in the message. The token is empty (zero-length).
|
||||
*
|
||||
* @param[in] aType The CoAP Type value.
|
||||
* @param[in] aCode The CoAP Code value.
|
||||
* @param[in] aMessageId The CoAP Message ID value.
|
||||
*
|
||||
* @retval kErrorNone Successfully initialized the message.
|
||||
* @retval kErrorNoBufs Could not grow the message to write the CoAP header.
|
||||
*/
|
||||
void Init(Type aType, Code aCode);
|
||||
Error Init(Type aType, Code aCode, uint16_t aMessageId);
|
||||
|
||||
/**
|
||||
* Initializes the CoAP header with specific Type and Code.
|
||||
* Initializes the message with a Type, Code, adds a random token, and appends a URI-path option.
|
||||
*
|
||||
* @param[in] aType The Type value.
|
||||
* @param[in] aCode The Code value.
|
||||
* @param[in] aUri The URI.
|
||||
* This method erases any previously written content in the message. The Message ID is set to zero. A random token
|
||||
* of default length (`Token::kDefaultLength`) is generated and added to the message.
|
||||
*
|
||||
* @retval kErrorNone Successfully appended the option.
|
||||
* @retval kErrorNoBufs The option length exceeds the buffer size.
|
||||
* @param[in] aType The CoAP Type value.
|
||||
* @param[in] aCode The CoAP Code value.
|
||||
* @param[in] aUri The URI string.
|
||||
*
|
||||
* @retval kErrorNone Successfully initialized the message and appended the URI-path option.
|
||||
* @retval kErrorNoBufs Could not grow the message to append the option.
|
||||
*/
|
||||
Error Init(Type aType, Code aCode, Uri aUri);
|
||||
|
||||
/**
|
||||
* Initializes the CoAP header as `kCodePost` with a given URI Path with its type determined from a
|
||||
* given destination IPv6 address.
|
||||
* Initializes a CoAP POST message, appends a URI Path, and adds a random token.
|
||||
*
|
||||
* @param[in] aDestination The message destination IPv6 address used to determine the CoAP type,
|
||||
* `kTypeNonConfirmable` if multicast address, `kTypeConfirmable` otherwise.
|
||||
* @param[in] aUri The URI.
|
||||
* This method erases any previously written content in the message.
|
||||
*
|
||||
* @retval kErrorNone Successfully appended the option.
|
||||
* @retval kErrorNoBufs The option length exceeds the buffer size.
|
||||
* The CoAP Type is determined from the destination IPv6 address: `kTypeNonConfirmable` for multicast and
|
||||
* `kTypeConfirmable` otherwise. The Message ID is set to zero. A random token of default length
|
||||
* (`Token::kDefaultLength`) is generated and added.
|
||||
*
|
||||
* @param[in] aDestination The message destination IPv6 address, used to determine the CoAP Type.
|
||||
* @param[in] aUri The URI string.
|
||||
*
|
||||
* @retval kErrorNone Successfully initialized the message and appended the URI-path option.
|
||||
* @retval kErrorNoBufs Could not grow the message to append the option.
|
||||
*/
|
||||
Error InitAsPost(const Ip6::Address &aDestination, Uri aUri);
|
||||
|
||||
/**
|
||||
* Writes header to the message. This must be called before sending the message.
|
||||
* Initializes a CoAP message as a response to a request message.
|
||||
*
|
||||
* Also checks whether the payload marker is set (`SetPayloadMarker()`) but the message contains no
|
||||
* payload, and if so it removes the payload marker from the message.
|
||||
* This method erases any previously written content in the message. The Message ID and Token are copied from the
|
||||
* request message.
|
||||
*
|
||||
* @param[in] aType The CoAP Type value.
|
||||
* @param[in] aCode The CoAP Code value.
|
||||
* @param[in] aRequest The request message to respond to.
|
||||
*
|
||||
* @retval kErrorNone Successfully initialized the message.
|
||||
* @retval kErrorNoBufs Could not grow the message to write the CoAP header.
|
||||
*/
|
||||
void Finish(void);
|
||||
Error InitAsResponse(Type aType, Code aCode, const Message &aRequest);
|
||||
|
||||
/**
|
||||
* Returns the Version value.
|
||||
* Parses the CoAP header and token.
|
||||
*
|
||||
* @returns The Version value.
|
||||
* @param[out] aInfo A reference to `HeaderInfo` to populate.
|
||||
*
|
||||
* @retval kErrorNone Successfully parsed the CoAP header. @p aInfo is updated.
|
||||
* @retval kErrorParse Failed to parse.
|
||||
*/
|
||||
uint8_t GetVersion(void) const { return GetHelpData().mHeader.GetVersion(); }
|
||||
Error ParseHeaderInfo(HeaderInfo &aInfo) const;
|
||||
|
||||
/**
|
||||
* Sets the Version value.
|
||||
* Reads the Type value.
|
||||
*
|
||||
* @param[in] aVersion The Version value.
|
||||
* @returns The Type value, or zero if the CoAP header is invalid or cannot be parsed.
|
||||
*/
|
||||
void SetVersion(uint8_t aVersion) { GetHelpData().mHeader.SetVersion(aVersion); }
|
||||
uint8_t ReadType(void) const;
|
||||
|
||||
/**
|
||||
* Returns the Type value.
|
||||
* Writes the Type value in CoAP header.
|
||||
*
|
||||
* @returns The Type value.
|
||||
*/
|
||||
uint8_t GetType(void) const { return GetHelpData().mHeader.GetType(); }
|
||||
/**
|
||||
* Sets the Type value.
|
||||
* This method requires that the message contains a valid CoAP header. Otherwise, no change is made.
|
||||
*
|
||||
* @param[in] aType The Type value.
|
||||
*/
|
||||
void SetType(Type aType) { GetHelpData().mHeader.SetType(aType); }
|
||||
void WriteType(Type aType);
|
||||
|
||||
/**
|
||||
* Returns the Code value.
|
||||
* Reads the Code value.
|
||||
*
|
||||
* @returns The Code value.
|
||||
* @returns The Code value, or zero if the CoAP header is invalid or cannot be parsed.
|
||||
*/
|
||||
uint8_t GetCode(void) const { return GetHelpData().mHeader.GetCode(); }
|
||||
uint8_t ReadCode(void) const;
|
||||
|
||||
/**
|
||||
* Sets the Code value.
|
||||
* Writes the Code value.
|
||||
*
|
||||
* This method requires that the message contains a valid CoAP header. Otherwise, no change is made.
|
||||
*
|
||||
* @param[in] aCode The Code value.
|
||||
*/
|
||||
void SetCode(Code aCode) { GetHelpData().mHeader.SetCode(aCode); }
|
||||
void WriteCode(Code aCode);
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_API_ENABLE
|
||||
/**
|
||||
@@ -378,18 +569,20 @@ public:
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the Message ID value.
|
||||
* Reads the Message ID value.
|
||||
*
|
||||
* @returns The Message ID value.
|
||||
* @returns The Message ID value, or zero if the CoAP header is invalid or cannot be parsed.
|
||||
*/
|
||||
uint16_t GetMessageId(void) const { return GetHelpData().mHeader.GetMessageId(); }
|
||||
uint16_t ReadMessageId(void) const;
|
||||
|
||||
/**
|
||||
* Sets the Message ID value.
|
||||
* Writes the Message ID value in CoAP header.
|
||||
*
|
||||
* This method requires that the message contains a valid CoAP header. Otherwise, no change is made.
|
||||
*
|
||||
* @param[in] aMessageId The Message ID value.
|
||||
*/
|
||||
void SetMessageId(uint16_t aMessageId) { GetHelpData().mHeader.SetMessageId(aMessageId); }
|
||||
void WriteMessageId(uint16_t aMessageId);
|
||||
|
||||
/**
|
||||
* Reads the Token length from the message
|
||||
@@ -623,164 +816,14 @@ public:
|
||||
Error AppendUriQueryOption(const char *aUriQuery) { return AppendStringOption(kOptionUriQuery, aUriQuery); }
|
||||
|
||||
/**
|
||||
* Reads and reassembles the URI path string and fills it into @p aUriPath.
|
||||
* Appends a Payload Marker indicating the beginning of the payload.
|
||||
*
|
||||
* @retval kErrorNone URI path string has been reassembled.
|
||||
* @retval kErrorNoBufs URI path string is too long.
|
||||
* It also sets the offset to the start of the payload.
|
||||
*
|
||||
* @retval kErrorNone Payload Marker was successfully added.
|
||||
* @retval kErrorNoBufs Could not grow the message to append the payload marker.
|
||||
*/
|
||||
Error GetUriPath(char *aUriPath) const;
|
||||
|
||||
/**
|
||||
* Adds Payload Marker indicating beginning of the payload to the CoAP header.
|
||||
*
|
||||
* It also set offset to the start of payload.
|
||||
*
|
||||
* @retval kErrorNone Payload Marker successfully added.
|
||||
* @retval kErrorNoBufs Message Payload Marker exceeds the buffer size.
|
||||
*/
|
||||
Error SetPayloadMarker(void);
|
||||
|
||||
/**
|
||||
* Returns the offset of the first CoAP option.
|
||||
*
|
||||
* @returns The offset of the first CoAP option.
|
||||
*/
|
||||
uint16_t GetOptionStart(void) const { return kMinHeaderLength + GetHelpData().mHeader.GetTokenLength(); }
|
||||
|
||||
/**
|
||||
* Parses CoAP header and moves offset end of CoAP header.
|
||||
*
|
||||
* @retval kErrorNone Successfully parsed CoAP header from the message.
|
||||
* @retval kErrorParse Failed to parse the CoAP header.
|
||||
*/
|
||||
Error ParseHeader(void);
|
||||
|
||||
/**
|
||||
* Sets a default response header based on request header.
|
||||
*
|
||||
* @param[in] aRequest The request message.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the default response header.
|
||||
* @retval kErrorNoBufs Insufficient message buffers available to set the default response header.
|
||||
*/
|
||||
Error SetDefaultResponseHeader(const Message &aRequest);
|
||||
|
||||
/**
|
||||
* Checks if a header is an empty message header.
|
||||
*
|
||||
* @retval TRUE Message is an empty message header.
|
||||
* @retval FALSE Message is not an empty message header.
|
||||
*/
|
||||
bool IsEmpty(void) const { return (GetCode() == kCodeEmpty); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a request header.
|
||||
*
|
||||
* @retval TRUE Message is a request header.
|
||||
* @retval FALSE Message is not a request header.
|
||||
*/
|
||||
bool IsRequest(void) const { return (GetCode() >= kCodeGet) && (GetCode() <= kCodeDelete); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the CoAP code in header is "Get" request.
|
||||
*
|
||||
* @retval TRUE Message is a Get request.
|
||||
* @retval FALSE Message is not a Get request.
|
||||
*/
|
||||
bool IsGetRequest(void) const { return GetCode() == kCodeGet; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the CoAP code in header is "Post" request.
|
||||
*
|
||||
* @retval TRUE Message is a Post request.
|
||||
* @retval FALSE Message is not a Post request.
|
||||
*/
|
||||
bool IsPostRequest(void) const { return GetCode() == kCodePost; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the CoAP code in header is "Put" request.
|
||||
*
|
||||
* @retval TRUE Message is a Put request.
|
||||
* @retval FALSE Message is not a Put request.
|
||||
*/
|
||||
bool IsPutRequest(void) const { return GetCode() == kCodePut; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the CoAP code in header is "Delete" request.
|
||||
*
|
||||
* @retval TRUE Message is a Delete request.
|
||||
* @retval FALSE Message is not a Delete request.
|
||||
*/
|
||||
bool IsDeleteRequest(void) const { return GetCode() == kCodeDelete; }
|
||||
|
||||
/**
|
||||
* Checks if a header is a response header.
|
||||
*
|
||||
* @retval TRUE Message is a response header.
|
||||
* @retval FALSE Message is not a response header.
|
||||
*/
|
||||
bool IsResponse(void) const { return GetCode() >= OT_COAP_CODE_RESPONSE_MIN; }
|
||||
|
||||
/**
|
||||
* Checks if a header is a CON message header.
|
||||
*
|
||||
* @retval TRUE Message is a CON message header.
|
||||
* @retval FALSE Message is not is a CON message header.
|
||||
*/
|
||||
bool IsConfirmable(void) const { return (GetType() == kTypeConfirmable); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a NON message header.
|
||||
*
|
||||
* @retval TRUE Message is a NON message header.
|
||||
* @retval FALSE Message is not is a NON message header.
|
||||
*/
|
||||
bool IsNonConfirmable(void) const { return (GetType() == kTypeNonConfirmable); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a ACK message header.
|
||||
*
|
||||
* @retval TRUE Message is a ACK message header.
|
||||
* @retval FALSE Message is not is a ACK message header.
|
||||
*/
|
||||
bool IsAck(void) const { return (GetType() == kTypeAck); }
|
||||
|
||||
/**
|
||||
* Checks if a header is a RST message header.
|
||||
*
|
||||
* @retval TRUE Message is a RST message header.
|
||||
* @retval FALSE Message is not is a RST message header.
|
||||
*/
|
||||
bool IsReset(void) const { return (GetType() == kTypeReset); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the header is a confirmable Post request (i.e, `kTypeConfirmable` with
|
||||
* `kCodePost`).
|
||||
*
|
||||
* @retval TRUE Message is a confirmable Post request.
|
||||
* @retval FALSE Message is not a confirmable Post request.
|
||||
*/
|
||||
bool IsConfirmablePostRequest(void) const;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the header is a non-confirmable Post request (i.e, `kTypeNonConfirmable` with
|
||||
* `kCodePost`).
|
||||
*
|
||||
* @retval TRUE Message is a non-confirmable Post request.
|
||||
* @retval FALSE Message is not a non-confirmable Post request.
|
||||
*/
|
||||
bool IsNonConfirmablePostRequest(void) const;
|
||||
|
||||
/**
|
||||
* Checks if the message requires an reset response if an error during low level CoAP processing occurred.
|
||||
*
|
||||
* A reset message is expected to be sent for NON and CON messages if the message can not be processed or a
|
||||
* duplicated message has been received.
|
||||
*
|
||||
* @retval TRUE Expect to respond with CoAP reset message on error.
|
||||
* @retval FALSE No CoAP reset message should be sent on error.
|
||||
*/
|
||||
bool RequireResetOnError(void) { return IsConfirmable() || IsNonConfirmable(); }
|
||||
Error AppendPayloadMarker(void);
|
||||
|
||||
/**
|
||||
* Creates a copy of this CoAP message.
|
||||
@@ -806,11 +849,6 @@ public:
|
||||
*/
|
||||
Message *Clone(void) const { return Clone(GetLength()); }
|
||||
|
||||
/**
|
||||
* Returns the minimal reserved bytes required for CoAP message.
|
||||
*/
|
||||
static uint16_t GetHelpDataReserved(void) { return sizeof(HelpData) + kHelpDataAlignment; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the next message after this as a `Coap::Message`.
|
||||
*
|
||||
@@ -862,11 +900,6 @@ private:
|
||||
|
||||
static constexpr uint8_t kPayloadMarker = 0xff;
|
||||
|
||||
static constexpr uint8_t kHelpDataAlignment = sizeof(uint16_t); // Alignment of help data.
|
||||
|
||||
static constexpr uint16_t kMinHeaderLength = 4;
|
||||
static constexpr uint16_t kMaxHeaderLength = 512;
|
||||
|
||||
static constexpr uint16_t kOption1ByteExtensionOffset = 13; // Delta/Length offset as specified (RFC 7252).
|
||||
static constexpr uint16_t kOption2ByteExtensionOffset = 269; // Delta/Length offset as specified (RFC 7252).
|
||||
|
||||
@@ -878,25 +911,21 @@ private:
|
||||
static constexpr uint32_t kBlockNumMax = 0xffff;
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class Header
|
||||
class Header : public Clearable<Header>
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kVersion1 = 1;
|
||||
|
||||
uint8_t GetSize(void) const { return kMinSize + GetTokenLength(); }
|
||||
bool IsValid(void) const;
|
||||
Error ParseFrom(const Message &aMessage);
|
||||
uint8_t GetVersion(void) const { return ReadBits<uint8_t, kVersionMask>(mVersionTypeToken); }
|
||||
void SetVersion(uint8_t aVersion) { WriteBits<uint8_t, kVersionMask>(mVersionTypeToken, aVersion); }
|
||||
uint8_t GetType(void) const { return ReadBits<uint8_t, kTypeMask>(mVersionTypeToken); }
|
||||
void SetType(Type aType) { WriteBits<uint8_t, kTypeMask>(mVersionTypeToken, aType); }
|
||||
uint8_t GetCode(void) const { return mCode; }
|
||||
void SetCode(Code aCode) { mCode = aCode; }
|
||||
uint16_t GetMessageId(void) const { return BigEndian::HostSwap16(mMessageId); }
|
||||
void SetMessageId(uint16_t aMessageId) { mMessageId = BigEndian::HostSwap16(aMessageId); }
|
||||
const uint8_t *GetToken(void) const { return mToken; }
|
||||
uint8_t GetTokenLength(void) const { return ReadBits<uint8_t, kTokenLengthMask>(mVersionTypeToken); }
|
||||
Error SetToken(const Token &aToken);
|
||||
uint8_t GetVersion(void) const { return ReadBits<uint8_t, kVersionMask>(mVersionTypeToken); }
|
||||
void SetVersion(uint8_t aVersion) { WriteBits<uint8_t, kVersionMask>(mVersionTypeToken, aVersion); }
|
||||
uint8_t GetType(void) const { return ReadBits<uint8_t, kTypeMask>(mVersionTypeToken); }
|
||||
void SetType(Type aType) { WriteBits<uint8_t, kTypeMask>(mVersionTypeToken, aType); }
|
||||
uint8_t GetCode(void) const { return mCode; }
|
||||
void SetCode(Code aCode) { mCode = aCode; }
|
||||
uint16_t GetMessageId(void) const { return BigEndian::HostSwap16(mMessageId); }
|
||||
void SetMessageId(uint16_t aMessageId) { mMessageId = BigEndian::HostSwap16(aMessageId); }
|
||||
uint8_t GetTokenLength(void) const { return ReadBits<uint8_t, kTokenLengthMask>(mVersionTypeToken); }
|
||||
void SetTokenLength(uint8_t aLength) { WriteBits<uint8_t, kTokenLengthMask>(mVersionTypeToken, aLength); }
|
||||
|
||||
private:
|
||||
/*
|
||||
@@ -907,31 +936,15 @@ private:
|
||||
* |Ver| T | TKL | (Version, Type and Token Length).
|
||||
* +-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
static constexpr uint8_t kVersionMask = 0x3 << 6;
|
||||
static constexpr uint8_t kTypeMask = 0x3 << 4;
|
||||
static constexpr uint8_t kTokenLengthMask = 0xf << 0;
|
||||
static constexpr uint16_t kMinSize = 4;
|
||||
|
||||
void SetTokenLength(uint8_t aLength) { WriteBits<uint8_t, kTokenLengthMask>(mVersionTypeToken, aLength); }
|
||||
static constexpr uint8_t kVersionMask = 0x3 << 6;
|
||||
static constexpr uint8_t kTypeMask = 0x3 << 4;
|
||||
static constexpr uint8_t kTokenLengthMask = 0xf << 0;
|
||||
|
||||
uint8_t mVersionTypeToken; // The CoAP Version, Type, and Token Length
|
||||
uint8_t mCode;
|
||||
uint16_t mMessageId;
|
||||
uint8_t mToken[kMaxTokenLength];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* Represents a HelpData used by this CoAP message.
|
||||
*/
|
||||
struct HelpData : public Clearable<HelpData>
|
||||
{
|
||||
Header mHeader;
|
||||
uint16_t mOptionLast;
|
||||
uint16_t mHeaderOffset; ///< The byte offset for the CoAP Header
|
||||
uint16_t mHeaderLength;
|
||||
bool mPayloadMarkerSet;
|
||||
};
|
||||
|
||||
class ConstIterator : public ot::Message::ConstIterator
|
||||
{
|
||||
public:
|
||||
@@ -953,23 +966,15 @@ private:
|
||||
Message *operator->(void) { return static_cast<Message *>(ot::Message::Iterator::operator->()); }
|
||||
};
|
||||
|
||||
static_assert(sizeof(HelpData) <= sizeof(Ip6::Header) + sizeof(Ip6::HopByHopHeader) + sizeof(Ip6::MplOption) +
|
||||
sizeof(Ip6::Udp::Header),
|
||||
"HelpData size exceeds the size of the reserved region in the message");
|
||||
|
||||
const HelpData &GetHelpData(void) const
|
||||
{
|
||||
static_assert(sizeof(HelpData) + kHelpDataAlignment <= kHeadBufferDataSize,
|
||||
"Insufficient buffer size for CoAP processing! Increase OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE.");
|
||||
|
||||
return *static_cast<const HelpData *>(OT_ALIGN(GetFirstData(), kHelpDataAlignment));
|
||||
}
|
||||
|
||||
HelpData &GetHelpData(void) { return AsNonConst(AsConst(this)->GetHelpData()); }
|
||||
|
||||
uint8_t WriteExtendedOptionField(uint16_t aValue, uint8_t *&aBuffer);
|
||||
|
||||
Error AppendOptionHeader(uint16_t aNumber, uint16_t aLength);
|
||||
uint16_t GetHeaderOffset(void) const { return GetMeshDest(); }
|
||||
void SetHeaderOffset(uint16_t aOffset) { SetMeshDest(aOffset); }
|
||||
uint16_t DetermineTokenOffset(void) const;
|
||||
Error DetermineOptionStartOffset(uint16_t &aOffset) const;
|
||||
Error ReadHeader(Header &aHeader) const;
|
||||
void WriteHeader(const Header &aHeader);
|
||||
Error ReadToken(const Header &aHeader, Token &aToken) const;
|
||||
uint8_t WriteExtendedOptionField(uint16_t aValue, uint8_t *&aBuffer);
|
||||
Error AppendOptionHeader(uint16_t aNumber, uint16_t aLength);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1091,16 +1096,6 @@ public:
|
||||
*/
|
||||
bool IsDone(void) const { return mOption.mLength == kIteratorDoneLength; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not there was a earlier parse error (i.e., whether the iterator is valid).
|
||||
*
|
||||
* After a parse errors, iterator would also be marked as done.
|
||||
*
|
||||
* @retval TRUE There was an earlier parse error and the iterator is not valid.
|
||||
* @retval FALSE There was no earlier parse error and the iterator is valid.
|
||||
*/
|
||||
bool HasParseErrored(void) const { return mNextOptionOffset == kNextOptionOffsetParseError; }
|
||||
|
||||
/**
|
||||
* Advances the iterator to the next CoAP Option in the header.
|
||||
*
|
||||
@@ -1164,12 +1159,22 @@ public:
|
||||
/**
|
||||
* Gets the offset of beginning of the CoAP message payload (after the CoAP header).
|
||||
*
|
||||
* MUST be used after the iterator is done (i.e. iterated through all options).
|
||||
* MUST be used after the iterator is done (i.e. successfully iterated through all options).
|
||||
*
|
||||
* @returns The offset of beginning of the CoAP message payload
|
||||
*/
|
||||
uint16_t GetPayloadMessageOffset(void) const { return mNextOptionOffset; }
|
||||
|
||||
/**
|
||||
* Inidcated whether or not the option ended with a payload marker.
|
||||
*
|
||||
* MUST be used after the iterator is done (i.e. successfully iterated through all options).
|
||||
*
|
||||
* @retval TRUE The message contains a payload marker.
|
||||
* @retval FALAE The message does not contain a payload marker.
|
||||
*/
|
||||
bool HasPayloadMarker(void) const { return IsDone() && (mOption.mNumber != 0); }
|
||||
|
||||
/**
|
||||
* Gets the offset of beginning of the CoAP Option Value.
|
||||
*
|
||||
@@ -1183,12 +1188,8 @@ public:
|
||||
// `mOption.mLength` value to indicate iterator is done.
|
||||
static constexpr uint16_t kIteratorDoneLength = 0xffff;
|
||||
|
||||
// Special `mNextOptionOffset` value to indicate a parse error.
|
||||
static constexpr uint16_t kNextOptionOffsetParseError = 0;
|
||||
|
||||
void MarkAsDone(void) { mOption.mLength = kIteratorDoneLength; }
|
||||
void MarkAsParseErrored(void) { MarkAsDone(), mNextOptionOffset = kNextOptionOffsetParseError; }
|
||||
|
||||
void MarkAsDone(void) { mOption.mLength = kIteratorDoneLength; }
|
||||
void SetHasPayloadMarker(bool aHasPayloadMarker) { mOption.mNumber = aHasPayloadMarker; }
|
||||
Error Read(uint16_t aLength, void *aBuffer);
|
||||
Error ReadExtendedOptionField(uint16_t &aValue);
|
||||
Error InitOrAdvance(const Message *aMessage, uint16_t aNumber);
|
||||
|
||||
@@ -125,7 +125,7 @@ void SecureSession::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength)
|
||||
{
|
||||
ot::Message *message = nullptr;
|
||||
|
||||
VerifyOrExit((message = Get<MessagePool>().Allocate(Message::kTypeIp6, Message::GetHelpDataReserved())) != nullptr);
|
||||
VerifyOrExit((message = Get<MessagePool>().Allocate(Message::kTypeIp6)) != nullptr);
|
||||
SuccessOrExit(message->AppendBytes(aBuf, aLength));
|
||||
|
||||
CoapBase::Receive(*message, GetMessageInfo());
|
||||
|
||||
@@ -59,7 +59,7 @@ Error AnnounceBeginClient::SendRequest(uint32_t aChannelMask,
|
||||
VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = message->InitAsPost(aAddress, kUriAnnounceBegin));
|
||||
SuccessOrExit(error = message->SetPayloadMarker());
|
||||
SuccessOrExit(error = message->AppendPayloadMarker());
|
||||
|
||||
SuccessOrExit(
|
||||
error = Tlv::Append<MeshCoP::CommissionerSessionIdTlv>(*message, Get<MeshCoP::Commissioner>().GetSessionId()));
|
||||
|
||||
@@ -360,7 +360,7 @@ template <> void Manager::HandleTmf<kUriRelayRx>(Coap::Msg &aMsg)
|
||||
|
||||
VerifyOrExit(mIsRunning);
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsNonConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
|
||||
|
||||
LogInfo("Received %s from %s", UriToString<kUriRelayRx>(), aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
|
||||
@@ -597,7 +597,7 @@ bool Manager::CoapDtlsSession::HandleResource(const char *aUriPath, Coap::Msg &a
|
||||
HandleTmfCommissionerKeepAlive(aMsg);
|
||||
break;
|
||||
case kUriRelayTx:
|
||||
HandleTmfRelayTx(aMsg.mMessage);
|
||||
HandleTmfRelayTx(aMsg);
|
||||
break;
|
||||
case kUriCommissionerGet:
|
||||
case kUriActiveGet:
|
||||
@@ -605,7 +605,7 @@ bool Manager::CoapDtlsSession::HandleResource(const char *aUriPath, Coap::Msg &a
|
||||
HandleTmfDatasetGet(aMsg.mMessage, uri);
|
||||
break;
|
||||
case kUriProxyTx:
|
||||
HandleTmfProxyTx(aMsg.mMessage);
|
||||
HandleTmfProxyTx(aMsg);
|
||||
break;
|
||||
default:
|
||||
didHandle = false;
|
||||
@@ -756,7 +756,7 @@ void Manager::CoapDtlsSession::HandleLeaderResponseToFwdTmf(const ForwardContext
|
||||
forwardMessage.Reset(NewPriorityMessage());
|
||||
VerifyOrExit(forwardMessage != nullptr, error = kErrorNoBufs);
|
||||
|
||||
if (aResponse->GetCode() == Coap::kCodeChanged)
|
||||
if (aResponse->ReadCode() == Coap::kCodeChanged)
|
||||
{
|
||||
uint8_t state;
|
||||
|
||||
@@ -784,13 +784,13 @@ void Manager::CoapDtlsSession::HandleLeaderResponseToFwdTmf(const ForwardContext
|
||||
}
|
||||
}
|
||||
|
||||
forwardMessage->Init(Coap::kTypeNonConfirmable, static_cast<Coap::Code>(aResponse->GetCode()));
|
||||
|
||||
SuccessOrExit(error =
|
||||
forwardMessage->Init(Coap::kTypeNonConfirmable, static_cast<Coap::Code>(aResponse->ReadCode())));
|
||||
SuccessOrExit(error = forwardMessage->WriteToken(aForwardContext.mToken));
|
||||
|
||||
if (aResponse->GetLength() > aResponse->GetOffset())
|
||||
{
|
||||
SuccessOrExit(error = forwardMessage->SetPayloadMarker());
|
||||
SuccessOrExit(error = forwardMessage->AppendPayloadMarker());
|
||||
}
|
||||
|
||||
SuccessOrExit(error = ForwardToCommissioner(forwardMessage.PassOwnership(), *aResponse));
|
||||
@@ -897,7 +897,7 @@ void Manager::CoapDtlsSession::SendErrorMessage(Error aError, const Coap::Token
|
||||
|
||||
code = (aError == kErrorParse) ? Coap::kCodeBadRequest : Coap::kCodeInternalError;
|
||||
|
||||
message->Init(Coap::kTypeNonConfirmable, code);
|
||||
SuccessOrExit(error = message->Init(Coap::kTypeNonConfirmable, code));
|
||||
SuccessOrExit(error = message->WriteToken(aToken));
|
||||
|
||||
SuccessOrExit(error = SendMessage(message.PassOwnership()));
|
||||
@@ -906,7 +906,7 @@ exit:
|
||||
LogWarnOnError(error, "send error CoAP message");
|
||||
}
|
||||
|
||||
void Manager::CoapDtlsSession::HandleTmfProxyTx(Coap::Message &aMessage)
|
||||
void Manager::CoapDtlsSession::HandleTmfProxyTx(Coap::Msg &aMsg)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
OwnedPtr<Message> message;
|
||||
@@ -918,9 +918,9 @@ void Manager::CoapDtlsSession::HandleTmfProxyTx(Coap::Message &aMessage)
|
||||
|
||||
VerifyOrExit(IsActiveCommissioner(), error = kErrorInvalidState);
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kUdpEncapsulation, offsetRange));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMsg.mMessage, Tlv::kUdpEncapsulation, offsetRange));
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(offsetRange, udpEncapHeader));
|
||||
SuccessOrExit(error = aMsg.mMessage.Read(offsetRange, udpEncapHeader));
|
||||
offsetRange.AdvanceOffset(sizeof(UdpEncapsulationTlvHeader));
|
||||
|
||||
VerifyOrExit(udpEncapHeader.GetSourcePort() > 0 && udpEncapHeader.GetDestinationPort() > 0, error = kErrorDrop);
|
||||
@@ -928,13 +928,13 @@ void Manager::CoapDtlsSession::HandleTmfProxyTx(Coap::Message &aMessage)
|
||||
message.Reset(Get<Ip6::Udp>().NewMessage());
|
||||
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMsg.mMessage, offsetRange));
|
||||
|
||||
messageInfo.SetSockPort(udpEncapHeader.GetSourcePort());
|
||||
messageInfo.SetSockAddr(Get<Manager>().GetCommissionerAloc());
|
||||
messageInfo.SetPeerPort(udpEncapHeader.GetDestinationPort());
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<Ip6AddressTlv>(aMessage, messageInfo.GetPeerAddr()));
|
||||
SuccessOrExit(error = Tlv::Find<Ip6AddressTlv>(aMsg.mMessage, messageInfo.GetPeerAddr()));
|
||||
|
||||
// On success the message ownership is transferred.
|
||||
SuccessOrExit(error = Get<Ip6::Udp>().SendDatagram(*message, messageInfo));
|
||||
@@ -946,7 +946,7 @@ exit:
|
||||
LogWarnOnError(error, "send proxy stream");
|
||||
}
|
||||
|
||||
void Manager::CoapDtlsSession::HandleTmfRelayTx(Coap::Message &aMessage)
|
||||
void Manager::CoapDtlsSession::HandleTmfRelayTx(Coap::Msg &aMsg)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t joinerRouterRloc;
|
||||
@@ -954,19 +954,19 @@ void Manager::CoapDtlsSession::HandleTmfRelayTx(Coap::Message &aMessage)
|
||||
Tmf::MessageInfo messageInfo(GetInstance());
|
||||
OffsetRange offsetRange;
|
||||
|
||||
VerifyOrExit(aMessage.IsNonConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
|
||||
|
||||
VerifyOrExit(IsActiveCommissioner(), error = kErrorInvalidState);
|
||||
|
||||
Log<kUriRelayTx>(kReceive);
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<JoinerRouterLocatorTlv>(aMessage, joinerRouterRloc));
|
||||
SuccessOrExit(error = Tlv::Find<JoinerRouterLocatorTlv>(aMsg.mMessage, joinerRouterRloc));
|
||||
|
||||
message.Reset(Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(kUriRelayTx));
|
||||
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
|
||||
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMsg.mMessage);
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMsg.mMessage, offsetRange));
|
||||
|
||||
messageInfo.SetSockAddrToRlocPeerAddrTo(joinerRouterRloc);
|
||||
messageInfo.SetSockPortToTmf();
|
||||
|
||||
@@ -304,8 +304,8 @@ private:
|
||||
|
||||
Error ForwardToCommissioner(OwnedPtr<Coap::Message> aForwardMessage, const Message &aMessage);
|
||||
void HandleTmfCommissionerKeepAlive(Coap::Msg &aMsg);
|
||||
void HandleTmfRelayTx(Coap::Message &aMessage);
|
||||
void HandleTmfProxyTx(Coap::Message &aMessage);
|
||||
void HandleTmfRelayTx(Coap::Msg &aMsg);
|
||||
void HandleTmfProxyTx(Coap::Msg &aMsg);
|
||||
void HandleTmfDatasetGet(Coap::Message &aMessage, Uri aUri);
|
||||
Error ForwardToLeader(const Coap::Msg &aMsg, Uri aUri);
|
||||
void SendErrorMessage(Error aError, const Coap::Token &aToken);
|
||||
|
||||
@@ -627,7 +627,7 @@ exit:
|
||||
|
||||
void Commissioner::HandleMgmtCommissionerGetResponse(Coap::Message *aMessage, Error aResult)
|
||||
{
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged);
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage->ReadCode() == Coap::kCodeChanged);
|
||||
LogInfo("Received %s response", UriToString<kUriCommissionerGet>());
|
||||
|
||||
exit:
|
||||
@@ -688,7 +688,7 @@ void Commissioner::HandleMgmtCommissionerSetResponse(Coap::Message *aMessage, Er
|
||||
uint8_t state;
|
||||
|
||||
SuccessOrExit(error = aResult);
|
||||
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged && Tlv::Find<StateTlv>(*aMessage, state) == kErrorNone &&
|
||||
VerifyOrExit(aMessage->ReadCode() == Coap::kCodeChanged && Tlv::Find<StateTlv>(*aMessage, state) == kErrorNone &&
|
||||
state != StateTlv::kPending,
|
||||
error = kErrorParse);
|
||||
|
||||
@@ -727,7 +727,7 @@ void Commissioner::HandleLeaderPetitionResponse(Coap::Message *aMessage, Error a
|
||||
bool retransmit = false;
|
||||
|
||||
VerifyOrExit(mState != kStateActive);
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged,
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage->ReadCode() == Coap::kCodeChanged,
|
||||
retransmit = (mState == kStatePetition));
|
||||
|
||||
LogInfo("Received %s response", UriToString<kUriLeaderPetition>());
|
||||
@@ -799,7 +799,7 @@ void Commissioner::HandleLeaderKeepAliveResponse(Coap::Message *aMessage, Error
|
||||
uint8_t state;
|
||||
|
||||
VerifyOrExit(mState == kStateActive);
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged,
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage->ReadCode() == Coap::kCodeChanged,
|
||||
IgnoreError(Stop(kDoNotSendKeepAlive)));
|
||||
|
||||
LogInfo("Received %s response", UriToString<kUriLeaderKeepAlive>());
|
||||
@@ -824,7 +824,7 @@ template <> void Commissioner::HandleTmf<kUriRelayRx>(Coap::Msg &aMsg)
|
||||
|
||||
VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsNonConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<JoinerUdpPortTlv>(aMsg.mMessage, joinerPort));
|
||||
SuccessOrExit(error = Tlv::Find<JoinerIidTlv>(aMsg.mMessage, joinerIid));
|
||||
@@ -893,7 +893,7 @@ void Commissioner::HandleJoinerSessionTimer(void)
|
||||
template <> void Commissioner::HandleTmf<kUriDatasetChanged>(Coap::Msg &aMsg)
|
||||
{
|
||||
VerifyOrExit(mState == kStateActive);
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
|
||||
LogInfo("Received %s", UriToString<kUriDatasetChanged>());
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ Error EnergyScanClient::SendQuery(uint32_t aChannelMas
|
||||
VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = message->InitAsPost(aAddress, kUriEnergyScan));
|
||||
SuccessOrExit(error = message->SetPayloadMarker());
|
||||
SuccessOrExit(error = message->AppendPayloadMarker());
|
||||
|
||||
SuccessOrExit(
|
||||
error = Tlv::Append<MeshCoP::CommissionerSessionIdTlv>(*message, Get<MeshCoP::Commissioner>().GetSessionId()));
|
||||
@@ -90,7 +90,7 @@ template <> void EnergyScanClient::HandleTmf<kUriEnergyReport>(Coap::Msg &aMsg)
|
||||
uint32_t mask;
|
||||
MeshCoP::EnergyListTlv energyListTlv;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
|
||||
LogInfo("Received %s", UriToString<kUriEnergyReport>());
|
||||
|
||||
|
||||
@@ -471,12 +471,15 @@ exit:
|
||||
|
||||
void Joiner::HandleJoinerFinalizeResponse(Coap::Message *aMessage, Error aResult)
|
||||
{
|
||||
uint8_t state;
|
||||
uint8_t state;
|
||||
Coap::HeaderInfo header;
|
||||
|
||||
VerifyOrExit(mState == kStateConnected && aResult == kErrorNone);
|
||||
OT_ASSERT(aMessage != nullptr);
|
||||
|
||||
VerifyOrExit(aMessage->IsAck() && aMessage->GetCode() == Coap::kCodeChanged);
|
||||
SuccessOrExit(aMessage->ParseHeaderInfo(header));
|
||||
|
||||
VerifyOrExit(header.IsAck() && header.GetCode() == Coap::kCodeChanged);
|
||||
|
||||
SuccessOrExit(Tlv::Find<StateTlv>(*aMessage, state));
|
||||
|
||||
@@ -499,7 +502,7 @@ template <> void Joiner::HandleTmf<kUriJoinerEntrust>(Coap::Msg &aMsg)
|
||||
Error error;
|
||||
Dataset::Info datasetInfo;
|
||||
|
||||
VerifyOrExit(mState == kStateEntrust && aMsg.mMessage.IsConfirmablePostRequest(), error = kErrorDrop);
|
||||
VerifyOrExit(mState == kStateEntrust && aMsg.IsConfirmablePostRequest(), error = kErrorDrop);
|
||||
|
||||
LogInfo("Received %s", UriToString<kUriJoinerEntrust>());
|
||||
LogCert("[THCI] direction=recv | type=JOIN_ENT.ntf");
|
||||
|
||||
@@ -162,7 +162,7 @@ template <> void JoinerRouter::HandleTmf<kUriRelayTx>(Coap::Msg &aMsg)
|
||||
Message::Settings settings(kNoLinkSecurity, Message::kPriorityNet);
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsNonConfirmablePostRequest(), error = kErrorDrop);
|
||||
VerifyOrExit(aMsg.IsNonConfirmablePostRequest(), error = kErrorDrop);
|
||||
|
||||
LogInfo("Received %s", UriToString<kUriRelayTx>());
|
||||
|
||||
@@ -310,7 +310,7 @@ void JoinerRouter::HandleJoinerEntrustResponse(Coap::Message *aMessage, Error aR
|
||||
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage != nullptr);
|
||||
|
||||
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged);
|
||||
VerifyOrExit(aMessage->ReadCode() == Coap::kCodeChanged);
|
||||
|
||||
LogInfo("Receive %s response", UriToString<kUriJoinerEntrust>());
|
||||
LogCert("[THCI] direction=recv | type=JOIN_ENT.rsp");
|
||||
|
||||
@@ -60,7 +60,7 @@ Error PanIdQueryClient::SendQuery(uint16_t aPanId,
|
||||
VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = message->InitAsPost(aAddress, kUriPanIdQuery));
|
||||
SuccessOrExit(error = message->SetPayloadMarker());
|
||||
SuccessOrExit(error = message->AppendPayloadMarker());
|
||||
|
||||
SuccessOrExit(
|
||||
error = Tlv::Append<MeshCoP::CommissionerSessionIdTlv>(*message, Get<MeshCoP::Commissioner>().GetSessionId()));
|
||||
@@ -86,7 +86,7 @@ template <> void PanIdQueryClient::HandleTmf<kUriPanIdConflict>(Coap::Msg &aMsg)
|
||||
uint16_t panId;
|
||||
uint32_t mask;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
|
||||
LogInfo("Received %s", UriToString<kUriPanIdConflict>());
|
||||
|
||||
|
||||
@@ -1119,7 +1119,7 @@ template <> void TcatAgent::HandleTmf<kUriTcatEnable>(Coap::Msg &aMsg)
|
||||
uint16_t durationSec = 0;
|
||||
uint32_t durationMs;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
LogInfo("Received %s from %s", UriToString<kUriTcatEnable>(),
|
||||
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
message = Get<Tmf::Agent>().NewResponseMessage(aMsg.mMessage);
|
||||
|
||||
@@ -655,7 +655,7 @@ template <> void AddressResolver::HandleTmf<kUriAddressNotify>(Coap::Msg &aMsg)
|
||||
CacheEntry *entry;
|
||||
CacheEntry *prev;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
|
||||
SuccessOrExit(Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, target));
|
||||
SuccessOrExit(Tlv::Find<ThreadMeshLocalEidTlv>(aMsg.mMessage, meshLocalIid));
|
||||
@@ -725,9 +725,10 @@ void AddressResolver::SendAddressError(const Ip6::Address &aTarget,
|
||||
|
||||
VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
message->Init(aDestination == nullptr ? Coap::kTypeNonConfirmable : Coap::kTypeConfirmable, Coap::kCodePost);
|
||||
SuccessOrExit(error = message->Init(aDestination == nullptr ? Coap::kTypeNonConfirmable : Coap::kTypeConfirmable,
|
||||
Coap::kCodePost));
|
||||
SuccessOrExit(error = message->AppendUriPathOptions(PathForUri(kUriAddressError)));
|
||||
SuccessOrExit(error = message->SetPayloadMarker());
|
||||
SuccessOrExit(error = message->AppendPayloadMarker());
|
||||
|
||||
SuccessOrExit(error = Tlv::Append<ThreadTargetTlv>(*message, aTarget));
|
||||
SuccessOrExit(error = Tlv::Append<ThreadMeshLocalEidTlv>(*message, aMeshLocalIid));
|
||||
@@ -766,11 +767,11 @@ template <> void AddressResolver::HandleTmf<kUriAddressError>(Coap::Msg &aMsg)
|
||||
Ip6::Address destination;
|
||||
#endif
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsPostRequest(), error = kErrorDrop);
|
||||
VerifyOrExit(aMsg.IsPostRequest(), error = kErrorDrop);
|
||||
|
||||
LogInfo("Received %s", UriToString<kUriAddressError>());
|
||||
|
||||
if (aMsg.mMessage.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
if (Get<Tmf::Agent>().SendEmptyAck(aMsg) == kErrorNone)
|
||||
{
|
||||
@@ -842,7 +843,7 @@ template <> void AddressResolver::HandleTmf<kUriAddressQuery>(Coap::Msg &aMsg)
|
||||
Ip6::Address target;
|
||||
uint32_t lastTransactionTime;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsNonConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
|
||||
|
||||
SuccessOrExit(Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, target));
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ template <> void AnnounceBeginServer::HandleTmf<kUriAnnounceBegin>(Coap::Msg &aM
|
||||
uint8_t count;
|
||||
uint16_t period;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsPostRequest());
|
||||
VerifyOrExit(aMsg.IsPostRequest());
|
||||
SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMsg.mMessage, mask));
|
||||
|
||||
SuccessOrExit(Tlv::Find<MeshCoP::CountTlv>(aMsg.mMessage, count));
|
||||
@@ -66,7 +66,7 @@ template <> void AnnounceBeginServer::HandleTmf<kUriAnnounceBegin>(Coap::Msg &aM
|
||||
|
||||
SendAnnounce(mask, count, period);
|
||||
|
||||
if (aMsg.mMessage.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
|
||||
LogInfo("Sent %s response", UriToString<kUriAnnounceBegin>());
|
||||
|
||||
@@ -113,7 +113,7 @@ template <> void AnycastLocator::HandleTmf<kUriAnycastLocate>(Coap::Msg &aMsg)
|
||||
{
|
||||
Coap::Message *message = nullptr;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
|
||||
message = Get<Tmf::Agent>().NewResponseMessage(aMsg.mMessage);
|
||||
VerifyOrExit(message != nullptr);
|
||||
|
||||
@@ -557,7 +557,7 @@ void DuaManager::HandleDuaResponse(Coap::Message *aMessage, Error aResult)
|
||||
VerifyOrExit(aResult == kErrorNone, error = kErrorParse);
|
||||
OT_ASSERT(aMessage != nullptr);
|
||||
|
||||
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged || aMessage->GetCode() >= Coap::kCodeBadRequest,
|
||||
VerifyOrExit(aMessage->ReadCode() == Coap::kCodeChanged || aMessage->ReadCode() >= Coap::kCodeBadRequest,
|
||||
error = kErrorParse);
|
||||
|
||||
error = ProcessDuaResponse(*aMessage);
|
||||
@@ -575,9 +575,9 @@ template <> void DuaManager::HandleTmf<kUriDuaRegistrationNotify>(Coap::Msg &aMs
|
||||
{
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsPostRequest(), error = kErrorParse);
|
||||
VerifyOrExit(aMsg.IsPostRequest(), error = kErrorParse);
|
||||
|
||||
if (aMsg.mMessage.IsConfirmable() && Get<Tmf::Agent>().SendEmptyAck(aMsg) == kErrorNone)
|
||||
if (aMsg.IsConfirmable() && Get<Tmf::Agent>().SendEmptyAck(aMsg) == kErrorNone)
|
||||
{
|
||||
LogInfo("Sent %s ack", UriToString<kUriDuaRegistrationNotify>());
|
||||
}
|
||||
@@ -595,7 +595,7 @@ Error DuaManager::ProcessDuaResponse(Coap::Message &aMessage)
|
||||
Ip6::Address target;
|
||||
uint8_t status;
|
||||
|
||||
if (aMessage.GetCode() >= Coap::kCodeBadRequest)
|
||||
if (aMessage.ReadCode() >= Coap::kCodeBadRequest)
|
||||
{
|
||||
status = kDuaGeneralFailure;
|
||||
target = mRegisteringDua;
|
||||
|
||||
@@ -58,7 +58,7 @@ template <> void EnergyScanServer::HandleTmf<kUriEnergyScan>(Coap::Msg &aMsg)
|
||||
uint32_t mask;
|
||||
MeshCoP::Tlv tlv;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsPostRequest());
|
||||
VerifyOrExit(aMsg.IsPostRequest());
|
||||
|
||||
SuccessOrExit(Tlv::Find<MeshCoP::CountTlv>(aMsg.mMessage, count));
|
||||
count = Clamp(count, kMinCount, kMaxCount);
|
||||
@@ -87,7 +87,7 @@ template <> void EnergyScanServer::HandleTmf<kUriEnergyScan>(Coap::Msg &aMsg)
|
||||
|
||||
mCommissioner = aMsg.mMessageInfo.GetPeerAddr();
|
||||
|
||||
if (aMsg.mMessage.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
|
||||
LogInfo("Sent %s ack", UriToString<kUriEnergyScan>());
|
||||
|
||||
@@ -1683,7 +1683,7 @@ private:
|
||||
|
||||
struct AddrSolicitInfo
|
||||
{
|
||||
Error ParseFrom(const Coap::Message &aMessage);
|
||||
Error ParseFrom(const Coap::Msg &aMsg);
|
||||
|
||||
Mac::ExtAddress mExtAddress;
|
||||
uint16_t mRequestedRloc16;
|
||||
|
||||
@@ -3333,7 +3333,7 @@ void Mle::HandleAddressSolicitResponse(Coap::Message *aMessage, const Ip6::Messa
|
||||
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage != nullptr && aMessageInfo != nullptr);
|
||||
|
||||
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged);
|
||||
VerifyOrExit(aMessage->ReadCode() == Coap::kCodeChanged);
|
||||
|
||||
Log(kMessageReceive, kTypeAddressReply, aMessageInfo->GetPeerAddr());
|
||||
|
||||
@@ -3459,18 +3459,18 @@ exit:
|
||||
return willBecomeRouter;
|
||||
}
|
||||
|
||||
Error Mle::AddrSolicitInfo::ParseFrom(const Coap::Message &aMessage)
|
||||
Error Mle::AddrSolicitInfo::ParseFrom(const Coap::Msg &aMsg)
|
||||
{
|
||||
// Parses a `kUriAddressSolicit` request message.
|
||||
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorParse);
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest(), error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<ThreadExtMacAddressTlv>(aMessage, mExtAddress));
|
||||
SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(aMessage, mReason));
|
||||
SuccessOrExit(error = Tlv::Find<ThreadExtMacAddressTlv>(aMsg.mMessage, mExtAddress));
|
||||
SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(aMsg.mMessage, mReason));
|
||||
|
||||
switch (Tlv::Find<ThreadRloc16Tlv>(aMessage, mRequestedRloc16))
|
||||
switch (Tlv::Find<ThreadRloc16Tlv>(aMsg.mMessage, mRequestedRloc16))
|
||||
{
|
||||
case kErrorNone:
|
||||
break;
|
||||
@@ -3482,7 +3482,7 @@ Error Mle::AddrSolicitInfo::ParseFrom(const Coap::Message &aMessage)
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
switch (Tlv::Find<XtalAccuracyTlv>(aMessage, mXtalAccuracy))
|
||||
switch (Tlv::Find<XtalAccuracyTlv>(aMsg.mMessage, mXtalAccuracy))
|
||||
{
|
||||
case kErrorNone:
|
||||
break;
|
||||
@@ -3576,7 +3576,7 @@ template <> void Mle::HandleTmf<kUriAddressSolicit>(Coap::Msg &aMsg)
|
||||
|
||||
Log(kMessageReceive, kTypeAddressSolicit, aMsg.mMessageInfo.GetPeerAddr());
|
||||
|
||||
SuccessOrExit(info.ParseFrom(aMsg.mMessage));
|
||||
SuccessOrExit(info.ParseFrom(aMsg));
|
||||
|
||||
ProcessAddressSolicit(info);
|
||||
|
||||
@@ -3637,7 +3637,7 @@ template <> void Mle::HandleTmf<kUriAddressRelease>(Coap::Msg &aMsg)
|
||||
|
||||
VerifyOrExit(mRole == kRoleLeader);
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
|
||||
Log(kMessageReceive, kTypeAddressRelease, aMsg.mMessageInfo.GetPeerAddr());
|
||||
|
||||
|
||||
@@ -468,7 +468,7 @@ Error MlrManager::ParseMlrResponse(Error aResult,
|
||||
aStatus = kMlrGeneralFailure;
|
||||
|
||||
VerifyOrExit(aResult == kErrorNone && aMessage != nullptr, error = kErrorParse);
|
||||
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged, error = kErrorParse);
|
||||
VerifyOrExit(aMessage->ReadCode() == Coap::kCodeChanged, error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(*aMessage, aStatus));
|
||||
|
||||
|
||||
@@ -630,13 +630,13 @@ exit:
|
||||
|
||||
template <> void Server::HandleTmf<kUriDiagnosticGetQuery>(Coap::Msg &aMsg)
|
||||
{
|
||||
VerifyOrExit(aMsg.mMessage.IsPostRequest());
|
||||
VerifyOrExit(aMsg.IsPostRequest());
|
||||
|
||||
LogInfo("Received %s from %s", UriToString<kUriDiagnosticGetQuery>(),
|
||||
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
|
||||
// DIAG_GET.qry may be sent as a confirmable request.
|
||||
if (aMsg.mMessage.IsConfirmable())
|
||||
if (aMsg.IsConfirmable())
|
||||
{
|
||||
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg));
|
||||
}
|
||||
@@ -886,7 +886,7 @@ void Server::HandleAnswerResponse(Coap::Message &aNextAnswer,
|
||||
|
||||
SuccessOrExit(error);
|
||||
VerifyOrExit(aResponse != nullptr && aMessageInfo != nullptr, error = kErrorDrop);
|
||||
VerifyOrExit(aResponse->GetCode() == Coap::kCodeChanged, error = kErrorDrop);
|
||||
VerifyOrExit(aResponse->ReadCode() == Coap::kCodeChanged, error = kErrorDrop);
|
||||
|
||||
SendNextAnswer(aNextAnswer, aMessageInfo->GetPeerAddr());
|
||||
|
||||
@@ -999,7 +999,7 @@ template <> void Server::HandleTmf<kUriDiagnosticGetRequest>(Coap::Msg &aMsg)
|
||||
Error error = kErrorNone;
|
||||
Coap::Message *response = nullptr;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest(), error = kErrorDrop);
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest(), error = kErrorDrop);
|
||||
|
||||
LogInfo("Received %s from %s", UriToString<kUriDiagnosticGetRequest>(),
|
||||
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
@@ -1021,7 +1021,7 @@ template <> void Server::HandleTmf<kUriDiagnosticReset>(Coap::Msg &aMsg)
|
||||
uint8_t type;
|
||||
Tlv tlv;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
|
||||
LogInfo("Received %s from %s", UriToString<kUriDiagnosticReset>(),
|
||||
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
@@ -1152,7 +1152,7 @@ exit:
|
||||
void Client::HandleGetResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult)
|
||||
{
|
||||
SuccessOrExit(aResult);
|
||||
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged, aResult = kErrorFailed);
|
||||
VerifyOrExit(aMessage->ReadCode() == Coap::kCodeChanged, aResult = kErrorFailed);
|
||||
|
||||
exit:
|
||||
mGetCallback.InvokeIfSet(aResult, aMessage, aMessageInfo);
|
||||
@@ -1160,7 +1160,7 @@ exit:
|
||||
|
||||
template <> void Client::HandleTmf<kUriDiagnosticGetAnswer>(Coap::Msg &aMsg)
|
||||
{
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
|
||||
LogInfo("Received %s from %s", ot::UriToString<kUriDiagnosticGetAnswer>(),
|
||||
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
|
||||
@@ -52,7 +52,7 @@ template <> void PanIdQueryServer::HandleTmf<kUriPanIdQuery>(Coap::Msg &aMsg)
|
||||
uint16_t panId;
|
||||
uint32_t mask;
|
||||
|
||||
VerifyOrExit(aMsg.mMessage.IsPostRequest());
|
||||
VerifyOrExit(aMsg.IsPostRequest());
|
||||
SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMsg.mMessage, mask));
|
||||
|
||||
SuccessOrExit(Tlv::Find<MeshCoP::PanIdTlv>(aMsg.mMessage, panId));
|
||||
@@ -62,7 +62,7 @@ template <> void PanIdQueryServer::HandleTmf<kUriPanIdQuery>(Coap::Msg &aMsg)
|
||||
mPanId = panId;
|
||||
mTimer.Start(kScanDelay);
|
||||
|
||||
if (aMsg.mMessage.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMsg));
|
||||
LogInfo("Sent %s ack", UriToString<kUriPanIdQuery>());
|
||||
|
||||
@@ -114,7 +114,7 @@ exit:
|
||||
|
||||
template <> void Client::HandleTmf<kUriHistoryAnswer>(Coap::Msg &aMsg)
|
||||
{
|
||||
VerifyOrExit(aMsg.mMessage.IsConfirmablePostRequest());
|
||||
VerifyOrExit(aMsg.IsConfirmablePostRequest());
|
||||
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg));
|
||||
|
||||
LogInfo("Received %s from %s", ot::UriToString<kUriHistoryAnswer>(),
|
||||
|
||||
@@ -49,12 +49,12 @@ Server::Server(Instance &aInstance)
|
||||
|
||||
template <> void Server::HandleTmf<kUriHistoryQuery>(Coap::Msg &aMsg)
|
||||
{
|
||||
VerifyOrExit(aMsg.mMessage.IsPostRequest());
|
||||
VerifyOrExit(aMsg.IsPostRequest());
|
||||
|
||||
LogInfo("Received %s from %s", UriToString<kUriHistoryQuery>(),
|
||||
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
|
||||
if (aMsg.mMessage.IsConfirmable())
|
||||
if (aMsg.IsConfirmable())
|
||||
{
|
||||
IgnoreError(Get<Tmf::Agent>().SendEmptyAck(aMsg));
|
||||
}
|
||||
@@ -282,7 +282,7 @@ void Server::HandleAnswerResponse(Coap::Message &aNextAnswer,
|
||||
|
||||
SuccessOrExit(error);
|
||||
VerifyOrExit(aResponse != nullptr && aMessageInfo != nullptr, error = kErrorDrop);
|
||||
VerifyOrExit(aResponse->GetCode() == Coap::kCodeChanged, error = kErrorDrop);
|
||||
VerifyOrExit(aResponse->ReadCode() == Coap::kCodeChanged, error = kErrorDrop);
|
||||
|
||||
SendNextAnswer(aNextAnswer, aMessageInfo->GetPeerAddr());
|
||||
|
||||
|
||||
@@ -199,13 +199,15 @@ void Otns::EmitCoapStatus(const char *aAction,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
Error *aError) const
|
||||
{
|
||||
Error error;
|
||||
char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
|
||||
StatusString string;
|
||||
Error error;
|
||||
char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
|
||||
StatusString string;
|
||||
Coap::HeaderInfo header;
|
||||
|
||||
SuccessOrExit(error = aMessage.ParseHeaderInfo(header));
|
||||
SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
|
||||
|
||||
string.Append("coap=%s,%d,%d,%d,%s,%s,%d", aAction, aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(),
|
||||
string.Append("coap=%s,%d,%d,%d,%s,%s,%d", aAction, header.GetMessageId(), header.GetType(), header.GetCode(),
|
||||
uriPath, aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
|
||||
|
||||
if (aError != nullptr)
|
||||
|
||||
@@ -206,6 +206,7 @@ ot_unit_test(checksum)
|
||||
ot_unit_test(child)
|
||||
ot_unit_test(child_table)
|
||||
ot_unit_test(cmd_line_parser)
|
||||
ot_unit_test(coap_message)
|
||||
ot_unit_test(crc)
|
||||
ot_unit_test(data)
|
||||
ot_unit_test(dataset)
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* Copyright (c) 2026, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "instance/instance.hpp"
|
||||
|
||||
#include "test_platform.h"
|
||||
#include "test_util.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
class UnitTester
|
||||
{
|
||||
public:
|
||||
static void TestCoapMessage(void)
|
||||
{
|
||||
Instance *instance;
|
||||
Coap::Message *message;
|
||||
Coap::HeaderInfo headerInfo;
|
||||
Coap::Token readToken;
|
||||
Coap::Token token;
|
||||
Coap::Option::Iterator iterator;
|
||||
uint8_t tokenLength;
|
||||
uint16_t length;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
Coap::Message::UriPathStringBuffer uriBuffer;
|
||||
|
||||
printf("TestCoapMessage()\n");
|
||||
|
||||
instance = static_cast<Instance *>(testInitInstance());
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
|
||||
message = AsCoapMessagePtr(instance->Get<MessagePool>().Allocate(Message::kTypeOther));
|
||||
VerifyOrQuit(message != nullptr);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
SuccessOrQuit(message->Init(Coap::kTypeNonConfirmable, Coap::kCodePut));
|
||||
|
||||
SuccessOrQuit(message->ParseHeaderInfo(headerInfo));
|
||||
VerifyOrQuit(headerInfo.GetType() == Coap::kTypeNonConfirmable);
|
||||
VerifyOrQuit(headerInfo.GetCode() == Coap::kCodePut);
|
||||
VerifyOrQuit(headerInfo.GetMessageId() == 0);
|
||||
VerifyOrQuit(headerInfo.GetToken().GetLength() == 0);
|
||||
|
||||
VerifyOrQuit(message->ReadType() == Coap::kTypeNonConfirmable);
|
||||
VerifyOrQuit(message->ReadCode() == Coap::kCodePut);
|
||||
VerifyOrQuit(message->ReadMessageId() == 0);
|
||||
|
||||
SuccessOrQuit(message->ReadTokenLength(tokenLength));
|
||||
VerifyOrQuit(tokenLength == 0);
|
||||
|
||||
SuccessOrQuit(message->ReadToken(readToken));
|
||||
VerifyOrQuit(readToken.GetLength() == 0);
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(!iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == message->GetLength());
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
SuccessOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeNonConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePut);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0);
|
||||
VerifyOrQuit(msg.GetToken().GetLength() == 0);
|
||||
|
||||
VerifyOrQuit(msg.mMessage.GetOffset() == msg.mMessage.GetLength());
|
||||
}
|
||||
|
||||
// AppendPayloadMaker
|
||||
|
||||
SuccessOrQuit(message->AppendPayloadMarker());
|
||||
VerifyOrQuit(message->GetOffset() == message->GetLength());
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == message->GetLength());
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
VerifyOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRejectIfNoPayloadWithPayloadMarker) != kErrorNone);
|
||||
}
|
||||
|
||||
// AppendPayloadMaker again should not make any changes
|
||||
|
||||
length = message->GetLength();
|
||||
SuccessOrQuit(message->AppendPayloadMarker());
|
||||
VerifyOrQuit(message->GetLength() == length);
|
||||
VerifyOrQuit(message->GetOffset() == length);
|
||||
|
||||
// Ensure payload marker is removed since we have no payload
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
SuccessOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeNonConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePut);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0);
|
||||
VerifyOrQuit(msg.GetToken().GetLength() == 0);
|
||||
|
||||
VerifyOrQuit(msg.mMessage.GetOffset() == msg.mMessage.GetLength());
|
||||
}
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(!iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == message->GetLength());
|
||||
|
||||
SuccessOrQuit(message->Append<uint8_t>(0xaa));
|
||||
VerifyOrQuit(iterator.Init(*message) != kErrorNone);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
SuccessOrQuit(message->Init(Coap::kTypeConfirmable, Coap::kCodePost, 0x1234));
|
||||
|
||||
SuccessOrQuit(message->ParseHeaderInfo(headerInfo));
|
||||
VerifyOrQuit(headerInfo.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(headerInfo.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(headerInfo.GetMessageId() == 0x1234);
|
||||
VerifyOrQuit(headerInfo.GetToken().GetLength() == 0);
|
||||
|
||||
VerifyOrQuit(message->ReadType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(message->ReadCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(message->ReadMessageId() == 0x1234);
|
||||
|
||||
SuccessOrQuit(message->ReadTokenLength(tokenLength));
|
||||
VerifyOrQuit(tokenLength == 0);
|
||||
|
||||
SuccessOrQuit(message->ReadToken(readToken));
|
||||
VerifyOrQuit(readToken.GetLength() == 0);
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(!iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == message->GetLength());
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
SuccessOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0x1234);
|
||||
VerifyOrQuit(msg.GetToken().GetLength() == 0);
|
||||
|
||||
VerifyOrQuit(msg.mMessage.GetOffset() == msg.mMessage.GetLength());
|
||||
}
|
||||
|
||||
// Write Token
|
||||
|
||||
token.mLength = 2;
|
||||
token.m8[0] = 0x11;
|
||||
token.m8[1] = 0x22;
|
||||
|
||||
SuccessOrQuit(message->WriteToken(token));
|
||||
|
||||
SuccessOrQuit(message->ParseHeaderInfo(headerInfo));
|
||||
VerifyOrQuit(headerInfo.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(headerInfo.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(headerInfo.GetMessageId() == 0x1234);
|
||||
VerifyOrQuit(headerInfo.GetToken().GetLength() == 2);
|
||||
|
||||
SuccessOrQuit(message->ReadToken(readToken));
|
||||
VerifyOrQuit(readToken.GetLength() == 2);
|
||||
VerifyOrQuit(readToken == token);
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(!iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == message->GetLength());
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
SuccessOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0x1234);
|
||||
VerifyOrQuit(msg.GetToken().GetLength() == 2);
|
||||
VerifyOrQuit(msg.GetToken() == token);
|
||||
|
||||
VerifyOrQuit(msg.mMessage.GetOffset() == msg.mMessage.GetLength());
|
||||
}
|
||||
|
||||
// Append URI-Path Option
|
||||
|
||||
SuccessOrQuit(message->AppendUriPathOptions("uri"));
|
||||
|
||||
SuccessOrQuit(message->ParseHeaderInfo(headerInfo));
|
||||
VerifyOrQuit(headerInfo.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(headerInfo.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(headerInfo.GetMessageId() == 0x1234);
|
||||
VerifyOrQuit(headerInfo.GetToken().GetLength() == 2);
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
|
||||
VerifyOrQuit(!iterator.IsDone());
|
||||
VerifyOrQuit(iterator.GetOption() != nullptr);
|
||||
VerifyOrQuit(iterator.GetOption()->GetNumber() == Coap::kOptionUriPath);
|
||||
VerifyOrQuit(iterator.GetOption()->GetLength() == 3);
|
||||
|
||||
SuccessOrQuit(iterator.Advance());
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(!iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == message->GetLength());
|
||||
|
||||
SuccessOrQuit(message->AppendPayloadMarker());
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
VerifyOrQuit(!iterator.IsDone());
|
||||
SuccessOrQuit(iterator.Advance());
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == message->GetLength());
|
||||
|
||||
// Append some payload after marker
|
||||
|
||||
length = message->GetLength();
|
||||
SuccessOrQuit(message->Append<uint8_t>(0xef));
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
VerifyOrQuit(!iterator.IsDone());
|
||||
SuccessOrQuit(iterator.Advance());
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == length);
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
SuccessOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0x1234);
|
||||
VerifyOrQuit(msg.GetToken().GetLength() == 2);
|
||||
VerifyOrQuit(msg.GetToken() == token);
|
||||
|
||||
VerifyOrQuit(msg.mMessage.GetOffset() == length);
|
||||
}
|
||||
|
||||
// Re-write Token
|
||||
|
||||
token.mLength = 2;
|
||||
token.m8[0] = 0x33;
|
||||
token.m8[1] = 0x44;
|
||||
|
||||
SuccessOrQuit(message->WriteToken(token));
|
||||
|
||||
SuccessOrQuit(message->ParseHeaderInfo(headerInfo));
|
||||
VerifyOrQuit(headerInfo.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(headerInfo.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(headerInfo.GetMessageId() == 0x1234);
|
||||
VerifyOrQuit(headerInfo.GetToken().GetLength() == 2);
|
||||
|
||||
SuccessOrQuit(message->ReadToken(readToken));
|
||||
VerifyOrQuit(readToken.GetLength() == 2);
|
||||
VerifyOrQuit(readToken == token);
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
SuccessOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0x1234);
|
||||
VerifyOrQuit(msg.GetToken().GetLength() == 2);
|
||||
VerifyOrQuit(msg.GetToken() == token);
|
||||
|
||||
VerifyOrQuit(msg.mMessage.GetOffset() == length);
|
||||
}
|
||||
|
||||
// Re-write token - changing token length afterwards is not allowed
|
||||
|
||||
token.mLength = 3;
|
||||
token.m8[2] = 0x55;
|
||||
|
||||
VerifyOrQuit(message->WriteToken(token) != kErrorNone);
|
||||
|
||||
SuccessOrQuit(message->ParseHeaderInfo(headerInfo));
|
||||
VerifyOrQuit(headerInfo.GetToken().GetLength() == 2);
|
||||
|
||||
token.mLength = 2;
|
||||
|
||||
SuccessOrQuit(message->ReadToken(readToken));
|
||||
VerifyOrQuit(readToken.GetLength() == 2);
|
||||
VerifyOrQuit(readToken == token);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
SuccessOrQuit(message->Init(Coap::kTypeConfirmable, Coap::kCodeGet, kUriCommissionerSet));
|
||||
|
||||
SuccessOrQuit(message->ParseHeaderInfo(headerInfo));
|
||||
VerifyOrQuit(headerInfo.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(headerInfo.GetCode() == Coap::kCodeGet);
|
||||
VerifyOrQuit(headerInfo.GetMessageId() == 0);
|
||||
VerifyOrQuit(headerInfo.GetToken().GetLength() == Coap::Token::kDefaultLength);
|
||||
|
||||
VerifyOrQuit(message->ReadType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(message->ReadCode() == Coap::kCodeGet);
|
||||
VerifyOrQuit(message->ReadMessageId() == 0);
|
||||
|
||||
SuccessOrQuit(message->ReadTokenLength(tokenLength));
|
||||
VerifyOrQuit(tokenLength == Coap::Token::kDefaultLength);
|
||||
|
||||
SuccessOrQuit(iterator.Init(*message));
|
||||
|
||||
VerifyOrQuit(!iterator.IsDone());
|
||||
VerifyOrQuit(iterator.GetOption() != nullptr);
|
||||
VerifyOrQuit(iterator.GetOption()->GetNumber() == Coap::kOptionUriPath);
|
||||
|
||||
SuccessOrQuit(iterator.Advance());
|
||||
VerifyOrQuit(!iterator.IsDone());
|
||||
VerifyOrQuit(iterator.GetOption() != nullptr);
|
||||
VerifyOrQuit(iterator.GetOption()->GetNumber() == Coap::kOptionUriPath);
|
||||
|
||||
SuccessOrQuit(iterator.Advance());
|
||||
VerifyOrQuit(iterator.IsDone());
|
||||
VerifyOrQuit(!iterator.HasPayloadMarker());
|
||||
VerifyOrQuit(iterator.GetPayloadMessageOffset() == message->GetLength());
|
||||
|
||||
SuccessOrQuit(message->ReadUriPathOptions(uriBuffer));
|
||||
VerifyOrQuit(StringMatch(uriBuffer, PathForUri(kUriCommissionerSet)));
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
SuccessOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodeGet);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0);
|
||||
VerifyOrQuit(msg.GetToken().GetLength() == 2);
|
||||
|
||||
VerifyOrQuit(msg.mMessage.GetOffset() == msg.mMessage.GetLength());
|
||||
}
|
||||
|
||||
// Re-write code, type, and message ID
|
||||
|
||||
message->WriteType(Coap::kTypeNonConfirmable);
|
||||
message->WriteCode(Coap::kCodePost);
|
||||
message->WriteMessageId(0x9876);
|
||||
|
||||
SuccessOrQuit(message->ParseHeaderInfo(headerInfo));
|
||||
VerifyOrQuit(headerInfo.GetType() == Coap::kTypeNonConfirmable);
|
||||
VerifyOrQuit(headerInfo.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(headerInfo.GetMessageId() == 0x9876);
|
||||
|
||||
{
|
||||
Coap::Msg msg(*message, messageInfo);
|
||||
|
||||
SuccessOrQuit(msg.ParseHeaderAndOptions(Coap::Msg::kRemovePayloadMarkerIfNoPayload));
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeNonConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0x9876);
|
||||
VerifyOrQuit(msg.GetToken().GetLength() == 2);
|
||||
|
||||
VerifyOrQuit(msg.mMessage.GetOffset() == msg.mMessage.GetLength());
|
||||
|
||||
// Msg::UpdateType()
|
||||
|
||||
msg.UpdateType(Coap::kTypeConfirmable);
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0x9876);
|
||||
|
||||
VerifyOrQuit(message->ReadType() == Coap::kTypeConfirmable);
|
||||
|
||||
// Msg::UpdateMessageId()
|
||||
|
||||
msg.UpdateMessageId(0xabcd);
|
||||
|
||||
VerifyOrQuit(msg.GetType() == Coap::kTypeConfirmable);
|
||||
VerifyOrQuit(msg.GetCode() == Coap::kCodePost);
|
||||
VerifyOrQuit(msg.GetMessageId() == 0xabcd);
|
||||
|
||||
VerifyOrQuit(message->ReadMessageId() == 0xabcd);
|
||||
}
|
||||
|
||||
message->Free();
|
||||
testFreeInstance(instance);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ot::UnitTester::TestCoapMessage();
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user