static SntpStatus_t sendSntpPacket()

in source/core_sntp_client.c [284:368]


static SntpStatus_t sendSntpPacket( const UdpTransportInterface_t * pNetworkIntf,
                                    uint32_t timeServer,
                                    uint16_t serverPort,
                                    SntpGetTime_t getTimeFunc,
                                    const uint8_t * pPacket,
                                    uint16_t packetSize,
                                    uint32_t timeoutMs )
{
    const uint8_t * pIndex = pPacket;
    int32_t bytesSent = 0;
    SntpTimestamp_t lastSendTime;
    bool shouldRetry = false;
    SntpStatus_t status = SntpErrorSendTimeout;

    assert( pPacket != NULL );
    assert( getTimeFunc != NULL );
    assert( pNetworkIntf != NULL );
    assert( packetSize >= SNTP_PACKET_BASE_SIZE );

    /* Record the starting time of attempting to send data. This begins the retry timeout
     * window. */
    getTimeFunc( &lastSendTime );

    /* Loop until the entire packet is sent. */
    do
    {
        /* Reset flag for retrying send operation for the iteration. If request packet cannot be
         * sent and timeout has not occurred, the flag will be set later for the next iteration. */
        shouldRetry = false;

        bytesSent = pNetworkIntf->sendTo( pNetworkIntf->pUserContext,
                                          timeServer,
                                          serverPort,
                                          pIndex,
                                          packetSize );

        if( bytesSent < 0 )
        {
            LogError( ( "Unable to send request packet: Transport send failed. "
                        "ErrorCode=%ld.", ( long int ) bytesSent ) );
            status = SntpErrorNetworkFailure;
        }
        else if( bytesSent == 0 )
        {
            /* No bytes were sent over the network. Retry send if we have not timed out. */

            SntpTimestamp_t currentTime;
            uint64_t elapsedTimeMs;

            getTimeFunc( &currentTime );

            /* Calculate time elapsed since last data was sent over network. */
            elapsedTimeMs = calculateElapsedTimeMs( &currentTime, &lastSendTime );

            /* Check for timeout if we have been waiting to send any data over the network. */
            if( elapsedTimeMs >= timeoutMs )
            {
                LogError( ( "Unable to send request packet: Timed out retrying send: "
                            "SendRetryTimeout=%ums", timeoutMs ) );
                status = SntpErrorSendTimeout;
            }
            else
            {
                shouldRetry = true;
            }
        }

        /* Partial sends are not supported by UDP, which only supports sending the entire datagram as a whole.
         * Thus, if the transport send function returns status representing partial send, it will be treated as failure. */
        else if( bytesSent != ( int32_t ) packetSize )
        {
            LogError( ( "Unable to send request packet: Transport send returned unexpected bytes sent. "
                        "ReturnCode=%ld, ExpectedCode=%u", ( long int ) bytesSent, packetSize ) );

            status = SntpErrorNetworkFailure;
        }
        else
        {
            /* The time request packet has been sent over the network. */
            status = SntpSuccess;
        }
    } while( shouldRetry == true );

    return status;
}