void TrickleTimer::StartNewInterval(void) { // Reset the counter and timer phase #ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT c = 0; #endif mPhase = kPhaseTransmit; // Initialize t if (I < 2) { // Immediate interval, just set t to 0 t = 0; } else if (mMode == kModeMPL) { // Initialize t to random value between (0, I] t = otPlatRandomGet() % I; } else if (mMode == kModePlainTimer) { // Initialize t to I, which has already been randomized in Start t = I; } else { // Initialize t to random value between (I/2, I] t = (I / 2) + otPlatRandomGet() % (I / 2); } // Start the timer for 't' milliseconds from now TimerMilli::Start(t); }
RequestMetadata::RequestMetadata(bool aConfirmable, const Ip6::MessageInfo &aMessageInfo, otCoapResponseHandler aHandler, void *aContext) { mDestinationPort = aMessageInfo.mPeerPort; mDestinationAddress = aMessageInfo.GetPeerAddr(); mResponseHandler = aHandler; mResponseContext = aContext; mRetransmissionCount = 0; mRetransmissionTimeout = Timer::SecToMsec(kAckTimeout); mRetransmissionTimeout += otPlatRandomGet() % (Timer::SecToMsec(kAckTimeout) * kAckRandomFactorNumerator / kAckRandomFactorDenominator - Timer::SecToMsec(kAckTimeout) + 1); if (aConfirmable) { // Set next retransmission timeout. mNextTimerShot = Timer::GetNow() + mRetransmissionTimeout; } else { // Set overall response timeout. mNextTimerShot = Timer::GetNow() + kMaxTransmitWait; } mAcknowledged = false; mConfirmable = aConfirmable; }
void MplBufferedMessageMetadata::GenerateNextTransmissionTime(uint32_t aCurrentTime, uint8_t aInterval) { // Emulate Trickle timer behavior and set up the next retransmission within [0,I) range. uint8_t t = aInterval == 0 ? aInterval : otPlatRandomGet() % aInterval; // Set transmission time at the beginning of the next interval. SetTransmissionTime(aCurrentTime + GetIntervalOffset() + t); SetIntervalOffset(aInterval - t); }
otError otPlatRandomGetTrue(uint8_t *aOutput, uint16_t aOutputLength) { for (uint16_t length = 0; length < aOutputLength; length++) { aOutput[length] = (uint8_t)otPlatRandomGet(); } return OT_ERROR_NONE; }
void Header::SetToken(uint8_t aTokenLength) { assert(aTokenLength <= kMaxTokenLength); uint8_t token[kMaxTokenLength] = { 0 }; for (uint8_t i = 0; i < aTokenLength; i++) { token[i] = static_cast<uint8_t>(otPlatRandomGet()); } SetToken(token, aTokenLength); }
otError otPlatRandomGetTrue(uint8_t *aOutput, uint16_t aOutputLength) { otError error = OT_ERROR_NONE; #if __SANITIZE_ADDRESS__ == 0 FILE * file = NULL; size_t readLength; otEXPECT_ACTION(aOutput && aOutputLength, error = OT_ERROR_INVALID_ARGS); file = fopen("/dev/urandom", "rb"); otEXPECT_ACTION(file != NULL, error = OT_ERROR_FAILED); readLength = fread(aOutput, 1, aOutputLength, file); otEXPECT_ACTION(readLength == aOutputLength, error = OT_ERROR_FAILED); exit: if (file != NULL) { fclose(file); } #else // __SANITIZE_ADDRESS__ /* * THE IMPLEMENTATION BELOW IS NOT COMPLIANT WITH THE THREAD SPECIFICATION. * * Address Sanitizer triggers test failures when reading random * values from /dev/urandom. The pseudo-random number generator * implementation below is only used to enable continuous * integration checks with Address Sanitizer enabled. */ otEXPECT_ACTION(aOutput && aOutputLength, error = OT_ERROR_INVALID_ARGS); for (uint16_t length = 0; length < aOutputLength; length++) { aOutput[length] = (uint8_t)otPlatRandomGet(); } exit: #endif // __SANITIZE_ADDRESS__ return error; }
ThreadError Local::Register(const Ip6::Address &aDestination) { ThreadError error = kThreadError_None; Coap::Header header; Message *message; Ip6::MessageInfo messageInfo; UpdateRloc(); mSocket.Open(&HandleUdpReceive, this); for (size_t i = 0; i < sizeof(mCoapToken); i++) { mCoapToken[i] = otPlatRandomGet(); } header.Init(); header.SetVersion(1); header.SetType(Coap::Header::kTypeConfirmable); header.SetCode(Coap::Header::kCodePost); header.SetMessageId(++mCoapMessageId); header.SetToken(mCoapToken, sizeof(mCoapToken)); header.AppendUriPathOptions(OPENTHREAD_URI_SERVER_DATA); header.AppendContentFormatOption(Coap::Header::kApplicationOctetStream); header.Finalize(); VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, error = kThreadError_NoBufs); SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength())); SuccessOrExit(error = message->Append(mTlvs, mLength)); memset(&messageInfo, 0, sizeof(messageInfo)); memcpy(&messageInfo.mPeerAddr, &aDestination, sizeof(messageInfo.mPeerAddr)); messageInfo.mPeerPort = kCoapUdpPort; SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); otLogInfoNetData("Sent network data registration\n"); exit: if (error != kThreadError_None && message != NULL) { Message::Free(*message); } return error; }
void TrickleTimer::Start(uint32_t aIntervalMin, uint32_t aIntervalMax, Mode aMode) { assert(!IsRunning()); // Set the interval limits and mode Imin = aIntervalMin; Imax = aIntervalMax; mMode = aMode; // Initialize I to [Imin, Imax] if (Imin == Imax) { I = Imin; } else { I = Imin + otPlatRandomGet() % (Imax - Imin); } // Start a new interval StartNewInterval(); }
void TestFuzz(uint32_t aSeconds) { // Set the radio capabilities to disable any Mac related timer dependencies g_testPlatRadioCaps = (otRadioCaps)(kRadioCapsAckTimeout | kRadioCapsTransmitRetries); // Set the platform function pointers g_TransmitRadioPacket.mPsdu = g_TransmitPsdu; g_testPlatRadioIsEnabled = testFuzzRadioIsEnabled; g_testPlatRadioEnable = testFuzzRadioEnable; g_testPlatRadioDisable = testFuzzRadioDisable; g_testPlatRadioReceive = testFuzzRadioReceive; g_testPlatRadioTransmit = testFuzzRadioTransmit; g_testPlatRadioGetTransmitBuffer = testFuzztRadioGetTransmitBuffer; // Initialize our timing variables uint32_t tStart = otPlatAlarmGetNow(); uint32_t tEnd = tStart + (aSeconds * 1000); otInstance *aInstance; #ifdef _WIN32 uint32_t seed = (uint32_t)time(NULL); srand(seed); Log("Initialized seed = 0x%X", seed); #endif #ifdef OPENTHREAD_MULTIPLE_INSTANCE size_t otInstanceBufferLength = 0; uint8_t *otInstanceBuffer = NULL; // Call to query the buffer size (void)otInstanceInit(NULL, &otInstanceBufferLength); // Call to allocate the buffer otInstanceBuffer = (uint8_t *)malloc(otInstanceBufferLength); VerifyOrQuit(otInstanceBuffer != NULL, "Failed to allocate otInstance"); memset(otInstanceBuffer, 0, otInstanceBufferLength); // Initialize Openthread with the buffer aInstance = otInstanceInit(otInstanceBuffer, &otInstanceBufferLength); #else aInstance = otInstanceInit(); #endif VerifyOrQuit(aInstance != NULL, "Failed to initialize otInstance"); // Start the Thread network otSetPanId(aInstance, (otPanId)0xFACE); otInterfaceUp(aInstance); otThreadStart(aInstance); uint32_t countRecv = 0; while (otPlatAlarmGetNow() < tEnd) { otProcessQueuedTasklets(aInstance); if (g_testPlatAlarmSet && otPlatAlarmGetNow() >= g_testPlatAlarmNext) { g_testPlatAlarmSet = false; otPlatAlarmFired(aInstance); } if (g_fRadioEnabled) { if (g_fTransmit) { g_fTransmit = false; otPlatRadioTransmitDone(aInstance, &g_TransmitRadioPacket, true, kThreadError_None); #ifdef DBG_FUZZ Log("<== transmit"); #endif } if (g_RecvChannel != 0) { uint8_t fuzzRecvBuff[128]; RadioPacket fuzzPacket; // Initialize the radio packet with a random length memset(&fuzzPacket, 0, sizeof(fuzzPacket)); fuzzPacket.mPsdu = fuzzRecvBuff; fuzzPacket.mChannel = g_RecvChannel; fuzzPacket.mLength = (uint8_t)(otPlatRandomGet() % 127); // Populate the length with random for (uint8_t i = 0; i < fuzzPacket.mLength; i++) { fuzzRecvBuff[i] = (uint8_t)otPlatRandomGet(); } // Clear the global flag g_RecvChannel = 0; // Indicate the receive complete otPlatRadioReceiveDone(aInstance, &fuzzPacket, kThreadError_None); countRecv++; #ifdef DBG_FUZZ Log("<== receive (%llu, %u bytes)", countRecv, fuzzPacket.mLength); #endif // Hack to get a receive poll immediately otSetChannel(aInstance, 11); } } } Log("%u packets received", countRecv); // Clean up the instance otInstanceFinalize(aInstance); #ifdef OPENTHREAD_MULTIPLE_INSTANCE free(otInstanceBuffer); #endif }
void TrickleTimer::HandleTimerFired(void) { Phase curPhase = mPhase; bool shouldContinue = true; // Default the current state to Dormant mPhase = kPhaseDormant; switch (curPhase) { // We have just reached time 't' case kPhaseTransmit: { // Are we not using redundancy or is the counter still less than it? #ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT if (k == 0 || c < k) #endif { // Invoke the transmission callback shouldContinue = TransmitFired(); } // Wait for the rest of the interval to elapse if (shouldContinue) { // If we are in plain timer mode, just randomize I and restart the interval if (mMode == kModePlainTimer) { // Initialize I to [Imin, Imax] I = Imin + otPlatRandomGet() % (Imax - Imin); // Start a new interval StartNewInterval(); } else { // Start next phase of the timer mPhase = kPhaseInterval; // Start the time for 'I - t' milliseconds TimerMilli::Start(I - t); } } break; } // We have just reached time 'I' case kPhaseInterval: { // Double 'I' to get the new interval length uint32_t newI = I == 0 ? 1 : I << 1; if (newI > Imax) { newI = Imax; } I = newI; // Invoke the interval expiration callback shouldContinue = IntervalExpiredFired(); if (shouldContinue) { // Start a new interval StartNewInterval(); } break; } default: assert(false); } }