[coap] reduce code size by avoiding using 64bit division (#4612)

- Removed OpenThread's default CoAP configuration macro, because they
  are fixed values by Thread spec.

- Use 32bit multiple only to detect overflow of application CoAP
  transmission parameters.

- Added documentation describing conditions of valid CoAP transmission
  parameters.
This commit is contained in:
Yakun Xu
2020-03-03 22:59:56 -08:00
committed by Jonathan Hui
parent a802bfb0f3
commit 6614d14c34
5 changed files with 68 additions and 57 deletions
+11 -2
View File
@@ -60,6 +60,10 @@ extern "C" {
#define OT_COAP_MAX_TOKEN_LENGTH 8 ///< Max token length as specified (RFC 7252).
#define OT_COAP_MAX_RETRANSMIT 30 ///< Max retransmit supported by OpenThread.
#define OT_COAP_MIN_ACK_TIMEOUT 1000 ///< Minimal ACK timeout in milliseconds supported by OpenThread.
/**
* CoAP Type values.
*
@@ -777,9 +781,14 @@ otMessage *otCoapNewMessage(otInstance *aInstance, const otMessageSettings *aSet
* @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.
* Otherwise, parameters given must meet the following conditions:
* 1. mMaxRetransmit is no more than OT_COAP_MAX_RETRANSMIT.
* 2. mAckRandomFactorNumerator / mAckRandomFactorDenominator must not be below 1.0.
* 3. The calculated exchange life time must not overflow uint32_t.
*
* @retval OT_ERROR_NONE Successfully sent CoAP message.
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
* @retval OT_ERROR_INVALID_ARGS @p aTxParameters is invalid.
* @retval OT_ERROR_NONE Successfully sent CoAP message.
* @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
*
*/
otError otCoapSendRequestWithParameters(otInstance * aInstance,
+14 -4
View File
@@ -217,11 +217,21 @@ otError otCoapSendRequestWithParameters(otInstance * aInstance,
void * aContext,
const otCoapTxParameters *aTxParameters)
{
Instance &instance = *static_cast<Instance *>(aInstance);
otError error;
Instance & instance = *static_cast<Instance *>(aInstance);
const Coap::TxParameters &txParameters = Coap::TxParameters::From(aTxParameters);
return instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
Coap::TxParameters::From(aTxParameters), aHandler, aContext);
if (aTxParameters != NULL)
{
VerifyOrExit(txParameters.IsValid(), error = OT_ERROR_INVALID_ARGS);
}
error = instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
txParameters, aHandler, aContext);
exit:
return error;
}
otError otCoapStart(otInstance *aInstance, uint16_t aPort)
+30 -3
View File
@@ -962,6 +962,33 @@ uint32_t ResponsesQueue::ResponseMetadata::GetRemainingTime(void) const
return (mDequeueTime > now) ? mDequeueTime - now : 0;
}
/// Return product of @p aValueA and @p aValueB if no overflow otherwise 0.
static uint32_t Multiply(uint32_t aValueA, uint32_t aValueB)
{
uint32_t result = aValueA * aValueB;
return (result / aValueA == aValueB) ? result : 0;
}
bool TxParameters::IsValid(void) const
{
bool rval = false;
if (mAckRandomFactorNumerator >= mAckRandomFactorDenominator && mAckTimeout >= OT_COAP_MIN_ACK_TIMEOUT &&
mMaxRetransmit <= OT_COAP_MAX_RETRANSMIT)
{
// Calulate exchange lifetime step by step and verify no overflow.
uint32_t tmp = Multiply(mAckTimeout, (1U << (mMaxRetransmit + 1)) - 1);
tmp /= mAckRandomFactorDenominator;
tmp = Multiply(tmp, mAckRandomFactorNumerator);
rval = (tmp != 0 && (tmp + mAckTimeout + 2 * kDefaultMaxLatency) > tmp);
}
return rval;
}
uint32_t TxParameters::CalculateInitialRetransmissionTimeout(void) const
{
return Random::NonCrypto::GetUint32InRange(
@@ -979,10 +1006,10 @@ uint32_t TxParameters::CalculateMaxTransmitWait(void) const
return CalculateSpan(mMaxRetransmit + 1);
}
uint32_t TxParameters::CalculateSpan(uint32_t aMaxRetx) const
uint32_t TxParameters::CalculateSpan(uint8_t aMaxRetx) const
{
return static_cast<uint32_t>(mAckTimeout * ((1ULL << aMaxRetx) - 1) * mAckRandomFactorNumerator /
mAckRandomFactorDenominator);
return static_cast<uint32_t>(mAckTimeout * ((1U << aMaxRetx) - 1) / mAckRandomFactorDenominator *
mAckRandomFactorNumerator);
}
const otCoapTxParameters TxParameters::kDefaultTxParameters = {
+13 -5
View File
@@ -102,6 +102,14 @@ public:
return aTxParameters ? *static_cast<const TxParameters *>(aTxParameters) : GetDefault();
}
/**
* This method validates whether the CoAP transmission parameters are valid.
*
* @returns Whether the parameters are valid.
*
*/
bool IsValid(void) const;
/**
* This static method returns default CoAP tx parameters.
*
@@ -113,17 +121,17 @@ public:
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,
kDefaultAckTimeout = 2000, // in millisecond
kDefaultAckRandomFactorNumerator = 3,
kDefaultAckRandomFactorDenominator = 2,
kDefaultMaxRetransmit = 4,
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;
uint32_t CalculateSpan(uint8_t aMaxRetx) const;
static const otCoapTxParameters kDefaultTxParameters;
};
-43
View File
@@ -35,49 +35,6 @@
#ifndef CONFIG_COAP_H_
#define CONFIG_COAP_H_
/**
* @def OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS
*
* Minimum spacing before first retransmission when ACK is not received, in milliseconds (RFC7252 default value
* is 2000).
*
*/
#ifndef OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS
#define OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS 2000
#endif
/**
* @def OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_NUMERATOR
*
* 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).
*
*/
#ifndef OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_NUMERATOR
#define OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_NUMERATOR 3
#endif
/**
* @def OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_DENOMINATOR
*
* 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).
*
*/
#ifndef OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_DENOMINATOR
#define OPENTHREAD_CONFIG_COAP_ACK_RANDOM_FACTOR_DENOMINATOR 2
#endif
/**
* @def OPENTHREAD_CONFIG_COAP_MAX_RETRANSMIT
*
* Maximum number of retransmissions for CoAP Confirmable messages (RFC7252 default value is 4).
*
*/
#ifndef OPENTHREAD_CONFIG_COAP_MAX_RETRANSMIT
#define OPENTHREAD_CONFIG_COAP_MAX_RETRANSMIT 4
#endif
/**
* @def OPENTHREAD_CONFIG_COAP_SERVER_MAX_CACHED_RESPONSES
*