diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab22e79..6c530ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: cmake -S test -B build/ \ -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE=Debug \ - -DBUILD_CLONE_SUBMODULES=ON \ + -DBUILD_UNIT_TESTS=ON \ -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror' make -C build/ all - name: Test @@ -35,6 +35,15 @@ jobs: uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main with: path: ./build/coverage.info + build-code-example: + runs-on: ubuntu-latest + steps: + - name: Clone This Repo + uses: actions/checkout@v2 + - name: Build code example + run: | + cmake -S test -b Build -DBUILD_CODE_EXAMPLE=ON + make -C build code_example_posix -j8 complexity: runs-on: ubuntu-latest steps: diff --git a/docs/doxygen/code_examples/backoff_algorithm_posix.c b/docs/doxygen/code_examples/backoff_algorithm_posix.c new file mode 100644 index 0000000..978a63e --- /dev/null +++ b/docs/doxygen/code_examples/backoff_algorithm_posix.c @@ -0,0 +1,84 @@ +#include "backoff_algorithm.h" +#include +#include +#include +#include +#include + +/* The maximum number of retries for the example code. */ +#define RETRY_MAX_ATTEMPTS ( 5U ) + +/* The maximum back-off delay (in milliseconds) for between retries in the example. */ +#define RETRY_MAX_BACKOFF_DELAY_MS ( 5000U ) + +/* The base back-off delay (in milliseconds) for retry configuration in the example. */ +#define RETRY_BACKOFF_BASE_MS ( 500U ) + +int main() +{ + /* @[code_example_backoffalgorithm_initializeparams] */ + /* Variables used in this example. */ + BackoffAlgorithmStatus_t retryStatus = BackoffAlgorithmSuccess; + BackoffAlgorithmContext_t retryParams; + char serverAddress[] = "amazon.com"; + uint16_t nextRetryBackoff = 0; + + /* Initialize reconnect attempts and interval. */ + BackoffAlgorithm_InitializeParams( &retryParams, + RETRY_BACKOFF_BASE_MS, + RETRY_MAX_BACKOFF_DELAY_MS, + RETRY_MAX_ATTEMPTS ); + /* @[code_example_backoffalgorithm_initializeparams] */ + + int32_t dnsStatus = -1; + struct addrinfo hints; + struct addrinfo ** pListHead = NULL; + struct timespec tp; + + /* Add hints to retrieve only TCP sockets in getaddrinfo. */ + ( void ) memset( &hints, 0, sizeof( hints ) ); + + /* Address family of either IPv4 or IPv6. */ + hints.ai_family = AF_UNSPEC; + /* TCP Socket. */ + hints.ai_socktype = ( int32_t ) SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + /* @[code_example_backoffalgorithm_getnextbackoff] */ + + /* Seed the pseudo random number generator used in this example (with call to + * rand() function provided by ISO C standard library) for use in backoff period + * calculation when retrying failed DNS resolution. */ + + /* Get current time to seed pseudo random number generator. */ + ( void ) clock_gettime( CLOCK_REALTIME, &tp ); + /* Seed pseudo random number generator with seconds. */ + srand( tp.tv_sec ); + + do + { + /* Perform a DNS lookup on the given host name. */ + dnsStatus = getaddrinfo( serverAddress, NULL, &hints, pListHead ); + + /* Retry if DNS resolution query failed. */ + if( dnsStatus != 0 ) + { + /* Generate a random number and get back-off value (in milliseconds) for the next retry. + * Note: It is recommended to use a random number generator that is seeded with + * device-specific entropy source so that backoff calculation across devices is different + * and possibility of network collision between devices attempting retries can be avoided. + * + * For the simplicity of this code example, the pseudo random number generator, rand() + * function is used. */ + retryStatus = BackoffAlgorithm_GetNextBackoff( &retryParams, rand(), &nextRetryBackoff ); + + /* Wait for the calculated backoff period before the next retry attempt of querying DNS. + * As usleep() takes nanoseconds as the parameter, we multiply the backoff period by 1000. */ + ( void ) usleep( nextRetryBackoff * 1000U ); + } + } while( ( dnsStatus != 0 ) && ( retryStatus != BackoffAlgorithmRetriesExhausted ) ); + + /* @[code_example_backoffalgorithm_getnextbackoff] */ + + return dnsStatus; +} diff --git a/docs/doxygen/config.doxyfile b/docs/doxygen/config.doxyfile index 01da3ef..665f932 100644 --- a/docs/doxygen/config.doxyfile +++ b/docs/doxygen/config.doxyfile @@ -797,7 +797,7 @@ EXCLUDE_SYMLINKS = NO # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = source/include docs/doxygen/include +EXAMPLE_PATH = source/include docs/doxygen/include docs/doxygen/code_examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and diff --git a/docs/doxygen/pages.dox b/docs/doxygen/pages.dox index 89d5e3a..c17cf6e 100644 --- a/docs/doxygen/pages.dox +++ b/docs/doxygen/pages.dox @@ -61,19 +61,34 @@ every path of execution and achieve 100% branch coverage.

*/ +/** +@page backoff_algorithm_example Code Example of backoffAlgorithm API +@brief Example POSIX application of retrying DNS resolution operation with exponential backoff-and-jitter with the backoffAlgorithm library. + +@include backoff_algorithm_posix.c + */ + /** @page backoff_algorithm_functions Functions @brief Primary functions of the backoffAlgorithm library:

@subpage define_backoffalgorithm_initializeparams
@subpage define_backoffalgorithm_getnextbackoff
+For a code example of using backoffAlgorithm library for retrying operation with exponential back-off and jitter, refer to @ref backoff_algorithm_example. + @page define_backoffalgorithm_initializeparams BackoffAlgorithm_InitializeParams @snippet backoff_algorithm.h define_backoffalgorithm_initializeparams @copydoc BackoffAlgorithm_InitializeParams +From the @ref backoff_algorithm_example, following is the part relevant to the @ref BackoffAlgorithm_InitializeParams API. +@snippet backoff_algorithm_posix.c code_example_backoffalgorithm_initializeparams + @page define_backoffalgorithm_getnextbackoff BackoffAlgorithm_GetNextBackoff -@snippet backoff_algorithm.h define_backoffalgorithm_getnextbackoff @copydoc BackoffAlgorithm_GetNextBackoff + +From the @ref backoff_algorithm_example, following is the part relevant to the @ref BackoffAlgorithm_GetNextBackoff API. +@snippet backoff_algorithm_posix.c code_example_backoffalgorithm_getnextbackoff + */