[coap] fix application coap retransmissions (#2264)

This commit is contained in:
Abtin Keshavarzian
2017-10-18 22:30:26 -07:00
committed by Jonathan Hui
parent 5c32a2e44e
commit e4d5cbf0c0
7 changed files with 199 additions and 101 deletions
+1 -1
View File
@@ -92,7 +92,7 @@ otInstance::otInstance(void) :
mLinkRaw(*this),
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
#if OPENTHREAD_ENABLE_APPLICATION_COAP
mApplicationCoap(mThreadNetif),
mApplicationCoap(*this),
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP
#if OPENTHREAD_CONFIG_ENABLE_DYNAMIC_LOG_LEVEL
mLogLevel(static_cast<otLogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL)),
+95 -67
View File
@@ -32,6 +32,7 @@
#include <openthread/platform/random.h>
#include "openthread-instance.h"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/logging.hpp"
@@ -47,34 +48,35 @@
namespace ot {
namespace Coap {
Coap::Coap(ThreadNetif &aNetif, Timer::Handler aRetransmissionHandler):
CoapBase::CoapBase(ThreadNetif &aNetif, Timer::Handler aRetransmissionTimerHandler,
Timer::Handler aResponsesQueueTimerHandler):
ThreadNetifLocator(aNetif),
mSocket(aNetif.GetIp6().mUdp),
mRetransmissionTimer(aNetif.GetInstance(), aRetransmissionHandler, this),
mRetransmissionTimer(aNetif.GetInstance(), aRetransmissionTimerHandler, this),
mResources(NULL),
mContext(NULL),
mInterceptor(NULL),
mResponsesQueue(aNetif),
mResponsesQueue(aNetif.GetInstance(), aResponsesQueueTimerHandler, this),
mDefaultHandler(NULL),
mDefaultHandlerContext(NULL)
{
mMessageId = static_cast<uint16_t>(otPlatRandomGet());
}
otError Coap::Start(uint16_t aPort)
otError CoapBase::Start(uint16_t aPort)
{
otError error;
Ip6::SockAddr sockaddr;
sockaddr.mPort = aPort;
SuccessOrExit(error = mSocket.Open(&Coap::HandleUdpReceive, this));
SuccessOrExit(error = mSocket.Open(&CoapBase::HandleUdpReceive, this));
SuccessOrExit(error = mSocket.Bind(sockaddr));
exit:
return error;
}
otError Coap::Stop(void)
otError CoapBase::Stop(void)
{
Message *message = mPendingRequests.GetHead();
Message *messageToRemove;
@@ -95,7 +97,7 @@ otError Coap::Stop(void)
return mSocket.Close();
}
otError Coap::AddResource(Resource &aResource)
otError CoapBase::AddResource(Resource &aResource)
{
otError error = OT_ERROR_NONE;
@@ -111,7 +113,7 @@ exit:
return error;
}
void Coap::RemoveResource(Resource &aResource)
void CoapBase::RemoveResource(Resource &aResource)
{
if (mResources == &aResource)
{
@@ -133,13 +135,13 @@ exit:
aResource.mNext = NULL;
}
void Coap::SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext)
void CoapBase::SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext)
{
mDefaultHandler = aHandler;
mDefaultHandlerContext = aContext;
}
Message *Coap::NewMessage(const Header &aHeader, uint8_t aPriority)
Message *CoapBase::NewMessage(const Header &aHeader, uint8_t aPriority)
{
Message *message = NULL;
@@ -155,8 +157,8 @@ exit:
return message;
}
otError Coap::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
otCoapResponseHandler aHandler, void *aContext)
otError CoapBase::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
otCoapResponseHandler aHandler, void *aContext)
{
otError error;
Header header;
@@ -210,13 +212,13 @@ exit:
return error;
}
otError Coap::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
otError CoapBase::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return mSocket.SendTo(aMessage, aMessageInfo);
}
otError Coap::SendEmptyMessage(Header::Type aType, const Header &aRequestHeader,
const Ip6::MessageInfo &aMessageInfo)
otError CoapBase::SendEmptyMessage(Header::Type aType, const Header &aRequestHeader,
const Ip6::MessageInfo &aMessageInfo)
{
otError error = OT_ERROR_NONE;
Header responseHeader;
@@ -241,8 +243,8 @@ exit:
return error;
}
otError Coap::SendHeaderResponse(Header::Code aCode, const Header &aRequestHeader,
const Ip6::MessageInfo &aMessageInfo)
otError CoapBase::SendHeaderResponse(Header::Code aCode, const Header &aRequestHeader,
const Ip6::MessageInfo &aMessageInfo)
{
otError error = OT_ERROR_NONE;
Header responseHeader;
@@ -286,23 +288,7 @@ exit:
return error;
}
Coap &Coap::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
Coap &coap = *static_cast<Coap *>(aContext.GetContext());
#else
Coap &coap = otGetThreadNetif().GetCoap();
OT_UNUSED_VARIABLE(aContext);
#endif
return coap;
}
void Coap::HandleRetransmissionTimer(Timer &aTimer)
{
GetOwner(aTimer).HandleRetransmissionTimer();
}
void Coap::HandleRetransmissionTimer(void)
void CoapBase::HandleRetransmissionTimer(void)
{
uint32_t now = TimerMilli::GetNow();
uint32_t nextDelta = 0xffffffff;
@@ -364,9 +350,9 @@ void Coap::HandleRetransmissionTimer(void)
}
}
void Coap::FinalizeCoapTransaction(Message &aRequest, const CoapMetadata &aCoapMetadata,
Header *aResponseHeader, Message *aResponse,
const Ip6::MessageInfo *aMessageInfo, otError aResult)
void CoapBase::FinalizeCoapTransaction(Message &aRequest, const CoapMetadata &aCoapMetadata,
Header *aResponseHeader, Message *aResponse,
const Ip6::MessageInfo *aMessageInfo, otError aResult)
{
DequeueMessage(aRequest);
@@ -377,7 +363,7 @@ void Coap::FinalizeCoapTransaction(Message &aRequest, const CoapMetadata &aCoapM
}
}
otError Coap::AbortTransaction(otCoapResponseHandler aHandler, void *aContext)
otError CoapBase::AbortTransaction(otCoapResponseHandler aHandler, void *aContext)
{
otError error = OT_ERROR_NOT_FOUND;
Message *message;
@@ -398,8 +384,8 @@ otError Coap::AbortTransaction(otCoapResponseHandler aHandler, void *aContext)
}
Message *Coap::CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength,
const CoapMetadata &aCoapMetadata)
Message *CoapBase::CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength,
const CoapMetadata &aCoapMetadata)
{
otError error = OT_ERROR_NONE;
Message *messageCopy = NULL;
@@ -441,7 +427,7 @@ exit:
return messageCopy;
}
void Coap::DequeueMessage(Message &aMessage)
void CoapBase::DequeueMessage(Message &aMessage)
{
mPendingRequests.Dequeue(aMessage);
@@ -458,7 +444,7 @@ void Coap::DequeueMessage(Message &aMessage)
// the timer would just shoot earlier and then it'd be setup again.
}
otError Coap::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
otError CoapBase::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
otError error;
Message *messageCopy = NULL;
@@ -480,8 +466,8 @@ exit:
return error;
}
Message *Coap::FindRelatedRequest(const Header &aResponseHeader, const Ip6::MessageInfo &aMessageInfo,
Header &aRequestHeader, CoapMetadata &aCoapMetadata)
Message *CoapBase::FindRelatedRequest(const Header &aResponseHeader, const Ip6::MessageInfo &aMessageInfo,
Header &aRequestHeader, CoapMetadata &aCoapMetadata)
{
Message *message = mPendingRequests.GetHead();
@@ -527,13 +513,13 @@ exit:
return message;
}
void Coap::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
void CoapBase::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
static_cast<Coap *>(aContext)->Receive(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
void Coap::Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void CoapBase::Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
otError error;
Header header;
@@ -557,8 +543,8 @@ exit:
}
}
void Coap::ProcessReceivedResponse(Header &aResponseHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
void CoapBase::ProcessReceivedResponse(Header &aResponseHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
Header requestHeader;
CoapMetadata coapMetadata;
@@ -636,7 +622,7 @@ exit:
}
}
void Coap::ProcessReceivedRequest(Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void CoapBase::ProcessReceivedRequest(Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
char uriPath[Resource::kMaxReceivedUriPath] = "";
char *curUriPath = uriPath;
@@ -758,8 +744,9 @@ CoapMetadata::CoapMetadata(bool aConfirmable, const Ip6::MessageInfo &aMessageIn
mConfirmable = aConfirmable;
}
ResponsesQueue::ResponsesQueue(ThreadNetif &aNetif):
mTimer(aNetif.GetInstance(), &ResponsesQueue::HandleTimer, this)
ResponsesQueue::ResponsesQueue(otInstance &aInstance, Timer::Handler aHandler, void *aContext):
mQueue(),
mTimer(aInstance, aHandler, aContext)
{
}
@@ -896,22 +883,6 @@ void ResponsesQueue::DequeueAllResponses(void)
}
}
ResponsesQueue &ResponsesQueue::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
ResponsesQueue &queue = *static_cast<ResponsesQueue *>(aContext.GetContext());
#else
ResponsesQueue &queue = otGetThreadNetif().GetCoap().mResponsesQueue;
OT_UNUSED_VARIABLE(aContext);
#endif
return queue;
}
void ResponsesQueue::HandleTimer(Timer &aTimer)
{
GetOwner(aTimer).HandleTimer();
}
void ResponsesQueue::HandleTimer(void)
{
Message *message;
@@ -940,5 +911,62 @@ uint32_t EnqueuedResponseHeader::GetRemainingTime(void) const
return remainingTime >= 0 ? static_cast<uint32_t>(remainingTime) : 0;
}
Coap::Coap(ThreadNetif &aNetif):
CoapBase(aNetif, &Coap::HandleRetransmissionTimer, &Coap::HandleResponsesQueueTimer)
{
}
Coap &Coap::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
Coap &coap = *static_cast<Coap *>(aContext.GetContext());
#else
Coap &coap = otGetThreadNetif().GetCoap();
OT_UNUSED_VARIABLE(aContext);
#endif
return coap;
}
void Coap::HandleRetransmissionTimer(Timer &aTimer)
{
GetOwner(aTimer).CoapBase::HandleRetransmissionTimer();
}
void Coap::HandleResponsesQueueTimer(Timer &aTimer)
{
GetOwner(aTimer).CoapBase::HandleResponsesQueueTimer();
}
#if OPENTHREAD_ENABLE_APPLICATION_COAP
ApplicationCoap::ApplicationCoap(otInstance &aInstance):
CoapBase(aInstance.mThreadNetif, &ApplicationCoap::HandleRetransmissionTimer,
&ApplicationCoap::HandleResponsesQueueTimer)
{
}
ApplicationCoap &ApplicationCoap::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
ApplicationCoap &coap = *static_cast<ApplicationCoap *>(aContext.GetContext());
#else
ApplicationCoap &coap = otGetInstance()->mApplicationCoap;
OT_UNUSED_VARIABLE(aContext);
#endif
return coap;
}
void ApplicationCoap::HandleRetransmissionTimer(Timer &aTimer)
{
GetOwner(aTimer).CoapBase::HandleRetransmissionTimer();
}
void ApplicationCoap::HandleResponsesQueueTimer(Timer &aTimer)
{
GetOwner(aTimer).CoapBase::HandleResponsesQueueTimer();
}
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP
} // namespace Coap
} // namespace ot
+87 -23
View File
@@ -93,7 +93,7 @@ enum
OT_TOOL_PACKED_BEGIN
class CoapMetadata
{
friend class Coap;
friend class CoapBase;
public:
@@ -199,7 +199,7 @@ private:
*/
class Resource : public otCoapResource
{
friend class Coap;
friend class CoapBase;
public:
enum
@@ -332,10 +332,12 @@ public:
/**
* Default class constructor.
*
* @param[in] aNetif A reference to the network interface that CoAP server should be assigned to.
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aHandler A timer handler provided by owner of `RespponseQueue`.
* @param[in] aContext A pointer to arbitrary context information (used along with timer handler).
*
*/
ResponsesQueue(ThreadNetif &aNetif);
ResponsesQueue(otInstance &aInstance, Timer::Handler aHandler, void *aContext);
/**
* Add given response to the cache.
@@ -403,6 +405,15 @@ public:
*/
const MessageQueue &GetResponses(void) const { return mQueue; }
/**
* Callback handler for timer.
*
* This method must be invoked by the owner of `ResponsesQueue` instance when the timer expires from the `aHandler`
* callback function provided in the constructor.
*
*/
void HandleTimer(void);
private:
enum
{
@@ -410,19 +421,16 @@ private:
};
void DequeueResponse(Message &aMessage) { mQueue.Dequeue(aMessage); aMessage.Free(); }
static ResponsesQueue &GetOwner(const Context &aContext);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
MessageQueue mQueue;
TimerMilli mTimer;
};
/**
* This class implements the CoAP client and server.
* This class implements the common base for CoAP client and server.
*
*/
class Coap: public ThreadNetifLocator
class CoapBase: public ThreadNetifLocator
{
friend class ResponsesQueue;
@@ -442,15 +450,6 @@ public:
*/
typedef otError(* Interceptor)(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
/**
* This constructor initializes the object.
*
* @param[in] aNetif A reference to the Netif object.
* @param[in] aRetransmissionHandler An optional pointer to the retransmission handler, used by CoapSecure.
*
*/
Coap(ThreadNetif &aNetif, Timer::Handler aRetransmissionHandler = &Coap::HandleRetransmissionTimer);
/**
* This method starts the CoAP service.
*
@@ -649,14 +648,37 @@ public:
const MessageQueue &GetCachedResponses(void) const { return mResponsesQueue.GetResponses(); }
protected:
/**
* This constructor initializes the object.
*
* @param[in] aNetif A reference to the Netif object.
* @param[in] aRetransmissionTimerHandler A timer handler provided by sub-class for `mRetranmissionTimer`.
* @param[in] aResponsesQueueTimerHandler A timer handler provided by sub-class for `mReponsesQueue` timer.
*
*/
CoapBase(ThreadNetif &aNetif, Timer::Handler aRetransmissionTimerHandler,
Timer::Handler aResponsesQueueTimerHandler);
/**
* Retransmission timer handler.
*
* This method must be invoked by sub-class when the timer expires from the `aRetransmissionTimerHandler`
* callback function provided in the constructor.
*
*/
void HandleRetransmissionTimer(void);
/**
* This method send a message.
* `ResponsesQueue` timer handler.
*
* This method must be invoked by sub-class when the timer expires from the `aResponsesQueueTimerHandler`
* callback function provided in the constructor.
*
*/
void HandleResponsesQueueTimer(void) { mResponsesQueue.HandleTimer(); }
/**
* 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.
@@ -698,10 +720,6 @@ private:
otError SendEmptyMessage(Header::Type aType, const Header &aRequestHeader,
const Ip6::MessageInfo &aMessageInfo);
static void HandleRetransmissionTimer(Timer &aTimer);
static Coap &GetOwner(const Context &aContext);
MessageQueue mPendingRequests;
uint16_t mMessageId;
TimerMilli mRetransmissionTimer;
@@ -716,6 +734,52 @@ private:
void *mDefaultHandlerContext;
};
/**
* This class implements the CoAP client and server.
*
*/
class Coap: public CoapBase
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aNetif A reference to the Netif object.
*
*/
Coap(ThreadNetif &aNetif);
private:
static Coap &GetOwner(const Context &aContext);
static void HandleRetransmissionTimer(Timer &aTimer);
static void HandleResponsesQueueTimer(Timer &aTimer);
};
#if OPENTHREAD_ENABLE_APPLICATION_COAP
/**
* This class implements the application CoAP client and server.
*
*/
class ApplicationCoap: public CoapBase
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aNetif A reference to the otInstance
*
*/
ApplicationCoap(otInstance &aInstance);
private:
static ApplicationCoap &GetOwner(const Context &aContext);
static void HandleRetransmissionTimer(Timer &aTimer);
static void HandleResponsesQueueTimer(Timer &aTimer);
};
#endif
} // namespace Coap
} // namespace ot
+12 -7
View File
@@ -46,7 +46,7 @@ namespace ot {
namespace Coap {
CoapSecure::CoapSecure(ThreadNetif &aNetif):
Coap(aNetif, &CoapSecure::HandleRetransmissionTimer),
CoapBase(aNetif, &CoapSecure::HandleRetransmissionTimer, &CoapSecure::HandleResponsesQueueTimer),
mConnectedCallback(NULL),
mConnectedContext(NULL),
mTransportCallback(NULL),
@@ -66,7 +66,7 @@ otError CoapSecure::Start(uint16_t aPort, TransportCallback aCallback, void *aCo
// to transmit/receive messages, so do not open it in that case.
if (mTransportCallback == NULL)
{
error = Coap::Start(aPort);
error = CoapBase::Start(aPort);
}
return error;
@@ -88,7 +88,7 @@ otError CoapSecure::Stop(void)
mTransportCallback = NULL;
mTransportContext = NULL;
return Coap::Stop();
return CoapBase::Stop();
}
otError CoapSecure::Connect(const Ip6::MessageInfo &aMessageInfo, ConnectedCallback aCallback, void *aContext)
@@ -134,7 +134,7 @@ otError CoapSecure::SendMessage(Message &aMessage, otCoapResponseHandler aHandle
VerifyOrExit(IsConnected(), error = OT_ERROR_INVALID_STATE);
error = Coap::SendMessage(aMessage, mPeerAddress, aHandler, aContext);
error = CoapBase::SendMessage(aMessage, mPeerAddress, aHandler, aContext);
exit:
otLogFuncExitErr(error);
@@ -144,7 +144,7 @@ exit:
otError CoapSecure::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
otCoapResponseHandler aHandler, void *aContext)
{
return Coap::SendMessage(aMessage, aMessageInfo, aHandler, aContext);
return CoapBase::SendMessage(aMessage, aMessageInfo, aHandler, aContext);
}
otError CoapSecure::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
@@ -222,7 +222,7 @@ void CoapSecure::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength)
VerifyOrExit((message = GetInstance().mMessagePool.New(Message::kTypeIp6, 0)) != NULL);
SuccessOrExit(message->Append(aBuf, aLength));
Coap::Receive(*message, mPeerAddress);
CoapBase::Receive(*message, mPeerAddress);
exit:
@@ -322,7 +322,12 @@ CoapSecure &CoapSecure::GetOwner(const Context &aContext)
void CoapSecure::HandleRetransmissionTimer(Timer &aTimer)
{
GetOwner(aTimer).Coap::HandleRetransmissionTimer();
GetOwner(aTimer).CoapBase::HandleRetransmissionTimer();
}
void CoapSecure::HandleResponsesQueueTimer(Timer &aTimer)
{
GetOwner(aTimer).CoapBase::HandleResponsesQueueTimer();
}
} // namespace Coap
+2 -1
View File
@@ -45,7 +45,7 @@ class ThreadNetif;
namespace Coap {
class CoapSecure: public Coap
class CoapSecure: public CoapBase
{
public:
/**
@@ -217,6 +217,7 @@ private:
void HandleUdpTransmit(void);
static void HandleRetransmissionTimer(Timer &aTimer);
static void HandleResponsesQueueTimer(Timer &aTimer);
static CoapSecure &GetOwner(const Context &aContext);
+1 -1
View File
@@ -52,7 +52,7 @@ enum
* This function create Message for MeshCoP
*
*/
inline Message *NewMeshCoPMessage(Coap::Coap &aCoap, const Coap::Header &aHeader)
inline Message *NewMeshCoPMessage(Coap::CoapBase &aCoap, const Coap::Header &aHeader)
{
return aCoap.NewMessage(aHeader, kMeshCoPMessagePriority);
}
+1 -1
View File
@@ -95,7 +95,7 @@ typedef struct otInstance
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
#if OPENTHREAD_ENABLE_APPLICATION_COAP
ot::Coap::Coap mApplicationCoap;
ot::Coap::ApplicationCoap mApplicationCoap;
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP
#if OPENTHREAD_CONFIG_ENABLE_DYNAMIC_LOG_LEVEL