mirror of
https://github.com/espressif/openthread.git
synced 2026-08-20 01:19:51 +00:00
[coap] misc enhancements and simplifications (#4554)
This commits contains the following changes: - Declare `Metadata` as a private inner class of `CoapBase`. Also replace constructors with `Init()` method and removes the default empty constructor (since it is not needed). - Add `ResponseMetadata` as private inner struct in `ResposeQueue`. - Simplify `ResponsesQueue::FindMatchedResponse()`. - Declare `CoapBase::Sender` as a protected type. - Use initializer list in `CoapBase` constructor. - Use `for` loop for iterating over messages in a message queue. - Define `ResponseHandler` and `RequestHandler` types. - Update `TxParameters` class. Add helper method for common calculation of span window, and remove unused constant definitions. - Move more complex method implementation from header file into `cpp` file (helps reduce code size). - Update comments and documentations.
This commit is contained in:
@@ -206,7 +206,7 @@ otError otCoapSendRequestWithParameters(otInstance * aInstance,
|
||||
|
||||
return instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
|
||||
Coap::CoapTxParameters::From(aTxParameters), aHandler, aContext);
|
||||
Coap::TxParameters::From(aTxParameters), aHandler, aContext);
|
||||
}
|
||||
|
||||
otError otCoapStart(otInstance *aInstance, uint16_t aPort)
|
||||
@@ -253,7 +253,7 @@ otError otCoapSendResponseWithParameters(otInstance * aInstance,
|
||||
|
||||
return instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
|
||||
Coap::CoapTxParameters::From(aTxParameters), NULL, NULL);
|
||||
Coap::TxParameters::From(aTxParameters), NULL, NULL);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
|
||||
|
||||
+213
-180
@@ -48,6 +48,8 @@ namespace Coap {
|
||||
|
||||
CoapBase::CoapBase(Instance &aInstance, Sender aSender)
|
||||
: InstanceLocator(aInstance)
|
||||
, mPendingRequests()
|
||||
, mMessageId(Random::NonCrypto::GetUint16())
|
||||
, mRetransmissionTimer(aInstance, &Coap::HandleRetransmissionTimer, this)
|
||||
, mResources()
|
||||
, mContext(NULL)
|
||||
@@ -57,42 +59,33 @@ CoapBase::CoapBase(Instance &aInstance, Sender aSender)
|
||||
, mDefaultHandlerContext(NULL)
|
||||
, mSender(aSender)
|
||||
{
|
||||
mMessageId = Random::NonCrypto::GetUint16();
|
||||
}
|
||||
|
||||
void CoapBase::ClearRequestsAndResponses(void)
|
||||
{
|
||||
Message * message = static_cast<Message *>(mPendingRequests.GetHead());
|
||||
Message * messageToRemove;
|
||||
CoapMetadata coapMetadata;
|
||||
|
||||
// Remove all pending messages.
|
||||
while (message != NULL)
|
||||
{
|
||||
messageToRemove = message;
|
||||
message = static_cast<Message *>(message->GetNext());
|
||||
|
||||
coapMetadata.ReadFrom(*messageToRemove);
|
||||
FinalizeCoapTransaction(*messageToRemove, coapMetadata, NULL, NULL, OT_ERROR_ABORT);
|
||||
}
|
||||
|
||||
ClearRequests(NULL); // Clear requests matching any address.
|
||||
mResponsesQueue.DequeueAllResponses();
|
||||
}
|
||||
|
||||
void CoapBase::ClearRequests(const Ip6::Address &aAddress)
|
||||
{
|
||||
ClearRequests(&aAddress);
|
||||
}
|
||||
|
||||
void CoapBase::ClearRequests(const Ip6::Address *aAddress)
|
||||
{
|
||||
Message *nextMessage;
|
||||
|
||||
// Remove pending messages with the specified source.
|
||||
for (Message *message = static_cast<Message *>(mPendingRequests.GetHead()); message != NULL; message = nextMessage)
|
||||
{
|
||||
CoapMetadata coapMetadata;
|
||||
nextMessage = static_cast<Message *>(message->GetNext());
|
||||
coapMetadata.ReadFrom(*message);
|
||||
Metadata metadata;
|
||||
|
||||
if (coapMetadata.mSourceAddress == aAddress)
|
||||
nextMessage = static_cast<Message *>(message->GetNext());
|
||||
metadata.ReadFrom(*message);
|
||||
|
||||
if ((aAddress == NULL) || (metadata.mSourceAddress == *aAddress))
|
||||
{
|
||||
FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_ABORT);
|
||||
FinalizeCoapTransaction(*message, metadata, NULL, NULL, OT_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,12 +101,18 @@ void CoapBase::RemoveResource(Resource &aResource)
|
||||
aResource.SetNext(NULL);
|
||||
}
|
||||
|
||||
void CoapBase::SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext)
|
||||
void CoapBase::SetDefaultHandler(RequestHandler aHandler, void *aContext)
|
||||
{
|
||||
mDefaultHandler = aHandler;
|
||||
mDefaultHandlerContext = aContext;
|
||||
}
|
||||
|
||||
void CoapBase::SetInterceptor(Interceptor aInterceptor, void *aContext)
|
||||
{
|
||||
mInterceptor = aInterceptor;
|
||||
mContext = aContext;
|
||||
}
|
||||
|
||||
Message *CoapBase::NewMessage(const otMessageSettings *aSettings)
|
||||
{
|
||||
Message *message = NULL;
|
||||
@@ -125,10 +124,15 @@ exit:
|
||||
return message;
|
||||
}
|
||||
|
||||
otError CoapBase::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return mSender(*this, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
otError CoapBase::SendMessage(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const CoapTxParameters &aTxParameters,
|
||||
otCoapResponseHandler aHandler,
|
||||
const TxParameters & aTxParameters,
|
||||
ResponseHandler aHandler,
|
||||
void * aContext)
|
||||
{
|
||||
otError error;
|
||||
@@ -152,21 +156,22 @@ otError CoapBase::SendMessage(Message & aMessage,
|
||||
|
||||
if (aMessage.IsConfirmable())
|
||||
{
|
||||
// Create a copy of entire message and enqueue it.
|
||||
copyLength = aMessage.GetLength();
|
||||
}
|
||||
else if (aMessage.IsNonConfirmable() && (aHandler != NULL))
|
||||
{
|
||||
// As we do not retransmit non confirmable messages, create a copy of header only, for token information.
|
||||
// As we do not retransmit non confirmable messages, create a
|
||||
// copy of header only, for token information.
|
||||
copyLength = aMessage.GetOptionStart();
|
||||
}
|
||||
|
||||
if (copyLength > 0)
|
||||
{
|
||||
CoapMetadata coapMetadata =
|
||||
CoapMetadata(aMessage.IsConfirmable(), aMessageInfo, aHandler, aContext, aTxParameters);
|
||||
VerifyOrExit((storedCopy = CopyAndEnqueueMessage(aMessage, copyLength, coapMetadata)) != NULL,
|
||||
error = OT_ERROR_NO_BUFS);
|
||||
Metadata metadata;
|
||||
|
||||
metadata.Init(aMessage.IsConfirmable(), aMessageInfo, aHandler, aContext, aTxParameters);
|
||||
storedCopy = CopyAndEnqueueMessage(aMessage, copyLength, metadata);
|
||||
VerifyOrExit(storedCopy != NULL, error = OT_ERROR_NO_BUFS);
|
||||
}
|
||||
|
||||
SuccessOrExit(error = Send(aMessage, aMessageInfo));
|
||||
@@ -181,6 +186,36 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError CoapBase::SendMessage(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
ResponseHandler aHandler,
|
||||
void * aContext)
|
||||
{
|
||||
return SendMessage(aMessage, aMessageInfo, TxParameters::GetDefault(), aHandler, aContext);
|
||||
}
|
||||
|
||||
otError CoapBase::SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return SendEmptyMessage(OT_COAP_TYPE_RESET, aRequest, aMessageInfo);
|
||||
}
|
||||
|
||||
otError CoapBase::SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return SendEmptyMessage(OT_COAP_TYPE_ACKNOWLEDGMENT, aRequest, aMessageInfo);
|
||||
}
|
||||
|
||||
otError CoapBase::SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return (aRequest.GetType() == OT_COAP_TYPE_CONFIRMABLE
|
||||
? SendHeaderResponse(OT_COAP_CODE_CHANGED, aRequest, aMessageInfo)
|
||||
: OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
otError CoapBase::SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return SendHeaderResponse(OT_COAP_CODE_NOT_FOUND, aRequest, aMessageInfo);
|
||||
}
|
||||
|
||||
otError CoapBase::SendEmptyMessage(Message::Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -253,46 +288,45 @@ void CoapBase::HandleRetransmissionTimer(void)
|
||||
{
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
TimeMilli nextTime = now.GetDistantFuture();
|
||||
CoapMetadata coapMetadata;
|
||||
Message * message;
|
||||
Metadata metadata;
|
||||
Message * nextMessage;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
for (message = static_cast<Message *>(mPendingRequests.GetHead()); message != NULL; message = nextMessage)
|
||||
for (Message *message = static_cast<Message *>(mPendingRequests.GetHead()); message != NULL; message = nextMessage)
|
||||
{
|
||||
nextMessage = static_cast<Message *>(message->GetNext());
|
||||
|
||||
coapMetadata.ReadFrom(*message);
|
||||
metadata.ReadFrom(*message);
|
||||
|
||||
if (now >= coapMetadata.mNextTimerShot)
|
||||
if (now >= metadata.mNextTimerShot)
|
||||
{
|
||||
if (!coapMetadata.mConfirmable || (coapMetadata.mRetransmissionsRemaining == 0))
|
||||
if (!metadata.mConfirmable || (metadata.mRetransmissionsRemaining == 0))
|
||||
{
|
||||
// No expected response or acknowledgment.
|
||||
FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_RESPONSE_TIMEOUT);
|
||||
FinalizeCoapTransaction(*message, metadata, NULL, NULL, OT_ERROR_RESPONSE_TIMEOUT);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Increment retransmission counter and timer.
|
||||
coapMetadata.mRetransmissionsRemaining--;
|
||||
coapMetadata.mRetransmissionTimeout *= 2;
|
||||
coapMetadata.mNextTimerShot = now + coapMetadata.mRetransmissionTimeout;
|
||||
coapMetadata.UpdateIn(*message);
|
||||
metadata.mRetransmissionsRemaining--;
|
||||
metadata.mRetransmissionTimeout *= 2;
|
||||
metadata.mNextTimerShot = now + metadata.mRetransmissionTimeout;
|
||||
metadata.UpdateIn(*message);
|
||||
|
||||
// Retransmit
|
||||
if (!coapMetadata.mAcknowledged)
|
||||
if (!metadata.mAcknowledged)
|
||||
{
|
||||
messageInfo.SetPeerAddr(coapMetadata.mDestinationAddress);
|
||||
messageInfo.SetPeerPort(coapMetadata.mDestinationPort);
|
||||
messageInfo.SetSockAddr(coapMetadata.mSourceAddress);
|
||||
messageInfo.SetPeerAddr(metadata.mDestinationAddress);
|
||||
messageInfo.SetPeerPort(metadata.mDestinationPort);
|
||||
messageInfo.SetSockAddr(metadata.mSourceAddress);
|
||||
|
||||
SendCopy(*message, messageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (nextTime > coapMetadata.mNextTimerShot)
|
||||
if (nextTime > metadata.mNextTimerShot)
|
||||
{
|
||||
nextTime = coapMetadata.mNextTimerShot;
|
||||
nextTime = metadata.mNextTimerShot;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,34 +337,33 @@ void CoapBase::HandleRetransmissionTimer(void)
|
||||
}
|
||||
|
||||
void CoapBase::FinalizeCoapTransaction(Message & aRequest,
|
||||
const CoapMetadata & aCoapMetadata,
|
||||
const Metadata & aMetadata,
|
||||
Message * aResponse,
|
||||
const Ip6::MessageInfo *aMessageInfo,
|
||||
otError aResult)
|
||||
{
|
||||
DequeueMessage(aRequest);
|
||||
|
||||
if (aCoapMetadata.mResponseHandler != NULL)
|
||||
if (aMetadata.mResponseHandler != NULL)
|
||||
{
|
||||
aCoapMetadata.mResponseHandler(aCoapMetadata.mResponseContext, aResponse, aMessageInfo, aResult);
|
||||
aMetadata.mResponseHandler(aMetadata.mResponseContext, aResponse, aMessageInfo, aResult);
|
||||
}
|
||||
}
|
||||
|
||||
otError CoapBase::AbortTransaction(otCoapResponseHandler aHandler, void *aContext)
|
||||
otError CoapBase::AbortTransaction(ResponseHandler aHandler, void *aContext)
|
||||
{
|
||||
otError error = OT_ERROR_NOT_FOUND;
|
||||
Message * message;
|
||||
Message * nextMessage;
|
||||
CoapMetadata coapMetadata;
|
||||
otError error = OT_ERROR_NOT_FOUND;
|
||||
Message *nextMessage;
|
||||
Metadata metadata;
|
||||
|
||||
for (message = static_cast<Message *>(mPendingRequests.GetHead()); message != NULL; message = nextMessage)
|
||||
for (Message *message = static_cast<Message *>(mPendingRequests.GetHead()); message != NULL; message = nextMessage)
|
||||
{
|
||||
nextMessage = static_cast<Message *>(message->GetNext());
|
||||
coapMetadata.ReadFrom(*message);
|
||||
metadata.ReadFrom(*message);
|
||||
|
||||
if (coapMetadata.mResponseHandler == aHandler && coapMetadata.mResponseContext == aContext)
|
||||
if (metadata.mResponseHandler == aHandler && metadata.mResponseContext == aContext)
|
||||
{
|
||||
FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_ABORT);
|
||||
FinalizeCoapTransaction(*message, metadata, NULL, NULL, OT_ERROR_ABORT);
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
@@ -338,22 +371,17 @@ otError CoapBase::AbortTransaction(otCoapResponseHandler aHandler, void *aContex
|
||||
return error;
|
||||
}
|
||||
|
||||
Message *CoapBase::CopyAndEnqueueMessage(const Message & aMessage,
|
||||
uint16_t aCopyLength,
|
||||
const CoapMetadata &aCoapMetadata)
|
||||
Message *CoapBase::CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const Metadata &aMetadata)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message *messageCopy = NULL;
|
||||
|
||||
// Create a message copy of requested size.
|
||||
VerifyOrExit((messageCopy = aMessage.Clone(aCopyLength)) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
// Append the copy with retransmission data.
|
||||
SuccessOrExit(error = aCoapMetadata.AppendTo(*messageCopy));
|
||||
SuccessOrExit(error = aMetadata.AppendTo(*messageCopy));
|
||||
|
||||
mRetransmissionTimer.FireAtIfEarlier(aCoapMetadata.mNextTimerShot);
|
||||
mRetransmissionTimer.FireAtIfEarlier(aMetadata.mNextTimerShot);
|
||||
|
||||
// Enqueue the message.
|
||||
mPendingRequests.Enqueue(*messageCopy);
|
||||
|
||||
exit:
|
||||
@@ -373,11 +401,9 @@ void CoapBase::DequeueMessage(Message &aMessage)
|
||||
|
||||
if (mRetransmissionTimer.IsRunning() && (mPendingRequests.GetHead() == NULL))
|
||||
{
|
||||
// No more requests pending, stop the timer.
|
||||
mRetransmissionTimer.Stop();
|
||||
}
|
||||
|
||||
// Free the message memory.
|
||||
aMessage.Free();
|
||||
|
||||
// No need to worry that the earliest pending message was removed -
|
||||
@@ -390,10 +416,9 @@ otError CoapBase::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMes
|
||||
Message *messageCopy = NULL;
|
||||
|
||||
// Create a message copy for lower layers.
|
||||
VerifyOrExit((messageCopy = aMessage.Clone(aMessage.GetLength() - sizeof(CoapMetadata))) != NULL,
|
||||
error = OT_ERROR_NO_BUFS);
|
||||
messageCopy = aMessage.Clone(aMessage.GetLength() - sizeof(Metadata));
|
||||
VerifyOrExit(messageCopy != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
// Send the copy.
|
||||
SuccessOrExit(error = Send(*messageCopy, aMessageInfo));
|
||||
|
||||
exit:
|
||||
@@ -408,18 +433,18 @@ exit:
|
||||
|
||||
Message *CoapBase::FindRelatedRequest(const Message & aResponse,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
CoapMetadata & aCoapMetadata)
|
||||
Metadata & aMetadata)
|
||||
{
|
||||
Message *message = static_cast<Message *>(mPendingRequests.GetHead());
|
||||
Message *message;
|
||||
|
||||
while (message != NULL)
|
||||
for (message = static_cast<Message *>(mPendingRequests.GetHead()); message != NULL;
|
||||
message = static_cast<Message *>(message->GetNext()))
|
||||
{
|
||||
aCoapMetadata.ReadFrom(*message);
|
||||
aMetadata.ReadFrom(*message);
|
||||
|
||||
if (((aCoapMetadata.mDestinationAddress == aMessageInfo.GetPeerAddr()) ||
|
||||
aCoapMetadata.mDestinationAddress.IsMulticast() ||
|
||||
aCoapMetadata.mDestinationAddress.IsAnycastRoutingLocator()) &&
|
||||
(aCoapMetadata.mDestinationPort == aMessageInfo.GetPeerPort()))
|
||||
if (((aMetadata.mDestinationAddress == aMessageInfo.GetPeerAddr()) ||
|
||||
aMetadata.mDestinationAddress.IsMulticast() || aMetadata.mDestinationAddress.IsAnycastRoutingLocator()) &&
|
||||
(aMetadata.mDestinationPort == aMessageInfo.GetPeerPort()))
|
||||
{
|
||||
switch (aResponse.GetType())
|
||||
{
|
||||
@@ -442,8 +467,6 @@ Message *CoapBase::FindRelatedRequest(const Message & aResponse,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
message = static_cast<Message *>(message->GetNext());
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -475,23 +498,19 @@ void CoapBase::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
|
||||
void CoapBase::ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
CoapMetadata coapMetadata;
|
||||
Message * request = NULL;
|
||||
otError error = OT_ERROR_NONE;
|
||||
Metadata metadata;
|
||||
Message *request = NULL;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
request = FindRelatedRequest(aMessage, aMessageInfo, coapMetadata);
|
||||
|
||||
if (request == NULL)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
request = FindRelatedRequest(aMessage, aMessageInfo, metadata);
|
||||
VerifyOrExit(request != NULL);
|
||||
|
||||
switch (aMessage.GetType())
|
||||
{
|
||||
case OT_COAP_TYPE_RESET:
|
||||
if (aMessage.IsEmpty())
|
||||
{
|
||||
FinalizeCoapTransaction(*request, coapMetadata, NULL, NULL, OT_ERROR_ABORT);
|
||||
FinalizeCoapTransaction(*request, metadata, NULL, NULL, OT_ERROR_ABORT);
|
||||
}
|
||||
|
||||
// Silently ignore non-empty reset messages (RFC 7252, p. 4.2).
|
||||
@@ -501,14 +520,14 @@ void CoapBase::ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo
|
||||
if (aMessage.IsEmpty())
|
||||
{
|
||||
// Empty acknowledgment.
|
||||
if (coapMetadata.mConfirmable)
|
||||
if (metadata.mConfirmable)
|
||||
{
|
||||
coapMetadata.mAcknowledged = true;
|
||||
coapMetadata.UpdateIn(*request);
|
||||
metadata.mAcknowledged = true;
|
||||
metadata.UpdateIn(*request);
|
||||
}
|
||||
|
||||
// Remove the message if response is not expected, otherwise await response.
|
||||
if (coapMetadata.mResponseHandler == NULL)
|
||||
if (metadata.mResponseHandler == NULL)
|
||||
{
|
||||
DequeueMessage(*request);
|
||||
}
|
||||
@@ -516,7 +535,7 @@ void CoapBase::ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo
|
||||
else if (aMessage.IsResponse() && aMessage.IsTokenEqual(*request))
|
||||
{
|
||||
// Piggybacked response.
|
||||
FinalizeCoapTransaction(*request, coapMetadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
|
||||
FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
// Silently ignore acknowledgments carrying requests (RFC 7252, p. 4.2)
|
||||
@@ -526,20 +545,20 @@ void CoapBase::ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo
|
||||
case OT_COAP_TYPE_CONFIRMABLE:
|
||||
// Send empty ACK if it is a CON message.
|
||||
SendAck(aMessage, aMessageInfo);
|
||||
FinalizeCoapTransaction(*request, coapMetadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
|
||||
FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
|
||||
break;
|
||||
|
||||
case OT_COAP_TYPE_NON_CONFIRMABLE:
|
||||
// Separate response.
|
||||
|
||||
if (coapMetadata.mDestinationAddress.IsMulticast() && coapMetadata.mResponseHandler != NULL)
|
||||
if (metadata.mDestinationAddress.IsMulticast() && metadata.mResponseHandler != NULL)
|
||||
{
|
||||
// If multicast non-confirmable request, allow multiple responses
|
||||
coapMetadata.mResponseHandler(coapMetadata.mResponseContext, &aMessage, &aMessageInfo, OT_ERROR_NONE);
|
||||
metadata.mResponseHandler(metadata.mResponseContext, &aMessage, &aMessageInfo, OT_ERROR_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
FinalizeCoapTransaction(*request, coapMetadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
|
||||
FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -551,7 +570,8 @@ exit:
|
||||
{
|
||||
if (aMessage.IsConfirmable() || aMessage.IsNonConfirmable())
|
||||
{
|
||||
// Successfully parsed a header but no matching request was found - reject the message by sending reset.
|
||||
// Successfully parsed a header but no matching request was
|
||||
// found - reject the message by sending reset.
|
||||
SendReset(aMessage, aMessageInfo);
|
||||
}
|
||||
}
|
||||
@@ -575,8 +595,8 @@ void CoapBase::ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo
|
||||
case OT_ERROR_NONE:
|
||||
cachedResponse->Finish();
|
||||
error = Send(*cachedResponse, aMessageInfo);
|
||||
|
||||
// fall through
|
||||
;
|
||||
|
||||
case OT_ERROR_NO_BUFS:
|
||||
ExitNow();
|
||||
@@ -644,11 +664,11 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
CoapMetadata::CoapMetadata(bool aConfirmable,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
otCoapResponseHandler aHandler,
|
||||
void * aContext,
|
||||
const CoapTxParameters &aTxParameters)
|
||||
void CoapBase::Metadata::Init(bool aConfirmable,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
ResponseHandler aHandler,
|
||||
void * aContext,
|
||||
const TxParameters & aTxParameters)
|
||||
{
|
||||
mSourceAddress = aMessageInfo.GetSockAddr();
|
||||
mDestinationPort = aMessageInfo.GetPeerPort();
|
||||
@@ -657,20 +677,23 @@ CoapMetadata::CoapMetadata(bool aConfirmable,
|
||||
mResponseContext = aContext;
|
||||
mRetransmissionsRemaining = aTxParameters.mMaxRetransmit;
|
||||
mRetransmissionTimeout = aTxParameters.CalculateInitialRetransmissionTimeout();
|
||||
mAcknowledged = false;
|
||||
mConfirmable = aConfirmable;
|
||||
mNextTimerShot =
|
||||
TimerMilli::GetNow() + (aConfirmable ? mRetransmissionTimeout : aTxParameters.CalculateMaxTransmitWait());
|
||||
}
|
||||
|
||||
if (aConfirmable)
|
||||
{
|
||||
// Set next retransmission timeout.
|
||||
mNextTimerShot = TimerMilli::GetNow() + mRetransmissionTimeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set overall response timeout.
|
||||
mNextTimerShot = TimerMilli::GetNow() + aTxParameters.CalculateMaxTransmitWait();
|
||||
}
|
||||
void CoapBase::Metadata::ReadFrom(const Message &aMessage)
|
||||
{
|
||||
uint16_t length = aMessage.GetLength();
|
||||
|
||||
mAcknowledged = false;
|
||||
mConfirmable = aConfirmable;
|
||||
assert(length >= sizeof(*this));
|
||||
aMessage.Read(length - sizeof(*this), sizeof(*this), this);
|
||||
}
|
||||
|
||||
int CoapBase::Metadata::UpdateIn(Message &aMessage) const
|
||||
{
|
||||
return aMessage.Write(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
|
||||
}
|
||||
|
||||
ResponsesQueue::ResponsesQueue(Instance &aInstance)
|
||||
@@ -689,7 +712,7 @@ otError ResponsesQueue::GetMatchedResponseCopy(const Message & aRequest,
|
||||
cacheResponse = FindMatchedResponse(aRequest, aMessageInfo);
|
||||
VerifyOrExit(cacheResponse != NULL, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
*aResponse = cacheResponse->Clone(cacheResponse->GetLength() - sizeof(EnqueuedResponseHeader));
|
||||
*aResponse = cacheResponse->Clone(cacheResponse->GetLength() - sizeof(ResponseMetadata));
|
||||
VerifyOrExit(*aResponse != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
exit:
|
||||
@@ -698,54 +721,42 @@ exit:
|
||||
|
||||
const Message *ResponsesQueue::FindMatchedResponse(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) const
|
||||
{
|
||||
Message *matchedResponse = NULL;
|
||||
Message *message;
|
||||
|
||||
for (Message *message = static_cast<Message *>(mQueue.GetHead()); message != NULL;
|
||||
message = static_cast<Message *>(message->GetNext()))
|
||||
for (message = static_cast<Message *>(mQueue.GetHead()); message != NULL;
|
||||
message = static_cast<Message *>(message->GetNext()))
|
||||
{
|
||||
EnqueuedResponseHeader enqueuedResponseHeader;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
enqueuedResponseHeader.ReadFrom(*message);
|
||||
messageInfo = enqueuedResponseHeader.GetMessageInfo();
|
||||
|
||||
// Check source endpoint
|
||||
if (messageInfo.GetPeerPort() != aMessageInfo.GetPeerPort())
|
||||
if (message->GetMessageId() == aRequest.GetMessageId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ResponseMetadata metadata;
|
||||
|
||||
if (messageInfo.GetPeerAddr() != aMessageInfo.GetPeerAddr())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
metadata.ReadFrom(*message);
|
||||
|
||||
// Check Message Id
|
||||
if (message->GetMessageId() != aRequest.GetMessageId())
|
||||
{
|
||||
continue;
|
||||
if ((metadata.mMessageInfo.GetPeerPort() == aMessageInfo.GetPeerPort()) &&
|
||||
(metadata.mMessageInfo.GetPeerAddr() == aMessageInfo.GetPeerAddr()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ExitNow(matchedResponse = message);
|
||||
}
|
||||
|
||||
exit:
|
||||
return matchedResponse;
|
||||
return message;
|
||||
}
|
||||
|
||||
void ResponsesQueue::EnqueueResponse(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const CoapTxParameters &aTxParameters)
|
||||
const TxParameters & aTxParameters)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message * responseCopy = NULL;
|
||||
uint16_t messageCount;
|
||||
uint16_t bufferCount;
|
||||
uint32_t exchangeLifetime = aTxParameters.CalculateExchangeLifetime();
|
||||
TimeMilli dequeueTime = TimerMilli::GetNow() + exchangeLifetime;
|
||||
EnqueuedResponseHeader enqueuedResponseHeader(dequeueTime, aMessageInfo);
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message * responseCopy = NULL;
|
||||
uint16_t messageCount;
|
||||
uint16_t bufferCount;
|
||||
uint32_t exchangeLifetime = aTxParameters.CalculateExchangeLifetime();
|
||||
ResponseMetadata metadata;
|
||||
|
||||
// return success if matched response already exists in the cache
|
||||
metadata.Init(TimerMilli::GetNow() + exchangeLifetime, aMessageInfo);
|
||||
|
||||
// Return success if matched response already exists in the cache.
|
||||
VerifyOrExit(FindMatchedResponse(aMessage, aMessageInfo) == NULL);
|
||||
|
||||
mQueue.GetInfo(messageCount, bufferCount);
|
||||
@@ -757,7 +768,7 @@ void ResponsesQueue::EnqueueResponse(Message & aMessage,
|
||||
|
||||
VerifyOrExit((responseCopy = aMessage.Clone()) != NULL);
|
||||
|
||||
SuccessOrExit(error = enqueuedResponseHeader.AppendTo(*responseCopy));
|
||||
SuccessOrExit(error = metadata.AppendTo(*responseCopy));
|
||||
mQueue.Enqueue(*responseCopy);
|
||||
|
||||
if (!mTimer.IsRunning())
|
||||
@@ -775,6 +786,12 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void ResponsesQueue::DequeueResponse(Message &aMessage)
|
||||
{
|
||||
mQueue.Dequeue(aMessage);
|
||||
aMessage.Free();
|
||||
}
|
||||
|
||||
void ResponsesQueue::DequeueOldestResponse(void)
|
||||
{
|
||||
Message *message;
|
||||
@@ -803,59 +820,70 @@ void ResponsesQueue::HandleTimer(Timer &aTimer)
|
||||
|
||||
void ResponsesQueue::HandleTimer(void)
|
||||
{
|
||||
Message * message;
|
||||
EnqueuedResponseHeader enqueuedResponseHeader;
|
||||
Message * message;
|
||||
ResponseMetadata metadata;
|
||||
|
||||
while ((message = static_cast<Message *>(mQueue.GetHead())) != NULL)
|
||||
{
|
||||
enqueuedResponseHeader.ReadFrom(*message);
|
||||
metadata.ReadFrom(*message);
|
||||
|
||||
if (TimerMilli::GetNow() >= enqueuedResponseHeader.mDequeueTime)
|
||||
if (TimerMilli::GetNow() >= metadata.mDequeueTime)
|
||||
{
|
||||
DequeueResponse(*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
mTimer.Start(enqueuedResponseHeader.GetRemainingTime());
|
||||
mTimer.Start(metadata.GetRemainingTime());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EnqueuedResponseHeader::GetRemainingTime(void) const
|
||||
void ResponsesQueue::ResponseMetadata::Init(TimeMilli aDequeueTime, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
uint32_t remainingTime = 0;
|
||||
|
||||
if (mDequeueTime > now)
|
||||
{
|
||||
remainingTime = mDequeueTime - now;
|
||||
}
|
||||
|
||||
return remainingTime;
|
||||
mDequeueTime = aDequeueTime;
|
||||
mMessageInfo = aMessageInfo;
|
||||
}
|
||||
|
||||
uint32_t CoapTxParameters::CalculateInitialRetransmissionTimeout(void) const
|
||||
void ResponsesQueue::ResponseMetadata::ReadFrom(const Message &aMessage)
|
||||
{
|
||||
uint16_t length = aMessage.GetLength();
|
||||
|
||||
assert(length >= sizeof(*this));
|
||||
aMessage.Read(length - sizeof(*this), sizeof(*this), this);
|
||||
}
|
||||
|
||||
uint32_t ResponsesQueue::ResponseMetadata::GetRemainingTime(void) const
|
||||
{
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
|
||||
return (mDequeueTime > now) ? mDequeueTime - now : 0;
|
||||
}
|
||||
|
||||
uint32_t TxParameters::CalculateInitialRetransmissionTimeout(void) const
|
||||
{
|
||||
return Random::NonCrypto::GetUint32InRange(
|
||||
mAckTimeout, mAckTimeout * mAckRandomFactorNumerator / mAckRandomFactorDenominator + 1);
|
||||
}
|
||||
|
||||
uint32_t CoapTxParameters::CalculateExchangeLifetime(void) const
|
||||
uint32_t TxParameters::CalculateExchangeLifetime(void) const
|
||||
{
|
||||
uint32_t maxTransmitSpan = static_cast<uint32_t>(mAckTimeout * ((1ULL << mMaxRetransmit) - 1) *
|
||||
mAckRandomFactorNumerator / mAckRandomFactorDenominator);
|
||||
uint32_t processingDelay = mAckTimeout;
|
||||
return maxTransmitSpan + 2 * kDefaultMaxLatency + processingDelay;
|
||||
// Final `mAckTimeout` is to account for processing delay.
|
||||
return CalculateSpan(mMaxRetransmit) + 2 * kDefaultMaxLatency + mAckTimeout;
|
||||
}
|
||||
|
||||
uint32_t CoapTxParameters::CalculateMaxTransmitWait(void) const
|
||||
uint32_t TxParameters::CalculateMaxTransmitWait(void) const
|
||||
{
|
||||
return static_cast<uint32_t>(mAckTimeout * ((2ULL << mMaxRetransmit) - 1) * mAckRandomFactorNumerator /
|
||||
return CalculateSpan(mMaxRetransmit + 1);
|
||||
}
|
||||
|
||||
uint32_t TxParameters::CalculateSpan(uint32_t aMaxRetx) const
|
||||
{
|
||||
return static_cast<uint32_t>(mAckTimeout * ((1ULL << aMaxRetx) - 1) * mAckRandomFactorNumerator /
|
||||
mAckRandomFactorDenominator);
|
||||
}
|
||||
|
||||
const otCoapTxParameters CoapTxParameters::kDefaultTxParameters = {
|
||||
const otCoapTxParameters TxParameters::kDefaultTxParameters = {
|
||||
kDefaultAckTimeout,
|
||||
kDefaultAckRandomFactorNumerator,
|
||||
kDefaultAckRandomFactorDenominator,
|
||||
@@ -898,6 +926,11 @@ void Coap::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessage
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
otError Coap::Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return static_cast<Coap &>(aCoapBase).Send(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
otError Coap::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return mSocket.IsBound() ? mSocket.SendTo(aMessage, aMessageInfo) : OT_ERROR_INVALID_STATE;
|
||||
|
||||
+128
-290
@@ -59,141 +59,75 @@ namespace Coap {
|
||||
*
|
||||
*/
|
||||
|
||||
class CoapTxParameters : public otCoapTxParameters
|
||||
/**
|
||||
* This type represents a function pointer which is called when a CoAP response is received or on the request timeout.
|
||||
*
|
||||
* Please see otCoapResponseHandler for details.
|
||||
*
|
||||
*/
|
||||
typedef otCoapResponseHandler ResponseHandler;
|
||||
|
||||
/**
|
||||
* This type represents a function pointer which is called when a CoAP request associated with a given URI path is
|
||||
* received.
|
||||
*
|
||||
* Please see otCoapRequestHandler for details.
|
||||
*
|
||||
*/
|
||||
typedef otCoapRequestHandler RequestHandler;
|
||||
|
||||
/**
|
||||
* This structure represents the CoAP transmission parameters.
|
||||
*
|
||||
*/
|
||||
class TxParameters : public otCoapTxParameters
|
||||
{
|
||||
friend class CoapBase;
|
||||
friend class ResponsesQueue;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Protocol Constants (RFC 7252).
|
||||
* This static method coverts a pointer to `otCoapTxParameters` to `Coap::TxParamters`
|
||||
*
|
||||
* If the pointer is NULL, the default parameters are used instead.
|
||||
*
|
||||
* @param[in] aTxParameters A pointer to tx parameter.
|
||||
*
|
||||
* @returns A reference to corresponding `TxParamters` if @p aTxParameters is not NULL, otherwise the default tx
|
||||
* parameters.
|
||||
*
|
||||
*/
|
||||
static const TxParameters &From(const otCoapTxParameters *aTxParameters)
|
||||
{
|
||||
return aTxParameters ? *static_cast<const TxParameters *>(aTxParameters) : GetDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* This static method returns default CoAP tx parameters.
|
||||
*
|
||||
* @returns The default tx parameters.
|
||||
*
|
||||
*/
|
||||
static const TxParameters &GetDefault(void) { return static_cast<const TxParameters &>(kDefaultTxParameters); }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kDefaultAckTimeout = OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS,
|
||||
kDefaultAckRandomFactorNumerator = OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_NUMERATOR,
|
||||
kDefaultAckRandomFactorDenominator = OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_DENOMINATOR,
|
||||
kDefaultMaxRetransmit = OPENTHREAD_CONFIG_COAP_MAX_RETRANSMIT,
|
||||
kDefaultNStart = 1,
|
||||
kDefaultLeisure = 5000, // in milliseconds
|
||||
kDefaultProbingRate = 1,
|
||||
|
||||
kDefaultMaxTransmitSpan = kDefaultAckTimeout * ((1ULL << kDefaultMaxRetransmit) - 1) *
|
||||
kDefaultAckRandomFactorNumerator / kDefaultAckRandomFactorDenominator,
|
||||
kDefaultMaxTransmitWait = kDefaultAckTimeout * ((2ULL << kDefaultMaxRetransmit) - 1) *
|
||||
kDefaultAckRandomFactorNumerator / kDefaultAckRandomFactorDenominator,
|
||||
kDefaultMaxLatency = 100000, // in milliseconds
|
||||
kDefaultProcessingDelay = kDefaultAckTimeout,
|
||||
kDefaultMaxRtt = 2 * kDefaultMaxLatency + kDefaultProcessingDelay,
|
||||
kDefaultExchangeLifetime = kDefaultMaxTransmitSpan + 2 * kDefaultMaxLatency + kDefaultProcessingDelay,
|
||||
kDefaultNonLifetime = kDefaultMaxTransmitSpan + kDefaultMaxLatency
|
||||
kDefaultMaxLatency = 100000, // in millisecond
|
||||
};
|
||||
|
||||
uint32_t CalculateInitialRetransmissionTimeout(void) const;
|
||||
uint32_t CalculateExchangeLifetime(void) const;
|
||||
uint32_t CalculateMaxTransmitWait(void) const;
|
||||
uint32_t CalculateSpan(uint32_t aMaxRetx) const;
|
||||
|
||||
static inline const CoapTxParameters &From(const otCoapTxParameters *aTxParameters)
|
||||
{
|
||||
return aTxParameters ? *static_cast<const CoapTxParameters *>(aTxParameters) : GetDefault();
|
||||
}
|
||||
|
||||
static inline const CoapTxParameters &GetDefault()
|
||||
{
|
||||
return *static_cast<const CoapTxParameters *>(&kDefaultTxParameters);
|
||||
}
|
||||
|
||||
private:
|
||||
static const otCoapTxParameters kDefaultTxParameters;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements metadata required for CoAP retransmission.
|
||||
*
|
||||
*/
|
||||
class CoapMetadata
|
||||
{
|
||||
friend class CoapBase;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor for the object.
|
||||
*
|
||||
*/
|
||||
CoapMetadata(void)
|
||||
: mDestinationPort(0)
|
||||
, mResponseHandler(NULL)
|
||||
, mResponseContext(NULL)
|
||||
, mNextTimerShot(0)
|
||||
, mRetransmissionTimeout(0)
|
||||
, mRetransmissionsRemaining(0)
|
||||
, mAcknowledged(false)
|
||||
, mConfirmable(false){};
|
||||
|
||||
/**
|
||||
* This constructor initializes the object with specific values.
|
||||
*
|
||||
* @param[in] aConfirmable Information if the request is confirmable or not.
|
||||
* @param[in] aMessageInfo Addressing information.
|
||||
* @param[in] aHandler Pointer to a handler function for the response.
|
||||
* @param[in] aContext Context for the handler function.
|
||||
* @param[in] aTxParameters Transmission parameters.
|
||||
*
|
||||
*/
|
||||
CoapMetadata(bool aConfirmable,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
otCoapResponseHandler aHandler,
|
||||
void * aContext,
|
||||
const CoapTxParameters &aTxParameters);
|
||||
|
||||
/**
|
||||
* This method appends request data to the message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully appended the bytes.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
|
||||
*
|
||||
*/
|
||||
otError AppendTo(Message &aMessage) const { return aMessage.Append(this, sizeof(*this)); }
|
||||
|
||||
/**
|
||||
* This method reads request data from the message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
*/
|
||||
void ReadFrom(const Message &aMessage)
|
||||
{
|
||||
uint16_t length = aMessage.Read(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
|
||||
assert(length == sizeof(*this));
|
||||
OT_UNUSED_VARIABLE(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method updates request data in the message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
* @returns The number of bytes updated.
|
||||
*
|
||||
*/
|
||||
int UpdateIn(Message &aMessage) const
|
||||
{
|
||||
return aMessage.Write(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
|
||||
}
|
||||
|
||||
private:
|
||||
Ip6::Address mSourceAddress; ///< IPv6 address of the message source.
|
||||
Ip6::Address mDestinationAddress; ///< IPv6 address of the message destination.
|
||||
uint16_t mDestinationPort; ///< UDP port of the message destination.
|
||||
otCoapResponseHandler mResponseHandler; ///< A function pointer that is called on response reception.
|
||||
void * mResponseContext; ///< A pointer to arbitrary context information.
|
||||
TimeMilli mNextTimerShot; ///< Time when the timer should shoot for this message.
|
||||
uint32_t mRetransmissionTimeout; ///< Delay that is applied to next retransmission.
|
||||
uint8_t mRetransmissionsRemaining; ///< Number of retransmissions remaining.
|
||||
bool mAcknowledged : 1; ///< Information that request was acknowledged.
|
||||
bool mConfirmable : 1; ///< Information that message is confirmable.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements CoAP resource handling.
|
||||
*
|
||||
@@ -211,11 +145,11 @@ public:
|
||||
/**
|
||||
* This constructor initializes the resource.
|
||||
*
|
||||
* @param[in] aUriPath A pointer to a NULL-terminated string for the Uri-Path.
|
||||
* @param[in] aUriPath A pointer to a NULL-terminated string for the URI path.
|
||||
* @param[in] aHandler A function pointer that is called when receiving a CoAP message for @p aUriPath.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*/
|
||||
Resource(const char *aUriPath, otCoapRequestHandler aHandler, void *aContext)
|
||||
Resource(const char *aUriPath, RequestHandler aHandler, void *aContext)
|
||||
{
|
||||
mUriPath = aUriPath;
|
||||
mHandler = aHandler;
|
||||
@@ -224,9 +158,9 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Uri-Path.
|
||||
* This method returns a pointer to the URI path.
|
||||
*
|
||||
* @returns A pointer to the Uri-Path.
|
||||
* @returns A pointer to the URI path.
|
||||
*
|
||||
*/
|
||||
const char *GetUriPath(void) const { return mUriPath; }
|
||||
@@ -238,81 +172,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements metadata required for caching CoAP responses.
|
||||
*
|
||||
*/
|
||||
class EnqueuedResponseHeader
|
||||
{
|
||||
friend class ResponsesQueue;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor creating empty object.
|
||||
*
|
||||
*/
|
||||
EnqueuedResponseHeader(void)
|
||||
: mDequeueTime(0)
|
||||
, mMessageInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor creating object with valid dequeue time and message info.
|
||||
*
|
||||
* @param[in] aMessageInfo The message info containing source endpoint identification.
|
||||
*
|
||||
*/
|
||||
explicit EnqueuedResponseHeader(TimeMilli aDequeueTime, const Ip6::MessageInfo &aMessageInfo)
|
||||
: mDequeueTime(aDequeueTime)
|
||||
, mMessageInfo(aMessageInfo)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method appends metadata to the message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully appended the bytes.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
|
||||
*/
|
||||
otError AppendTo(Message &aMessage) const { return aMessage.Append(this, sizeof(*this)); }
|
||||
|
||||
/**
|
||||
* This method reads request data from the message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
*/
|
||||
void ReadFrom(const Message &aMessage)
|
||||
{
|
||||
uint16_t length = aMessage.Read(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
|
||||
assert(length == sizeof(*this));
|
||||
OT_UNUSED_VARIABLE(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns number of milliseconds in which the message should be sent.
|
||||
*
|
||||
* @returns The number of milliseconds in which the message should be sent.
|
||||
*
|
||||
*/
|
||||
uint32_t GetRemainingTime(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the message info of cached CoAP response.
|
||||
*
|
||||
* @returns The message info of the cached CoAP response.
|
||||
*
|
||||
*/
|
||||
const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
|
||||
|
||||
private:
|
||||
TimeMilli mDequeueTime;
|
||||
const Ip6::MessageInfo mMessageInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class caches CoAP responses to implement message deduplication.
|
||||
*
|
||||
@@ -341,9 +200,7 @@ public:
|
||||
* @param[in] aTxParameters Transmission parameters.
|
||||
*
|
||||
*/
|
||||
void EnqueueResponse(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const CoapTxParameters &aTxParameters);
|
||||
void EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const TxParameters &aTxParameters);
|
||||
|
||||
/**
|
||||
* This method removes the oldest response from the cache.
|
||||
@@ -385,23 +242,19 @@ private:
|
||||
kMaxCachedResponses = OPENTHREAD_CONFIG_COAP_SERVER_MAX_CACHED_RESPONSES,
|
||||
};
|
||||
|
||||
/**
|
||||
* This method checks whether a CoAP response exists in the cache that matches a given Message ID and source
|
||||
* endpoint.
|
||||
*
|
||||
* @param[in] aRequest The CoAP message containing Message ID.
|
||||
* @param[in] aMessageInfo The message info containing source endpoint address and port.
|
||||
*
|
||||
* @returns A pointer to the matching cached response or NULL if not found.
|
||||
*
|
||||
*/
|
||||
const Message *FindMatchedResponse(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) const;
|
||||
|
||||
void DequeueResponse(Message &aMessage)
|
||||
struct ResponseMetadata
|
||||
{
|
||||
mQueue.Dequeue(aMessage);
|
||||
aMessage.Free();
|
||||
}
|
||||
void Init(TimeMilli aDequeueTime, const Ip6::MessageInfo &aMessageInfo);
|
||||
otError AppendTo(Message &aMessage) const { return aMessage.Append(this, sizeof(*this)); }
|
||||
void ReadFrom(const Message &aMessage);
|
||||
uint32_t GetRemainingTime(void) const;
|
||||
|
||||
TimeMilli mDequeueTime;
|
||||
Ip6::MessageInfo mMessageInfo;
|
||||
};
|
||||
|
||||
const Message *FindMatchedResponse(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) const;
|
||||
void DequeueResponse(Message &aMessage);
|
||||
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
void HandleTimer(void);
|
||||
@@ -419,19 +272,6 @@ class CoapBase : public InstanceLocator
|
||||
friend class ResponsesQueue;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called to send a CoAP message.
|
||||
*
|
||||
* @param[in] aCoapBase A reference to the CoAP agent.
|
||||
* @param[in] aMessage A reference to the message to send.
|
||||
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully sent CoAP message.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
|
||||
*
|
||||
*/
|
||||
typedef otError (*Sender)(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This function pointer is called before CoAP server processing a CoAP message.
|
||||
*
|
||||
@@ -486,7 +326,7 @@ public:
|
||||
* @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
|
||||
*
|
||||
*/
|
||||
void SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext);
|
||||
void SetDefaultHandler(RequestHandler aHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* This method creates a new message with a CoAP header.
|
||||
@@ -515,13 +355,13 @@ public:
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully sent CoAP message.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP message.
|
||||
*
|
||||
*/
|
||||
otError SendMessage(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const CoapTxParameters &aTxParameters,
|
||||
otCoapResponseHandler aHandler = NULL,
|
||||
const TxParameters & aTxParameters,
|
||||
ResponseHandler aHandler = NULL,
|
||||
void * aContext = NULL);
|
||||
|
||||
/**
|
||||
@@ -537,16 +377,13 @@ public:
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully sent CoAP message.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
|
||||
*
|
||||
*/
|
||||
otError SendMessage(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
otCoapResponseHandler aHandler = NULL,
|
||||
void * aContext = NULL)
|
||||
{
|
||||
return SendMessage(aMessage, aMessageInfo, CoapTxParameters::GetDefault(), aHandler, aContext);
|
||||
}
|
||||
ResponseHandler aHandler = NULL,
|
||||
void * aContext = NULL);
|
||||
|
||||
/**
|
||||
* This method sends a CoAP reset message.
|
||||
@@ -559,10 +396,7 @@ public:
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aRequest is not of confirmable type.
|
||||
*
|
||||
*/
|
||||
otError SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return SendEmptyMessage(OT_COAP_TYPE_RESET, aRequest, aMessageInfo);
|
||||
}
|
||||
otError SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This method sends header-only CoAP response message.
|
||||
@@ -589,10 +423,7 @@ public:
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type.
|
||||
*
|
||||
*/
|
||||
otError SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return SendEmptyMessage(OT_COAP_TYPE_ACKNOWLEDGMENT, aRequest, aMessageInfo);
|
||||
}
|
||||
otError SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This method sends a CoAP ACK message on which a dummy CoAP response is piggybacked.
|
||||
@@ -605,12 +436,7 @@ public:
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type.
|
||||
*
|
||||
*/
|
||||
otError SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return (aRequest.GetType() == OT_COAP_TYPE_CONFIRMABLE
|
||||
? SendHeaderResponse(OT_COAP_CODE_CHANGED, aRequest, aMessageInfo)
|
||||
: OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
otError SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This method sends a header-only CoAP message to indicate no resource matched for the request.
|
||||
@@ -622,10 +448,7 @@ public:
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
|
||||
*
|
||||
*/
|
||||
otError SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return SendHeaderResponse(OT_COAP_CODE_NOT_FOUND, aRequest, aMessageInfo);
|
||||
}
|
||||
otError SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This method aborts CoAP transactions associated with given handler and context.
|
||||
@@ -639,7 +462,7 @@ public:
|
||||
* @retval OT_ERROR_NOT_FOUND CoAP transaction associated with given handler was not found.
|
||||
*
|
||||
*/
|
||||
otError AbortTransaction(otCoapResponseHandler aHandler, void *aContext);
|
||||
otError AbortTransaction(ResponseHandler aHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* This method sets interceptor to be called before processing a CoAP packet.
|
||||
@@ -648,11 +471,7 @@ public:
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
void SetInterceptor(Interceptor aInterceptor, void *aContext)
|
||||
{
|
||||
mInterceptor = aInterceptor;
|
||||
mContext = aContext;
|
||||
}
|
||||
void SetInterceptor(Interceptor aInterceptor, void *aContext);
|
||||
|
||||
/**
|
||||
* This method returns a reference to the request message list.
|
||||
@@ -671,6 +490,19 @@ public:
|
||||
const MessageQueue &GetCachedResponses(void) const { return mResponsesQueue.GetResponses(); }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This function pointer is called to send a CoAP message.
|
||||
*
|
||||
* @param[in] aCoapBase A reference to the CoAP agent.
|
||||
* @param[in] aMessage A reference to the message to send.
|
||||
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully sent CoAP message.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
|
||||
*
|
||||
*/
|
||||
typedef otError (*Sender)(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
@@ -679,7 +511,7 @@ protected:
|
||||
* member method of a descendant of this class.
|
||||
*
|
||||
*/
|
||||
explicit CoapBase(Instance &aInstance, Sender aSender);
|
||||
CoapBase(Instance &aInstance, Sender aSender);
|
||||
|
||||
/**
|
||||
* This method receives a CoAP message.
|
||||
@@ -691,16 +523,39 @@ protected:
|
||||
void Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
private:
|
||||
struct Metadata
|
||||
{
|
||||
void Init(bool aConfirmable,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
ResponseHandler aHandler,
|
||||
void * aContext,
|
||||
const TxParameters & aTxParameters);
|
||||
|
||||
otError AppendTo(Message &aMessage) const { return aMessage.Append(this, sizeof(*this)); }
|
||||
void ReadFrom(const Message &aMessage);
|
||||
int UpdateIn(Message &aMessage) const;
|
||||
|
||||
Ip6::Address mSourceAddress; // IPv6 address of the message source.
|
||||
Ip6::Address mDestinationAddress; // IPv6 address of the message destination.
|
||||
uint16_t mDestinationPort; // UDP port of the message destination.
|
||||
ResponseHandler mResponseHandler; // A function pointer that is called on response reception.
|
||||
void * mResponseContext; // A pointer to arbitrary context information.
|
||||
TimeMilli mNextTimerShot; // Time when the timer should shoot for this message.
|
||||
uint32_t mRetransmissionTimeout; // Delay that is applied to next retransmission.
|
||||
uint8_t mRetransmissionsRemaining; // Number of retransmissions remaining.
|
||||
bool mAcknowledged : 1; // Information that request was acknowledged.
|
||||
bool mConfirmable : 1; // Information that message is confirmable.
|
||||
};
|
||||
|
||||
static void HandleRetransmissionTimer(Timer &aTimer);
|
||||
void HandleRetransmissionTimer(void);
|
||||
|
||||
Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const CoapMetadata &aCoapMetadata);
|
||||
void ClearRequests(const Ip6::Address *aAddress);
|
||||
Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const Metadata &aMetadata);
|
||||
void DequeueMessage(Message &aMessage);
|
||||
Message *FindRelatedRequest(const Message & aResponse,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
CoapMetadata & aCoapMetadata);
|
||||
Message *FindRelatedRequest(const Message &aResponse, const Ip6::MessageInfo &aMessageInfo, Metadata &aMetadata);
|
||||
void FinalizeCoapTransaction(Message & aRequest,
|
||||
const CoapMetadata & aCoapMetadata,
|
||||
const Metadata & aMetadata,
|
||||
Message * aResponse,
|
||||
const Ip6::MessageInfo *aMessageInfo,
|
||||
otError aResult);
|
||||
@@ -711,20 +566,7 @@ private:
|
||||
otError SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
otError SendEmptyMessage(Message::Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This method sends a message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message to send.
|
||||
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully sent CoAP message.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
|
||||
*
|
||||
*/
|
||||
otError Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return mSender(*this, aMessage, aMessageInfo);
|
||||
}
|
||||
otError Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
MessageQueue mPendingRequests;
|
||||
uint16_t mMessageId;
|
||||
@@ -736,10 +578,10 @@ private:
|
||||
Interceptor mInterceptor;
|
||||
ResponsesQueue mResponsesQueue;
|
||||
|
||||
otCoapRequestHandler mDefaultHandler;
|
||||
void * mDefaultHandlerContext;
|
||||
RequestHandler mDefaultHandler;
|
||||
void * mDefaultHandlerContext;
|
||||
|
||||
Sender mSender;
|
||||
const Sender mSender;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -778,13 +620,9 @@ public:
|
||||
otError Stop(void);
|
||||
|
||||
private:
|
||||
static otError Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return static_cast<Coap &>(aCoapBase).Send(aMessage, aMessageInfo);
|
||||
}
|
||||
otError Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
static otError Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
otError Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
Ip6::UdpSocket mSocket;
|
||||
};
|
||||
|
||||
@@ -152,7 +152,7 @@ void CoapSecure::SetSslAuthMode(bool aVerifyPeerCertificate)
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
|
||||
otError CoapSecure::SendMessage(Message &aMessage, otCoapResponseHandler aHandler, void *aContext)
|
||||
otError CoapSecure::SendMessage(Message &aMessage, ResponseHandler aHandler, void *aContext)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
@@ -166,7 +166,7 @@ exit:
|
||||
|
||||
otError CoapSecure::SendMessage(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
otCoapResponseHandler aHandler,
|
||||
ResponseHandler aHandler,
|
||||
void * aContext)
|
||||
{
|
||||
return CoapBase::SendMessage(aMessage, aMessageInfo, aHandler, aContext);
|
||||
|
||||
@@ -262,7 +262,7 @@ public:
|
||||
* @retval OT_ERROR_INVALID_STATE DTLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
otError SendMessage(Message &aMessage, otCoapResponseHandler aHandler = NULL, void *aContext = NULL);
|
||||
otError SendMessage(Message &aMessage, ResponseHandler aHandler = NULL, void *aContext = NULL);
|
||||
|
||||
/**
|
||||
* This method sends a CoAP message over secure DTLS connection.
|
||||
@@ -283,7 +283,7 @@ public:
|
||||
*/
|
||||
otError SendMessage(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
otCoapResponseHandler aHandler = NULL,
|
||||
ResponseHandler aHandler = NULL,
|
||||
void * aContext = NULL);
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user