diff --git a/src/core/coap/coap_base.cpp b/src/core/coap/coap_base.cpp index 7e76f3cb2..aea4e6d9e 100644 --- a/src/core/coap/coap_base.cpp +++ b/src/core/coap/coap_base.cpp @@ -86,5 +86,31 @@ void CoapBase::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMes *static_cast(aMessageInfo)); } +ThreadError CoapBase::SendEmptyMessage(Header::Type aType, const Header &aRequestHeader, + const Ip6::MessageInfo &aMessageInfo) +{ + ThreadError error = kThreadError_None; + Coap::Header responseHeader; + Message *message = NULL; + + VerifyOrExit(aRequestHeader.GetType() == kCoapTypeConfirmable, error = kThreadError_InvalidArgs); + + responseHeader.Init(aType, kCoapCodeEmpty); + responseHeader.SetMessageId(aRequestHeader.GetMessageId()); + + VerifyOrExit((message = NewMessage(responseHeader)) != NULL, error = kThreadError_NoBufs); + + SuccessOrExit(error = mSender(this, *message, aMessageInfo)); + +exit: + + if (error != kThreadError_None && message != NULL) + { + message->Free(); + } + + return error; +} + } // namespace Coap } // namespace Thread diff --git a/src/core/coap/coap_base.hpp b/src/core/coap/coap_base.hpp index a91cce02a..85cf813aa 100644 --- a/src/core/coap/coap_base.hpp +++ b/src/core/coap/coap_base.hpp @@ -152,6 +152,36 @@ public: */ uint16_t GetPort(void) { return mSocket.GetSockName().mPort; }; + /** + * This method sends a CoAP reset message. + * + * @param[in] aRequestHeader A reference to the CoAP Header that was used in CoAP request. + * @param[in] aMessageInfo The message info corresponding to the CoAP request. + * + * @retval kThreadError_None Successfully enqueued the CoAP response message. + * @retval kThreadError_NoBufs Insufficient buffers available to send the CoAP response. + * @retval kThreadError_InvalidArgs The @p aRequestHeader header is not of confirmable type. + * + */ + ThreadError SendReset(Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo) { + return SendEmptyMessage(kCoapTypeReset, aRequestHeader, aMessageInfo); + }; + + /** + * This method sends a CoAP ACK empty message which is used in Separate Response for confirmable requests. + * + * @param[in] aRequestHeader A reference to the CoAP Header that was used in CoAP request. + * @param[in] aMessageInfo The message info corresponding to the CoAP request. + * + * @retval kThreadError_None Successfully enqueued the CoAP response message. + * @retval kThreadError_NoBufs Insufficient buffers available to send the CoAP response. + * @retval kThreadError_InvalidArgs The @p aRequestHeader header is not of confirmable type. + * + */ + ThreadError SendAck(Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo) { + return SendEmptyMessage(kCoapTypeAcknowledgment, aRequestHeader, aMessageInfo); + }; + protected: ThreadError Start(const Ip6::SockAddr &aSockAddr); ThreadError Stop(void); @@ -161,6 +191,22 @@ protected: ReceiverFunction mReceiver; private: + + /** + * This method sends a CoAP empty message, i.e. a header-only message with code equals kCoapCodeEmpty. + * + * @param[in] aType The message type + * @param[in] aRequestHeader A reference to the CoAP Header that was used in CoAP request. + * @param[in] aMessageInfo The message info corresponding to the CoAP request. + * + * @retval kThreadError_None Successfully enqueued the CoAP response message. + * @retval kThreadError_NoBufs Insufficient buffers available to send the CoAP response. + * @retval kThreadError_InvalidArgs The @p aRequestHeader header is not of confirmable type. + * + */ + ThreadError SendEmptyMessage(Header::Type aType, const Header &aRequestHeader, + const Ip6::MessageInfo &aMessageInfo); + static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); }; diff --git a/src/core/coap/coap_client.cpp b/src/core/coap/coap_client.cpp index 6b45567cb..12be70359 100644 --- a/src/core/coap/coap_client.cpp +++ b/src/core/coap/coap_client.cpp @@ -229,31 +229,6 @@ exit: return error; } -void Client::SendEmptyMessage(const Ip6::Address &aAddress, uint16_t aPort, uint16_t aMessageId, Header::Type aType) -{ - Header header; - Ip6::MessageInfo messageInfo; - Message *message; - ThreadError error = kThreadError_None; - - header.Init(aType, kCoapCodeEmpty); - header.SetMessageId(aMessageId); - - VerifyOrExit((message = NewMessage(header)) != NULL); - - messageInfo.SetPeerAddr(aAddress); - messageInfo.SetPeerPort(aPort); - - SuccessOrExit(error = mSender(this, *message, messageInfo)); - -exit: - - if (error != kThreadError_None && message != NULL) - { - message->Free(); - } -} - void Client::HandleRetransmissionTimer(void *aContext) { static_cast(aContext)->HandleRetransmissionTimer(); @@ -435,13 +410,14 @@ void Client::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &a break; case kCoapTypeConfirmable: - case kCoapTypeNonConfirmable: - if (responseHeader.IsConfirmable()) - { - // Send empty ACK if it is a CON message. - SendEmptyAck(aMessageInfo.GetPeerAddr(), aMessageInfo.GetPeerPort(), responseHeader.GetMessageId()); - } + // Send empty ACK if it is a CON message. + SendAck(responseHeader, aMessageInfo); + // fall through + ; + + case kCoapTypeNonConfirmable: + // Separate response. FinalizeCoapTransaction(*message, requestMetadata, &responseHeader, &aMessage, &aMessageInfo, kThreadError_None); break; @@ -454,7 +430,7 @@ exit: if (responseHeader.IsConfirmable() || responseHeader.IsNonConfirmable()) { // Successfully parsed a header but no matching request was found - reject the message by sending reset. - SendReset(aMessageInfo.GetPeerAddr(), aMessageInfo.GetPeerPort(), responseHeader.GetMessageId()); + SendReset(responseHeader, aMessageInfo); } } } diff --git a/src/core/coap/coap_client.hpp b/src/core/coap/coap_client.hpp index 41455b427..eff9ee242 100644 --- a/src/core/coap/coap_client.hpp +++ b/src/core/coap/coap_client.hpp @@ -241,14 +241,6 @@ private: Message *aResponse, const Ip6::MessageInfo *aMessageInfo, ThreadError aResult); ThreadError SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - void SendEmptyMessage(const Ip6::Address &aAddress, uint16_t aPort, uint16_t aMessageId, Header::Type aType); - void SendReset(const Ip6::Address &aAddress, uint16_t aPort, uint16_t aMessageId) { - SendEmptyMessage(aAddress, aPort, aMessageId, kCoapTypeReset); - }; - void SendEmptyAck(const Ip6::Address &aAddress, uint16_t aPort, uint16_t aMessageId) { - SendEmptyMessage(aAddress, aPort, aMessageId, kCoapTypeAcknowledgment); - }; - static void HandleRetransmissionTimer(void *aContext); void HandleRetransmissionTimer(void);