Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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;
}
Esempio n. 8
0
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();
}
Esempio n. 9
0
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
}
Esempio n. 10
0
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);
    }
}