[timer] add helper methods for common timer use patterns and simplify code (#4243)

This commit adds helper methods in `Timer` class which cover commonly
repeated use patterns by other modules.

Method `FireAt()` allows a timer to be started with a given fire time.
`FireAtIfEarlier()` (re-)schedules the timer with a given a fire time
only if the timer is not running or if the new given fire time is
earlier than the current fire time.

Modules mle, coap, ip6-mpl, joiner-router, dns-clinet, and sntp-client
are updated to use the new methods.
This commit is contained in:
Abtin Keshavarzian
2019-11-07 04:45:34 -08:00
committed by Jonathan Hui
parent ecf7a7050f
commit aab693f9c3
16 changed files with 179 additions and 364 deletions
+20 -46
View File
@@ -259,42 +259,34 @@ void CoapBase::HandleRetransmissionTimer(Timer &aTimer)
void CoapBase::HandleRetransmissionTimer(void)
{
TimeMilli now = TimerMilli::GetNow();
uint32_t nextDelta = TimeMilli::kMaxDuration;
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextTime = now.GetDistantFuture();
CoapMetadata coapMetadata;
Message * message = static_cast<Message *>(mPendingRequests.GetHead());
Message * nextMessage = NULL;
Message * message;
Message * nextMessage;
Ip6::MessageInfo messageInfo;
while (message != NULL)
for (message = static_cast<Message *>(mPendingRequests.GetHead()); message != NULL; message = nextMessage)
{
nextMessage = static_cast<Message *>(message->GetNext());
coapMetadata.ReadFrom(*message);
if (coapMetadata.IsLater(now))
if (now >= coapMetadata.mNextTimerShot)
{
uint32_t diff = coapMetadata.mNextTimerShot - now;
// Calculate the next delay and choose the lowest.
if (diff < nextDelta)
if (!coapMetadata.mConfirmable || (coapMetadata.mRetransmissionCount >= kMaxRetransmit))
{
nextDelta = diff;
// No expected response or acknowledgment.
FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_RESPONSE_TIMEOUT);
continue;
}
}
else if ((coapMetadata.mConfirmable) && (coapMetadata.mRetransmissionCount < kMaxRetransmit))
{
// Increment retransmission counter and timer.
coapMetadata.mRetransmissionCount++;
coapMetadata.mRetransmissionTimeout *= 2;
coapMetadata.mNextTimerShot = now + coapMetadata.mRetransmissionTimeout;
coapMetadata.UpdateIn(*message);
// Check if retransmission time is lower than current lowest.
if (coapMetadata.mRetransmissionTimeout < nextDelta)
{
nextDelta = coapMetadata.mRetransmissionTimeout;
}
// Retransmit
if (!coapMetadata.mAcknowledged)
{
@@ -305,18 +297,16 @@ void CoapBase::HandleRetransmissionTimer(void)
SendCopy(*message, messageInfo);
}
}
else
{
// No expected response or acknowledgment.
FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_RESPONSE_TIMEOUT);
}
message = nextMessage;
if (nextTime > coapMetadata.mNextTimerShot)
{
nextTime = coapMetadata.mNextTimerShot;
}
}
if (nextDelta != TimeMilli::kMaxDuration)
if (nextTime < now.GetDistantFuture())
{
mRetransmissionTimer.Start(nextDelta);
mRetransmissionTimer.FireAt(nextTime);
}
}
@@ -369,23 +359,7 @@ Message *CoapBase::CopyAndEnqueueMessage(const Message & aMessage,
// Append the copy with retransmission data.
SuccessOrExit(error = aCoapMetadata.AppendTo(*messageCopy));
// Setup the timer.
if (mRetransmissionTimer.IsRunning())
{
TimeMilli alarmFireTime;
// If timer is already running, check if it should be restarted with earlier fire time.
alarmFireTime = mRetransmissionTimer.GetFireTime();
if (aCoapMetadata.IsEarlier(alarmFireTime))
{
mRetransmissionTimer.Start(aCoapMetadata.mRetransmissionTimeout);
}
}
else
{
mRetransmissionTimer.Start(aCoapMetadata.mRetransmissionTimeout);
}
mRetransmissionTimer.FireAtIfEarlier(aCoapMetadata.mNextTimerShot);
// Enqueue the message.
mPendingRequests.Enqueue(*messageCopy);
@@ -835,7 +809,7 @@ void ResponsesQueue::HandleTimer(void)
{
enqueuedResponseHeader.ReadFrom(*message);
if (enqueuedResponseHeader.IsEarlier(TimerMilli::GetNow()))
if (TimerMilli::GetNow() >= enqueuedResponseHeader.mDequeueTime)
{
DequeueResponse(*message);
}
+2 -33
View File
@@ -158,28 +158,6 @@ public:
return aMessage.Write(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
}
/**
* This method checks if the message shall be sent before the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent before the given time.
* @retval FALSE Otherwise.
*
*/
bool IsEarlier(TimeMilli aTime) const { return aTime >= mNextTimerShot; }
/**
* This method checks if the message shall be sent after the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent after the given time.
* @retval FALSE Otherwise.
*
*/
bool IsLater(TimeMilli aTime) const { return aTime < mNextTimerShot; }
private:
Ip6::Address mSourceAddress; ///< IPv6 address of the message source.
Ip6::Address mDestinationAddress; ///< IPv6 address of the message destination.
@@ -251,6 +229,8 @@ private:
*/
class EnqueuedResponseHeader
{
friend class ResponsesQueue;
public:
/**
* Default constructor creating empty object.
@@ -297,17 +277,6 @@ public:
OT_UNUSED_VARIABLE(length);
}
/**
* This method checks if the message shall be sent before the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent before the given time.
* @retval FALSE Otherwise.
*
*/
bool IsEarlier(TimeMilli aTime) const { return aTime >= mDequeueTime; }
/**
* This method returns number of milliseconds in which the message should be sent.
*
+29
View File
@@ -217,6 +217,30 @@ public:
*/
bool operator>(const Time &aOther) const { return (aOther < *this); }
/**
* This method returns a new `Time` instance which is in distant future relative to current `Time` object.
*
* The returned distance future `Time` is guaranteed to be equal or after (as defined by comparison operator `<=`)
* any other `Time` which is after this `Time` object, i.e., for any `t` for which we have `*this <= t`, it is
* ensured that `t <= this->GetGetDistantFuture()`.
*
* @returns A new `Time` in distance future relative to current `Time` object.
*
*/
Time GetDistantFuture(void) const { return Time(mValue + kDistantFuture); }
/**
* This method returns a new `Time` instance which is in distant past relative to current `Time` object.
*
* The returned distance past `Time` is guaranteed to be equal or before (as defined by comparison operator `>=`)
* any other `Time` which is before this `Time` object, i.e., for any `t` for which we have `*this >= t`, it is
* ensured that `t >= this->GetDistantPast()`.
*
* @returns A new `Time` in distance past relative to current `Time` object.
*
*/
Time GetDistantPast(void) const { return Time(mValue - kDistantFuture); }
/**
* This static method converts a given number of seconds to milliseconds.
*
@@ -234,6 +258,11 @@ public:
static uint32_t MsecToSec(uint32_t aMilliseconds) { return aMilliseconds / 1000u; }
private:
enum
{
kDistantFuture = (1UL << 31),
};
uint32_t mValue;
};
+20 -2
View File
@@ -76,10 +76,23 @@ void TimerMilli::Start(uint32_t aDelay)
void TimerMilli::StartAt(TimeMilli aStartTime, uint32_t aDelay)
{
assert(aDelay <= kMaxDelay);
mFireTime = aStartTime + aDelay;
FireAt(aStartTime + aDelay);
}
void TimerMilli::FireAt(TimeMilli aFireTime)
{
mFireTime = aFireTime;
Get<TimerMilliScheduler>().Add(*this);
}
void TimerMilli::FireAtIfEarlier(TimeMilli aFireTime)
{
if (!IsRunning() || (mFireTime > aFireTime))
{
FireAt(aFireTime);
}
}
void TimerMilli::Stop(void)
{
Get<TimerMilliScheduler>().Remove(*this);
@@ -220,7 +233,12 @@ void TimerMicro::Start(uint32_t aDelay)
void TimerMicro::StartAt(TimeMicro aStartTime, uint32_t aDelay)
{
assert(aDelay <= kMaxDelay);
mFireTime = aStartTime + aDelay;
FireAt(aStartTime + aDelay);
}
void TimerMicro::FireAt(TimeMicro aFireTime)
{
mFireTime = aFireTime;
Get<TimerMicroScheduler>().Add(*this);
}
+25
View File
@@ -175,6 +175,23 @@ public:
*/
void StartAt(TimeMilli sStartTime, uint32_t aDelay);
/**
* This method schedules the timer to fire at a given fire time.
*
* @param[in] aFireTime The fire time.
*
*/
void FireAt(TimeMilli aFireTime);
/**
* This method (re-)schedules the timer with a given a fire time only if the timer is not running or the new given
* fire time is earlier than the current fire time.
*
* @param[in] aFireTime The fire time.
*
*/
void FireAtIfEarlier(TimeMilli aFireTime);
/**
* This method stops the timer.
*
@@ -381,6 +398,14 @@ public:
*/
void StartAt(TimeMicro aStartTime, uint32_t aDelay);
/**
* This method schedules the timer to fire at a given fire time.
*
* @param[in] aFireTime The fire time.
*
*/
void FireAt(TimeMicro aFireTime);
/**
* This method stops the timer.
*
+2 -3
View File
@@ -371,7 +371,6 @@ void JoinerRouter::SendDelayedJoinerEntrust(void)
{
DelayedJoinEntHeader delayedJoinEnt;
Coap::Message * message = static_cast<Coap::Message *>(mDelayedJoinEnts.GetHead());
TimeMilli now = TimerMilli::GetNow();
Ip6::MessageInfo messageInfo;
VerifyOrExit(message != NULL);
@@ -383,9 +382,9 @@ void JoinerRouter::SendDelayedJoinerEntrust(void)
VerifyOrExit(!mExpectJoinEntRsp ||
memcmp(Get<KeyManager>().GetKek(), delayedJoinEnt.GetKek(), KeyManager::kMaxKeyLength) == 0);
if (delayedJoinEnt.IsLater(now))
if (TimerMilli::GetNow() < delayedJoinEnt.GetSendTime())
{
mTimer.Start(delayedJoinEnt.GetSendTime() - now);
mTimer.FireAt(delayedJoinEnt.GetSendTime());
}
else
{
-20
View File
@@ -203,26 +203,6 @@ public:
*/
const uint8_t *GetKek(void) const { return mKek; }
/**
* This method checks if the message shall be sent before the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent before the given time.
* @retval FALSE Otherwise.
*/
bool IsEarlier(TimeMilli aTime) const { return aTime > mSendTime; }
/**
* This method checks if the message shall be sent after the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent after the given time.
* @retval FALSE Otherwise.
*/
bool IsLater(TimeMilli aTime) const { return aTime < mSendTime; }
private:
Ip6::MessageInfo mMessageInfo; ///< Message info of the message to send.
TimeMilli mSendTime; ///< Time when the message shall be sent.
+21 -50
View File
@@ -183,10 +183,8 @@ exit:
Message *Client::CopyAndEnqueueMessage(const Message &aMessage, const QueryMetadata &aQueryMetadata)
{
otError error = OT_ERROR_NONE;
TimeMilli now = TimerMilli::GetNow();
Message * messageCopy = NULL;
TimeMilli nextTransmissionTime;
otError error = OT_ERROR_NONE;
Message *messageCopy = NULL;
// Create a message copy for further retransmissions.
VerifyOrExit((messageCopy = aMessage.Clone()) != NULL, error = OT_ERROR_NO_BUFS);
@@ -195,21 +193,7 @@ Message *Client::CopyAndEnqueueMessage(const Message &aMessage, const QueryMetad
SuccessOrExit(error = aQueryMetadata.AppendTo(*messageCopy));
mPendingQueries.Enqueue(*messageCopy);
// Setup the timer.
if (mRetransmissionTimer.IsRunning())
{
// If timer is already running, check if it should be restarted with earlier fire time.
nextTransmissionTime = mRetransmissionTimer.GetFireTime();
if (aQueryMetadata.IsEarlier(nextTransmissionTime))
{
mRetransmissionTimer.Start(aQueryMetadata.mTransmissionTime - now);
}
}
else
{
mRetransmissionTimer.Start(aQueryMetadata.mTransmissionTime - now);
}
mRetransmissionTimer.FireAtIfEarlier(aQueryMetadata.mTransmissionTime);
exit:
@@ -418,45 +402,34 @@ void Client::HandleRetransmissionTimer(Timer &aTimer)
void Client::HandleRetransmissionTimer(void)
{
TimeMilli now = TimerMilli::GetNow();
uint32_t nextDelta = TimeMilli::kMaxDuration;
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextTime = now.GetDistantFuture();
QueryMetadata queryMetadata;
Message * message = mPendingQueries.GetHead();
Message * nextMessage = NULL;
Message * message;
Message * nextMessage;
Ip6::MessageInfo messageInfo;
while (message != NULL)
for (message = mPendingQueries.GetHead(); message != NULL; message = nextMessage)
{
nextMessage = message->GetNext();
queryMetadata.ReadFrom(*message);
if (queryMetadata.IsLater(now))
if (now >= queryMetadata.mTransmissionTime)
{
uint32_t diff = queryMetadata.mTransmissionTime - TimerMilli::GetNow();
// Calculate the next delay and choose the lowest.
if (diff < nextDelta)
if (queryMetadata.mRetransmissionCount >= kMaxRetransmit)
{
nextDelta = diff;
// No expected response.
FinalizeDnsTransaction(*message, queryMetadata, NULL, 0, OT_ERROR_RESPONSE_TIMEOUT);
continue;
}
}
else if (queryMetadata.mRetransmissionCount < kMaxRetransmit)
{
uint32_t diff;
// Increment retransmission counter and timer.
queryMetadata.mRetransmissionCount++;
queryMetadata.mTransmissionTime = now + kResponseTimeout;
queryMetadata.UpdateIn(*message);
diff = kResponseTimeout;
// Check if retransmission time is lower than current lowest.
if (diff < nextDelta)
{
nextDelta = kResponseTimeout;
}
// Retransmit
messageInfo.SetPeerAddr(queryMetadata.mDestinationAddress);
messageInfo.SetPeerPort(queryMetadata.mDestinationPort);
@@ -464,18 +437,16 @@ void Client::HandleRetransmissionTimer(void)
SendCopy(*message, messageInfo);
}
else
{
// No expected response.
FinalizeDnsTransaction(*message, queryMetadata, NULL, 0, OT_ERROR_RESPONSE_TIMEOUT);
}
message = nextMessage;
if (nextTime > queryMetadata.mTransmissionTime)
{
nextTime = queryMetadata.mTransmissionTime;
}
}
if (nextDelta != TimeMilli::kMaxDuration)
if (nextTime < now.GetDistantFuture())
{
mRetransmissionTimer.Start(nextDelta);
mRetransmissionTimer.FireAt(nextTime);
}
}
-20
View File
@@ -108,26 +108,6 @@ public:
return aMessage.Write(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
}
/**
* This method checks if the message shall be sent before the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent before the given time.
* @retval FALSE Otherwise.
*/
bool IsEarlier(TimeMilli aTime) const { return aTime > mTransmissionTime; }
/**
* This method checks if the message shall be sent after the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent after the given time.
* @retval FALSE Otherwise.
*/
bool IsLater(TimeMilli aTime) const { return aTime < mTransmissionTime; }
private:
const char * mHostname; ///< A hostname to be find.
otDnsResponseHandler mResponseHandler; ///< A function pointer that is called on response reception.
+15 -42
View File
@@ -235,11 +235,9 @@ exit:
void Mpl::AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence, bool aIsOutbound)
{
TimeMilli now = TimerMilli::GetNow();
otError error = OT_ERROR_NONE;
Message * messageCopy = NULL;
MplBufferedMessageMetadata messageMetadata;
TimeMilli nextTransmissionTime;
uint8_t hopLimit = 0;
#if OPENTHREAD_CONFIG_MPL_DYNAMIC_INTERVAL_ENABLE
@@ -262,27 +260,12 @@ void Mpl::AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSeque
messageMetadata.SetSeedId(aSeedId);
messageMetadata.SetSequence(aSequence);
messageMetadata.SetTransmissionCount(aIsOutbound ? 1 : 0);
messageMetadata.GenerateNextTransmissionTime(now, interval);
messageMetadata.GenerateNextTransmissionTime(TimerMilli::GetNow(), interval);
// Append the message with MplBufferedMessageMetadata and add it to the queue.
SuccessOrExit(error = messageMetadata.AppendTo(*messageCopy));
mBufferedMessageSet.Enqueue(*messageCopy);
if (mRetransmissionTimer.IsRunning())
{
// If timer is already running, check if it should be restarted with earlier fire time.
nextTransmissionTime = mRetransmissionTimer.GetFireTime();
if (messageMetadata.IsEarlier(nextTransmissionTime))
{
mRetransmissionTimer.Start(messageMetadata.GetTransmissionTime() - now);
}
}
else
{
// Otherwise just set the timer.
mRetransmissionTimer.Start(messageMetadata.GetTransmissionTime() - now);
}
mRetransmissionTimer.FireAtIfEarlier(messageMetadata.GetTransmissionTime());
exit:
@@ -333,26 +316,23 @@ void Mpl::HandleRetransmissionTimer(Timer &aTimer)
void Mpl::HandleRetransmissionTimer(void)
{
TimeMilli now = TimerMilli::GetNow();
uint32_t nextDelta = TimeMilli::kMaxDuration;
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextTime = now.GetDistantFuture();
MplBufferedMessageMetadata messageMetadata;
Message * message;
Message * nextMessage;
Message *message = mBufferedMessageSet.GetHead();
Message *nextMessage = NULL;
while (message != NULL)
for (message = mBufferedMessageSet.GetHead(); message != NULL; message = nextMessage)
{
nextMessage = message->GetNext();
messageMetadata.ReadFrom(*message);
if (messageMetadata.IsLater(now))
if (now < messageMetadata.GetTransmissionTime())
{
uint32_t diff = messageMetadata.GetTransmissionTime() - now;
// Calculate the next retransmission time and choose the lowest.
if (diff < nextDelta)
if (nextTime > messageMetadata.GetTransmissionTime())
{
nextDelta = diff;
nextTime = messageMetadata.GetTransmissionTime();
}
}
else
@@ -362,8 +342,6 @@ void Mpl::HandleRetransmissionTimer(void)
if (messageMetadata.GetTransmissionCount() < GetTimerExpirations())
{
uint32_t diff;
Message *messageCopy = message->Clone(message->GetLength() - sizeof(MplBufferedMessageMetadata));
if (messageCopy != NULL)
@@ -379,12 +357,9 @@ void Mpl::HandleRetransmissionTimer(void)
messageMetadata.GenerateNextTransmissionTime(now, kDataMessageInterval);
messageMetadata.UpdateIn(*message);
diff = messageMetadata.GetTransmissionTime() - now;
// Check if retransmission time is lower than the current lowest one.
if (diff < nextDelta)
if (nextTime > messageMetadata.GetTransmissionTime())
{
nextDelta = diff;
nextTime = messageMetadata.GetTransmissionTime();
}
}
else
@@ -409,13 +384,11 @@ void Mpl::HandleRetransmissionTimer(void)
}
}
}
message = nextMessage;
}
if (nextDelta != TimeMilli::kMaxDuration)
if (nextTime < now.GetDistantFuture())
{
mRetransmissionTimer.Start(nextDelta);
mRetransmissionTimer.FireAt(nextTime);
}
}
-20
View File
@@ -311,26 +311,6 @@ public:
return aMessage.Write(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
}
/**
* This method checks if the message shall be sent before the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent before the given time.
* @retval FALSE Otherwise.
*/
bool IsEarlier(TimeMilli aTime) const { return aTime > mTransmissionTime; }
/**
* This method checks if the message shall be sent after the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent after the given time.
* @retval FALSE Otherwise.
*/
bool IsLater(TimeMilli aTime) const { return aTime < mTransmissionTime; }
/**
* This method returns the MPL Seed Id value.
*
+20 -50
View File
@@ -189,10 +189,8 @@ exit:
Message *Client::CopyAndEnqueueMessage(const Message &aMessage, const QueryMetadata &aQueryMetadata)
{
otError error = OT_ERROR_NONE;
TimeMilli now = TimerMilli::GetNow();
Message * messageCopy = NULL;
TimeMilli nextTransmissionTime;
otError error = OT_ERROR_NONE;
Message *messageCopy = NULL;
// Create a message copy for further retransmissions.
VerifyOrExit((messageCopy = aMessage.Clone()) != NULL, error = OT_ERROR_NO_BUFS);
@@ -201,21 +199,7 @@ Message *Client::CopyAndEnqueueMessage(const Message &aMessage, const QueryMetad
SuccessOrExit(error = aQueryMetadata.AppendTo(*messageCopy));
mPendingQueries.Enqueue(*messageCopy);
// Setup the timer.
if (mRetransmissionTimer.IsRunning())
{
// If timer is already running, check if it should be restarted with earlier fire time.
nextTransmissionTime = mRetransmissionTimer.GetFireTime();
if (aQueryMetadata.IsEarlier(nextTransmissionTime))
{
mRetransmissionTimer.Start(aQueryMetadata.mTransmissionTime - now);
}
}
else
{
mRetransmissionTimer.Start(aQueryMetadata.mTransmissionTime - now);
}
mRetransmissionTimer.FireAtIfEarlier(aQueryMetadata.mTransmissionTime);
exit:
@@ -311,45 +295,33 @@ void Client::HandleRetransmissionTimer(Timer &aTimer)
void Client::HandleRetransmissionTimer(void)
{
TimeMilli now = TimerMilli::GetNow();
uint32_t nextDelta = TimeMilli::kMaxDuration;
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextTime = now.GetDistantFuture();
QueryMetadata queryMetadata;
Message * message = mPendingQueries.GetHead();
Message * nextMessage = NULL;
Message * message;
Message * nextMessage;
Ip6::MessageInfo messageInfo;
while (message != NULL)
for (message = mPendingQueries.GetHead(); message != NULL; message = nextMessage)
{
nextMessage = message->GetNext();
queryMetadata.ReadFrom(*message);
if (queryMetadata.IsLater(now))
if (now >= queryMetadata.mTransmissionTime)
{
uint32_t diff = queryMetadata.mTransmissionTime - now;
// Calculate the next delay and choose the lowest.
if (diff < nextDelta)
if (queryMetadata.mRetransmissionCount >= kMaxRetransmit)
{
nextDelta = diff;
// No expected response.
FinalizeSntpTransaction(*message, queryMetadata, 0, OT_ERROR_RESPONSE_TIMEOUT);
continue;
}
}
else if (queryMetadata.mRetransmissionCount < kMaxRetransmit)
{
uint32_t diff;
// Increment retransmission counter and timer.
queryMetadata.mRetransmissionCount++;
queryMetadata.mTransmissionTime = now + kResponseTimeout;
queryMetadata.UpdateIn(*message);
diff = kResponseTimeout;
// Check if retransmission time is lower than current lowest.
if (diff < nextDelta)
{
nextDelta = diff;
}
// Retransmit
messageInfo.SetPeerAddr(queryMetadata.mDestinationAddress);
messageInfo.SetPeerPort(queryMetadata.mDestinationPort);
@@ -357,18 +329,16 @@ void Client::HandleRetransmissionTimer(void)
SendCopy(*message, messageInfo);
}
else
{
// No expected response.
FinalizeSntpTransaction(*message, queryMetadata, 0, OT_ERROR_RESPONSE_TIMEOUT);
}
message = nextMessage;
if (nextTime > queryMetadata.mTransmissionTime)
{
nextTime = queryMetadata.mTransmissionTime;
}
}
if (nextDelta != TimeMilli::kMaxDuration)
if (nextTime < now.GetDistantFuture())
{
mRetransmissionTimer.Start(nextDelta);
mRetransmissionTimer.FireAt(nextTime);
}
}
-20
View File
@@ -472,26 +472,6 @@ public:
return aMessage.Write(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
}
/**
* This method checks if the message shall be sent before the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent before the given time.
* @retval FALSE Otherwise.
*/
bool IsEarlier(TimeMilli aTime) const { return aTime > mTransmissionTime; }
/**
* This method checks if the message shall be sent after the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent after the given time.
* @retval FALSE Otherwise.
*/
bool IsLater(TimeMilli aTime) const { return aTime < mTransmissionTime; }
private:
uint32_t mTransmitTimestamp; ///< Time at the client when the request departed for the server.
otSntpResponseHandler mResponseHandler; ///< A function pointer that is called on response reception.
+15 -36
View File
@@ -1884,24 +1884,22 @@ void Mle::HandleDelayedResponseTimer(Timer &aTimer)
void Mle::HandleDelayedResponseTimer(void)
{
DelayedResponseHeader delayedResponse;
TimeMilli now = TimerMilli::GetNow();
uint32_t nextDelay = TimeMilli::kMaxDuration;
Message * message = mDelayedResponses.GetHead();
Message * nextMessage = NULL;
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextSendTime = now.GetDistantFuture();
Message * message;
Message * nextMessage;
while (message != NULL)
for (message = mDelayedResponses.GetHead(); message != NULL; message = nextMessage)
{
nextMessage = message->GetNext();
delayedResponse.ReadFrom(*message);
if (delayedResponse.IsLater(now))
if (now < delayedResponse.GetSendTime())
{
uint32_t diff = delayedResponse.GetSendTime() - now;
// Calculate the next delay and choose the lowest.
if (diff < nextDelay)
if (nextSendTime > delayedResponse.GetSendTime())
{
nextDelay = diff;
nextSendTime = delayedResponse.GetSendTime();
}
}
else
@@ -1917,7 +1915,7 @@ void Mle::HandleDelayedResponseTimer(void)
LogMleMessage("Send delayed message", delayedResponse.GetDestination());
// Here enters fast poll mode, as for Rx-Off-when-idle device, the enqueued msg should
// be Mle Data Reqeuest.
// be Mle Data Request.
// Note: Finer-grade check (e.g. message subtype) might be required when deciding whether
// or not enters fast poll mode fast poll mode if there are other type of delayed message
// for Rx-Off-when-idle device.
@@ -1931,13 +1929,11 @@ void Mle::HandleDelayedResponseTimer(void)
message->Free();
}
}
message = nextMessage;
}
if (nextDelay != TimeMilli::kMaxDuration)
if (nextSendTime < now.GetDistantFuture())
{
mDelayedResponseTimer.Start(nextDelay);
mDelayedResponseTimer.FireAt(nextSendTime);
}
}
@@ -2561,30 +2557,13 @@ exit:
otError Mle::AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay)
{
otError error = OT_ERROR_NONE;
TimeMilli alarmFireTime;
TimeMilli sendTime = TimerMilli::GetNow() + aDelay;
otError error = OT_ERROR_NONE;
DelayedResponseHeader delayedResponse(TimerMilli::GetNow() + aDelay, aDestination);
// Append the message with DelayedRespnoseHeader and add to the list.
DelayedResponseHeader delayedResponse(sendTime, aDestination);
SuccessOrExit(error = delayedResponse.AppendTo(aMessage));
mDelayedResponses.Enqueue(aMessage);
if (mDelayedResponseTimer.IsRunning())
{
// If timer is already running, check if it should be restarted with earlier fire time.
alarmFireTime = mDelayedResponseTimer.GetFireTime();
if (delayedResponse.IsEarlier(alarmFireTime))
{
mDelayedResponseTimer.Start(aDelay);
}
}
else
{
// Otherwise just set the timer.
mDelayedResponseTimer.Start(aDelay);
}
mDelayedResponseTimer.FireAtIfEarlier(delayedResponse.GetSendTime());
exit:
return error;
-22
View File
@@ -440,28 +440,6 @@ public:
*/
const Ip6::Address &GetDestination(void) const { return mDestination; }
/**
* This method checks if the message shall be sent before the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent before the given time.
* @retval FALSE Otherwise.
*
*/
bool IsEarlier(TimeMilli aTime) { return aTime > mSendTime; }
/**
* This method checks if the message shall be sent after the given time.
*
* @param[in] aTime A time to compare.
*
* @retval TRUE If the message shall be sent after the given time.
* @retval FALSE Otherwise.
*
*/
bool IsLater(TimeMilli aTime) { return aTime < mSendTime; }
private:
Ip6::Address mDestination; ///< IPv6 address of the message destination.
TimeMilli mSendTime; ///< Time when the message shall be sent.
+10
View File
@@ -633,6 +633,16 @@ int TestTimerTime(void)
VerifyOrQuit((t1 >= t2), "Time >= failed.\n");
VerifyOrQuit(t1 - t2 == duration, "Time difference failed\n");
t2 = t1.GetDistantFuture();
VerifyOrQuit((t1 < t2), "GetDistanceFuture() failed\n");
t2 += 1;
VerifyOrQuit(!(t1 < t2), "GetDistanceFuture() failed\n");
t2 = t1.GetDistantPast();
VerifyOrQuit((t1 > t2), "GetDistantPast() failed\n");
t2 -= 1;
VerifyOrQuit(!(t1 > t2), "GetDistantPast() failed\n");
printf("--> PASSED\n");
}
}