mirror of
https://github.com/espressif/openthread.git
synced 2026-10-05 07:17:39 +00:00
Separate response support (#1571)
* Move empty message to coap_base. Both client and server needs this feature to handle separate response. * remove unnecessary check * make CoapBase::SendEmptyMessage() private. * add comment to indicate intentional fall through
This commit is contained in:
@@ -86,5 +86,31 @@ void CoapBase::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMes
|
||||
*static_cast<const Ip6::MessageInfo *>(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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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<Client *>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user