[coap] make transmission parameters dynamically configurable (#4481)

This commit is contained in:
Diego Ismirlian
2020-02-21 16:07:48 -08:00
committed by GitHub
parent 167d616bc2
commit 67f33091f0
9 changed files with 401 additions and 91 deletions
+87 -6
View File
@@ -361,6 +361,40 @@ typedef struct otCoapResource
struct otCoapResource *mNext; ///< The next CoAP resource in the list
} otCoapResource;
/**
* This structure represents the CoAP transmission parameters.
*
*/
typedef struct otCoapTxParameters
{
/**
* Minimum spacing before first retransmission when ACK is not received, in milliseconds (RFC7252 default value is
* 2000ms).
*
*/
uint32_t mAckTimeout;
/**
* Numerator of ACK_RANDOM_FACTOR used to calculate maximum spacing before first retransmission when ACK is not
* received (RFC7252 default value of ACK_RANDOM_FACTOR is 1.5; must not be decreased below 1).
*
*/
uint8_t mAckRandomFactorNumerator;
/**
* Denominator of ACK_RANDOM_FACTOR used to calculate maximum spacing before first retransmission when ACK is not
* received (RFC7252 default value of ACK_RANDOM_FACTOR is 1.5; must not be decreased below 1).
*
*/
uint8_t mAckRandomFactorDenominator;
/**
* Maximum number of retransmissions for CoAP Confirmable messages (RFC7252 default value is 4).
*
*/
uint8_t mMaxRetransmit;
} otCoapTxParameters;
/**
* This function initializes the CoAP header.
*
@@ -693,6 +727,30 @@ otError otCoapOptionIteratorGetOptionValue(otCoapOptionIterator *aIterator, void
*/
otMessage *otCoapNewMessage(otInstance *aInstance, const otMessageSettings *aSettings);
/**
* This function sends a CoAP request with custom transmission parameters.
*
* If a response for a request is expected, respective function and context information should be provided.
* If no response is expected, these arguments should be NULL pointers.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aMessage A pointer to the message to send.
* @param[in] aMessageInfo A pointer to the message info associated with @p aMessage.
* @param[in] aHandler A function pointer that shall be called on response reception or timeout.
* @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
* @param[in] aTxParameters A pointer to transmission parameters for this request. Use NULL for defaults.
*
* @retval OT_ERROR_NONE Successfully sent CoAP message.
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
*
*/
otError otCoapSendRequestWithParameters(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
otCoapResponseHandler aHandler,
void * aContext,
const otCoapTxParameters *aTxParameters);
/**
* This function sends a CoAP request.
*
@@ -709,11 +767,14 @@ otMessage *otCoapNewMessage(otInstance *aInstance, const otMessageSettings *aSet
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
*
*/
otError otCoapSendRequest(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
otCoapResponseHandler aHandler,
void * aContext);
static inline otError otCoapSendRequest(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
otCoapResponseHandler aHandler,
void * aContext)
{
return otCoapSendRequestWithParameters(aInstance, aMessage, aMessageInfo, aHandler, aContext, NULL);
}
/**
* This function starts the CoAP server.
@@ -767,6 +828,23 @@ void otCoapRemoveResource(otInstance *aInstance, otCoapResource *aResource);
*/
void otCoapSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandler, void *aContext);
/**
* This function sends a CoAP response from the server with custom transmission parameters.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aMessage A pointer to the CoAP response to send.
* @param[in] aMessageInfo A pointer to the message info associated with @p aMessage.
* @param[in] aTxParameters A pointer to transmission parameters for this response. Use NULL for defaults.
*
* @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
*
*/
otError otCoapSendResponseWithParameters(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
const otCoapTxParameters *aTxParameters);
/**
* This function sends a CoAP response from the server.
*
@@ -778,7 +856,10 @@ void otCoapSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandle
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
*
*/
otError otCoapSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo);
static inline otError otCoapSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
return otCoapSendResponseWithParameters(aInstance, aMessage, aMessageInfo, NULL);
}
/**
* @}
+39
View File
@@ -57,6 +57,7 @@ coap response sent
* [help](#help)
* [delete](#delete-address-uri-path-type-payload)
* [get](#get-address-uri-path-type)
* [parameters](#parameters)
* [post](#post-address-uri-path-type-payload)
* [put](#put-address-uri-path-type-payload)
* [resource](#resource-uri-path)
@@ -72,6 +73,7 @@ coap response sent
help
delete
get
parameters
post
put
resource
@@ -105,6 +107,43 @@ Done
Done
```
### parameters \<type\> \["default"|<ack\_timeout\> <ack\_random\_factor\_numerator\> <ack\_random\_factor\_denominator\> <max\_retransmit\>\]
Sets transmission parameters for the following interactions.
* type: "request" for CoAP requests and "response" for CoAP responses.
If no more parameters are given, the command prints the current configuration:
```bash
> coap parameters request
Transmission parameters for request:
ACK_TIMEOUT=1000 ms, ACK_RANDOM_FACTOR=255/254, MAX_RETRANSMIT=2
Done
```
If `"default"` is given, the command sets the default configuration for the transmission parameters.
```bash
> coap parameters request default
Transmission parameters for request:
default
Done
```
Also, you can specify the transmission parameters in the command line:
* ack\_timeout (0~UINT32\_MAX): RFC7252 ACK\_TIMEOUT, in milliseconds.
* ack\_random\_factor\_numerator, ack\_random\_factor\_denominator (0~255):
RFC7252 ACK\_RANDOM\_FACTOR=ack\_random\_factor\_numerator/ack\_random\_factor\_denominator.
* max\_retransmit (0~255): RFC7252 MAX_RETRANSMIT.
```bash
> coap parameters request 1000 255 254 2
Transmission parameters for request:
ACK_TIMEOUT=1000 ms, ACK_RANDOM_FACTOR=255/254, MAX_RETRANSMIT=2
Done
```
### post \<address\> \<uri-path\> \[type\] \[payload\]
* address: IPv6 address of the CoAP server.
+87 -6
View File
@@ -45,13 +45,17 @@ namespace ot {
namespace Cli {
const struct Coap::Command Coap::sCommands[] = {
{"help", &Coap::ProcessHelp}, {"delete", &Coap::ProcessRequest}, {"get", &Coap::ProcessRequest},
{"post", &Coap::ProcessRequest}, {"put", &Coap::ProcessRequest}, {"resource", &Coap::ProcessResource},
{"start", &Coap::ProcessStart}, {"stop", &Coap::ProcessStop},
{"help", &Coap::ProcessHelp}, {"delete", &Coap::ProcessRequest},
{"get", &Coap::ProcessRequest}, {"parameters", &Coap::ProcessParameters},
{"post", &Coap::ProcessRequest}, {"put", &Coap::ProcessRequest},
{"resource", &Coap::ProcessResource}, {"start", &Coap::ProcessStart},
{"stop", &Coap::ProcessStop},
};
Coap::Coap(Interpreter &aInterpreter)
: mInterpreter(aInterpreter)
, mUseDefaultRequestTxParameters(true)
, mUseDefaultResponseTxParameters(true)
{
memset(&mResource, 0, sizeof(mResource));
}
@@ -137,6 +141,80 @@ otError Coap::ProcessStop(int argc, char *argv[])
return otCoapStop(mInterpreter.mInstance);
}
otError Coap::ProcessParameters(int argc, char *argv[])
{
otError error = OT_ERROR_NONE;
VerifyOrExit(argc > 0, error = OT_ERROR_INVALID_ARGS);
bool * defaultTxParameters;
otCoapTxParameters *txParameters;
if (strcmp(argv[1], "request") == 0)
{
txParameters = &mRequestTxParameters;
defaultTxParameters = &mUseDefaultRequestTxParameters;
}
else if (strcmp(argv[1], "response") == 0)
{
txParameters = &mResponseTxParameters;
defaultTxParameters = &mUseDefaultResponseTxParameters;
}
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
if (argc > 2)
{
if (strcmp(argv[2], "default") == 0)
{
*defaultTxParameters = true;
}
else
{
unsigned long value;
VerifyOrExit(argc >= 6, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = mInterpreter.ParseUnsignedLong(argv[2], value));
txParameters->mAckTimeout = static_cast<uint32_t>(value);
SuccessOrExit(error = mInterpreter.ParseUnsignedLong(argv[3], value));
VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS);
txParameters->mAckRandomFactorNumerator = static_cast<uint8_t>(value);
SuccessOrExit(error = mInterpreter.ParseUnsignedLong(argv[4], value));
VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS);
txParameters->mAckRandomFactorDenominator = static_cast<uint8_t>(value);
SuccessOrExit(error = mInterpreter.ParseUnsignedLong(argv[5], value));
VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS);
txParameters->mMaxRetransmit = static_cast<uint8_t>(value);
VerifyOrExit(txParameters->mAckRandomFactorNumerator > txParameters->mAckRandomFactorDenominator,
error = OT_ERROR_INVALID_ARGS);
*defaultTxParameters = false;
}
}
mInterpreter.mServer->OutputFormat("Transmission parameters for %s:\r\n", argv[1]);
if (*defaultTxParameters)
{
mInterpreter.mServer->OutputFormat("default\r\n");
}
else
{
mInterpreter.mServer->OutputFormat("ACK_TIMEOUT=%u ms, ACK_RANDOM_FACTOR=%u/%u, MAX_RETRANSMIT=%u\r\n",
txParameters->mAckTimeout, txParameters->mAckRandomFactorNumerator,
txParameters->mAckRandomFactorDenominator, txParameters->mMaxRetransmit);
}
exit:
return error;
}
otError Coap::ProcessRequest(int argc, char *argv[])
{
otError error = OT_ERROR_NONE;
@@ -233,11 +311,13 @@ otError Coap::ProcessRequest(int argc, char *argv[])
if ((coapType == OT_COAP_TYPE_CONFIRMABLE) || (coapCode == OT_COAP_CODE_GET))
{
error = otCoapSendRequest(mInterpreter.mInstance, message, &messageInfo, &Coap::HandleResponse, this);
error = otCoapSendRequestWithParameters(mInterpreter.mInstance, message, &messageInfo, &Coap::HandleResponse,
this, GetRequestTxParameters());
}
else
{
error = otCoapSendRequest(mInterpreter.mInstance, message, &messageInfo, NULL, NULL);
error = otCoapSendRequestWithParameters(mInterpreter.mInstance, message, &messageInfo, NULL, NULL,
GetResponseTxParameters());
}
exit:
@@ -339,7 +419,8 @@ void Coap::HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo)
SuccessOrExit(error = otMessageAppend(responseMessage, &responseContent, sizeof(responseContent)));
}
SuccessOrExit(error = otCoapSendResponse(mInterpreter.mInstance, responseMessage, aMessageInfo));
SuccessOrExit(error = otCoapSendResponseWithParameters(mInterpreter.mInstance, responseMessage, aMessageInfo,
GetResponseTxParameters()));
}
exit:
+17
View File
@@ -85,6 +85,7 @@ private:
void PrintPayload(otMessage *aMessage) const;
otError ProcessHelp(int argc, char *argv[]);
otError ProcessParameters(int argc, char *argv[]);
otError ProcessRequest(int argc, char *argv[]);
otError ProcessResource(int argc, char *argv[]);
otError ProcessStart(int argc, char *argv[]);
@@ -96,9 +97,25 @@ private:
static void HandleResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
void HandleResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
const otCoapTxParameters *GetRequestTxParameters(void) const
{
return mUseDefaultRequestTxParameters ? NULL : &mRequestTxParameters;
}
const otCoapTxParameters *GetResponseTxParameters(void) const
{
return mUseDefaultResponseTxParameters ? NULL : &mResponseTxParameters;
}
static const Command sCommands[];
Interpreter & mInterpreter;
bool mUseDefaultRequestTxParameters;
bool mUseDefaultResponseTxParameters;
otCoapTxParameters mRequestTxParameters;
otCoapTxParameters mResponseTxParameters;
otCoapResource mResource;
char mUriPath[kMaxUriLength];
};
+14 -9
View File
@@ -195,17 +195,18 @@ otError otCoapOptionIteratorGetOptionValue(otCoapOptionIterator *aIterator, void
return static_cast<Coap::OptionIterator *>(aIterator)->GetOptionValue(aValue);
}
otError otCoapSendRequest(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
otCoapResponseHandler aHandler,
void * aContext)
otError otCoapSendRequestWithParameters(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
otCoapResponseHandler aHandler,
void * aContext,
const otCoapTxParameters *aTxParameters)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo), aHandler,
aContext);
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
Coap::CoapTxParameters::From(aTxParameters), aHandler, aContext);
}
otError otCoapStart(otInstance *aInstance, uint16_t aPort)
@@ -243,12 +244,16 @@ void otCoapSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandle
instance.GetApplicationCoap().SetDefaultHandler(aHandler, aContext);
}
otError otCoapSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo)
otError otCoapSendResponseWithParameters(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
const otCoapTxParameters *aTxParameters)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
Coap::CoapTxParameters::From(aTxParameters), NULL, NULL);
}
#endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
+53 -23
View File
@@ -109,18 +109,18 @@ exit:
otError CoapBase::SendMessage(Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const CoapTxParameters &aTxParameters,
otCoapResponseHandler aHandler,
void * aContext)
{
otError error;
CoapMetadata coapMetadata;
Message * storedCopy = NULL;
uint16_t copyLength = 0;
otError error;
Message *storedCopy = NULL;
uint16_t copyLength = 0;
switch (aMessage.GetType())
{
case OT_COAP_TYPE_ACKNOWLEDGMENT:
mResponsesQueue.EnqueueResponse(aMessage, aMessageInfo);
mResponsesQueue.EnqueueResponse(aMessage, aMessageInfo, aTxParameters);
break;
case OT_COAP_TYPE_RESET:
assert(aMessage.GetCode() == OT_COAP_CODE_EMPTY);
@@ -145,7 +145,8 @@ otError CoapBase::SendMessage(Message & aMessage,
if (copyLength > 0)
{
coapMetadata = CoapMetadata(aMessage.IsConfirmable(), aMessageInfo, aHandler, aContext);
CoapMetadata coapMetadata =
CoapMetadata(aMessage.IsConfirmable(), aMessageInfo, aHandler, aContext, aTxParameters);
VerifyOrExit((storedCopy = CopyAndEnqueueMessage(aMessage, copyLength, coapMetadata)) != NULL,
error = OT_ERROR_NO_BUFS);
}
@@ -247,7 +248,7 @@ void CoapBase::HandleRetransmissionTimer(void)
if (now >= coapMetadata.mNextTimerShot)
{
if (!coapMetadata.mConfirmable || (coapMetadata.mRetransmissionCount >= kMaxRetransmit))
if (!coapMetadata.mConfirmable || (coapMetadata.mRetransmissionsRemaining == 0))
{
// No expected response or acknowledgment.
FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_RESPONSE_TIMEOUT);
@@ -255,7 +256,7 @@ void CoapBase::HandleRetransmissionTimer(void)
}
// Increment retransmission counter and timer.
coapMetadata.mRetransmissionCount++;
coapMetadata.mRetransmissionsRemaining--;
coapMetadata.mRetransmissionTimeout *= 2;
coapMetadata.mNextTimerShot = now + coapMetadata.mRetransmissionTimeout;
coapMetadata.UpdateIn(*message);
@@ -623,18 +624,16 @@ exit:
CoapMetadata::CoapMetadata(bool aConfirmable,
const Ip6::MessageInfo &aMessageInfo,
otCoapResponseHandler aHandler,
void * aContext)
void * aContext,
const CoapTxParameters &aTxParameters)
{
mSourceAddress = aMessageInfo.GetSockAddr();
mDestinationPort = aMessageInfo.GetPeerPort();
mDestinationAddress = aMessageInfo.GetPeerAddr();
mResponseHandler = aHandler;
mResponseContext = aContext;
mRetransmissionCount = 0;
mRetransmissionTimeout = Time::SecToMsec(kAckTimeout);
mRetransmissionTimeout += Random::NonCrypto::GetUint32InRange(
0, Time::SecToMsec(kAckTimeout) * kAckRandomFactorNumerator / kAckRandomFactorDenominator -
Time::SecToMsec(kAckTimeout) + 1);
mSourceAddress = aMessageInfo.GetSockAddr();
mDestinationPort = aMessageInfo.GetPeerPort();
mDestinationAddress = aMessageInfo.GetPeerAddr();
mResponseHandler = aHandler;
mResponseContext = aContext;
mRetransmissionsRemaining = aTxParameters.mMaxRetransmit;
mRetransmissionTimeout = aTxParameters.CalculateInitialRetransmissionTimeout();
if (aConfirmable)
{
@@ -644,7 +643,7 @@ CoapMetadata::CoapMetadata(bool aConfirmable,
else
{
// Set overall response timeout.
mNextTimerShot = TimerMilli::GetNow() + Time::SecToMsec(kMaxTransmitWait);
mNextTimerShot = TimerMilli::GetNow() + aTxParameters.CalculateMaxTransmitWait();
}
mAcknowledged = false;
@@ -711,13 +710,17 @@ exit:
return matchedResponse;
}
void ResponsesQueue::EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void ResponsesQueue::EnqueueResponse(Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const CoapTxParameters &aTxParameters)
{
otError error = OT_ERROR_NONE;
Message * responseCopy = NULL;
EnqueuedResponseHeader enqueuedResponseHeader(aMessageInfo);
uint16_t messageCount;
uint16_t bufferCount;
uint32_t exchangeLifetime = aTxParameters.CalculateExchangeLifetime();
TimeMilli dequeueTime = TimerMilli::GetNow() + exchangeLifetime;
EnqueuedResponseHeader enqueuedResponseHeader(dequeueTime, aMessageInfo);
// return success if matched response already exists in the cache
VerifyOrExit(FindMatchedResponse(aMessage, aMessageInfo) == NULL);
@@ -736,7 +739,7 @@ void ResponsesQueue::EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &
if (!mTimer.IsRunning())
{
mTimer.Start(Time::SecToMsec(kExchangeLifetime));
mTimer.Start(exchangeLifetime);
}
exit:
@@ -809,6 +812,33 @@ uint32_t EnqueuedResponseHeader::GetRemainingTime(void) const
return remainingTime;
}
uint32_t CoapTxParameters::CalculateInitialRetransmissionTimeout(void) const
{
return Random::NonCrypto::GetUint32InRange(
mAckTimeout, mAckTimeout * mAckRandomFactorNumerator / mAckRandomFactorDenominator + 1);
}
uint32_t CoapTxParameters::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;
}
uint32_t CoapTxParameters::CalculateMaxTransmitWait(void) const
{
return static_cast<uint32_t>(mAckTimeout * ((2ULL << mMaxRetransmit) - 1) * mAckRandomFactorNumerator /
mAckRandomFactorDenominator);
}
const otCoapTxParameters CoapTxParameters::kDefaultTxParameters = {
kDefaultAckTimeout,
kDefaultAckRandomFactorNumerator,
kDefaultAckRandomFactorDenominator,
kDefaultMaxRetransmit,
};
Coap::Coap(Instance &aInstance)
: CoapBase(aInstance, &Coap::Send)
, mSocket(aInstance.Get<Ip6::Udp>())
+94 -43
View File
@@ -59,30 +59,50 @@ namespace Coap {
*
*/
/**
* Protocol Constants (RFC 7252).
*
*/
enum
class CoapTxParameters : public otCoapTxParameters
{
kAckTimeout = OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT,
kAckRandomFactorNumerator = OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_NUMERATOR,
kAckRandomFactorDenominator = OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_DENOMINATOR,
kMaxRetransmit = OPENTHREAD_CONFIG_COAP_MAX_RETRANSMIT,
kNStart = 1,
kDefaultLeisure = 5,
kProbingRate = 1,
public:
/**
* Protocol Constants (RFC 7252).
*
*/
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,
// Note that 2 << (kMaxRetransmit - 1) is equal to kMaxRetransmit power of 2
kMaxTransmitSpan =
kAckTimeout * ((2 << (kMaxRetransmit - 1)) - 1) * kAckRandomFactorNumerator / kAckRandomFactorDenominator,
kMaxTransmitWait =
kAckTimeout * ((2 << kMaxRetransmit) - 1) * kAckRandomFactorNumerator / kAckRandomFactorDenominator,
kMaxLatency = 100,
kProcessingDelay = kAckTimeout,
kMaxRtt = 2 * kMaxLatency + kProcessingDelay,
kExchangeLifetime = kMaxTransmitSpan + 2 * (kMaxLatency) + kProcessingDelay,
kNonLifetime = kMaxTransmitSpan + kMaxLatency
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
};
uint32_t CalculateInitialRetransmissionTimeout(void) const;
uint32_t CalculateExchangeLifetime(void) const;
uint32_t CalculateMaxTransmitWait(void) 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;
};
/**
@@ -104,23 +124,25 @@ public:
, mResponseContext(NULL)
, mNextTimerShot(0)
, mRetransmissionTimeout(0)
, mRetransmissionCount(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] 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);
void * aContext,
const CoapTxParameters &aTxParameters);
/**
* This method appends request data to the message.
@@ -160,16 +182,16 @@ public:
}
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 mRetransmissionCount; ///< Number of retransmissions.
bool mAcknowledged : 1; ///< Information that request was acknowledged.
bool mConfirmable : 1; ///< Information that message is confirmable.
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.
};
/**
@@ -241,8 +263,8 @@ public:
* @param[in] aMessageInfo The message info containing source endpoint identification.
*
*/
explicit EnqueuedResponseHeader(const Ip6::MessageInfo &aMessageInfo)
: mDequeueTime(TimerMilli::GetNow() + Time::SecToMsec(kExchangeLifetime))
explicit EnqueuedResponseHeader(TimeMilli aDequeueTime, const Ip6::MessageInfo &aMessageInfo)
: mDequeueTime(aDequeueTime)
, mMessageInfo(aMessageInfo)
{
}
@@ -316,9 +338,12 @@ public:
*
* @param[in] aMessage The CoAP response to add to the cache.
* @param[in] aMessageInfo The message info corresponding to @p aMessage.
* @param[in] aTxParameters Transmission parameters.
*
*/
void EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void EnqueueResponse(Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const CoapTxParameters &aTxParameters);
/**
* This method removes the oldest response from the cache.
@@ -469,7 +494,30 @@ public:
Message *NewMessage(const otMessageSettings *aSettings = NULL);
/**
* This method sends a CoAP message.
* This method sends a CoAP message with custom transmission parameters.
*
* If a response for a request is expected, respective function and context information should be provided.
* If no response is expected, these arguments should be NULL pointers.
* If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
*
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aTxParameters A reference to transmission parameters for this message.
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @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.
*
*/
otError SendMessage(Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const CoapTxParameters &aTxParameters,
otCoapResponseHandler aHandler = NULL,
void * aContext = NULL);
/**
* This method sends a CoAP message with default transmission parameters.
*
* If a response for a request is expected, respective function and context information should be provided.
* If no response is expected, these arguments should be NULL pointers.
@@ -487,7 +535,10 @@ public:
otError SendMessage(Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
otCoapResponseHandler aHandler = NULL,
void * aContext = NULL);
void * aContext = NULL)
{
return SendMessage(aMessage, aMessageInfo, CoapTxParameters::GetDefault(), aHandler, aContext);
}
/**
* This method sends a CoAP reset message.
+5 -4
View File
@@ -36,13 +36,14 @@
#define CONFIG_COAP_H_
/**
* @def OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT
* @def OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS
*
* Minimum spacing before first retransmission when ACK is not received (RFC7252 default value is 2).
* Minimum spacing before first retransmission when ACK is not received, in milliseconds (RFC7252 default value
* is 2000).
*
*/
#ifndef OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT
#define OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT 2
#ifndef OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS
#define OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS 2000
#endif
/**
@@ -463,4 +463,9 @@
#error "OPENTHREAD_CONFIG_INITIAL_LOG_LEVEL was replaced by OPENTHREAD_CONFIG_LOG_LEVEL_INIT."
#endif
#ifdef OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT
#error \
"OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT (in seconds) was replaced by OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS (in milliseconds)"
#endif
#endif // OPENTHREAD_CORE_CONFIG_CHECK_H_