Restructure platform directory (#382)

This updates the platform and logging directory and moves it to the following places:
FreeRTOS\FreeRTOS-Plus\Source\Utilities
FreeRTOS\FreeRTOS-Plus\Source\Application-Protocols\network_transport\freertos_plus_tcp

Project files are updated to follow suite. All updated demos are tested to work as expected.
This commit is contained in:
Oscar Michael Abrina 2020-11-05 16:47:43 -08:00 committed by GitHub
parent 330b8c002f
commit 01e59a036c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 224 additions and 218 deletions

View file

@ -20,7 +20,7 @@
*/
/**
* @file freertos_plus_tcp_sockets_wrapper.c
* @file sockets_wrapper.c
* @brief FreeRTOS Sockets connect and disconnect wrapper implementation.
*/
@ -30,7 +30,7 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "freertos_plus_tcp_sockets_wrapper.h"
#include "sockets_wrapper.h"
/*-----------------------------------------------------------*/

View file

@ -20,12 +20,12 @@
*/
/**
* @file freertos_plus_tcp_sockets_wrapper.h
* @file sockets_wrapper.h
* @brief FreeRTOS Sockets connect and disconnect function wrapper.
*/
#ifndef FREERTOS_SOCKETS_WRAPPER_H_
#define FREERTOS_SOCKETS_WRAPPER_H_
#ifndef SOCKETS_WRAPPER_H
#define SOCKETS_WRAPPER_H
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
@ -83,4 +83,4 @@ BaseType_t Sockets_Connect( Socket_t * pTcpSocket,
*/
void Sockets_Disconnect( Socket_t tcpSocket );
#endif /* ifndef FREERTOS_SOCKETS_WRAPPER_H_ */
#endif /* ifndef SOCKETS_WRAPPER_H */

View file

@ -36,10 +36,10 @@
#include "FreeRTOS_Sockets.h"
/* TLS transport header. */
#include "freertos_plus_tcp_mbedtls.h"
#include "using_mbedtls.h"
/* FreeRTOS Socket wrapper include. */
#include "freertos_plus_tcp_sockets_wrapper.h"
#include "sockets_wrapper.h"
/* mbedTLS util includes. */
#include "mbedtls_error.h"

View file

@ -24,8 +24,8 @@
* @brief TLS transport interface header.
*/
#ifndef TLS_FREERTOS_H_
#define TLS_FREERTOS_H_
#ifndef USING_MBEDTLS
#define USING_MBEDTLS
/**************************************************/
/******* DO NOT CHANGE the following order ********/
@ -196,4 +196,4 @@ int32_t TLS_FreeRTOS_send( NetworkContext_t * pNetworkContext,
const void * pBuffer,
size_t bytesToSend );
#endif /* ifndef TLS_FREERTOS_H_ */
#endif /* ifndef USING_MBEDTLS */

View file

@ -39,10 +39,10 @@
#include "FreeRTOS_Sockets.h"
/* TLS transport header. */
#include "freertos_plus_tcp_mbedtls_pkcs11.h"
#include "using_mbedtls_pkcs11.h"
/* FreeRTOS Socket wrapper include. */
#include "freertos_plus_tcp_sockets_wrapper.h"
#include "sockets_wrapper.h"
/* mbedTLS util includes. */
#include "mbedtls_error.h"

View file

@ -27,8 +27,8 @@
* PKCS #11 when using TLS.
*/
#ifndef TLS_FREERTOS_H_
#define TLS_FREERTOS_H_
#ifndef USING_MBEDTLS_PKCS11
#define USING_MBEDTLS_PKCS11
/**************************************************/
/******* DO NOT CHANGE the following order ********/
@ -209,4 +209,4 @@ int32_t TLS_FreeRTOS_send( NetworkContext_t * pNetworkContext,
const void * pBuffer,
size_t bytesToSend );
#endif /* ifndef TLS_FREERTOS_H_ */
#endif /* ifndef USING_MBEDTLS_PKCS11 */

View file

@ -30,10 +30,10 @@
#include "FreeRTOS_Sockets.h"
/* FreeRTOS Socket wrapper include. */
#include "freertos_plus_tcp_sockets_wrapper.h"
#include "sockets_wrapper.h"
/* Transport interface include. */
#include "freertos_plus_tcp_plaintext.h"
#include "using_plaintext.h"
PlaintextTransportStatus_t Plaintext_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
const char * pHostName,

View file

@ -19,8 +19,8 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef TRANSPORT_INTERFACE_FREERTOS_H_
#define TRANSPORT_INTERFACE_FREERTOS_H_
#ifndef USING_PLAINTEXT_H
#define USING_PLAINTEXT_H
/**************************************************/
/******* DO NOT CHANGE the following order ********/
@ -127,4 +127,4 @@ int32_t Plaintext_FreeRTOS_send( NetworkContext_t * pNetworkContext,
const void * pBuffer,
size_t bytesToSend );
#endif /* ifndef TRANSPORT_INTERFACE_FREERTOS_H_ */
#endif /* ifndef USING_PLAINTEXT_H */

View file

@ -0,0 +1,6 @@
Building a network transport implementation:
1. Go into the sub directory for the TCP/IP stack you are using (e.g. freertos_plus_tcp).
2. Build the wrapper file located in the directory (i.e. sockets_wrapper.c).
3. Select an additional folder based on the TLS stack you are using (e.g. using_mbedtls), or the using_plaintext folder if not using TLS.
4. Build and include all files from the selected folder.

View file

@ -1,63 +0,0 @@
/*
* FreeRTOS Error Code Stringification utilities for mbed TLS v2.16.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file mbedtls_error.h
* @brief Stringification utilities for high-level and low-level codes of mbed TLS.
*/
#ifndef MBEDTLS_ERROR_H_
#define MBEDTLS_ERROR_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Translate an mbed TLS high level code into its string representation.
* Result includes a terminating null byte.
*
* @param errnum The error code containing the high-level code.
* @return The string representation if high-level code is present; otherwise NULL.
*
* @warning The string returned by this function must never be modified.
*/
const char * mbedtls_strerror_highlevel( int32_t errnum );
/**
* @brief Translate an mbed TLS low level code into its string representation,
* Result includes a terminating null byte.
*
* @param errnum The error code containing the low-level code.
* @return The string representation if low-level code is present; otherwise NULL.
*
* @warning The string returned by this function must never be modified.
*/
const char * mbedtls_strerror_lowlevel( int32_t errnum );
#ifdef __cplusplus
}
#endif
#endif /* ifndef MBEDTLS_ERROR_H_ */

View file

@ -1,286 +0,0 @@
/*
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* @file mbedtls_freertos_port.c
* @brief Implements mbed TLS platform functions for FreeRTOS.
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "FreeRTOS_Sockets.h"
/* mbed TLS includes. */
#include "mbedtls_config.h"
#include "threading_alt.h"
#include "mbedtls/entropy.h"
/*-----------------------------------------------------------*/
/**
* @brief Allocates memory for an array of members.
*
* @param[in] nmemb Number of members that need to be allocated.
* @param[in] size Size of each member.
*
* @return Pointer to the beginning of newly allocated memory.
*/
void * mbedtls_platform_calloc( size_t nmemb,
size_t size )
{
size_t totalSize = nmemb * size;
void * pBuffer = NULL;
/* Check that neither nmemb nor size were 0. */
if( totalSize > 0 )
{
/* Overflow check. */
if( ( totalSize / size ) == nmemb )
{
pBuffer = pvPortMalloc( totalSize );
if( pBuffer != NULL )
{
( void ) memset( pBuffer, 0x00, totalSize );
}
}
}
return pBuffer;
}
/*-----------------------------------------------------------*/
/**
* @brief Frees the space previously allocated by calloc.
*
* @param[in] ptr Pointer to the memory to be freed.
*/
void mbedtls_platform_free( void * ptr )
{
vPortFree( ptr );
}
/*-----------------------------------------------------------*/
/**
* @brief Sends data over FreeRTOS+TCP sockets.
*
* @param[in] ctx The network context containing the socket handle.
* @param[in] buf Buffer containing the bytes to send.
* @param[in] len Number of bytes to send from the buffer.
*
* @return Number of bytes sent on success; else a negative value.
*/
int mbedtls_platform_send( void * ctx,
const unsigned char * buf,
size_t len )
{
Socket_t socket;
configASSERT( ctx != NULL );
configASSERT( buf != NULL );
socket = ( Socket_t ) ctx;
return ( int ) FreeRTOS_send( socket, buf, len, 0 );
}
/*-----------------------------------------------------------*/
/**
* @brief Receives data from FreeRTOS+TCP socket.
*
* @param[in] ctx The network context containing the socket handle.
* @param[out] buf Buffer to receive bytes into.
* @param[in] len Number of bytes to receive from the network.
*
* @return Number of bytes received if successful; Negative value on error.
*/
int mbedtls_platform_recv( void * ctx,
unsigned char * buf,
size_t len )
{
Socket_t socket;
configASSERT( ctx != NULL );
configASSERT( buf != NULL );
socket = ( Socket_t ) ctx;
return ( int ) FreeRTOS_recv( socket, buf, len, 0 );
}
/*-----------------------------------------------------------*/
/**
* @brief Creates a mutex.
*
* @param[in, out] pMutex mbedtls mutex handle.
*/
void mbedtls_platform_mutex_init( mbedtls_threading_mutex_t * pMutex )
{
configASSERT( pMutex != NULL );
/* Create a statically-allocated FreeRTOS mutex. This should never fail as
* storage is provided. */
pMutex->mutexHandle = xSemaphoreCreateMutexStatic( &( pMutex->mutexStorage ) );
configASSERT( pMutex->mutexHandle != NULL );
}
/*-----------------------------------------------------------*/
/**
* @brief Frees a mutex.
*
* @param[in] pMutex mbedtls mutex handle.
*
* @note This function is an empty stub as nothing needs to be done to free
* a statically allocated FreeRTOS mutex.
*/
void mbedtls_platform_mutex_free( mbedtls_threading_mutex_t * pMutex )
{
/* Nothing needs to be done to free a statically-allocated FreeRTOS mutex. */
( void ) pMutex;
}
/*-----------------------------------------------------------*/
/**
* @brief Function to lock a mutex.
*
* @param[in] pMutex mbedtls mutex handle.
*
* @return 0 (success) is always returned as any other failure is asserted.
*/
int mbedtls_platform_mutex_lock( mbedtls_threading_mutex_t * pMutex )
{
BaseType_t mutexStatus = 0;
configASSERT( pMutex != NULL );
/* mutexStatus is not used if asserts are disabled. */
( void ) mutexStatus;
/* This function should never fail if the mutex is initialized. */
mutexStatus = xSemaphoreTake( pMutex->mutexHandle, portMAX_DELAY );
configASSERT( mutexStatus == pdTRUE );
return 0;
}
/*-----------------------------------------------------------*/
/**
* @brief Function to unlock a mutex.
*
* @param[in] pMutex mbedtls mutex handle.
*
* @return 0 is always returned as any other failure is asserted.
*/
int mbedtls_platform_mutex_unlock( mbedtls_threading_mutex_t * pMutex )
{
BaseType_t mutexStatus = 0;
configASSERT( pMutex != NULL );
/* mutexStatus is not used if asserts are disabled. */
( void ) mutexStatus;
/* This function should never fail if the mutex is initialized. */
mutexStatus = xSemaphoreGive( pMutex->mutexHandle );
configASSERT( mutexStatus == pdTRUE );
return 0;
}
/*-----------------------------------------------------------*/
/**
* @brief Function to generate a random number.
*
* @param[in] data Callback context.
* @param[out] output The address of the buffer that receives the random number.
* @param[in] len Maximum size of the random number to be generated.
* @param[out] olen The size, in bytes, of the #output buffer.
*
* @return 0 if no critical failures occurred,
* MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise.
*/
int mbedtls_platform_entropy_poll( void * data,
unsigned char * output,
size_t len,
size_t * olen )
{
int status = 0;
NTSTATUS rngStatus = 0;
configASSERT( output != NULL );
configASSERT( olen != NULL );
/* Context is not used by this function. */
( void ) data;
/* TLS requires a secure random number generator; use the RNG provided
* by Windows. This function MUST be re-implemented for other platforms. */
rngStatus =
BCryptGenRandom( NULL, output, len, BCRYPT_USE_SYSTEM_PREFERRED_RNG );
if( rngStatus == 0 )
{
/* All random bytes generated. */
*olen = len;
}
else
{
/* RNG failure. */
*olen = 0;
status = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
return status;
}
/*-----------------------------------------------------------*/
/**
* @brief Function to generate a random number based on a hardware poll.
*
* For this FreeRTOS Windows port, this function is redirected by calling
* #mbedtls_platform_entropy_poll.
*
* @param[in] data Callback context.
* @param[out] output The address of the buffer that receives the random number.
* @param[in] len Maximum size of the random number to be generated.
* @param[out] olen The size, in bytes, of the #output buffer.
*
* @return 0 if no critical failures occurred,
* MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise.
*/
int mbedtls_hardware_poll( void * data,
unsigned char * output,
size_t len,
size_t * olen )
{
return mbedtls_platform_entropy_poll( data, output, len, olen );
}
/*-----------------------------------------------------------*/

View file

@ -1,54 +0,0 @@
/*
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file threading_alt.h
* @brief mbed TLS threading functions implemented for FreeRTOS.
*/
#ifndef MBEDTLS_THREADING_ALT_H_
#define MBEDTLS_THREADING_ALT_H_
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "semphr.h"
/**
* @brief mbed TLS mutex type.
*
* mbed TLS requires platform specific definition for the mutext type. Defining the type for
* FreeRTOS with FreeRTOS semaphore
* handle and semaphore storage as members.
*/
typedef struct mbedtls_threading_mutex
{
SemaphoreHandle_t mutexHandle;
StaticSemaphore_t mutexStorage;
} mbedtls_threading_mutex_t;
/* mbed TLS mutex functions. */
void mbedtls_platform_mutex_init( mbedtls_threading_mutex_t * pMutex );
void mbedtls_platform_mutex_free( mbedtls_threading_mutex_t * pMutex );
int mbedtls_platform_mutex_lock( mbedtls_threading_mutex_t * pMutex );
int mbedtls_platform_mutex_unlock( mbedtls_threading_mutex_t * pMutex );
#endif /* ifndef MBEDTLS_THREADING_ALT_H_ */

View file

@ -1,101 +0,0 @@
/*
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file retry_utils.c
* @brief Utility implementation of backoff logic, used for attempting retries of failed processes.
*/
/* Standard includes. */
#include <stdint.h>
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "retry_utils.h"
#define MILLISECONDS_PER_SECOND ( 1000U ) /**< @brief Milliseconds per second. */
extern UBaseType_t uxRand( void );
/*-----------------------------------------------------------*/
RetryUtilsStatus_t RetryUtils_BackoffAndSleep( RetryUtilsParams_t * pRetryParams )
{
RetryUtilsStatus_t status = RetryUtilsRetriesExhausted;
uint32_t backOffDelayMs = 0;
/* If pRetryParams->maxRetryAttempts is set to 0, try forever. */
if( ( pRetryParams->attemptsDone < pRetryParams->maxRetryAttempts ) ||
( 0U == pRetryParams->maxRetryAttempts ) )
{
/* Choose a random value for back-off time between 0 and the max jitter value. */
backOffDelayMs = uxRand() % pRetryParams->nextJitterMax;
/* Wait for backoff time to expire for the next retry. */
vTaskDelay( pdMS_TO_TICKS( backOffDelayMs * MILLISECONDS_PER_SECOND ) );
/* Increment backoff counts. */
pRetryParams->attemptsDone++;
/* Double the max jitter value for the next retry attempt, only
* if the new value will be less than the max backoff time value. */
if( pRetryParams->nextJitterMax < ( MAX_RETRY_BACKOFF_SECONDS / 2U ) )
{
pRetryParams->nextJitterMax += pRetryParams->nextJitterMax;
}
else
{
pRetryParams->nextJitterMax = MAX_RETRY_BACKOFF_SECONDS;
}
status = RetryUtilsSuccess;
}
else
{
/* When max retry attempts are exhausted, let application know by
* returning RetryUtilsRetriesExhausted. Application may choose to
* restart the retry process after calling RetryUtils_ParamsReset(). */
status = RetryUtilsRetriesExhausted;
RetryUtils_ParamsReset( pRetryParams );
}
return status;
}
/*-----------------------------------------------------------*/
void RetryUtils_ParamsReset( RetryUtilsParams_t * pRetryParams )
{
uint32_t jitter = 0;
/* Reset attempts done to zero so that the next retry cycle can start. */
pRetryParams->attemptsDone = 0;
/* Calculate jitter value using picking a random number. */
jitter = ( uxRand() % MAX_JITTER_VALUE_SECONDS );
/* Reset the backoff value to the initial time out value plus jitter. */
pRetryParams->nextJitterMax = INITIAL_RETRY_BACKOFF_SECONDS + jitter;
}
/*-----------------------------------------------------------*/

View file

@ -1,245 +0,0 @@
/*
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file retry_utils.h
* @brief Declaration of the exponential backoff retry logic utility functions
* and constants.
*/
#ifndef RETRY_UTILS_H_
#define RETRY_UTILS_H_
/* Standard include. */
#include <stdint.h>
/**
* @page retryutils_page Retry Utilities
* @brief An abstraction of utilities for retrying with exponential back off and
* jitter.
*
* @section retryutils_overview Overview
* The retry utilities are a set of APIs that aid in retrying with exponential
* backoff and jitter. Exponential backoff with jitter is strongly recommended
* for retrying failed actions over the network with servers. Please see
* https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ for
* more information about the benefits with AWS.
*
* Exponential backoff with jitter is typically used when retrying a failed
* connection to the server. In an environment with poor connectivity, a client
* can get disconnected at any time. A backoff strategy helps the client to
* conserve battery by not repeatedly attempting reconnections when they are
* unlikely to succeed.
*
* Before retrying the failed communication to the server there is a quiet period.
* In this quiet period, the task that is retrying must sleep for some random
* amount of seconds between 0 and the lesser of a base value and a predefined
* maximum. The base is doubled with each retry attempt until the maximum is
* reached.<br>
*
* > sleep_seconds = random_between( 0, min( 2<sup>attempts_count</sup> * base_seconds, maximum_seconds ) )
*
* @section retryutils_implementation Implementing Retry Utils
*
* The functions that must be implemented are:<br>
* - @ref RetryUtils_ParamsReset
* - @ref RetryUtils_BackoffAndSleep
*
* The functions are used as shown in the diagram below. This is the exponential
* backoff with jitter loop:
*
* @image html retry_utils_flow.png width=25%
*
* The following steps give guidance on implementing the Retry Utils. An example
* implementation of the Retry Utils for a POSIX platform can be found in file
* @ref retry_utils_posix.c.
*
* -# Implementing @ref RetryUtils_ParamsReset
* @snippet this define_retryutils_paramsreset
*<br>
* This function initializes @ref RetryUtilsParams_t. It is expected to set
* @ref RetryUtilsParams_t.attemptsDone to zero. It is also expected to set
* @ref RetryUtilsParams_t.nextJitterMax to @ref INITIAL_RETRY_BACKOFF_SECONDS
* plus some random amount of seconds, jitter. This jitter is a random number
* between 0 and @ref MAX_JITTER_VALUE_SECONDS. This function must be called
* before entering the exponential backoff with jitter loop using
* @ref RetryUtils_BackoffAndSleep.<br><br>
* Please follow the example below to implement your own @ref RetryUtils_ParamsReset.
* The lines with FIXME comments should be updated.
* @code{c}
* void RetryUtils_ParamsReset( RetryUtilsParams_t * pRetryParams )
* {
* uint32_t jitter = 0;
*
* // Reset attempts done to zero so that the next retry cycle can start.
* pRetryParams->attemptsDone = 0;
*
* // Seed pseudo random number generator with the current time. FIXME: Your
* // system may have another method to retrieve the current time to seed the
* // pseudo random number generator.
* srand( time( NULL ) );
*
* // Calculate jitter value using picking a random number.
* jitter = ( rand() % MAX_JITTER_VALUE_SECONDS );
*
* // Reset the backoff value to the initial time out value plus jitter.
* pRetryParams->nextJitterMax = INITIAL_RETRY_BACKOFF_SECONDS + jitter;
* }
* @endcode<br>
*
* -# Implementing @ref RetryUtils_BackoffAndSleep
* @snippet this define_retryutils_backoffandsleep
* <br>
* When this function is invoked, the calling task is expected to sleep a random
* number of seconds between 0 and @ref RetryUtilsParams_t.nextJitterMax. After
* sleeping this function must double @ref RetryUtilsParams_t.nextJitterMax, but
* not exceeding @ref MAX_RETRY_BACKOFF_SECONDS. When @ref RetryUtilsParams_t.maxRetryAttempts
* are reached this function should return @ref RetryUtilsRetriesExhausted, unless
* @ref RetryUtilsParams_t.maxRetryAttempts is set to zero.
* When @ref RetryUtilsRetriesExhausted is returned the calling application can
* stop trying with a failure, or it can call @ref RetryUtils_ParamsReset again
* and restart the exponential back off with jitter loop.<br><br>
* Please follow the example below to implement your own @ref RetryUtils_BackoffAndSleep.
* The lines with FIXME comments should be updated.
* @code{c}
* RetryUtilsStatus_t RetryUtils_BackoffAndSleep( RetryUtilsParams_t * pRetryParams )
* {
* RetryUtilsStatus_t status = RetryUtilsRetriesExhausted;
* // The quiet period delay in seconds.
* int backOffDelay = 0;
*
* // If pRetryParams->maxRetryAttempts is set to 0, try forever.
* if( ( pRetryParams->attemptsDone < pRetryParams->maxRetryAttempts ) ||
* ( 0U == pRetryParams->maxRetryAttempts ) )
* {
* // Choose a random value for back-off time between 0 and the max jitter value.
* backOffDelay = rand() % pRetryParams->nextJitterMax;
*
* // Wait for backoff time to expire for the next retry.
* ( void ) myThreadSleepFunction( backOffDelay ); // FIXME: Replace with your system's thread sleep function.
*
* // Increment backoff counts.
* pRetryParams->attemptsDone++;
*
* // Double the max jitter value for the next retry attempt, only
* // if the new value will be less than the max backoff time value.
* if( pRetryParams->nextJitterMax < ( MAX_RETRY_BACKOFF_SECONDS / 2U ) )
* {
* pRetryParams->nextJitterMax += pRetryParams->nextJitterMax;
* }
* else
* {
* pRetryParams->nextJitterMax = MAX_RETRY_BACKOFF_SECONDS;
* }
*
* status = RetryUtilsSuccess;
* }
* else
* {
* // When max retry attempts are exhausted, let application know by
* // returning RetryUtilsRetriesExhausted. Application may choose to
* // restart the retry process after calling RetryUtils_ParamsReset().
* status = RetryUtilsRetriesExhausted;
* RetryUtils_ParamsReset( pRetryParams );
* }
*
* return status;
* }
* @endcode
*/
/**
* @brief Max number of retry attempts. Set this value to 0 if the client must
* retry forever.
*/
#define MAX_RETRY_ATTEMPTS 4U
/**
* @brief Initial fixed backoff value in seconds between two successive
* retries. A random jitter value is added to every backoff value.
*/
#define INITIAL_RETRY_BACKOFF_SECONDS 1U
/**
* @brief Max backoff value in seconds.
*/
#define MAX_RETRY_BACKOFF_SECONDS 128U
/**
* @brief Max jitter value in seconds.
*/
#define MAX_JITTER_VALUE_SECONDS 5U
/**
* @brief Status for @ref RetryUtils_BackoffAndSleep.
*/
typedef enum RetryUtilsStatus
{
RetryUtilsSuccess = 0, /**< @brief The function returned successfully after sleeping. */
RetryUtilsRetriesExhausted /**< @brief The function exhausted all retry attempts. */
} RetryUtilsStatus_t;
/**
* @brief Represents parameters required for retry logic.
*/
typedef struct RetryUtilsParams
{
/**
* @brief Max number of retry attempts. Set this value to 0 if the client must
* retry forever.
*/
uint32_t maxRetryAttempts;
/**
* @brief The cumulative count of backoff delay cycles completed
* for retries.
*/
uint32_t attemptsDone;
/**
* @brief The max jitter value for backoff time in retry attempt.
*/
uint32_t nextJitterMax;
} RetryUtilsParams_t;
/**
* @brief Resets the retry timeout value and number of attempts.
* This function must be called by the application before a new retry attempt.
*
* @param[in, out] pRetryParams Structure containing attempts done and timeout
* value.
*/
void RetryUtils_ParamsReset( RetryUtilsParams_t * pRetryParams );
/**
* @brief Simple platform specific exponential backoff function. The application
* must use this function between retry failures to add exponential delay.
* This function will block the calling task for the current timeout value.
*
* @param[in, out] pRetryParams Structure containing retry parameters.
*
* @return #RetryUtilsSuccess after a successful sleep, #RetryUtilsRetriesExhausted
* when all attempts are exhausted.
*/
RetryUtilsStatus_t RetryUtils_BackoffAndSleep( RetryUtilsParams_t * pRetryParams );
#endif /* ifndef RETRY_UTILS_H_ */