From ac8e94a7331ac262d1869403895b87e0fe699f05 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 29 May 2019 14:17:39 -0500 Subject: [PATCH 001/264] Update version numbers for next planned release, update checklist --- CMakeLists.txt | 2 +- docs/Doxyfile | 2 +- tools/version/release_checklist.md | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d303b992..18cc755fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.3) ########################## Global Project Attributes ########################## -project(lwpa VERSION 0.2.0) +project(lwpa VERSION 0.3.0) if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) if (MSVC) diff --git a/docs/Doxyfile b/docs/Doxyfile index 29848626a..e2d0ede71 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = lwpa # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.2.0 +PROJECT_NUMBER = 0.3.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/version/release_checklist.md b/tools/version/release_checklist.md index c4f111c96..2b9682233 100644 --- a/tools/version/release_checklist.md +++ b/tools/version/release_checklist.md @@ -17,3 +17,7 @@ * Include `-r` flag to specify a release build - [ ] Mark as release on the releases page - [ ] Create build report +- [ ] Merge `master` back into `develop` +- [ ] Update 3-digit versions to next planned version in all relevant places: + * CMakeLists.txt + * Doxyfile From 7e91e08fd1a164ffc064120c9997280ac0dbe684 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 29 May 2019 14:21:10 -0500 Subject: [PATCH 002/264] Update doxygen colors for next release number --- docs/Doxyfile | 4 ++-- tools/version/release_checklist.md | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/Doxyfile b/docs/Doxyfile index e2d0ede71..61990604d 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -1226,7 +1226,7 @@ HTML_EXTRA_FILES = # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_COLORSTYLE_HUE = 115 +HTML_COLORSTYLE_HUE = 37 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A @@ -1234,7 +1234,7 @@ HTML_COLORSTYLE_HUE = 115 # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_COLORSTYLE_SAT = 76 +HTML_COLORSTYLE_SAT = 85 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 diff --git a/tools/version/release_checklist.md b/tools/version/release_checklist.md index 2b9682233..188a5f8b9 100644 --- a/tools/version/release_checklist.md +++ b/tools/version/release_checklist.md @@ -18,6 +18,10 @@ - [ ] Mark as release on the releases page - [ ] Create build report - [ ] Merge `master` back into `develop` + +## Starting work on a new release + - [ ] Update 3-digit versions to next planned version in all relevant places: * CMakeLists.txt * Doxyfile +- [ ] Pick a new color for Doxygen From a2eb6de9a14be66ba61a594902ed1be13668c134 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 29 May 2019 16:35:39 -0500 Subject: [PATCH 003/264] Add third party software checking to release checklist --- tools/version/release_checklist.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/version/release_checklist.md b/tools/version/release_checklist.md index 188a5f8b9..9defe1e47 100644 --- a/tools/version/release_checklist.md +++ b/tools/version/release_checklist.md @@ -3,6 +3,8 @@ - [ ] Make sure there is a clean/working build on the `develop` branch. - [ ] Review and update `CHANGELOG.md` - [ ] Check `docs/mainpage.md` and `README.md` to make sure they are still accurate +- [ ] Check `ThirdPartySoftware.txt` to make sure it is still accurate and doesn't need any + additions - [ ] Generate docs for the version * Follow `tools/ci/publish_docs.sh` manually, except replace "head" with version number in the form "vM.m" From 1fc3a84b3260638b74fd90c88920fe3e9f0142fd Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 31 May 2019 18:13:17 -0500 Subject: [PATCH 004/264] Add preliminary toolchain file for MQX/Kinetis/CW --- .../codewarrior-kinetis-mqx.cmake | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake diff --git a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake new file mode 100644 index 000000000..1689d948c --- /dev/null +++ b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake @@ -0,0 +1,43 @@ +# A CMake toolchain file for cross-compiling for NXP Kinetis (ARM Cortex-M4) with MQX RTOS and the +# CodeWarrior 10.6 gcc toolchain. +# +# Usage: cmake -DCMAKE_TOOLCHAIN_FILE=../tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake \ +# -DMQX_BOARD_DIR=path/to/mqx/board/dir .. +# +# MQX_BOARD_DIR can also be set in this file so that it does not have to be provided at the command +# line, like so: +# set(MQX_BOARD_DIR path/to/mqx/board/dir) + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR ARM) + +if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) + message(FATAL_ERROR "CodeWarrior is Windows-only.") +endif() + +if(NOT DEFINED CODEWARRIOR_ROOT) + set(CODEWARRIOR_ROOT "C:/Freescale/CW MCU v10.6") # The default install location on Windows. +endif() + +set(TOOLS_ROOT ${CODEWARRIOR_ROOT}/Cross_Tools/arm-none-eabi-gcc-4_7_3) +set(CMAKE_C_COMPILER ${TOOLS_ROOT}/bin/arm-none-eabi-gcc.exe) +set(CMAKE_CXX_COMPILER ${TOOLS_ROOT}/bin/arm-none-eabi-g++.exe) + +set(LWPA_PLATFORM mqx) +add_compile_options( + -nostdinc + -ffunction-sections + -fdata-sections + -Wall + -std=gnu99 + -fno-strict-aliasing + -fmessage-length=0 + -specs=ewl_c9x.specs +) +add_compile_definitions(_EWL_C99 _DEBUG) +include_directories( + ${CODEWARRIOR_ROOT}/MCU/ARM_GCC_Support/ewl/EWL_C/include + ${CODEWARRIOR_ROOT}/MCU/ARM_GCC_Support/ewl/EWL_Runtime/include +) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) From b87901fc6ad67c9fdd17dab1e16936312fce2a41 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 31 May 2019 18:31:00 -0500 Subject: [PATCH 005/264] Add preliminary toolchain file for MQX/Kinetis/IAR --- .../codewarrior-kinetis-mqx.cmake | 14 ++++---- .../cross-toolchains/iar-kinetis-mqx.cmake | 33 +++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake diff --git a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake index 1689d948c..e2d51b656 100644 --- a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake +++ b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake @@ -15,13 +15,13 @@ if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) message(FATAL_ERROR "CodeWarrior is Windows-only.") endif() -if(NOT DEFINED CODEWARRIOR_ROOT) - set(CODEWARRIOR_ROOT "C:/Freescale/CW MCU v10.6") # The default install location on Windows. +if(NOT DEFINED CODEWARRIOR_INSTALL_DIR) + set(CODEWARRIOR_INSTALL_DIR "C:/Freescale/CW MCU v10.6") # The default install location on Windows. endif() -set(TOOLS_ROOT ${CODEWARRIOR_ROOT}/Cross_Tools/arm-none-eabi-gcc-4_7_3) -set(CMAKE_C_COMPILER ${TOOLS_ROOT}/bin/arm-none-eabi-gcc.exe) -set(CMAKE_CXX_COMPILER ${TOOLS_ROOT}/bin/arm-none-eabi-g++.exe) +set(TOOLS_DIR ${CODEWARRIOR_INSTALL_DIR}/Cross_Tools/arm-none-eabi-gcc-4_7_3) +set(CMAKE_C_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-gcc.exe) +set(CMAKE_CXX_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-g++.exe) set(LWPA_PLATFORM mqx) add_compile_options( @@ -36,8 +36,8 @@ add_compile_options( ) add_compile_definitions(_EWL_C99 _DEBUG) include_directories( - ${CODEWARRIOR_ROOT}/MCU/ARM_GCC_Support/ewl/EWL_C/include - ${CODEWARRIOR_ROOT}/MCU/ARM_GCC_Support/ewl/EWL_Runtime/include + ${CODEWARRIOR_INSTALL_DIR}/MCU/ARM_GCC_Support/ewl/EWL_C/include + ${CODEWARRIOR_INSTALL_DIR}/MCU/ARM_GCC_Support/ewl/EWL_Runtime/include ) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) diff --git a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake new file mode 100644 index 000000000..c7619d375 --- /dev/null +++ b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake @@ -0,0 +1,33 @@ +# A CMake toolchain file for cross-compiling for NXP Kinetis (ARM Cortex-M4) with MQX RTOS and the +# IAR Embedded Workbench toolchain. +# +# Usage: cmake -DCMAKE_TOOLCHAIN_FILE=../tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake \ +# -DMQX_BOARD_DIR=path/to/mqx/board/dir .. +# +# MQX_BOARD_DIR can also be set in this file so that it does not have to be provided at the command +# line, like so: +# set(MQX_BOARD_DIR path/to/mqx/board/dir) + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR ARM) + +if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) + message(FATAL_ERROR "IAR is Windows-only.") +endif() + +if(NOT DEFINED IAR_INSTALL_DIR) + set(IAR_INSTALL_DIR "C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.5") # The default install location on Windows. +endif() + +set(CMAKE_C_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe) +set(CMAKE_CXX_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe) + +set(LWPA_PLATFORM mqx) +add_compile_options( + --endian=little + --cpu=Cortex-M4 + --fpu=VFPv4_sp + --dlib_config normal +) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) From 92fa85eca411296c874242d1bfe07e2e7d8d1078 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 3 Jun 2019 12:49:01 -0500 Subject: [PATCH 006/264] Add placeholder common for MQX --- src/lwpa_plat/mqx/lwpa/common.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/lwpa_plat/mqx/lwpa/common.c diff --git a/src/lwpa_plat/mqx/lwpa/common.c b/src/lwpa_plat/mqx/lwpa/common.c new file mode 100644 index 000000000..e69de29bb From 71284a93b6764e248e284c7da2b6e7b0a0a6557e Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 3 Jun 2019 13:03:46 -0500 Subject: [PATCH 007/264] Add newest clang-format from style docs, and do a reformatting pass --- .clang-format | 2 +- include/lwpa/common.h | 5 +- include/lwpa/error.h | 2 +- include/lwpa/lock.h | 12 +- include/lwpa/log.h | 24 +-- include/lwpa/mempool.h | 16 +- include/lwpa/netint.h | 6 +- include/lwpa/pdu.h | 10 +- include/lwpa/rbtree.h | 66 +++--- include/lwpa/root_layer_pdu.h | 24 +-- include/lwpa/socket.h | 58 +++--- include/lwpa/thread.h | 4 +- include/lwpa/timer.h | 2 +- include/lwpa/uuid.h | 16 +- include/lwpa_mock/socket.h | 46 ++-- include/lwpa_plat/freertos/lwpa/plat_lock.h | 28 +-- include/lwpa_plat/freertos/lwpa/plat_thread.h | 12 +- include/lwpa_plat/linux/lwpa/plat_socket.h | 5 +- include/lwpa_plat/mqx/lwpa/plat_lock.h | 18 +- include/lwpa_plat/mqx/lwpa/plat_socket.h | 4 +- include/lwpa_plat/mqx/lwpa/plat_thread.h | 12 +- include/lwpa_plat/windows/lwpa/plat_lock.h | 10 +- include/lwpa_plat/windows/lwpa/plat_socket.h | 8 +- include/lwpa_plat/windows/lwpa/plat_thread.h | 8 +- src/lwpa/log.c | 41 ++-- src/lwpa/md5.h | 13 +- src/lwpa/md5c.c | 22 +- src/lwpa/mempool.c | 22 +- src/lwpa/pdu.c | 2 +- src/lwpa/rbtree.c | 78 +++---- src/lwpa/root_layer_pdu.c | 32 +-- src/lwpa/uuid.c | 18 +- src/lwpa_mock/socket.c | 46 ++-- src/lwpa_plat/freertos_lwip/lwpa/lock.c | 32 +-- src/lwpa_plat/freertos_lwip/lwpa/netint.c | 34 +-- src/lwpa_plat/freertos_lwip/lwpa/socket.c | 94 ++++----- src/lwpa_plat/freertos_lwip/lwpa/thread.c | 8 +- src/lwpa_plat/linux/lwpa/common.c | 2 +- src/lwpa_plat/linux/lwpa/plat_uuid.c | 6 +- src/lwpa_plat/linux/lwpa/socket.c | 52 ++--- src/lwpa_plat/mqx/lwpa/lock.c | 22 +- src/lwpa_plat/mqx/lwpa/netint.c | 30 +-- src/lwpa_plat/mqx/lwpa/plat_uuid.c | 4 +- src/lwpa_plat/mqx/lwpa/socket.c | 78 +++---- src/lwpa_plat/mqx/lwpa/thread.c | 8 +- src/lwpa_plat/windows/lwpa/lock.c | 10 +- src/lwpa_plat/windows/lwpa/netint.c | 60 +++--- src/lwpa_plat/windows/lwpa/plat_uuid.c | 6 +- src/lwpa_plat/windows/lwpa/socket.c | 196 +++++++++--------- src/lwpa_plat/windows/lwpa/thread.c | 12 +- src/lwpa_plat/windows/lwpa/timer.c | 2 +- tests/unit/main.cpp | 2 +- tests/unit/mqx/iar/test_log.c | 14 +- tests/unit/mqx/iar/test_mempool.c | 6 +- tests/unit/mqx/iar/test_mutex.c | 4 +- tests/unit/mqx/iar/test_netint.c | 6 +- tests/unit/mqx/iar/test_pack.c | 42 ++-- tests/unit/mqx/iar/test_rbtree.c | 32 +-- tests/unit/mqx/iar/test_rwlock.c | 6 +- tests/unit/mqx/iar/test_signal.c | 4 +- tests/unit/mqx/iar/test_socket.c | 28 +-- tests/unit/mqx/iar/test_thread.c | 10 +- tests/unit/mqx/testio.h | 13 +- tests/unit/test_log.cpp | 36 ++-- tests/unit/test_mempool.cpp | 10 +- tests/unit/test_mutex.cpp | 4 +- tests/unit/test_netint.cpp | 14 +- tests/unit/test_pack.cpp | 36 ++-- tests/unit/test_rbtree.cpp | 30 +-- tests/unit/test_rwlock.cpp | 6 +- tests/unit/test_signal.cpp | 4 +- tests/unit/test_socket.cpp | 34 +-- tests/unit/test_socket_poll.cpp | 10 +- tests/unit/test_thread.cpp | 12 +- tests/unit/test_timer.cpp | 10 +- tests/unit/test_uuid.cpp | 2 +- 76 files changed, 840 insertions(+), 863 deletions(-) diff --git a/.clang-format b/.clang-format index 6c936b8da..209b53cdd 100644 --- a/.clang-format +++ b/.clang-format @@ -35,7 +35,7 @@ AllowShortLoopsOnASingleLine: false BreakConstructorInitializers: BeforeComma ColumnLimit: 120 DerivePointerAlignment: false -PointerAlignment: Right +PointerAlignment: Left SortIncludes: false # Leave Doxygen directives alone diff --git a/include/lwpa/common.h b/include/lwpa/common.h index ea952e144..a498e93f1 100644 --- a/include/lwpa/common.h +++ b/include/lwpa/common.h @@ -38,13 +38,12 @@ * @{ */ - /*! For lwpa_ functions that take a millisecond timeout, this means to wait indefinitely. */ #define LWPA_WAIT_FOREVER -1 #define LWPA_FEATURE_SOCKETS 0x00000001u -#define LWPA_FEATURE_TIMERS 0x00000002u -#define LWPA_FEATURES_ALL 0xffffffffu +#define LWPA_FEATURE_TIMERS 0x00000002u +#define LWPA_FEATURES_ALL 0xffffffffu typedef uint32_t lwpa_features_t; diff --git a/include/lwpa/error.h b/include/lwpa/error.h index 913b67765..721d8f792 100644 --- a/include/lwpa/error.h +++ b/include/lwpa/error.h @@ -104,7 +104,7 @@ typedef enum extern "C" { #endif -extern const char *lwpa_error_strings[LWPA_NUM_ERROR_CODES]; +extern const char* lwpa_error_strings[LWPA_NUM_ERROR_CODES]; /*! \brief Get a string representation of an error code. * \param errcode lwpa error code. diff --git a/include/lwpa/lock.h b/include/lwpa/lock.h index 191c5c35d..b44c29f9a 100644 --- a/include/lwpa/lock.h +++ b/include/lwpa/lock.h @@ -53,7 +53,7 @@ namespace lwpa class MutexGuard { public: - explicit MutexGuard(lwpa_mutex_t &mutex) : mutex_(mutex) + explicit MutexGuard(lwpa_mutex_t& mutex) : mutex_(mutex) { if (!lwpa_mutex_take(&mutex_, LWPA_WAIT_FOREVER)) throw std::runtime_error("lwpa_mutex_take failed."); @@ -61,7 +61,7 @@ class MutexGuard ~MutexGuard() { lwpa_mutex_give(&mutex_); } private: - lwpa_mutex_t &mutex_; + lwpa_mutex_t& mutex_; }; /// \brief Read lock guard around an \ref lwpa_rwlock. @@ -80,7 +80,7 @@ class MutexGuard class ReadGuard { public: - explicit ReadGuard(lwpa_rwlock_t &rwlock) : rwlock_(rwlock) + explicit ReadGuard(lwpa_rwlock_t& rwlock) : rwlock_(rwlock) { if (!lwpa_rwlock_readlock(&rwlock_, LWPA_WAIT_FOREVER)) throw std::runtime_error("lwpa_rwlock_readlock failed."); @@ -88,7 +88,7 @@ class ReadGuard ~ReadGuard() { lwpa_rwlock_readunlock(&rwlock_); } private: - lwpa_rwlock_t &rwlock_; + lwpa_rwlock_t& rwlock_; }; /// \brief Write lock guard around an \ref lwpa_rwlock. @@ -107,7 +107,7 @@ class ReadGuard class WriteGuard { public: - explicit WriteGuard(lwpa_rwlock_t &rwlock) : rwlock_(rwlock) + explicit WriteGuard(lwpa_rwlock_t& rwlock) : rwlock_(rwlock) { if (!lwpa_rwlock_writelock(&rwlock_, LWPA_WAIT_FOREVER)) throw std::runtime_error("lwpa_rwlock_writelock failed."); @@ -115,7 +115,7 @@ class WriteGuard ~WriteGuard() { lwpa_rwlock_writeunlock(&rwlock_); } private: - lwpa_rwlock_t &rwlock_; + lwpa_rwlock_t& rwlock_; }; /// @} diff --git a/include/lwpa/log.h b/include/lwpa/log.h index 725a4bbf3..d318beae1 100644 --- a/include/lwpa/log.h +++ b/include/lwpa/log.h @@ -110,9 +110,9 @@ #define LWPA_LOG_TIMESTAMP_LEN (10u /*Date*/ + 1u /*T*/ + 12u /*Time*/ + 6u /*Offset*/ + 1u /*Nullterm*/) /*! The maximum length of the syslog header. */ -#define LWPA_SYSLOG_HEADER_MAX_LEN \ +#define LWPA_SYSLOG_HEADER_MAX_LEN \ (5u /*PRIVAL*/ + 3u /*Version*/ + 1u /*SP*/ + (LWPA_LOG_TIMESTAMP_LEN - 1u) /*Timestamp*/ + 1u /*SP*/ + \ - (LWPA_LOG_HOSTNAME_MAX_LEN - 1u) + 1u /*SP*/ + (LWPA_LOG_APP_NAME_MAX_LEN - 1u) + 1u /*SP*/ + \ + (LWPA_LOG_HOSTNAME_MAX_LEN - 1u) + 1u /*SP*/ + (LWPA_LOG_APP_NAME_MAX_LEN - 1u) + 1u /*SP*/ + \ (LWPA_LOG_PROCID_MAX_LEN - 1u) + 1u /*SP*/ + 1u /*MSGID*/ + 1u /*SP*/ + 1u /*STRUCTURED-DATA*/ + 1u /*SP*/) /*! The minimum length of a buffer passed to lwpa_create_syslog_str(). */ @@ -160,7 +160,7 @@ typedef struct LwpaLogTimeParams * \param[in] raw_str The original log string that was passed to lwpa_log() or lwpa_vlog(). Will * overlap with one of syslog_str or human_str. */ -typedef void (*lwpa_log_callback)(void *context, const char *syslog_str, const char *human_str, const char *raw_str); +typedef void (*lwpa_log_callback)(void* context, const char* syslog_str, const char* human_str, const char* raw_str); /*! \brief Time callback function. * @@ -170,7 +170,7 @@ typedef void (*lwpa_log_callback)(void *context, const char *syslog_str, const c * module. * \param[out] time_params Fill this in with the current local time. */ -typedef void (*lwpa_log_time_fn)(void *context, LwpaLogTimeParams *time_params); +typedef void (*lwpa_log_time_fn)(void* context, LwpaLogTimeParams* time_params); /*! Which types of log message(s) the lwpa_log() and lwpa_vlog() functions create. */ typedef enum @@ -214,7 +214,7 @@ typedef struct LwpaLogParams * NULL, no timestamp will be added to log messages. */ lwpa_log_time_fn time_fn; /*! Application context that will be passed back with the log callback function. */ - void *context; + void* context; } LwpaLogParams; #define lwpa_setlogmask(logparamsptr, newlogmask) ((logparamsptr)->log_mask = newlogmask) @@ -231,8 +231,8 @@ extern "C" { #ifdef __ICCARM__ #pragma __printf_args #endif -bool lwpa_create_syslog_str(char *buf, size_t buflen, const LwpaLogTimeParams *time, - const LwpaSyslogParams *syslog_params, int pri, const char *format, ...) +bool lwpa_create_syslog_str(char* buf, size_t buflen, const LwpaLogTimeParams* time, + const LwpaSyslogParams* syslog_params, int pri, const char* format, ...) #ifdef __GNUC__ __attribute__((__format__(__printf__, 6, 7))) #endif @@ -241,25 +241,25 @@ bool lwpa_create_syslog_str(char *buf, size_t buflen, const LwpaLogTimeParams *t #ifdef __ICCARM__ #pragma __printf_args #endif -bool lwpa_create_human_log_str(char *buf, size_t buflen, const LwpaLogTimeParams *time, const char *format, ...) +bool lwpa_create_human_log_str(char* buf, size_t buflen, const LwpaLogTimeParams* time, const char* format, ...) #ifdef __GNUC__ __attribute__((__format__(__printf__, 4, 5))) #endif ; -void lwpa_sanitize_syslog_params(LwpaSyslogParams *params); -bool lwpa_validate_log_params(LwpaLogParams *params); +void lwpa_sanitize_syslog_params(LwpaSyslogParams* params); +bool lwpa_validate_log_params(LwpaLogParams* params); #ifdef __ICCARM__ #pragma __printf_args #endif -void lwpa_log(const LwpaLogParams *params, int pri, const char *format, ...) +void lwpa_log(const LwpaLogParams* params, int pri, const char* format, ...) #ifdef __GNUC__ __attribute__((__format__(__printf__, 3, 4))) #endif ; -void lwpa_vlog(const LwpaLogParams *params, int pri, const char *format, va_list args); +void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list args); #ifdef __cplusplus } diff --git a/include/lwpa/mempool.h b/include/lwpa/mempool.h index b06633513..73103af7a 100644 --- a/include/lwpa/mempool.h +++ b/include/lwpa/mempool.h @@ -43,7 +43,7 @@ typedef struct LwpaMempool LwpaMempool; struct LwpaMempool { - LwpaMempool *next; + LwpaMempool* next; }; /*! (Not for direct usage) A memory pool description structure. Do not declare or use this structure @@ -53,10 +53,10 @@ typedef struct LwpaMempoolDesc { const size_t elem_size; /*!< The size of each element. */ const size_t pool_size; /*!< The number of elements in the pool. */ - LwpaMempool *freelist; /*!< The current freelist. */ - LwpaMempool *const list; /*!< The array of mempool list structs. */ + LwpaMempool* freelist; /*!< The current freelist. */ + LwpaMempool* const list; /*!< The array of mempool list structs. */ size_t current_used; /*!< The number of pool elements that have currently been allocated. */ - void *const pool; /*!< The actual pool memory. */ + void* const pool; /*!< The actual pool memory. */ } LwpaMempoolDesc; /*! \brief Declare a pool as an external variable. @@ -156,10 +156,10 @@ typedef struct LwpaMempoolDesc extern "C" { #endif -lwpa_error_t lwpa_mempool_init_priv(LwpaMempoolDesc *desc); -void *lwpa_mempool_alloc_priv(LwpaMempoolDesc *desc); -void lwpa_mempool_free_priv(LwpaMempoolDesc *desc, void *elem); -size_t lwpa_mempool_used_priv(LwpaMempoolDesc *desc); +lwpa_error_t lwpa_mempool_init_priv(LwpaMempoolDesc* desc); +void* lwpa_mempool_alloc_priv(LwpaMempoolDesc* desc); +void lwpa_mempool_free_priv(LwpaMempoolDesc* desc, void* elem); +size_t lwpa_mempool_used_priv(LwpaMempoolDesc* desc); #ifdef __cplusplus } diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index dddb036ac..20153d049 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -39,9 +39,9 @@ extern "C" { #endif size_t lwpa_netint_get_num_interfaces(); -size_t lwpa_netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_size); -bool lwpa_netint_get_default_interface(LwpaNetintInfo *netint); -const LwpaNetintInfo *lwpa_netint_get_iface_for_dest(const LwpaIpAddr *dest, const LwpaNetintInfo *netint_arr, +size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size); +bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint); +const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, size_t netint_arr_size); // typedef void (*netint_change_notification)(void *context); diff --git a/include/lwpa/pdu.h b/include/lwpa/pdu.h index a0ddbbbaf..f17d18272 100644 --- a/include/lwpa/pdu.h +++ b/include/lwpa/pdu.h @@ -111,11 +111,11 @@ /*! Holds state data used when parsing multiple PDUs in a PDU block. */ typedef struct LwpaPdu { - const uint8_t *pvector; - const uint8_t *pheader; - const uint8_t *pdata; + const uint8_t* pvector; + const uint8_t* pheader; + const uint8_t* pdata; size_t datalen; - const uint8_t *pnextpdu; + const uint8_t* pnextpdu; } LwpaPdu; /*! Default LwpaPdu initializer values; must be used to intialize an LwpaPdu when parsing the first @@ -149,7 +149,7 @@ typedef struct LwpaPduConstraints extern "C" { #endif -bool lwpa_parse_pdu(const uint8_t *buf, size_t buflen, const LwpaPduConstraints *constraints, LwpaPdu *pdu); +bool lwpa_parse_pdu(const uint8_t* buf, size_t buflen, const LwpaPduConstraints* constraints, LwpaPdu* pdu); #ifdef __cplusplus } diff --git a/include/lwpa/rbtree.h b/include/lwpa/rbtree.h index 42c174bc5..6f13a8234 100644 --- a/include/lwpa/rbtree.h +++ b/include/lwpa/rbtree.h @@ -75,7 +75,7 @@ typedef struct LwpaRbTree LwpaRbTree; * 0 (node_a's value is equal to node_b's value)\n * > 0 (node_a's value is greater than node_b's value) */ -typedef int (*lwpa_rbtree_node_cmp_f)(const LwpaRbTree *self, const LwpaRbNode *node_a, const LwpaRbNode *node_b); +typedef int (*lwpa_rbtree_node_cmp_f)(const LwpaRbTree* self, const LwpaRbNode* node_a, const LwpaRbNode* node_b); /*! \brief A function type to be called for each node in a tree. * @@ -87,7 +87,7 @@ typedef int (*lwpa_rbtree_node_cmp_f)(const LwpaRbTree *self, const LwpaRbNode * * \param[in] self The tree in which the node resides. * \param[in] node The node for which an action should be performed. */ -typedef void (*lwpa_rbtree_node_f)(const LwpaRbTree *self, LwpaRbNode *node); +typedef void (*lwpa_rbtree_node_f)(const LwpaRbTree* self, LwpaRbNode* node); /*! \brief A function type to allocate a new node. * @@ -97,7 +97,7 @@ typedef void (*lwpa_rbtree_node_f)(const LwpaRbTree *self, LwpaRbNode *node); * * \return Pointer to the newly allocated node. */ -typedef LwpaRbNode *(*lwpa_rbnode_alloc_f)(); +typedef LwpaRbNode* (*lwpa_rbnode_alloc_f)(); /*! \brief A function type to deallocate a node. * @@ -107,7 +107,7 @@ typedef LwpaRbNode *(*lwpa_rbnode_alloc_f)(); * * \param[in] node Pointer to node to deallocate. */ -typedef void (*lwpa_rbnode_dealloc_f)(LwpaRbNode *node); +typedef void (*lwpa_rbnode_dealloc_f)(LwpaRbNode* node); /*!@}*/ @@ -115,8 +115,8 @@ typedef void (*lwpa_rbnode_dealloc_f)(LwpaRbNode *node); struct LwpaRbNode { int red; /*!< The node color: red (1), black (0) */ - LwpaRbNode *link[2]; /*!< Child node links: left [0], right [1] */ - void *value; /*!< The value object represented by this node. */ + LwpaRbNode* link[2]; /*!< Child node links: left [0], right [1] */ + void* value; /*!< The value object represented by this node. */ }; /*! \brief A red-black tree. @@ -125,12 +125,12 @@ struct LwpaRbNode */ struct LwpaRbTree { - LwpaRbNode *root; /*!< The root node of the tree. */ + LwpaRbNode* root; /*!< The root node of the tree. */ lwpa_rbtree_node_cmp_f cmp; /*!< A function to use for comparing two nodes. */ size_t size; /*!< The current count of nodes in the tree. */ lwpa_rbnode_alloc_f alloc_f; /*!< A function to use for allocating a new node.*/ lwpa_rbnode_dealloc_f dealloc_f; /*!< A function to use for deallocating a node. */ - void *info; /*!< User provided, not used by lwpa_rbtree. */ + void* info; /*!< User provided, not used by lwpa_rbtree. */ }; /*! \brief A red-black tree iterator. @@ -139,41 +139,41 @@ struct LwpaRbTree */ typedef struct LwpaRbIter { - LwpaRbTree *tree; /*!< The tree being iterated over. */ - LwpaRbNode *node; /*!< The current node. */ - LwpaRbNode *path[LWPA_RB_ITER_MAX_HEIGHT]; /*!< The traversal path to the current node. */ + LwpaRbTree* tree; /*!< The tree being iterated over. */ + LwpaRbNode* node; /*!< The current node. */ + LwpaRbNode* path[LWPA_RB_ITER_MAX_HEIGHT]; /*!< The traversal path to the current node. */ size_t top; /*!< Top of the traversal stack. */ - void *info; /*!< User provided, not used by lwpa_rbiter. */ + void* info; /*!< User provided, not used by lwpa_rbiter. */ } LwpaRbIter; #ifdef __cplusplus extern "C" { #endif -int lwpa_rbtree_node_cmp_ptr_cb(const LwpaRbTree *self, const LwpaRbNode *a, const LwpaRbNode *b); -void lwpa_rbtree_node_dealloc_cb(const LwpaRbTree *self, LwpaRbNode *node); +int lwpa_rbtree_node_cmp_ptr_cb(const LwpaRbTree* self, const LwpaRbNode* a, const LwpaRbNode* b); +void lwpa_rbtree_node_dealloc_cb(const LwpaRbTree* self, LwpaRbNode* node); -LwpaRbNode *lwpa_rbnode_init(LwpaRbNode *self, void *value); +LwpaRbNode* lwpa_rbnode_init(LwpaRbNode* self, void* value); -LwpaRbTree *lwpa_rbtree_init(LwpaRbTree *self, lwpa_rbtree_node_cmp_f cmp, lwpa_rbnode_alloc_f alloc_f, +LwpaRbTree* lwpa_rbtree_init(LwpaRbTree* self, lwpa_rbtree_node_cmp_f cmp, lwpa_rbnode_alloc_f alloc_f, lwpa_rbnode_dealloc_f dealloc_f); -void *lwpa_rbtree_find(LwpaRbTree *self, void *value); -int lwpa_rbtree_insert(LwpaRbTree *self, void *value); -int lwpa_rbtree_remove(LwpaRbTree *self, void *value); -int lwpa_rbtree_clear(LwpaRbTree *self); -size_t lwpa_rbtree_size(LwpaRbTree *self); - -int lwpa_rbtree_insert_node(LwpaRbTree *self, LwpaRbNode *node); -int lwpa_rbtree_remove_with_cb(LwpaRbTree *self, void *value, lwpa_rbtree_node_f node_cb); -int lwpa_rbtree_clear_with_cb(LwpaRbTree *self, lwpa_rbtree_node_f node_cb); - -int lwpa_rbtree_test(LwpaRbTree *self, LwpaRbNode *root); - -LwpaRbIter *lwpa_rbiter_init(LwpaRbIter *self); -void *lwpa_rbiter_first(LwpaRbIter *self, LwpaRbTree *tree); -void *lwpa_rbiter_last(LwpaRbIter *self, LwpaRbTree *tree); -void *lwpa_rbiter_next(LwpaRbIter *self); -void *lwpa_rbiter_prev(LwpaRbIter *self); +void* lwpa_rbtree_find(LwpaRbTree* self, void* value); +int lwpa_rbtree_insert(LwpaRbTree* self, void* value); +int lwpa_rbtree_remove(LwpaRbTree* self, void* value); +int lwpa_rbtree_clear(LwpaRbTree* self); +size_t lwpa_rbtree_size(LwpaRbTree* self); + +int lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node); +int lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f node_cb); +int lwpa_rbtree_clear_with_cb(LwpaRbTree* self, lwpa_rbtree_node_f node_cb); + +int lwpa_rbtree_test(LwpaRbTree* self, LwpaRbNode* root); + +LwpaRbIter* lwpa_rbiter_init(LwpaRbIter* self); +void* lwpa_rbiter_first(LwpaRbIter* self, LwpaRbTree* tree); +void* lwpa_rbiter_last(LwpaRbIter* self, LwpaRbTree* tree); +void* lwpa_rbiter_next(LwpaRbIter* self); +void* lwpa_rbiter_prev(LwpaRbIter* self); #ifdef __cplusplus } diff --git a/include/lwpa/root_layer_pdu.h b/include/lwpa/root_layer_pdu.h index e996921ca..7b6faa3ec 100644 --- a/include/lwpa/root_layer_pdu.h +++ b/include/lwpa/root_layer_pdu.h @@ -66,7 +66,7 @@ typedef struct LwpaTcpPreamble { /*! Pointer to the beginning of the Root Layer PDU block */ - const uint8_t *rlp_block; + const uint8_t* rlp_block; /*! Length of the Root Layer PDU block */ size_t rlp_block_len; } LwpaTcpPreamble; @@ -75,7 +75,7 @@ typedef struct LwpaTcpPreamble typedef struct LwpaUdpPreamble { /*! Pointer to the beginning of the Root Layer PDU block */ - const uint8_t *rlp_block; + const uint8_t* rlp_block; /*! Length of the Root Layer PDU block */ size_t rlp_block_len; } LwpaUdpPreamble; @@ -88,7 +88,7 @@ typedef struct LwpaRootLayerPdu /*! The Vector indicates the type of data contained in the Data segment. */ uint32_t vector; /*! A pointer to the Data segment of this PDU. */ - const uint8_t *pdata; + const uint8_t* pdata; /*! The length of the Data segment of this PDU. */ size_t datalen; } LwpaRootLayerPdu; @@ -97,16 +97,16 @@ typedef struct LwpaRootLayerPdu extern "C" { #endif -bool lwpa_parse_tcp_preamble(const uint8_t *buf, size_t buflen, LwpaTcpPreamble *preamble); -bool lwpa_parse_udp_preamble(const uint8_t *buf, size_t buflen, LwpaUdpPreamble *preamble); -bool lwpa_parse_root_layer_header(const uint8_t *buf, size_t buflen, LwpaRootLayerPdu *pdu, LwpaRootLayerPdu *last_pdu); -bool lwpa_parse_root_layer_pdu(const uint8_t *buf, size_t buflen, LwpaRootLayerPdu *pdu, LwpaPdu *last_pdu); +bool lwpa_parse_tcp_preamble(const uint8_t* buf, size_t buflen, LwpaTcpPreamble* preamble); +bool lwpa_parse_udp_preamble(const uint8_t* buf, size_t buflen, LwpaUdpPreamble* preamble); +bool lwpa_parse_root_layer_header(const uint8_t* buf, size_t buflen, LwpaRootLayerPdu* pdu, LwpaRootLayerPdu* last_pdu); +bool lwpa_parse_root_layer_pdu(const uint8_t* buf, size_t buflen, LwpaRootLayerPdu* pdu, LwpaPdu* last_pdu); -size_t lwpa_pack_tcp_preamble(uint8_t *buf, size_t buflen, size_t rlp_block_len); -size_t lwpa_pack_udp_preamble(uint8_t *buf, size_t buflen); -size_t lwpa_root_layer_buf_size(const LwpaRootLayerPdu *pdu_block, size_t num_pdus); -size_t lwpa_pack_root_layer_header(uint8_t *buf, size_t buflen, const LwpaRootLayerPdu *pdu); -size_t lwpa_pack_root_layer_block(uint8_t *buf, size_t buflen, const LwpaRootLayerPdu *pdu_block, size_t num_pdus); +size_t lwpa_pack_tcp_preamble(uint8_t* buf, size_t buflen, size_t rlp_block_len); +size_t lwpa_pack_udp_preamble(uint8_t* buf, size_t buflen); +size_t lwpa_root_layer_buf_size(const LwpaRootLayerPdu* pdu_block, size_t num_pdus); +size_t lwpa_pack_root_layer_header(uint8_t* buf, size_t buflen, const LwpaRootLayerPdu* pdu); +size_t lwpa_pack_root_layer_block(uint8_t* buf, size_t buflen, const LwpaRootLayerPdu* pdu_block, size_t num_pdus); #ifdef __cplusplus } diff --git a/include/lwpa/socket.h b/include/lwpa/socket.h index c37393abb..ea9a4ab9a 100644 --- a/include/lwpa/socket.h +++ b/include/lwpa/socket.h @@ -142,23 +142,23 @@ typedef struct LwpaMreq extern "C" { #endif -lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr *address, lwpa_socket_t *conn_sock); -lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr *address); +lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock); +lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address); lwpa_error_t lwpa_close(lwpa_socket_t id); -lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr *address); -lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr *address); -lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr *address); -lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void *option_value, size_t *option_len); +lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address); +lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address); +lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address); +lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len); lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog); -int lwpa_recv(lwpa_socket_t id, void *buffer, size_t length, int flags); -int lwpa_recvfrom(lwpa_socket_t id, void *buffer, size_t length, int flags, LwpaSockaddr *address); +int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags); +int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address); /* recvmsg - not implemented */ -int lwpa_send(lwpa_socket_t id, const void *message, size_t length, int flags); +int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags); /* sendmsg - not implemented */ -int lwpa_sendto(lwpa_socket_t id, const void *message, size_t length, int flags, const LwpaSockaddr *dest_addr); -lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void *option_value, size_t option_len); +int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr); +lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len); lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how); -lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t *id); +lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* id); /* int protocol - not necessary */ /* socketpair - not implemented */ @@ -187,17 +187,17 @@ typedef struct LwpaPollEvent lwpa_socket_t socket; /*!< Socket which had activity. */ lwpa_poll_events_t events; /*!< Event(s) that occurred on the socket. */ lwpa_error_t err; /*!< More information about an error that occurred on the socket. */ - void *user_data; /*!< The user data that was given when this socket was added. */ + void* user_data; /*!< The user data that was given when this socket was added. */ } LwpaPollEvent; -lwpa_error_t lwpa_poll_context_init(LwpaPollContext *context); -void lwpa_poll_context_deinit(LwpaPollContext *context); -lwpa_error_t lwpa_poll_add_socket(LwpaPollContext *context, lwpa_socket_t socket, lwpa_poll_events_t events, - void *user_data); -lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext *context, lwpa_socket_t socket, lwpa_poll_events_t new_events, - void *new_user_data); -void lwpa_poll_remove_socket(LwpaPollContext *context, lwpa_socket_t socket); -lwpa_error_t lwpa_poll_wait(LwpaPollContext *context, LwpaPollEvent *event, int timeout_ms); +lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context); +void lwpa_poll_context_deinit(LwpaPollContext* context); +lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, + void* user_data); +lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, + void* new_user_data); +void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket); +lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms); /************************ Mimic getaddrinfo() API ****************************/ @@ -218,18 +218,18 @@ typedef struct LwpaAddrinfo int ai_family; /*!< i.e. LWPA_AF_xxx */ int ai_socktype; /*!< i.e. LWPA_STREAM or LWPA_DGRAM */ int ai_protocol; /*!< i.e. LWPA_IPPROTO_xxx */ - char *ai_canonname; /*!< Canonical name for host */ + char* ai_canonname; /*!< Canonical name for host */ LwpaSockaddr ai_addr; /*!< Address of host */ - void *pd[2]; /*!< Used by internal platform logic; don't touch */ + void* pd[2]; /*!< Used by internal platform logic; don't touch */ } LwpaAddrinfo; -lwpa_error_t lwpa_getaddrinfo(const char *hostname, const char *service, const LwpaAddrinfo *hints, - LwpaAddrinfo *result); +lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, + LwpaAddrinfo* result); -bool lwpa_nextaddr(LwpaAddrinfo *ai); +bool lwpa_nextaddr(LwpaAddrinfo* ai); /* Call with any of the LwpaAddrinfos in the list to free the whole list */ -void lwpa_freeaddrinfo(LwpaAddrinfo *ai); +void lwpa_freeaddrinfo(LwpaAddrinfo* ai); /************************* Mimic inet_xtox() API *****************************/ @@ -238,8 +238,8 @@ void lwpa_freeaddrinfo(LwpaAddrinfo *ai); /*! Maximum length of the string representation of an IPv6 address. */ #define LWPA_INET6_ADDRSTRLEN 46 -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size); -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char *src, LwpaIpAddr *dest); +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size); +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest); #ifdef __cplusplus } diff --git a/include/lwpa/thread.h b/include/lwpa/thread.h index 283886e34..28d0d5e4c 100644 --- a/include/lwpa/thread.h +++ b/include/lwpa/thread.h @@ -24,8 +24,8 @@ typedef struct LwpaThreadParams { unsigned int thread_priority; unsigned int stack_size; - char *thread_name; - void *platform_data; + char* thread_name; + void* platform_data; } LwpaThreadParams; #include "lwpa/plat_thread.h" diff --git a/include/lwpa/timer.h b/include/lwpa/timer.h index f153031e8..c4944d804 100644 --- a/include/lwpa/timer.h +++ b/include/lwpa/timer.h @@ -91,7 +91,7 @@ uint32_t lwpa_getms(); * \param timer Pointer to the LwpaTimer of which to get the remaining time. * \return Remaining time in milliseconds or 0 (timer is expired). */ -uint32_t lwpa_timer_remaining(const LwpaTimer *timer); +uint32_t lwpa_timer_remaining(const LwpaTimer* timer); #ifdef __cplusplus } diff --git a/include/lwpa/uuid.h b/include/lwpa/uuid.h index 7dde9585e..b7bfdf135 100644 --- a/include/lwpa/uuid.h +++ b/include/lwpa/uuid.h @@ -75,15 +75,15 @@ extern const LwpaUuid kLwpaNullUuid; /*! The maximum number of bytes required to hold an ASCII string representation of a UUID. */ #define LWPA_UUID_STRING_BYTES 37 -void lwpa_uuid_to_string(char *buf, const LwpaUuid *uuid); -bool lwpa_string_to_uuid(LwpaUuid *uuid, const char *buf, size_t buflen); +void lwpa_uuid_to_string(char* buf, const LwpaUuid* uuid); +bool lwpa_string_to_uuid(LwpaUuid* uuid, const char* buf, size_t buflen); /************************ UUID Generation Functions **************************/ -lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid *uuid); -lwpa_error_t lwpa_generate_v3_uuid(LwpaUuid *uuid, const char *devstr, const uint8_t *macaddr, uint32_t uuidnum); -lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid *uuid); -lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid *uuid); +lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid); +lwpa_error_t lwpa_generate_v3_uuid(LwpaUuid* uuid, const char* devstr, const uint8_t* macaddr, uint32_t uuidnum); +lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid); +lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid* uuid); #ifdef __cplusplus } @@ -94,12 +94,12 @@ lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid *uuid); /* Comparison operators for UUIDs */ -inline bool operator<(const LwpaUuid &a, const LwpaUuid &b) +inline bool operator<(const LwpaUuid& a, const LwpaUuid& b) { return (lwpa_uuid_cmp(&a, &b) < 0); } -inline bool operator==(const LwpaUuid &a, const LwpaUuid &b) +inline bool operator==(const LwpaUuid& a, const LwpaUuid& b) { return (lwpa_uuid_cmp(&a, &b) == 0); } diff --git a/include/lwpa_mock/socket.h b/include/lwpa_mock/socket.h index 9ad98de12..54c4d3ea0 100644 --- a/include/lwpa_mock/socket.h +++ b/include/lwpa_mock/socket.h @@ -34,37 +34,35 @@ extern "C" { #endif -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_accept, lwpa_socket_t, LwpaSockaddr *, lwpa_socket_t *); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_bind, lwpa_socket_t, const LwpaSockaddr *); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_accept, lwpa_socket_t, LwpaSockaddr*, lwpa_socket_t*); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_bind, lwpa_socket_t, const LwpaSockaddr*); DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_close, lwpa_socket_t); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_connect, lwpa_socket_t, const LwpaSockaddr *); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getpeername, lwpa_socket_t, LwpaSockaddr *); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getsockname, lwpa_socket_t, LwpaSockaddr *); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getsockopt, lwpa_socket_t, int, int, void *, size_t *); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_connect, lwpa_socket_t, const LwpaSockaddr*); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getpeername, lwpa_socket_t, LwpaSockaddr*); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getsockname, lwpa_socket_t, LwpaSockaddr*); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getsockopt, lwpa_socket_t, int, int, void*, size_t*); DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_listen, lwpa_socket_t, int); -DECLARE_FAKE_VALUE_FUNC(int, lwpa_recv, lwpa_socket_t, void *, size_t, int); -DECLARE_FAKE_VALUE_FUNC(int, lwpa_recvfrom, lwpa_socket_t, void *, size_t, int, LwpaSockaddr *); -DECLARE_FAKE_VALUE_FUNC(int, lwpa_send, lwpa_socket_t, const void *, size_t, int); -DECLARE_FAKE_VALUE_FUNC(int, lwpa_sendto, lwpa_socket_t, const void *, size_t, int, const LwpaSockaddr *); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_setsockopt, lwpa_socket_t, int, int, const void *, size_t); +DECLARE_FAKE_VALUE_FUNC(int, lwpa_recv, lwpa_socket_t, void*, size_t, int); +DECLARE_FAKE_VALUE_FUNC(int, lwpa_recvfrom, lwpa_socket_t, void*, size_t, int, LwpaSockaddr*); +DECLARE_FAKE_VALUE_FUNC(int, lwpa_send, lwpa_socket_t, const void*, size_t, int); +DECLARE_FAKE_VALUE_FUNC(int, lwpa_sendto, lwpa_socket_t, const void*, size_t, int, const LwpaSockaddr*); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_setsockopt, lwpa_socket_t, int, int, const void*, size_t); DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_shutdown, lwpa_socket_t, int); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_socket, unsigned int, unsigned int, lwpa_socket_t *); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_socket, unsigned int, unsigned int, lwpa_socket_t*); DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_setblocking, lwpa_socket_t, bool); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_context_init, LwpaPollContext *); -DECLARE_FAKE_VOID_FUNC(lwpa_poll_context_deinit, LwpaPollContext *); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_add_socket, LwpaPollContext *, lwpa_socket_t, lwpa_poll_events_t, - void *); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_modify_socket, LwpaPollContext *, lwpa_socket_t, lwpa_poll_events_t, - void *); -DECLARE_FAKE_VOID_FUNC(lwpa_poll_remove_socket, LwpaPollContext *, lwpa_socket_t); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_wait, LwpaPollContext *, LwpaPollEvent *, int); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_context_init, LwpaPollContext*); +DECLARE_FAKE_VOID_FUNC(lwpa_poll_context_deinit, LwpaPollContext*); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_add_socket, LwpaPollContext*, lwpa_socket_t, lwpa_poll_events_t, void*); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_modify_socket, LwpaPollContext*, lwpa_socket_t, lwpa_poll_events_t, + void*); +DECLARE_FAKE_VOID_FUNC(lwpa_poll_remove_socket, LwpaPollContext*, lwpa_socket_t); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_wait, LwpaPollContext*, LwpaPollEvent*, int); -DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getaddrinfo, const char *, const char *, const LwpaAddrinfo *, - LwpaAddrinfo *); -DECLARE_FAKE_VALUE_FUNC(bool, lwpa_nextaddr, LwpaAddrinfo *); -DECLARE_FAKE_VOID_FUNC(lwpa_freeaddrinfo, LwpaAddrinfo *); +DECLARE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getaddrinfo, const char*, const char*, const LwpaAddrinfo*, LwpaAddrinfo*); +DECLARE_FAKE_VALUE_FUNC(bool, lwpa_nextaddr, LwpaAddrinfo*); +DECLARE_FAKE_VOID_FUNC(lwpa_freeaddrinfo, LwpaAddrinfo*); #define LWPA_SOCKET_DO_FOR_ALL_FAKES(operation) \ operation(lwpa_accept); \ diff --git a/include/lwpa_plat/freertos/lwpa/plat_lock.h b/include/lwpa_plat/freertos/lwpa/plat_lock.h index afcd25012..a5fc5f47a 100644 --- a/include/lwpa_plat/freertos/lwpa/plat_lock.h +++ b/include/lwpa_plat/freertos/lwpa/plat_lock.h @@ -31,17 +31,17 @@ extern "C" { typedef SemaphoreHandle_t lwpa_mutex_t; -bool lwpa_mutex_create(lwpa_mutex_t *id); -bool lwpa_mutex_take(lwpa_mutex_t *id, int wait_ms); -void lwpa_mutex_give(lwpa_mutex_t *id); -void lwpa_mutex_destroy(lwpa_mutex_t *id); +bool lwpa_mutex_create(lwpa_mutex_t* id); +bool lwpa_mutex_take(lwpa_mutex_t* id, int wait_ms); +void lwpa_mutex_give(lwpa_mutex_t* id); +void lwpa_mutex_destroy(lwpa_mutex_t* id); typedef SemaphoreHandle_t lwpa_signal_t; -bool lwpa_signal_create(lwpa_signal_t *id); -bool lwpa_signal_wait(lwpa_signal_t *id, int wait_ms); -void lwpa_signal_post(lwpa_signal_t *id); -void lwpa_signal_destroy(lwpa_signal_t *id); +bool lwpa_signal_create(lwpa_signal_t* id); +bool lwpa_signal_wait(lwpa_signal_t* id, int wait_ms); +void lwpa_signal_post(lwpa_signal_t* id); +void lwpa_signal_destroy(lwpa_signal_t* id); typedef struct { @@ -49,12 +49,12 @@ typedef struct unsigned int reader_count; } lwpa_rwlock_t; -bool lwpa_rwlock_create(lwpa_rwlock_t *id); -bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms); -void lwpa_rwlock_readunlock(lwpa_rwlock_t *id); -bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms); -void lwpa_rwlock_writeunlock(lwpa_rwlock_t *id); -void lwpa_rwlock_destroy(lwpa_rwlock_t *id); +bool lwpa_rwlock_create(lwpa_rwlock_t* id); +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms); +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms); +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); +void lwpa_rwlock_destroy(lwpa_rwlock_t* id); #ifdef __cplusplus } diff --git a/include/lwpa_plat/freertos/lwpa/plat_thread.h b/include/lwpa_plat/freertos/lwpa/plat_thread.h index 55a98c743..e407a14a3 100644 --- a/include/lwpa_plat/freertos/lwpa/plat_thread.h +++ b/include/lwpa_plat/freertos/lwpa/plat_thread.h @@ -34,8 +34,8 @@ typedef struct LwpaThreadParams { unsigned int thread_priority; unsigned int stack_size; - char *thread_name; - void *platform_data; + char* thread_name; + void* platform_data; } LwpaThreadParams; #define LWPA_THREAD_DEFAULT_PRIORITY (configMAX_PRIORITIES / 2) @@ -44,14 +44,14 @@ typedef struct LwpaThreadParams typedef struct { - void (*fn)(void *); - void *arg; + void (*fn)(void*); + void* arg; SemaphoreHandle_t sig; TaskHandle_t tid; } lwpa_thread_t; -bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void (*thread_fn)(void *), void *thread_arg); -bool lwpa_thread_stop(lwpa_thread_t *id, int wait_ms); +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); +bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); #define lwpa_thread_sleep(sleep_ms) vTaskDelay(pdMS_TO_TICKS(sleep_ms)) #ifdef __cplusplus diff --git a/include/lwpa_plat/linux/lwpa/plat_socket.h b/include/lwpa_plat/linux/lwpa/plat_socket.h index a5e329ace..af8abd85a 100644 --- a/include/lwpa_plat/linux/lwpa/plat_socket.h +++ b/include/lwpa_plat/linux/lwpa/plat_socket.h @@ -39,12 +39,11 @@ typedef int lwpa_socket_t; extern "C" { #endif -bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa); -size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa); +bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); +size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa); #ifdef __cplusplus } #endif #endif /* _LWPA_PLAT_SOCKET_H_ */ - diff --git a/include/lwpa_plat/mqx/lwpa/plat_lock.h b/include/lwpa_plat/mqx/lwpa/plat_lock.h index d6eea8756..3a51a5e16 100644 --- a/include/lwpa_plat/mqx/lwpa/plat_lock.h +++ b/include/lwpa_plat/mqx/lwpa/plat_lock.h @@ -31,15 +31,15 @@ extern "C" { typedef LWSEM_STRUCT lwpa_mutex_t; -bool lwpa_mutex_create(lwpa_mutex_t *id); -bool lwpa_mutex_take(lwpa_mutex_t *id, int wait_ms); +bool lwpa_mutex_create(lwpa_mutex_t* id); +bool lwpa_mutex_take(lwpa_mutex_t* id, int wait_ms); #define lwpa_mutex_give(idptr) ((void)_lwsem_post((LWSEM_STRUCT_PTR)(idptr))) #define lwpa_mutex_destroy(idptr) ((void)_lwsem_destroy((LWSEM_STRUCT_PTR)(idptr))) typedef LWEVENT_STRUCT lwpa_signal_t; -bool lwpa_signal_create(lwpa_signal_t *id); -bool lwpa_signal_wait(lwpa_signal_t *id, int wait_ms); +bool lwpa_signal_create(lwpa_signal_t* id); +bool lwpa_signal_wait(lwpa_signal_t* id, int wait_ms); #define lwpa_signal_post(idptr) ((void)_lwevent_set((LWEVENT_STRUCT_PTR)(idptr), 1u)) #define lwpa_signal_destroy(idptr) ((void)_lwevent_destroy((LWEVENT_STRUCT_PTR)(idptr))) @@ -49,11 +49,11 @@ typedef struct unsigned int reader_count; } lwpa_rwlock_t; -bool lwpa_rwlock_create(lwpa_rwlock_t *id); -bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms); -void lwpa_rwlock_readunlock(lwpa_rwlock_t *id); -bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms); -void lwpa_rwlock_writeunlock(lwpa_rwlock_t *id); +bool lwpa_rwlock_create(lwpa_rwlock_t* id); +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms); +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms); +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); #define lwpa_rwlock_destroy(idptr) ((void)_lwsem_destroy(&((idptr)->sem))) #ifdef __cplusplus diff --git a/include/lwpa_plat/mqx/lwpa/plat_socket.h b/include/lwpa_plat/mqx/lwpa/plat_socket.h index 7be74c92c..bde7ea873 100644 --- a/include/lwpa_plat/mqx/lwpa/plat_socket.h +++ b/include/lwpa_plat/mqx/lwpa/plat_socket.h @@ -39,8 +39,8 @@ extern "C" { #define ip_plat_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) #define ip_lwpa_to_plat_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) -bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa); -size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa); +bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); +size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa); #ifdef __cplusplus } diff --git a/include/lwpa_plat/mqx/lwpa/plat_thread.h b/include/lwpa_plat/mqx/lwpa/plat_thread.h index bfb91c276..e9bd670c0 100644 --- a/include/lwpa_plat/mqx/lwpa/plat_thread.h +++ b/include/lwpa_plat/mqx/lwpa/plat_thread.h @@ -32,8 +32,8 @@ typedef struct LwpaThreadParams { unsigned int thread_priority; unsigned int stack_size; - char *thread_name; - void *platform_data; + char* thread_name; + void* platform_data; } LwpaThreadParams; typedef struct LwpaThreadParamsMqx @@ -50,14 +50,14 @@ typedef struct LwpaThreadParamsMqx typedef struct { - void (*fn)(void *); - void *arg; + void (*fn)(void*); + void* arg; LWSEM_STRUCT sig; _task_id tid; } lwpa_thread_t; -bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void (*thread_fn)(void *), void *thread_arg); -bool lwpa_thread_stop(lwpa_thread_t *id, int wait_ms); +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); +bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); #define lwpa_thread_sleep(sleep_ms) _time_delay(sleep_ms) #ifdef __cplusplus diff --git a/include/lwpa_plat/windows/lwpa/plat_lock.h b/include/lwpa_plat/windows/lwpa/plat_lock.h index 34bf6e561..8de00d994 100644 --- a/include/lwpa_plat/windows/lwpa/plat_lock.h +++ b/include/lwpa_plat/windows/lwpa/plat_lock.h @@ -45,7 +45,7 @@ typedef struct CRITICAL_SECTION cs; } lwpa_mutex_t; -bool lwpa_mutex_create(lwpa_mutex_t *id); +bool lwpa_mutex_create(lwpa_mutex_t* id); #define lwpa_mutex_take(idptr, wait_ms) \ (((idptr) && (idptr)->valid) \ ? (((wait_ms) == 0) ? TryEnterCriticalSection(&(idptr)->cs) : (EnterCriticalSection(&(idptr)->cs), true)) \ @@ -68,7 +68,7 @@ bool lwpa_mutex_create(lwpa_mutex_t *id); typedef HANDLE lwpa_signal_t; -bool lwpa_signal_create(lwpa_signal_t *id); +bool lwpa_signal_create(lwpa_signal_t* id); #define lwpa_signal_wait(idptr, wait_ms) \ ((idptr) ? (WAIT_OBJECT_0 == \ WaitForSingleObject(*(idptr), ((wait_ms) == LWPA_WAIT_FOREVER ? INFINITE : (DWORD)wait_ms))) \ @@ -93,15 +93,15 @@ typedef struct LONG reader_count; } lwpa_rwlock_t; -bool lwpa_rwlock_create(lwpa_rwlock_t *id); -bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms); +bool lwpa_rwlock_create(lwpa_rwlock_t* id); +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms); #define lwpa_rwlock_readunlock(idptr) \ do \ { \ if (idptr) \ InterlockedDecrement(&(idptr)->reader_count); \ } while (0) -bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms); +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms); #define lwpa_rwlock_writeunlock(idptr) \ do \ { \ diff --git a/include/lwpa_plat/windows/lwpa/plat_socket.h b/include/lwpa_plat/windows/lwpa/plat_socket.h index cd0b0355c..966c57f57 100644 --- a/include/lwpa_plat/windows/lwpa/plat_socket.h +++ b/include/lwpa_plat/windows/lwpa/plat_socket.h @@ -45,7 +45,7 @@ typedef struct LwpaPollCtxSocket { lwpa_socket_t socket; lwpa_poll_events_t events; - void *user_data; + void* user_data; } LwpaPollCtxSocket; typedef struct LwpaPollFdSet @@ -59,7 +59,7 @@ typedef struct LwpaPollContext bool valid; lwpa_mutex_t lock; - LwpaPollCtxSocket *sockets; + LwpaPollCtxSocket* sockets; size_t socket_arr_size; size_t num_valid_sockets; @@ -78,8 +78,8 @@ extern "C" { #define ip_plat_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) #define ip_lwpa_to_plat_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) -bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa); -size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa); +bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); +size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa); #ifdef __cplusplus } diff --git a/include/lwpa_plat/windows/lwpa/plat_thread.h b/include/lwpa_plat/windows/lwpa/plat_thread.h index 4e9307842..cfa086b80 100644 --- a/include/lwpa_plat/windows/lwpa/plat_thread.h +++ b/include/lwpa_plat/windows/lwpa/plat_thread.h @@ -47,14 +47,14 @@ extern "C" { typedef struct { - void (*fn)(void *); - void *arg; + void (*fn)(void*); + void* arg; HANDLE tid; char name[LWPA_THREAD_NAME_MAX_LENGTH]; } lwpa_thread_t; -bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void (*thread_fn)(void *), void *thread_arg); -bool lwpa_thread_stop(lwpa_thread_t *id, int wait_ms); +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); +bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); #define lwpa_thread_sleep(sleep_ms) Sleep(sleep_ms) #ifdef __cplusplus diff --git a/src/lwpa/log.c b/src/lwpa/log.c index 9d43ce0ec..12fbe0c4c 100644 --- a/src/lwpa/log.c +++ b/src/lwpa/log.c @@ -39,13 +39,13 @@ #define DEFAULT_FACILITY LWPA_LOG_LOCAL1 /* Replace non-printing characters and spaces with '_'. Replace characters above 127 with '?'. */ -static void sanitize_str(char *str) +static void sanitize_str(char* str) { /* C library functions like isprint()/isgraph() are not used here because their behavior is not * well-defined in the presence of non-ASCII characters. */ - unsigned char *cp; - for (cp = (unsigned char *)str; *cp != '\0'; ++cp) + unsigned char* cp; + for (cp = (unsigned char*)str; *cp != '\0'; ++cp) { if (*cp < 33 || *cp == 127) *cp = '_'; @@ -63,7 +63,7 @@ static void sanitize_str(char *str) * * \param[in,out] params Syslog params to sanitize. */ -void lwpa_sanitize_syslog_params(LwpaSyslogParams *params) +void lwpa_sanitize_syslog_params(LwpaSyslogParams* params) { if (LWPA_LOG_FAC(params->facility) >= LWPA_LOG_NFACILITIES) params->facility = DEFAULT_FACILITY; @@ -81,7 +81,7 @@ void lwpa_sanitize_syslog_params(LwpaSyslogParams *params) * \param[in,out] params lwpa_log_params to validate. * \return true (params are valid) or false (params are invalid). */ -bool lwpa_validate_log_params(LwpaLogParams *params) +bool lwpa_validate_log_params(LwpaLogParams* params) { if (!params || !params->log_fn) { @@ -96,7 +96,7 @@ bool lwpa_validate_log_params(LwpaLogParams *params) } /* Enforce the range rules defined in the LwpaLogTimeParams struct definition. */ -static bool validate_time(const LwpaLogTimeParams *tparams) +static bool validate_time(const LwpaLogTimeParams* tparams) { return (tparams->year >= 0 && tparams->year <= 9999 && tparams->month >= 1 && tparams->month <= 12 && tparams->day >= 1 && tparams->day <= 31 && tparams->hour >= 0 && tparams->hour <= 23 && @@ -105,7 +105,7 @@ static bool validate_time(const LwpaLogTimeParams *tparams) } /* Build the current timestamp. Buffer must be of length LWPA_LOG_TIMESTAMP_LEN. */ -static void make_timestamp(const LwpaLogTimeParams *tparams, char *buf, bool human_readable) +static void make_timestamp(const LwpaLogTimeParams* tparams, char* buf, bool human_readable) { bool timestamp_created = false; @@ -128,8 +128,7 @@ static void make_timestamp(const LwpaLogTimeParams *tparams, char *buf, bool hum else { snprintf(&buf[print_res], LWPA_LOG_TIMESTAMP_LEN - (size_t)print_res, "%s%02d:%02d", - tparams->utc_offset > 0 ? "+" : "-", abs(tparams->utc_offset) / 60, - abs(tparams->utc_offset) % 60); + tparams->utc_offset > 0 ? "+" : "-", abs(tparams->utc_offset) / 60, abs(tparams->utc_offset) % 60); } timestamp_created = true; @@ -146,7 +145,7 @@ static void make_timestamp(const LwpaLogTimeParams *tparams, char *buf, bool hum } /* Get the current time via either the standard C library or a time callback. */ -static bool get_time(const LwpaLogParams *params, LwpaLogTimeParams *time_params) +static bool get_time(const LwpaLogParams* params, LwpaLogTimeParams* time_params) { if (params->time_fn) { @@ -160,8 +159,8 @@ static bool get_time(const LwpaLogParams *params, LwpaLogTimeParams *time_params /* Create a log message with syslog header given the appropriate va_list. Returns a pointer to the * original message within the syslog message, or NULL on failure. */ -static char *lwpa_vcreate_syslog_str(char *buf, size_t buflen, const LwpaLogTimeParams *tparams, - const LwpaSyslogParams *syslog_params, int pri, const char *format, va_list args) +static char* lwpa_vcreate_syslog_str(char* buf, size_t buflen, const LwpaLogTimeParams* tparams, + const LwpaSyslogParams* syslog_params, int pri, const char* format, va_list args) { if (!buf || buflen < LWPA_SYSLOG_HEADER_MAX_LEN || !syslog_params || !format) return NULL; @@ -204,8 +203,8 @@ static char *lwpa_vcreate_syslog_str(char *buf, size_t buflen, const LwpaLogTime * \param[in] format Log message with printf-style format specifiers. Provide additional arguments * as appropriate for format specifiers. */ -bool lwpa_create_syslog_str(char *buf, size_t buflen, const LwpaLogTimeParams *time, - const LwpaSyslogParams *syslog_params, int pri, const char *format, ...) +bool lwpa_create_syslog_str(char* buf, size_t buflen, const LwpaLogTimeParams* time, + const LwpaSyslogParams* syslog_params, int pri, const char* format, ...) { va_list args; bool res; @@ -217,7 +216,7 @@ bool lwpa_create_syslog_str(char *buf, size_t buflen, const LwpaLogTimeParams *t /* Create a log message with a human-readable header given the appropriate va_list. Returns a * pointer to the original message within the log message, or NULL on failure. */ -static char *lwpa_vcreate_human_log_str(char *buf, size_t buflen, const LwpaLogTimeParams *time, const char *format, +static char* lwpa_vcreate_human_log_str(char* buf, size_t buflen, const LwpaLogTimeParams* time, const char* format, va_list args) { if (!buf || buflen < LWPA_LOG_TIMESTAMP_LEN + 1 || !format) @@ -259,7 +258,7 @@ static char *lwpa_vcreate_human_log_str(char *buf, size_t buflen, const LwpaLogT * \param[in] format Log message with printf-style format specifiers. Provide additional arguments * as appropriate for format specifiers. */ -bool lwpa_create_human_log_str(char *buf, size_t buflen, const LwpaLogTimeParams *time, const char *format, ...) +bool lwpa_create_human_log_str(char* buf, size_t buflen, const LwpaLogTimeParams* time, const char* format, ...) { va_list args; bool res; @@ -278,7 +277,7 @@ bool lwpa_create_human_log_str(char *buf, size_t buflen, const LwpaLogTimeParams * \param[in] format Log message with printf-style format specifiers. Provide additional arguments * as appropriate for format specifiers. */ -void lwpa_log(const LwpaLogParams *params, int pri, const char *format, ...) +void lwpa_log(const LwpaLogParams* params, int pri, const char* format, ...) { va_list args; va_start(args, format); @@ -296,13 +295,13 @@ void lwpa_log(const LwpaLogParams *params, int pri, const char *format, ...) * \param[in] format Log message with printf-style format specifiers. * \param[in] args Argument list for the format specifiers in format. */ -void lwpa_vlog(const LwpaLogParams *params, int pri, const char *format, va_list args) +void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list args) { char syslogmsg[LWPA_SYSLOG_STR_MAX_LEN + 1]; char humanlogmsg[LWPA_HUMAN_LOG_STR_MAX_LEN + 1]; - char *syslog_msg_ptr = NULL; - char *humanlog_msg_ptr = NULL; - char *raw_msg_ptr = NULL; + char* syslog_msg_ptr = NULL; + char* humanlog_msg_ptr = NULL; + char* raw_msg_ptr = NULL; LwpaLogTimeParams time_params; bool have_time; diff --git a/src/lwpa/md5.h b/src/lwpa/md5.h index dda4265b3..2712c73ce 100644 --- a/src/lwpa/md5.h +++ b/src/lwpa/md5.h @@ -1,5 +1,5 @@ /* MD5.H - header file for MD5C.C -*/ + */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. @@ -30,14 +30,15 @@ documentation and/or software. #include "lwpa/int.h" -typedef struct { - uint32_t state[4]; // state (ABCD) - uint32_t count[2]; // number of bits, modulo 2^64 (lsb first) - uint8_t buffer[64]; // input buffer +typedef struct +{ + uint32_t state[4]; // state (ABCD) + uint32_t count[2]; // number of bits, modulo 2^64 (lsb first) + uint8_t buffer[64]; // input buffer } MD5_CTX; void MD5Init(MD5_CTX* context); void MD5Update(MD5_CTX* context, const uint8_t* input, unsigned int inputLen); void MD5Final(uint8_t digest[16], MD5_CTX* context); -#endif //_MD5_H_ +#endif //_MD5_H_ diff --git a/src/lwpa/md5c.c b/src/lwpa/md5c.c index b4ce85601..819350592 100644 --- a/src/lwpa/md5c.c +++ b/src/lwpa/md5c.c @@ -46,8 +46,8 @@ documentation and/or software. #define S44 21 static void MD5Transform(uint32_t[4], const uint8_t[64]); -static void Encode(uint8_t *, uint32_t *, unsigned int); -static void Decode(uint32_t *, const uint8_t *, unsigned int); +static void Encode(uint8_t*, uint32_t*, unsigned int); +static void Decode(uint32_t*, const uint8_t*, unsigned int); static uint8_t PADDING[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -94,7 +94,7 @@ Rotation is separate from addition to prevent recomputation. /* MD5 initialization. Begins an MD5 operation, writing a new context. */ -void MD5Init(MD5_CTX *context) +void MD5Init(MD5_CTX* context) { context->count[0] = context->count[1] = 0; /* Load magic initialization constants.*/ @@ -108,7 +108,7 @@ void MD5Init(MD5_CTX *context) operation, processing another message block, and updating the context. */ -void MD5Update(MD5_CTX *context, const uint8_t *input, unsigned int inputLen) +void MD5Update(MD5_CTX* context, const uint8_t* input, unsigned int inputLen) { unsigned int i, index, partLen; @@ -127,7 +127,7 @@ void MD5Update(MD5_CTX *context, const uint8_t *input, unsigned int inputLen) /* Transform as many times as possible.*/ if (inputLen >= partLen) { - memcpy((uint8_t *)&context->buffer[index], (uint8_t *)input, partLen); + memcpy((uint8_t*)&context->buffer[index], (uint8_t*)input, partLen); MD5Transform(context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) @@ -139,13 +139,13 @@ void MD5Update(MD5_CTX *context, const uint8_t *input, unsigned int inputLen) i = 0; /* Buffer remaining input */ - memcpy((uint8_t *)&context->buffer[index], (uint8_t *)&input[i], inputLen - i); + memcpy((uint8_t*)&context->buffer[index], (uint8_t*)&input[i], inputLen - i); } /* MD5 finalization. Ends an MD5 message-digest operation, writing the the message digest and zeroizing the context. */ -void MD5Final(uint8_t digest[16], MD5_CTX *context) +void MD5Final(uint8_t digest[16], MD5_CTX* context) { uint8_t bits[8]; unsigned int index, padLen; @@ -165,7 +165,7 @@ void MD5Final(uint8_t digest[16], MD5_CTX *context) Encode(digest, context->state, 16); /* Zeroize sensitive information.*/ - memset((uint8_t *)context, 0, sizeof(*context)); + memset((uint8_t*)context, 0, sizeof(*context)); } /* MD5 basic transformation. Transforms state based on block. @@ -254,13 +254,13 @@ static void MD5Transform(uint32_t state[4], const uint8_t block[64]) state[3] += d; /* Zeroize sensitive information.*/ - memset((uint8_t *)x, 0, sizeof(x)); + memset((uint8_t*)x, 0, sizeof(x)); } /* Encodes input (uint32_t) into output (uint8_t). Assumes len is a multiple of 4. */ -static void Encode(uint8_t *output, uint32_t *input, unsigned int len) +static void Encode(uint8_t* output, uint32_t* input, unsigned int len) { unsigned int i, j; @@ -276,7 +276,7 @@ static void Encode(uint8_t *output, uint32_t *input, unsigned int len) /* Decodes input (uint8_t) into output (uint32_t). Assumes len is a multiple of 4. */ -static void Decode(uint32_t *output, const uint8_t *input, unsigned int len) +static void Decode(uint32_t* output, const uint8_t* input, unsigned int len) { unsigned int i, j; diff --git a/src/lwpa/mempool.c b/src/lwpa/mempool.c index 0936005dc..a4c9060b6 100644 --- a/src/lwpa/mempool.c +++ b/src/lwpa/mempool.c @@ -26,7 +26,7 @@ static bool mempool_lock_initted = false; static lwpa_mutex_t mempool_lock; -lwpa_error_t lwpa_mempool_init_priv(LwpaMempoolDesc *desc) +lwpa_error_t lwpa_mempool_init_priv(LwpaMempoolDesc* desc) { lwpa_error_t res = kLwpaErrSys; @@ -52,21 +52,21 @@ lwpa_error_t lwpa_mempool_init_priv(LwpaMempoolDesc *desc) return res; } -void *lwpa_mempool_alloc_priv(LwpaMempoolDesc *desc) +void* lwpa_mempool_alloc_priv(LwpaMempoolDesc* desc) { - void *elem = NULL; + void* elem = NULL; if (lwpa_mutex_take(&mempool_lock, LWPA_WAIT_FOREVER)) { - char *c_pool = (char *)desc->pool; - LwpaMempool *elem_desc = desc->freelist; + char* c_pool = (char*)desc->pool; + LwpaMempool* elem_desc = desc->freelist; if (elem_desc) { ptrdiff_t index = elem_desc - desc->list; if (index >= 0) { desc->freelist = elem_desc->next; - elem = (void *)(c_pool + ((size_t)index * desc->elem_size)); + elem = (void*)(c_pool + ((size_t)index * desc->elem_size)); ++desc->current_used; } } @@ -76,17 +76,17 @@ void *lwpa_mempool_alloc_priv(LwpaMempoolDesc *desc) return elem; } -void lwpa_mempool_free_priv(LwpaMempoolDesc *desc, void *elem) +void lwpa_mempool_free_priv(LwpaMempoolDesc* desc, void* elem) { - char *c_pool = (char *)desc->pool; + char* c_pool = (char*)desc->pool; - ptrdiff_t offset = (char *)elem - c_pool; + ptrdiff_t offset = (char*)elem - c_pool; if (offset >= 0) { if (((size_t)offset % desc->elem_size == 0) && lwpa_mutex_take(&mempool_lock, LWPA_WAIT_FOREVER)) { size_t index = (size_t)offset / desc->elem_size; - LwpaMempool *elem_desc = &desc->list[index]; + LwpaMempool* elem_desc = &desc->list[index]; elem_desc->next = desc->freelist; desc->freelist = elem_desc; --desc->current_used; @@ -95,7 +95,7 @@ void lwpa_mempool_free_priv(LwpaMempoolDesc *desc, void *elem) } } -size_t lwpa_mempool_used_priv(LwpaMempoolDesc *desc) +size_t lwpa_mempool_used_priv(LwpaMempoolDesc* desc) { size_t res = 0; if (lwpa_mutex_take(&mempool_lock, LWPA_WAIT_FOREVER)) diff --git a/src/lwpa/pdu.c b/src/lwpa/pdu.c index 12b096a0f..0c78b2ade 100644 --- a/src/lwpa/pdu.c +++ b/src/lwpa/pdu.c @@ -31,7 +31,7 @@ * with data from this PDU. * \return true (PDU was parsed successfully) or false (parse error or no more PDUs in the block). */ -bool lwpa_parse_pdu(const uint8_t *buf, size_t buflen, const LwpaPduConstraints *constraints, LwpaPdu *pdu) +bool lwpa_parse_pdu(const uint8_t* buf, size_t buflen, const LwpaPduConstraints* constraints, LwpaPdu* pdu) { const uint8_t *this_pdu, *buf_end, *prev_vect, *prev_head, *prev_data, *cur_ptr; uint8_t flags_byte; diff --git a/src/lwpa/rbtree.c b/src/lwpa/rbtree.c index 64187db86..69814a8fd 100644 --- a/src/lwpa/rbtree.c +++ b/src/lwpa/rbtree.c @@ -38,7 +38,7 @@ /* lwpa_rbnode */ -static LwpaRbNode *lwpa_rbnode_alloc(LwpaRbTree *tree) +static LwpaRbNode* lwpa_rbnode_alloc(LwpaRbTree* tree) { if (tree && tree->alloc_f) return tree->alloc_f(); @@ -55,7 +55,7 @@ static LwpaRbNode *lwpa_rbnode_alloc(LwpaRbTree *tree) * \param[in] value Pointer to the value to assign to the node. * \return Pointer to the node that was initialized. */ -LwpaRbNode *lwpa_rbnode_init(LwpaRbNode *self, void *value) +LwpaRbNode* lwpa_rbnode_init(LwpaRbNode* self, void* value) { if (self) { @@ -66,12 +66,12 @@ LwpaRbNode *lwpa_rbnode_init(LwpaRbNode *self, void *value) return self; } -static LwpaRbNode *rb_node_create(LwpaRbTree *tree, void *value) +static LwpaRbNode* rb_node_create(LwpaRbTree* tree, void* value) { return lwpa_rbnode_init(lwpa_rbnode_alloc(tree), value); } -static void rb_node_dealloc(LwpaRbNode *self, const LwpaRbTree *tree) +static void rb_node_dealloc(LwpaRbNode* self, const LwpaRbTree* tree) { if (self && tree && tree->dealloc_f) { @@ -79,14 +79,14 @@ static void rb_node_dealloc(LwpaRbNode *self, const LwpaRbTree *tree) } } -static int rb_node_is_red(const LwpaRbNode *self) +static int rb_node_is_red(const LwpaRbNode* self) { return self ? self->red : 0; } -static LwpaRbNode *rb_node_rotate(LwpaRbNode *self, int dir) +static LwpaRbNode* rb_node_rotate(LwpaRbNode* self, int dir) { - LwpaRbNode *result = NULL; + LwpaRbNode* result = NULL; if (self) { result = self->link[!dir]; @@ -98,9 +98,9 @@ static LwpaRbNode *rb_node_rotate(LwpaRbNode *self, int dir) return result; } -static LwpaRbNode *rb_node_rotate2(LwpaRbNode *self, int dir) +static LwpaRbNode* rb_node_rotate2(LwpaRbNode* self, int dir) { - LwpaRbNode *result = NULL; + LwpaRbNode* result = NULL; if (self) { self->link[!dir] = rb_node_rotate(self->link[!dir], !dir); @@ -116,7 +116,7 @@ static LwpaRbNode *rb_node_rotate2(LwpaRbNode *self, int dir) * This function can be supplied as an argument to any function that takes a * #lwpa_rbtree_node_cmp_f. Simply compares the pointer addresses of the two node values. */ -int lwpa_rbtree_node_cmp_ptr_cb(const LwpaRbTree *self, const LwpaRbNode *a, const LwpaRbNode *b) +int lwpa_rbtree_node_cmp_ptr_cb(const LwpaRbTree* self, const LwpaRbNode* a, const LwpaRbNode* b) { (void)self; return (a->value > b->value) - (a->value < b->value); @@ -127,7 +127,7 @@ int lwpa_rbtree_node_cmp_ptr_cb(const LwpaRbTree *self, const LwpaRbNode *a, con * This function can be supplied as an argument to any function that takes a #lwpa_rbtree_node_f. * Simply deallocates the node using the tree's dealloc_f. */ -void lwpa_rbtree_node_dealloc_cb(const LwpaRbTree *self, LwpaRbNode *node) +void lwpa_rbtree_node_dealloc_cb(const LwpaRbTree* self, LwpaRbNode* node) { rb_node_dealloc(node, self); } @@ -145,7 +145,7 @@ void lwpa_rbtree_node_dealloc_cb(const LwpaRbTree *self, LwpaRbNode *node) * \param[in] dealloc_f A function to use for deallocating node structures. * \return Pointer to the tree that was initialized. */ -LwpaRbTree *lwpa_rbtree_init(LwpaRbTree *self, lwpa_rbtree_node_cmp_f node_cmp_cb, lwpa_rbnode_alloc_f alloc_f, +LwpaRbTree* lwpa_rbtree_init(LwpaRbTree* self, lwpa_rbtree_node_cmp_f node_cmp_cb, lwpa_rbnode_alloc_f alloc_f, lwpa_rbnode_dealloc_f dealloc_f) { if (self) @@ -168,13 +168,13 @@ LwpaRbTree *lwpa_rbtree_init(LwpaRbTree *self, lwpa_rbtree_node_cmp_f node_cmp_c * \param[in] value Value to find. * \return Pointer to the value (value found) or NULL (value not found). */ -void *lwpa_rbtree_find(LwpaRbTree *self, void *value) +void* lwpa_rbtree_find(LwpaRbTree* self, void* value) { - void *result = NULL; + void* result = NULL; if (self) { LwpaRbNode node; - LwpaRbNode *it = self->root; + LwpaRbNode* it = self->root; int cmp = 0; node.value = value; @@ -207,7 +207,7 @@ void *lwpa_rbtree_find(LwpaRbTree *self, void *value) * \return 1 (the value was inserted or the value already existed in the tree) or 0 (an error * occurred). */ -int lwpa_rbtree_insert(LwpaRbTree *self, void *value) +int lwpa_rbtree_insert(LwpaRbTree* self, void* value) { return lwpa_rbtree_insert_node(self, rb_node_create(self, value)); } @@ -224,7 +224,7 @@ int lwpa_rbtree_insert(LwpaRbTree *self, void *value) * \return 1 (the value was inserted or the value already existed in the tree) or 0 (an error * occurred). */ -int lwpa_rbtree_insert_node(LwpaRbTree *self, LwpaRbNode *node) +int lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node) { int result = 0; if (self && node) @@ -313,7 +313,7 @@ int lwpa_rbtree_insert_node(LwpaRbTree *self, LwpaRbNode *node) * \return 1 (the value was removed) or 0 (the value did not exist in the tree or an error * occurred). */ -int lwpa_rbtree_remove(LwpaRbTree *self, void *value) +int lwpa_rbtree_remove(LwpaRbTree* self, void* value) { int result = 0; if (self) @@ -334,12 +334,12 @@ int lwpa_rbtree_remove(LwpaRbTree *self, void *value) * \return 1 (the value was removed) or 0 (the value did not exist in the tree or an error * occurred). */ -int lwpa_rbtree_remove_with_cb(LwpaRbTree *self, void *value, lwpa_rbtree_node_f node_cb) +int lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f node_cb) { LwpaRbNode head = {0}; /* False tree root */ LwpaRbNode node; /* Value wrapper node */ LwpaRbNode *q, *p, *g; /* Helpers */ - LwpaRbNode *f = NULL; /* Found item */ + LwpaRbNode* f = NULL; /* Found item */ int dir = 1; if (!self || self->root == NULL) @@ -379,7 +379,7 @@ int lwpa_rbtree_remove_with_cb(LwpaRbTree *self, void *value, lwpa_rbtree_node_f } else if (!rb_node_is_red(q->link[!dir])) { - LwpaRbNode *s = p->link[!last]; + LwpaRbNode* s = p->link[!last]; if (s) { if (!rb_node_is_red(s->link[!last]) && !rb_node_is_red(s->link[last])) @@ -410,7 +410,7 @@ int lwpa_rbtree_remove_with_cb(LwpaRbTree *self, void *value, lwpa_rbtree_node_f /* Replace and remove the saved node */ if (f) { - void *tmp = f->value; + void* tmp = f->value; f->value = q->value; q->value = tmp; @@ -440,7 +440,7 @@ int lwpa_rbtree_remove_with_cb(LwpaRbTree *self, void *value, lwpa_rbtree_node_f * \param[in] self Tree to clear. * \return 1 (the tree was cleared) or 0 (an error occurred). */ -int lwpa_rbtree_clear(LwpaRbTree *self) +int lwpa_rbtree_clear(LwpaRbTree* self) { int result = 0; if (self) @@ -458,13 +458,13 @@ int lwpa_rbtree_clear(LwpaRbTree *self) * \param[in] node_cb Callback function to call with each node and value being removed. * \return 1 (the tree was cleared) or 0 (an error occurred). */ -int lwpa_rbtree_clear_with_cb(LwpaRbTree *self, lwpa_rbtree_node_f node_cb) +int lwpa_rbtree_clear_with_cb(LwpaRbTree* self, lwpa_rbtree_node_f node_cb) { int result = 0; if (self && node_cb) { - LwpaRbNode *node = self->root; - LwpaRbNode *save = NULL; + LwpaRbNode* node = self->root; + LwpaRbNode* save = NULL; /* Rotate away the left links so that we can treat this like the destruction of a linked list */ while (node) @@ -496,7 +496,7 @@ int lwpa_rbtree_clear_with_cb(LwpaRbTree *self, lwpa_rbtree_node_f node_cb) * \param[in] self The tree of which to get the size. * \return The number of values currently in the tree. */ -size_t lwpa_rbtree_size(LwpaRbTree *self) +size_t lwpa_rbtree_size(LwpaRbTree* self) { size_t result = 0; if (self) @@ -513,7 +513,7 @@ size_t lwpa_rbtree_size(LwpaRbTree *self) * \param[in] root Node at which to start the test. All nodes beneath this node will be tested. * \return 1 (no violations were found) or 0 (a violation was found). */ -int lwpa_rbtree_test(LwpaRbTree *self, LwpaRbNode *root) +int lwpa_rbtree_test(LwpaRbTree* self, LwpaRbNode* root) { int lh, rh; @@ -523,8 +523,8 @@ int lwpa_rbtree_test(LwpaRbTree *self, LwpaRbNode *root) } else { - LwpaRbNode *ln = root->link[0]; - LwpaRbNode *rn = root->link[1]; + LwpaRbNode* ln = root->link[0]; + LwpaRbNode* rn = root->link[1]; /* Consecutive red links */ if (rb_node_is_red(root)) @@ -568,7 +568,7 @@ int lwpa_rbtree_test(LwpaRbTree *self, LwpaRbNode *root) * \param[in] self The iterator to be initialized. * \return Pointer to the iterator that was initialized. */ -LwpaRbIter *lwpa_rbiter_init(LwpaRbIter *self) +LwpaRbIter* lwpa_rbiter_init(LwpaRbIter* self) { if (self) { @@ -581,9 +581,9 @@ LwpaRbIter *lwpa_rbiter_init(LwpaRbIter *self) /* Internal function, init traversal object, dir determines whether to begin traversal at the * smallest or largest valued node. */ -static void *rb_iter_start(LwpaRbIter *self, LwpaRbTree *tree, int dir) +static void* rb_iter_start(LwpaRbIter* self, LwpaRbTree* tree, int dir) { - void *result = NULL; + void* result = NULL; if (self) { self->tree = tree; @@ -606,7 +606,7 @@ static void *rb_iter_start(LwpaRbIter *self, LwpaRbTree *tree, int dir) } /* Traverse a red black tree in the user-specified direction (0 asc, 1 desc) */ -static void *rb_iter_move(LwpaRbIter *self, int dir) +static void* rb_iter_move(LwpaRbIter* self, int dir) { if (self->node->link[dir] != NULL) { @@ -622,7 +622,7 @@ static void *rb_iter_move(LwpaRbIter *self, int dir) else { /* Move to the next branch */ - LwpaRbNode *last = NULL; + LwpaRbNode* last = NULL; do { if (self->top == 0) @@ -646,7 +646,7 @@ static void *rb_iter_move(LwpaRbIter *self, int dir) * \param[in] tree Tree of which to get the first value. * \return Pointer to the first value or NULL (the tree was empty or invalid). */ -void *lwpa_rbiter_first(LwpaRbIter *self, LwpaRbTree *tree) +void* lwpa_rbiter_first(LwpaRbIter* self, LwpaRbTree* tree) { return rb_iter_start(self, tree, 0); } @@ -660,7 +660,7 @@ void *lwpa_rbiter_first(LwpaRbIter *self, LwpaRbTree *tree) * \param[in] tree Tree of which to get the last value. * \return Pointer to the last value or NULL (the tree was empty or invalid). */ -void *lwpa_rbiter_last(LwpaRbIter *self, LwpaRbTree *tree) +void* lwpa_rbiter_last(LwpaRbIter* self, LwpaRbTree* tree) { return rb_iter_start(self, tree, 1); } @@ -673,7 +673,7 @@ void *lwpa_rbiter_last(LwpaRbIter *self, LwpaRbTree *tree) * \param[in] self Iterator to advance. * \return Pointer to next higher value, or NULL (the end of the tree has been reached). */ -void *lwpa_rbiter_next(LwpaRbIter *self) +void* lwpa_rbiter_next(LwpaRbIter* self) { return rb_iter_move(self, 1); } @@ -686,7 +686,7 @@ void *lwpa_rbiter_next(LwpaRbIter *self) * \param[in] self Iterator to reverse-advance. * \return Pointer to next lower value, or NULL (the beginning of the tree has been reached). */ -void *lwpa_rbiter_prev(LwpaRbIter *self) +void* lwpa_rbiter_prev(LwpaRbIter* self) { return rb_iter_move(self, 0); } diff --git a/src/lwpa/root_layer_pdu.c b/src/lwpa/root_layer_pdu.c index 21cf7f7dd..c5389bcff 100644 --- a/src/lwpa/root_layer_pdu.c +++ b/src/lwpa/root_layer_pdu.c @@ -48,7 +48,7 @@ * \return true (preamble was parsed successfully) or false (buffer too short or buffer does not * contain a valid TCP preamble). */ -bool lwpa_parse_tcp_preamble(const uint8_t *buf, size_t buflen, LwpaTcpPreamble *preamble) +bool lwpa_parse_tcp_preamble(const uint8_t* buf, size_t buflen, LwpaTcpPreamble* preamble) { if (!preamble || !buf || (buflen < ACN_TCP_PREAMBLE_SIZE)) return false; @@ -73,9 +73,9 @@ bool lwpa_parse_tcp_preamble(const uint8_t *buf, size_t buflen, LwpaTcpPreamble * \return true (preamble was parsed successfully) or false (buffer too short or buffer does not * contain a valid UDP preamble). */ -bool lwpa_parse_udp_preamble(const uint8_t *buf, size_t buflen, LwpaUdpPreamble *preamble) +bool lwpa_parse_udp_preamble(const uint8_t* buf, size_t buflen, LwpaUdpPreamble* preamble) { - const uint8_t *pcur; + const uint8_t* pcur; uint16_t preamble_len, postamble_len; if (!preamble || !buf || (buflen < ACN_UDP_PREAMBLE_SIZE)) @@ -107,7 +107,7 @@ bool lwpa_parse_udp_preamble(const uint8_t *buf, size_t buflen, LwpaUdpPreamble * first PDU in the block. * \return true (PDU was parsed successfully) or false (parse error or no more PDUs in the block). */ -bool lwpa_parse_root_layer_header(const uint8_t *buf, size_t buflen, LwpaRootLayerPdu *pdu, LwpaRootLayerPdu *last_pdu) +bool lwpa_parse_root_layer_header(const uint8_t* buf, size_t buflen, LwpaRootLayerPdu* pdu, LwpaRootLayerPdu* last_pdu) { uint32_t min_pdu_len, pdu_len; bool extlength, inheritvect, inherithead, inheritdata; @@ -205,7 +205,7 @@ bool lwpa_parse_root_layer_header(const uint8_t *buf, size_t buflen, LwpaRootLay * \param[in,out] last_pdu State data for future calls. * \return true (PDU was parsed successfully) or false (parse error or no more PDUs in the block). */ -bool lwpa_parse_root_layer_pdu(const uint8_t *buf, size_t buflen, LwpaRootLayerPdu *pdu, LwpaPdu *last_pdu) +bool lwpa_parse_root_layer_pdu(const uint8_t* buf, size_t buflen, LwpaRootLayerPdu* pdu, LwpaPdu* last_pdu) { LwpaPduConstraints rlp_constraints = {/* vector_size */ 4, /* header_size */ 16}; @@ -233,9 +233,9 @@ bool lwpa_parse_root_layer_pdu(const uint8_t *buf, size_t buflen, LwpaRootLayerP * #ACN_UDP_PREAMBLE_SIZE. * \return Number of bytes packed (success) or 0 (failure). */ -size_t lwpa_pack_udp_preamble(uint8_t *buf, size_t buflen) +size_t lwpa_pack_udp_preamble(uint8_t* buf, size_t buflen) { - uint8_t *cur_ptr; + uint8_t* cur_ptr; if (!buf || buflen < ACN_UDP_PREAMBLE_SIZE) return 0; @@ -261,9 +261,9 @@ size_t lwpa_pack_udp_preamble(uint8_t *buf, size_t buflen) * this TCP preamble. * \return Number of bytes packed (success) or 0 (failure). */ -size_t lwpa_pack_tcp_preamble(uint8_t *buf, size_t buflen, size_t rlp_block_len) +size_t lwpa_pack_tcp_preamble(uint8_t* buf, size_t buflen, size_t rlp_block_len) { - uint8_t *cur_ptr; + uint8_t* cur_ptr; if (!buf || buflen < ACN_TCP_PREAMBLE_SIZE) return 0; @@ -285,9 +285,9 @@ size_t lwpa_pack_tcp_preamble(uint8_t *buf, size_t buflen, size_t rlp_block_len) * \param[in] num_pdus Size of the pdu_block array. * \return Buffer size to allocate. */ -size_t lwpa_root_layer_buf_size(const LwpaRootLayerPdu *pdu_block, size_t num_pdus) +size_t lwpa_root_layer_buf_size(const LwpaRootLayerPdu* pdu_block, size_t num_pdus) { - const LwpaRootLayerPdu *pdu; + const LwpaRootLayerPdu* pdu; size_t block_size = 0; for (pdu = pdu_block; pdu < pdu_block + num_pdus; ++pdu) @@ -311,9 +311,9 @@ size_t lwpa_root_layer_buf_size(const LwpaRootLayerPdu *pdu_block, size_t num_pd * \param[in] pdu PDU for which to pack the header into a buffer. * \return Number of bytes packed (success) or 0 (failure). */ -size_t lwpa_pack_root_layer_header(uint8_t *buf, size_t buflen, const LwpaRootLayerPdu *pdu) +size_t lwpa_pack_root_layer_header(uint8_t* buf, size_t buflen, const LwpaRootLayerPdu* pdu) { - uint8_t *cur_ptr = buf; + uint8_t* cur_ptr = buf; if (!buf || !pdu || buflen < ACN_RLP_HEADER_SIZE_EXT_LEN) return 0; @@ -349,10 +349,10 @@ size_t lwpa_pack_root_layer_header(uint8_t *buf, size_t buflen, const LwpaRootLa * value returned by lwpa_root_layer_buf_size(); this is because this function performs * more optimizations related to PDU inheritance. */ -size_t lwpa_pack_root_layer_block(uint8_t *buf, size_t buflen, const LwpaRootLayerPdu *pdu_block, size_t num_pdus) +size_t lwpa_pack_root_layer_block(uint8_t* buf, size_t buflen, const LwpaRootLayerPdu* pdu_block, size_t num_pdus) { - uint8_t *cur_ptr = buf; - const LwpaRootLayerPdu *pdu; + uint8_t* cur_ptr = buf; + const LwpaRootLayerPdu* pdu; LwpaRootLayerPdu last_pdu = {{{0}}, 0, NULL, 0}; if (!buf || !pdu_block || (lwpa_root_layer_buf_size(pdu_block, num_pdus)) > buflen) diff --git a/src/lwpa/uuid.c b/src/lwpa/uuid.c index 076ed4caf..00b88d0ed 100644 --- a/src/lwpa/uuid.c +++ b/src/lwpa/uuid.c @@ -40,9 +40,9 @@ const LwpaUuid kLwpaNullUuid = {{0}}; * behavior, this buffer should be at least of size #LWPA_UUID_STRING_BYTES. * \param[in] uuid UUID to convert to a string. */ -void lwpa_uuid_to_string(char *buf, const LwpaUuid *uuid) +void lwpa_uuid_to_string(char* buf, const LwpaUuid* uuid) { - const uint8_t *c = uuid->data; + const uint8_t* c = uuid->data; /* Automatically suppresses MSVC warning - minimum buffer size is well documented and cannot be * exceeded by this format string. */ @@ -61,11 +61,11 @@ void lwpa_uuid_to_string(char *buf, const LwpaUuid *uuid) * \param[in] buflen Size in bytes of buf. * \return true (parse successful) or false (parse failure). */ -bool lwpa_string_to_uuid(LwpaUuid *uuid, const char *buf, size_t buflen) +bool lwpa_string_to_uuid(LwpaUuid* uuid, const char* buf, size_t buflen) { - const char *from_ptr = buf; + const char* from_ptr = buf; uint8_t to_buf[LWPA_UUID_BYTES]; - uint8_t *to_ptr = to_buf; + uint8_t* to_ptr = to_buf; bool first = true; /* Whether we are doing the first or second nibble of the byte */ if (!uuid || !buf || buflen == 0) @@ -129,7 +129,7 @@ bool lwpa_string_to_uuid(LwpaUuid *uuid, const char *buf, size_t buflen) */ /* Quick utility for generating a uuid out of a md5 hash buffer */ -static void generate_from_hash(LwpaUuid *uuid_out, MD5_CTX *pmd5) +static void generate_from_hash(LwpaUuid* uuid_out, MD5_CTX* pmd5) { uint8_t buffer[LWPA_UUID_BYTES]; MD5Final(buffer, pmd5); @@ -162,7 +162,7 @@ static void generate_from_hash(LwpaUuid *uuid_out, MD5_CTX *pmd5) * \return #kLwpaErrOk: UUID generated successfully.\n * #kLwpaErrInvalid: Invalid argument provided. */ -lwpa_error_t lwpa_generate_v3_uuid(LwpaUuid *uuid, const char *devstr, const uint8_t *macaddr, uint32_t uuidnum) +lwpa_error_t lwpa_generate_v3_uuid(LwpaUuid* uuid, const char* devstr, const uint8_t* macaddr, uint32_t uuidnum) { MD5_CTX md5; uint8_t num[4]; @@ -176,9 +176,9 @@ lwpa_error_t lwpa_generate_v3_uuid(LwpaUuid *uuid, const char *devstr, const uin MD5Update(&md5, ns, 16); /* The string we'll be encoding is "lwpa device,[devstr][macaddr][uuidnum in network order]" */ - MD5Update(&md5, (uint8_t *)"lwpa device, ", 13); + MD5Update(&md5, (uint8_t*)"lwpa device, ", 13); if (devstr) - MD5Update(&md5, (uint8_t *)(devstr), (unsigned int)strlen(devstr)); + MD5Update(&md5, (uint8_t*)(devstr), (unsigned int)strlen(devstr)); MD5Update(&md5, macaddr, 6); diff --git a/src/lwpa_mock/socket.c b/src/lwpa_mock/socket.c index 1cc15aafc..cba64f8cb 100644 --- a/src/lwpa_mock/socket.c +++ b/src/lwpa_mock/socket.c @@ -19,34 +19,32 @@ #include "lwpa_mock/socket.h" -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_accept, lwpa_socket_t, LwpaSockaddr *, lwpa_socket_t *); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_bind, lwpa_socket_t, const LwpaSockaddr *); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_accept, lwpa_socket_t, LwpaSockaddr*, lwpa_socket_t*); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_bind, lwpa_socket_t, const LwpaSockaddr*); DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_close, lwpa_socket_t); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_connect, lwpa_socket_t, const LwpaSockaddr *); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getpeername, lwpa_socket_t, LwpaSockaddr *); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getsockname, lwpa_socket_t, LwpaSockaddr *); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getsockopt, lwpa_socket_t, int, int, void *, size_t *); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_connect, lwpa_socket_t, const LwpaSockaddr*); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getpeername, lwpa_socket_t, LwpaSockaddr*); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getsockname, lwpa_socket_t, LwpaSockaddr*); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getsockopt, lwpa_socket_t, int, int, void*, size_t*); DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_listen, lwpa_socket_t, int); -DEFINE_FAKE_VALUE_FUNC(int, lwpa_recv, lwpa_socket_t, void *, size_t, int); -DEFINE_FAKE_VALUE_FUNC(int, lwpa_recvfrom, lwpa_socket_t, void *, size_t, int, LwpaSockaddr *); -DEFINE_FAKE_VALUE_FUNC(int, lwpa_send, lwpa_socket_t, const void *, size_t, int); -DEFINE_FAKE_VALUE_FUNC(int, lwpa_sendto, lwpa_socket_t, const void *, size_t, int, const LwpaSockaddr *); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_setsockopt, lwpa_socket_t, int, int, const void *, size_t); +DEFINE_FAKE_VALUE_FUNC(int, lwpa_recv, lwpa_socket_t, void*, size_t, int); +DEFINE_FAKE_VALUE_FUNC(int, lwpa_recvfrom, lwpa_socket_t, void*, size_t, int, LwpaSockaddr*); +DEFINE_FAKE_VALUE_FUNC(int, lwpa_send, lwpa_socket_t, const void*, size_t, int); +DEFINE_FAKE_VALUE_FUNC(int, lwpa_sendto, lwpa_socket_t, const void*, size_t, int, const LwpaSockaddr*); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_setsockopt, lwpa_socket_t, int, int, const void*, size_t); DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_shutdown, lwpa_socket_t, int); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_socket, unsigned int, unsigned int, lwpa_socket_t *); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_socket, unsigned int, unsigned int, lwpa_socket_t*); DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_setblocking, lwpa_socket_t, bool); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_context_init, LwpaPollContext *); -DEFINE_FAKE_VOID_FUNC(lwpa_poll_context_deinit, LwpaPollContext *); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_add_socket, LwpaPollContext *, lwpa_socket_t, lwpa_poll_events_t, - void *); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_modify_socket, LwpaPollContext *, lwpa_socket_t, lwpa_poll_events_t, - void *); -DEFINE_FAKE_VOID_FUNC(lwpa_poll_remove_socket, LwpaPollContext *, lwpa_socket_t); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_wait, LwpaPollContext *, LwpaPollEvent *, int); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_context_init, LwpaPollContext*); +DEFINE_FAKE_VOID_FUNC(lwpa_poll_context_deinit, LwpaPollContext*); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_add_socket, LwpaPollContext*, lwpa_socket_t, lwpa_poll_events_t, void*); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_modify_socket, LwpaPollContext*, lwpa_socket_t, lwpa_poll_events_t, + void*); +DEFINE_FAKE_VOID_FUNC(lwpa_poll_remove_socket, LwpaPollContext*, lwpa_socket_t); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_poll_wait, LwpaPollContext*, LwpaPollEvent*, int); -DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getaddrinfo, const char *, const char *, const LwpaAddrinfo *, - LwpaAddrinfo *); -DEFINE_FAKE_VALUE_FUNC(bool, lwpa_nextaddr, LwpaAddrinfo *); -DEFINE_FAKE_VOID_FUNC(lwpa_freeaddrinfo, LwpaAddrinfo *); +DEFINE_FAKE_VALUE_FUNC(lwpa_error_t, lwpa_getaddrinfo, const char*, const char*, const LwpaAddrinfo*, LwpaAddrinfo*); +DEFINE_FAKE_VALUE_FUNC(bool, lwpa_nextaddr, LwpaAddrinfo*); +DEFINE_FAKE_VOID_FUNC(lwpa_freeaddrinfo, LwpaAddrinfo*); diff --git a/src/lwpa_plat/freertos_lwip/lwpa/lock.c b/src/lwpa_plat/freertos_lwip/lwpa/lock.c index 6f3eda18e..00c4101b7 100644 --- a/src/lwpa_plat/freertos_lwip/lwpa/lock.c +++ b/src/lwpa_plat/freertos_lwip/lwpa/lock.c @@ -23,12 +23,12 @@ #define convert_ms_to_ticks(ms) ((ms == LWPA_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(ms)) -bool lwpa_mutex_create(lwpa_mutex_t *id) +bool lwpa_mutex_create(lwpa_mutex_t* id) { return id ? ((*id = (lwpa_mutex_t)xSemaphoreCreateMutex()) != NULL) : false; } -bool lwpa_mutex_take(lwpa_mutex_t *id, int wait_ms) +bool lwpa_mutex_take(lwpa_mutex_t* id, int wait_ms) { if (id) { @@ -38,13 +38,13 @@ bool lwpa_mutex_take(lwpa_mutex_t *id, int wait_ms) return false; } -void lwpa_mutex_give(lwpa_mutex_t *id) +void lwpa_mutex_give(lwpa_mutex_t* id) { if (id && *id) xSemaphoreGive((SemaphoreHandle_t)*id); } -void lwpa_mutex_destroy(lwpa_mutex_t *id) +void lwpa_mutex_destroy(lwpa_mutex_t* id) { if (id && *id) { @@ -53,23 +53,23 @@ void lwpa_mutex_destroy(lwpa_mutex_t *id) } } -bool lwpa_signal_create(lwpa_signal_t *id) +bool lwpa_signal_create(lwpa_signal_t* id) { return id ? ((*id = (lwpa_signal_t)xSemaphoreCreateBinary()) != NULL) : false; } -bool lwpa_signal_wait(lwpa_signal_t *id, int wait_ms) +bool lwpa_signal_wait(lwpa_signal_t* id, int wait_ms) { return (id && *id) ? (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, convert_ms_to_ticks(wait_ms))) : false; } -void lwpa_signal_post(lwpa_signal_t *id) +void lwpa_signal_post(lwpa_signal_t* id) { if (id && *id) xSemaphoreGive((SemaphoreHandle_t)*id); } -void lwpa_signal_destroy(lwpa_signal_t *id) +void lwpa_signal_destroy(lwpa_signal_t* id) { if (id && *id) { @@ -78,21 +78,21 @@ void lwpa_signal_destroy(lwpa_signal_t *id) } } -static void atomic_inc(unsigned int *count) +static void atomic_inc(unsigned int* count) { portENTER_CRITICAL(); (*count)++; portEXIT_CRITICAL(); } -static void atomic_dec(unsigned int *count) +static void atomic_dec(unsigned int* count) { portENTER_CRITICAL(); (*count)--; portEXIT_CRITICAL(); } -bool lwpa_rwlock_create(lwpa_rwlock_t *id) +bool lwpa_rwlock_create(lwpa_rwlock_t* id) { if (id && (NULL != (id->sem = xSemaphoreCreateMutex()))) { @@ -102,7 +102,7 @@ bool lwpa_rwlock_create(lwpa_rwlock_t *id) return false; } -bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms) +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms) { if (!id || !id->sem) return false; @@ -118,13 +118,13 @@ bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms) return false; } -void lwpa_rwlock_readunlock(lwpa_rwlock_t *id) +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) { if (id && id->sem) atomic_dec(&id->reader_count); } -bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms) +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms) { TickType_t initial_time; @@ -162,13 +162,13 @@ bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms) return false; } -void lwpa_rwlock_writeunlock(lwpa_rwlock_t *id) +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) { if (id && id->sem) xSemaphoreGive(id->sem); } -void lwpa_rwlock_destroy(lwpa_rwlock_t *id) +void lwpa_rwlock_destroy(lwpa_rwlock_t* id) { if (id && id->sem) { diff --git a/src/lwpa_plat/freertos_lwip/lwpa/netint.c b/src/lwpa_plat/freertos_lwip/lwpa/netint.c index c21cf82b2..34a80a822 100644 --- a/src/lwpa_plat/freertos_lwip/lwpa/netint.c +++ b/src/lwpa_plat/freertos_lwip/lwpa/netint.c @@ -21,10 +21,10 @@ #include #include "lwip/netif.h" -static bool mask_is_empty(const LwpaIpAddr *mask); -static bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr *mask); +static bool mask_is_empty(const LwpaIpAddr* mask); +static bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask); -static void copy_interface_info(struct netif *lwip_netint, LwpaNetintInfo *netint) +static void copy_interface_info(struct netif* lwip_netint, LwpaNetintInfo* netint) { netint->ifindex = (int)lwip_netint->num; if (lwip_netint->hwaddr_len == NETINTINFO_MAC_LEN) @@ -82,7 +82,7 @@ static void copy_interface_info(struct netif *lwip_netint, LwpaNetintInfo *netin size_t netint_get_num_interfaces() { size_t num_interfaces = 0; - struct netif *netint; + struct netif* netint; for (netint = netif_list; netint; netint = netint->next) { /* Skip loopback interfaces */ @@ -92,10 +92,10 @@ size_t netint_get_num_interfaces() return num_interfaces; } -size_t netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_size) +size_t netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) { size_t num_interfaces = 0; - struct netif *lwip_netint; + struct netif* lwip_netint; if (!netint_arr || netint_arr_size == 0) return 0; @@ -116,7 +116,7 @@ size_t netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_size) return num_interfaces; } -bool netint_get_default_interface(LwpaNetintInfo *netint) +bool netint_get_default_interface(LwpaNetintInfo* netint) { if (netint && netif_default) { @@ -126,7 +126,7 @@ bool netint_get_default_interface(LwpaNetintInfo *netint) return false; } -bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr *mask) +bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask) { if (lwpaip_is_v4(ip1) && lwpaip_is_v4(ip2) && lwpaip_is_v4(mask)) { @@ -135,9 +135,9 @@ bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr else if (lwpaip_is_v6(ip1) && lwpaip_is_v6(ip2) && lwpaip_is_v6(mask)) { size_t i; - const uint32_t *p1 = (const uint32_t *)lwpaip_v6_address(ip1); - const uint32_t *p2 = (const uint32_t *)lwpaip_v6_address(ip2); - const uint32_t *pm = (const uint32_t *)lwpaip_v6_address(mask); + const uint32_t* p1 = (const uint32_t*)lwpaip_v6_address(ip1); + const uint32_t* p2 = (const uint32_t*)lwpaip_v6_address(ip2); + const uint32_t* pm = (const uint32_t*)lwpaip_v6_address(mask); for (i = 0; i < IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) { @@ -149,7 +149,7 @@ bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr return false; } -bool mask_is_empty(const LwpaIpAddr *mask) +bool mask_is_empty(const LwpaIpAddr* mask) { uint32_t mask_part = 0; @@ -158,19 +158,19 @@ bool mask_is_empty(const LwpaIpAddr *mask) else if (lwpaip_is_v6(mask)) { size_t i; - const uint32_t *p = (const uint32_t *)lwpaip_v6_address(mask); + const uint32_t* p = (const uint32_t*)lwpaip_v6_address(mask); for (i = 0; i < IPV6_BYTES / 4; ++i, ++p) mask_part |= *p; } return (mask_part == 0); } -const LwpaNetintInfo *netint_get_iface_for_dest(const LwpaIpAddr *dest, const LwpaNetintInfo *netint_arr, +const LwpaNetintInfo* netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, size_t netint_arr_size) { - const LwpaNetintInfo *res = NULL; - const LwpaNetintInfo *def = NULL; - const LwpaNetintInfo *netint; + const LwpaNetintInfo* res = NULL; + const LwpaNetintInfo* def = NULL; + const LwpaNetintInfo* netint; if (!dest || !netint_arr || netint_arr_size == 0) return false; diff --git a/src/lwpa_plat/freertos_lwip/lwpa/socket.c b/src/lwpa_plat/freertos_lwip/lwpa/socket.c index c772f0758..0e3edec20 100644 --- a/src/lwpa_plat/freertos_lwip/lwpa/socket.c +++ b/src/lwpa_plat/freertos_lwip/lwpa/socket.c @@ -85,12 +85,12 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /* clang-format on */ -static bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) +static bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) { #if LWIP_IPV4 - struct sockaddr_in *sin = (struct sockaddr_in *)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sa->port = ntohs(sin->sin_port); lwpaip_set_v4_address(&sa->ip, ntohl(sin->sin_addr.s_addr)); return true; @@ -101,7 +101,7 @@ static bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) else if (pfsa->sa_family == AF_INET6) { #if LWIP_IPV6 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sa->port = ntohs(sin6->sin6_port); lwpaip_set_v6_address(&sa->ip, sin6->sin6_addr.s6_addr); return true; @@ -112,13 +112,13 @@ static bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) return false; } -static socklen_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa) +static socklen_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) { socklen_t ret = 0; if (lwpaip_is_v4(&sa->ip)) { #if LWIP_IPV4 - struct sockaddr_in *sin = (struct sockaddr_in *)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sin->sin_family = AF_INET; sin->sin_port = htons(sa->port); sin->sin_addr.s_addr = htonl(lwpaip_v4_address(&sa->ip)); @@ -128,7 +128,7 @@ static socklen_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr else if (lwpaip_is_v6(&sa->ip)) { #if LWIP_IPV6 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(sa->port); memcpy(sin6->sin6_addr.s6_addr, lwpaip_v6_address(&sa->ip), IPV6_BYTES); @@ -138,7 +138,7 @@ static socklen_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr return ret; } -lwpa_error_t lwpa_socket_init(void *platform_data) +lwpa_error_t lwpa_socket_init(void* platform_data) { /* No initialization is necessary on this platform. */ (void)platform_data; @@ -150,77 +150,77 @@ void lwpa_socket_deinit() /* No deinitialization is necessary on this platform. */ } -int lwpa_accept(void *id, LwpaSockaddr *address) +int lwpa_accept(void* id, LwpaSockaddr* address) { /* TODO */ return -1; } -int lwpa_bind(void *id, const LwpaSockaddr *address) +int lwpa_bind(void* id, const LwpaSockaddr* address) { int res = -1; if (address) { struct sockaddr_storage ss; - socklen_t sa_size = sockaddr_lwpa_to_plat((struct sockaddr *)&ss, address); + socklen_t sa_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, address); if (sa_size > 0) - res = bind((int)id, (struct sockaddr *)&ss, sa_size); + res = bind((int)id, (struct sockaddr*)&ss, sa_size); } return res; } -int lwpa_close(void *id) +int lwpa_close(void* id) { return close((int)id); } -int lwpa_connect(void *id, const LwpaSockaddr *address) +int lwpa_connect(void* id, const LwpaSockaddr* address) { /* TODO */ return -1; } -int lwpa_getpeername(void *id, LwpaSockaddr *address) +int lwpa_getpeername(void* id, LwpaSockaddr* address) { /* TODO */ return -1; } -int lwpa_getsockname(void *id, LwpaSockaddr *address) +int lwpa_getsockname(void* id, LwpaSockaddr* address) { int res = -1; if (address) { struct sockaddr_storage ss; socklen_t size = sizeof ss; - if (0 == getsockname((int)id, (struct sockaddr *)&ss, &size)) + if (0 == getsockname((int)id, (struct sockaddr*)&ss, &size)) { - if (sockaddr_plat_to_lwpa(address, (struct sockaddr *)&ss)) + if (sockaddr_plat_to_lwpa(address, (struct sockaddr*)&ss)) res = 0; } } return res; } -int lwpa_getsockopt(void *id, int level, int option_name, void *option_value, size_t *option_len) +int lwpa_getsockopt(void* id, int level, int option_name, void* option_value, size_t* option_len) { /* TODO */ return -1; } -int lwpa_listen(void *id, int backlog) +int lwpa_listen(void* id, int backlog) { /* TODO */ return -1; } -int lwpa_recv(void *id, void *buffer, size_t length, int flags) +int lwpa_recv(void* id, void* buffer, size_t length, int flags) { /* TODO */ return -1; } -int lwpa_recvfrom(void *id, void *buffer, size_t length, int flags, LwpaSockaddr *address) +int lwpa_recvfrom(void* id, void* buffer, size_t length, int flags, LwpaSockaddr* address) { int res = -1; int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; @@ -230,13 +230,13 @@ int lwpa_recvfrom(void *id, void *buffer, size_t length, int flags, LwpaSockaddr if (!buffer) return res; - res = recvfrom((int)id, buffer, length, impl_flags, (struct sockaddr *)&fromaddr, &fromlen); + res = recvfrom((int)id, buffer, length, impl_flags, (struct sockaddr*)&fromaddr, &fromlen); if (res >= 0) { if (address && fromlen > 0) { - if (!sockaddr_plat_to_lwpa(address, (struct sockaddr *)&fromaddr)) + if (!sockaddr_plat_to_lwpa(address, (struct sockaddr*)&fromaddr)) res = -1; } } @@ -244,13 +244,13 @@ int lwpa_recvfrom(void *id, void *buffer, size_t length, int flags, LwpaSockaddr return res; } -int lwpa_send(void *id, const void *message, size_t length, int flags) +int lwpa_send(void* id, const void* message, size_t length, int flags) { /* TODO */ return -1; } -int lwpa_sendto(void *id, const void *message, size_t length, int flags, const LwpaSockaddr *dest_addr) +int lwpa_sendto(void* id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) { int res = -1; socklen_t ss_size; @@ -259,12 +259,12 @@ int lwpa_sendto(void *id, const void *message, size_t length, int flags, const L if (!dest_addr || !message) return res; - if ((ss_size = sockaddr_lwpa_to_plat((struct sockaddr *)&ss, dest_addr)) > 0) - res = sendto((int)id, message, length, 0, (struct sockaddr *)&ss, ss_size); + if ((ss_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, dest_addr)) > 0) + res = sendto((int)id, message, length, 0, (struct sockaddr*)&ss, ss_size); return res; } -int lwpa_setsockopt(void *id, int level, int option_name, const void *option_value, size_t option_len) +int lwpa_setsockopt(void* id, int level, int option_name, const void* option_value, size_t option_len) { int res = -1; @@ -287,7 +287,7 @@ int lwpa_setsockopt(void *id, int level, int option_name, const void *option_val case LWPA_SO_RCVTIMEO: if (option_len == sizeof(int)) { - int ms = *(int *)option_value; + int ms = *(int*)option_value; struct timeval val = {ms / 1000, (ms % 1000) * 1000}; res = setsockopt((int)id, SOL_SOCKET, SO_RCVTIMEO, &val, sizeof val); } @@ -295,7 +295,7 @@ int lwpa_setsockopt(void *id, int level, int option_name, const void *option_val case LWPA_SO_SNDTIMEO: if (option_len == sizeof(int)) { - int ms = *(int *)option_value; + int ms = *(int*)option_value; struct timeval val = {ms / 1000, (ms % 1000) * 1000}; res = setsockopt((int)id, SOL_SOCKET, SO_SNDTIMEO, &val, sizeof val); } @@ -328,7 +328,7 @@ int lwpa_setsockopt(void *id, int level, int option_name, const void *option_val case LWPA_MCAST_JOIN_GROUP: if (option_len == sizeof(struct lwpa_mreq)) { - LwpaMreq *amreq = (LwpaMreq *)option_value; + LwpaMreq* amreq = (LwpaMreq*)option_value; if (lwpaip_is_v4(&amreq->group)) { struct ip_mreq val; @@ -341,7 +341,7 @@ int lwpa_setsockopt(void *id, int level, int option_name, const void *option_val case LWPA_MCAST_LEAVE_GROUP: if (option_len == sizeof(struct lwpa_mreq)) { - LwpaMreq *amreq = (LwpaMreq *)option_value; + LwpaMreq* amreq = (LwpaMreq*)option_value; if (lwpaip_is_v4(&amreq->group)) { struct ip_mreq val; @@ -354,7 +354,7 @@ int lwpa_setsockopt(void *id, int level, int option_name, const void *option_val case LWPA_IP_MULTICAST_IF: if (option_len == sizeof(struct lwpa_ip)) { - LwpaIpAddr *netint = (LwpaIpAddr *)option_value; + LwpaIpAddr* netint = (LwpaIpAddr*)option_value; if (lwpaip_is_v4(netint)) { struct in_addr val; @@ -365,13 +365,13 @@ int lwpa_setsockopt(void *id, int level, int option_name, const void *option_val break; case LWPA_IP_MULTICAST_TTL: { - unsigned char val = (unsigned char)*(int *)option_value; + unsigned char val = (unsigned char)*(int*)option_value; res = setsockopt((int)id, IPPROTO_IP, IP_MULTICAST_TTL, &val, sizeof val); } break; case LWPA_IP_MULTICAST_LOOP: { - unsigned char val = (unsigned char)*(int *)option_value; + unsigned char val = (unsigned char)*(int*)option_value; res = setsockopt((int)id, IPPROTO_IP, IP_MULTICAST_LOOP, &val, sizeof val); } break; @@ -427,14 +427,14 @@ int lwpa_setsockopt(void *id, int level, int option_name, const void *option_val return res; } -int lwpa_shutdown(void *id, int how) +int lwpa_shutdown(void* id, int how) { if (how >= 0 && how < LWPA_NUM_SHUT) return shutdown((int)id, shutmap[how]); return -1; } -lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t *id) +lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* id) { if (id) { @@ -460,11 +460,11 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t * return kLwpaErrInvalid; } -int lwpa_poll(LwpaPollfd *fds, size_t nfds, int timeout_ms) +int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) { fd_set readfds; fd_set writefds; - LwpaPollfd *fd; + LwpaPollfd* fd; int nplatfds; int sel_res; int nreadfds = 0, nwritefds = 0; @@ -527,10 +527,10 @@ int lwpa_poll(LwpaPollfd *fds, size_t nfds, int timeout_ms) return sel_res; } -int lwpa_getaddrinfo(const char *hostname, const char *service, const LwpaAddrinfo *hints, LwpaAddrinfo *result) +int lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, LwpaAddrinfo* result) { int res; - struct addrinfo *pf_res; + struct addrinfo* pf_res; struct addrinfo pf_hints; if ((!hostname && !service) || !result) @@ -556,11 +556,11 @@ int lwpa_getaddrinfo(const char *hostname, const char *service, const LwpaAddrin return res; } -bool lwpa_nextaddr(LwpaAddrinfo *ai) +bool lwpa_nextaddr(LwpaAddrinfo* ai) { if (ai && ai->pd[1]) { - struct addrinfo *pf_ai = (struct addrinfo *)ai->pd[1]; + struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; if (!sockaddr_plat_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) return false; @@ -592,13 +592,13 @@ bool lwpa_nextaddr(LwpaAddrinfo *ai) return false; } -void lwpa_freeaddrinfo(LwpaAddrinfo *ai) +void lwpa_freeaddrinfo(LwpaAddrinfo* ai) { if (ai) - freeaddrinfo((struct addrinfo *)ai->pd[0]); + freeaddrinfo((struct addrinfo*)ai->pd[0]); } -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size) +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) { if (!src || !dest) return kLwpaErrInvalid; @@ -626,7 +626,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size) } } -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char *src, LwpaIpAddr *dest) +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) { if (!src || !dest) return kLwpaErrInvalid; diff --git a/src/lwpa_plat/freertos_lwip/lwpa/thread.c b/src/lwpa_plat/freertos_lwip/lwpa/thread.c index 82ae8bb0f..6f354f663 100644 --- a/src/lwpa_plat/freertos_lwip/lwpa/thread.c +++ b/src/lwpa_plat/freertos_lwip/lwpa/thread.c @@ -21,9 +21,9 @@ #define convert_ms_to_ticks(ms) ((ms == LWPA_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(ms)) -static void thread_func_internal(void *pvParameters) +static void thread_func_internal(void* pvParameters) { - lwpa_thread_t *thread_data = (lwpa_thread_t *)pvParameters; + lwpa_thread_t* thread_data = (lwpa_thread_t*)pvParameters; if (thread_data) { thread_data->fn(thread_data->arg); @@ -32,7 +32,7 @@ static void thread_func_internal(void *pvParameters) vTaskDelete(NULL); } -bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void (*thread_fn)(void *), void *thread_arg) +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg) { if (!id || !params || !thread_fn) return false; @@ -51,7 +51,7 @@ bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void return false; } -bool lwpa_thread_stop(lwpa_thread_t *id, int wait_ms) +bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms) { bool res; diff --git a/src/lwpa_plat/linux/lwpa/common.c b/src/lwpa_plat/linux/lwpa/common.c index 5df9d2dda..e16a62a36 100644 --- a/src/lwpa_plat/linux/lwpa/common.c +++ b/src/lwpa_plat/linux/lwpa/common.c @@ -33,5 +33,5 @@ lwpa_error_t lwpa_init(lwpa_features_t features) void lwpa_deinit(lwpa_features_t features) { - (void) features; + (void)features; } \ No newline at end of file diff --git a/src/lwpa_plat/linux/lwpa/plat_uuid.c b/src/lwpa_plat/linux/lwpa/plat_uuid.c index 36945be8a..5a39fa00d 100644 --- a/src/lwpa_plat/linux/lwpa/plat_uuid.c +++ b/src/lwpa_plat/linux/lwpa/plat_uuid.c @@ -24,7 +24,7 @@ // Use Linux APIs to generate UUIDs. // https://linux.die.net/man/3/uuid_generate -lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid *uuid) +lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) { if (!uuid) return kLwpaErrInvalid; @@ -35,7 +35,7 @@ lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid *uuid) return kLwpaErrOk; } -lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid *uuid) +lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid) { if (!uuid) return kLwpaErrInvalid; @@ -46,7 +46,7 @@ lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid *uuid) return kLwpaErrOk; } -lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid *uuid) +lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid* uuid) { if (!uuid) return kLwpaErrInvalid; diff --git a/src/lwpa_plat/linux/lwpa/socket.c b/src/lwpa_plat/linux/lwpa/socket.c index 41440ec3c..b77fe7ac7 100644 --- a/src/lwpa_plat/linux/lwpa/socket.c +++ b/src/lwpa_plat/linux/lwpa/socket.c @@ -22,18 +22,18 @@ #include #include -bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) +bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) { - struct sockaddr_in *sin = (struct sockaddr_in *)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sa->port = ntohs(sin->sin_port); lwpaip_set_v4_address(&sa->ip, ntohl(sin->sin_addr.s_addr)); return true; } else if (pfsa->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sa->port = ntohs(sin6->sin6_port); lwpaip_set_v6_address(&sa->ip, sin6->sin6_addr.s6_addr); return true; @@ -41,12 +41,12 @@ bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) return false; } -size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa) +size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; if (lwpaip_is_v4(&sa->ip)) { - struct sockaddr_in *sin = (struct sockaddr_in *)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sin->sin_family = AF_INET; sin->sin_port = htons(sa->port); sin->sin_addr.s_addr = htonl(lwpaip_v4_address(&sa->ip)); @@ -54,7 +54,7 @@ size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa) } else if (lwpaip_is_v6(&sa->ip)) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(sa->port); memcpy(sin6->sin6_addr.s6_addr, lwpaip_v6_address(&sa->ip), LWPA_IPV6_BYTES); @@ -140,7 +140,7 @@ static lwpa_error_t err_plat_to_lwpa(int wsaerror) } */ -lwpa_error_t lwpa_socket_init(void *platform_data) +lwpa_error_t lwpa_socket_init(void* platform_data) { return kLwpaErrNotImpl; } @@ -149,7 +149,7 @@ void lwpa_socket_deinit() { } -lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr *address, lwpa_socket_t *conn_sock) +lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { /* struct sockaddr_storage ss; @@ -176,7 +176,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr *address, lwpa_socket_t return kLwpaErrNotImpl; } -lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr *address) +lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) { /* struct sockaddr_storage ss; @@ -205,7 +205,7 @@ lwpa_error_t lwpa_close(lwpa_socket_t id) return kLwpaErrNotImpl; } -lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr *address) +lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) { /* struct sockaddr_storage ss; @@ -225,7 +225,7 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr *address) return kLwpaErrNotImpl; } -lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr *address) +lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) { /* TODO */ (void)id; @@ -233,7 +233,7 @@ lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr *address) return kLwpaErrNotImpl; } -lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr *address) +lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) { /* int res; @@ -255,7 +255,7 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr *address) return kLwpaErrNotImpl; } -lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void *option_value, size_t *option_len) +lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) { /* TODO */ (void)id; @@ -275,7 +275,7 @@ lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) return kLwpaErrNotImpl; } -int lwpa_recv(lwpa_socket_t id, void *buffer, size_t length, int flags) +int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) { /* int res; @@ -290,7 +290,7 @@ int lwpa_recv(lwpa_socket_t id, void *buffer, size_t length, int flags) return kLwpaErrNotImpl; } -int lwpa_recvfrom(lwpa_socket_t id, void *buffer, size_t length, int flags, LwpaSockaddr *address) +int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address) { /* int res; @@ -317,7 +317,7 @@ int lwpa_recvfrom(lwpa_socket_t id, void *buffer, size_t length, int flags, Lwpa return kLwpaErrNotImpl; } -int lwpa_send(lwpa_socket_t id, const void *message, size_t length, int flags) +int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) { /* int res; @@ -332,7 +332,7 @@ int lwpa_send(lwpa_socket_t id, const void *message, size_t length, int flags) return kLwpaErrNotImpl; } -int lwpa_sendto(lwpa_socket_t id, const void *message, size_t length, int flags, const LwpaSockaddr *dest_addr) +int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) { /* int res = -1; @@ -351,7 +351,7 @@ int lwpa_sendto(lwpa_socket_t id, const void *message, size_t length, int flags, return kLwpaErrNotImpl; } -lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void *option_value, size_t option_len) +lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) { // int res = -1; // @@ -548,7 +548,7 @@ lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) return kLwpaErrNotImpl; } -lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t *id) +lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* id) { if (id) { @@ -568,7 +568,7 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) } /* TODO move to an overlapped IO implementation on Windows for better performance. */ -int lwpa_poll(LwpaPollfd *fds, size_t nfds, int timeout_ms) +int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) { // fd_set readfds, writefds, exceptfds; // LwpaPollfd *fd; @@ -667,8 +667,8 @@ int lwpa_poll(LwpaPollfd *fds, size_t nfds, int timeout_ms) return (int)kLwpaErrNotImpl; } -lwpa_error_t lwpa_getaddrinfo(const char *hostname, const char *service, const LwpaAddrinfo *hints, - LwpaAddrinfo *result) +lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, + LwpaAddrinfo* result) { /* int res; @@ -700,7 +700,7 @@ lwpa_error_t lwpa_getaddrinfo(const char *hostname, const char *service, const L return kLwpaErrNotImpl; } -bool lwpa_nextaddr(LwpaAddrinfo *ai) +bool lwpa_nextaddr(LwpaAddrinfo* ai) { // if (ai && ai->pd[1]) // { @@ -736,7 +736,7 @@ bool lwpa_nextaddr(LwpaAddrinfo *ai) return false; } -void lwpa_freeaddrinfo(LwpaAddrinfo *ai) +void lwpa_freeaddrinfo(LwpaAddrinfo* ai) { /* if (ai) @@ -744,7 +744,7 @@ void lwpa_freeaddrinfo(LwpaAddrinfo *ai) */ } -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size) +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) { if (!src || !dest) return kLwpaErrInvalid; @@ -772,7 +772,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size) } } -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char *src, LwpaIpAddr *dest) +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) { if (!src || !dest) return kLwpaErrInvalid; diff --git a/src/lwpa_plat/mqx/lwpa/lock.c b/src/lwpa_plat/mqx/lwpa/lock.c index 385b5e293..c1f35e0c0 100644 --- a/src/lwpa_plat/mqx/lwpa/lock.c +++ b/src/lwpa_plat/mqx/lwpa/lock.c @@ -54,17 +54,17 @@ static bool sem_take(LWSEM_STRUCT_PTR id, int wait_ms) return (MQX_OK == _lwsem_wait_ticks(id, ticks)); } -bool lwpa_mutex_create(lwpa_mutex_t *id) +bool lwpa_mutex_create(lwpa_mutex_t* id) { return sem_create((LWSEM_STRUCT_PTR)id, 1); } -bool lwpa_mutex_take(lwpa_mutex_t *id, int wait_ms) +bool lwpa_mutex_take(lwpa_mutex_t* id, int wait_ms) { return sem_take(id, wait_ms); } -bool lwpa_signal_create(lwpa_signal_t *id) +bool lwpa_signal_create(lwpa_signal_t* id) { if (!msec_per_tick_initted) { @@ -75,7 +75,7 @@ bool lwpa_signal_create(lwpa_signal_t *id) return (MQX_OK == _lwevent_create((LWEVENT_STRUCT_PTR)id, LWEVENT_AUTO_CLEAR)); } -bool lwpa_signal_wait(lwpa_signal_t *id, int wait_ms) +bool lwpa_signal_wait(lwpa_signal_t* id, int wait_ms) { _mqx_uint ticks = convert_ms_to_ticks(wait_ms); if (MQX_OK == _lwevent_wait_ticks((LWEVENT_STRUCT_PTR)id, 1u, true, ticks)) @@ -86,21 +86,21 @@ bool lwpa_signal_wait(lwpa_signal_t *id, int wait_ms) return false; } -static void atomic_inc(unsigned int *count) +static void atomic_inc(unsigned int* count) { _int_disable(); (*count)++; _int_enable(); } -static void atomic_dec(unsigned int *count) +static void atomic_dec(unsigned int* count) { _int_disable(); (*count)--; _int_enable(); } -bool lwpa_rwlock_create(lwpa_rwlock_t *id) +bool lwpa_rwlock_create(lwpa_rwlock_t* id) { if (id && sem_create(&id->sem, 1)) { @@ -110,7 +110,7 @@ bool lwpa_rwlock_create(lwpa_rwlock_t *id) return false; } -bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms) +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms) { if (!id) return false; @@ -126,13 +126,13 @@ bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms) return false; } -void lwpa_rwlock_readunlock(lwpa_rwlock_t *id) +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) { if (id) atomic_dec(&id->reader_count); } -bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms) +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms) { uint32_t initial_time; TIME_STRUCT tm; @@ -172,7 +172,7 @@ bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms) return false; } -void lwpa_rwlock_writeunlock(lwpa_rwlock_t *id) +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) { _lwsem_post(&id->sem); } diff --git a/src/lwpa_plat/mqx/lwpa/netint.c b/src/lwpa_plat/mqx/lwpa/netint.c index b8103cb60..602176d6a 100644 --- a/src/lwpa_plat/mqx/lwpa/netint.c +++ b/src/lwpa_plat/mqx/lwpa/netint.c @@ -25,10 +25,10 @@ #include "lwpa_int.h" -static bool mask_is_empty(const LwpaIpAddr *mask); -static bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr *mask); +static bool mask_is_empty(const LwpaIpAddr* mask); +static bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask); -static void copy_interface_info(size_t mqx_index, LwpaNetintInfo *netint) +static void copy_interface_info(size_t mqx_index, LwpaNetintInfo* netint) { IPCFG_IP_ADDRESS_DATA ip_data; @@ -56,7 +56,7 @@ size_t netint_get_num_interfaces() return BSP_ENET_DEVICE_COUNT; } -size_t netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_size) +size_t netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) { size_t i; @@ -72,7 +72,7 @@ size_t netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_size) return i; } -bool netint_get_default_interface(LwpaNetintInfo *netint) +bool netint_get_default_interface(LwpaNetintInfo* netint) { if (netint) { @@ -82,7 +82,7 @@ bool netint_get_default_interface(LwpaNetintInfo *netint) return false; } -bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr *mask) +bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask) { if (lwpaip_is_v4(ip1) && lwpaip_is_v4(ip2) && lwpaip_is_v4(mask)) { @@ -91,9 +91,9 @@ bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr else if (lwpaip_is_v6(ip1) && lwpaip_is_v6(ip2) && lwpaip_is_v6(mask)) { size_t i; - const uint32_t *p1 = (const uint32_t *)lwpaip_v6_address(ip1); - const uint32_t *p2 = (const uint32_t *)lwpaip_v6_address(ip2); - const uint32_t *pm = (const uint32_t *)lwpaip_v6_address(mask); + const uint32_t* p1 = (const uint32_t*)lwpaip_v6_address(ip1); + const uint32_t* p2 = (const uint32_t*)lwpaip_v6_address(ip2); + const uint32_t* pm = (const uint32_t*)lwpaip_v6_address(mask); for (i = 0; i < IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) { @@ -105,7 +105,7 @@ bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr return false; } -bool mask_is_empty(const LwpaIpAddr *mask) +bool mask_is_empty(const LwpaIpAddr* mask) { uint32_t mask_part = 0; @@ -114,19 +114,19 @@ bool mask_is_empty(const LwpaIpAddr *mask) else if (lwpaip_is_v6(mask)) { size_t i; - const uint32_t *p = (const uint32_t *)lwpaip_v6_address(mask); + const uint32_t* p = (const uint32_t*)lwpaip_v6_address(mask); for (i = 0; i < IPV6_BYTES / 4; ++i, ++p) mask_part |= *p; } return (mask_part == 0); } -const LwpaNetintInfo *netint_get_iface_for_dest(const LwpaIpAddr *dest, const LwpaNetintInfo *netint_arr, +const LwpaNetintInfo* netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, size_t netint_arr_size) { - const LwpaNetintInfo *res = NULL; - const LwpaNetintInfo *def = NULL; - const LwpaNetintInfo *netint; + const LwpaNetintInfo* res = NULL; + const LwpaNetintInfo* def = NULL; + const LwpaNetintInfo* netint; if (!dest || !netint_arr || netint_arr_size == 0) return false; diff --git a/src/lwpa_plat/mqx/lwpa/plat_uuid.c b/src/lwpa_plat/mqx/lwpa/plat_uuid.c index eeb11f157..2a3b2421a 100644 --- a/src/lwpa_plat/mqx/lwpa/plat_uuid.c +++ b/src/lwpa_plat/mqx/lwpa/plat_uuid.c @@ -20,12 +20,12 @@ #include "lwpa/uuid.h" /* We don't have the capability to generate V1 or V4 UUIDs on MQX RTOS. */ -lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid *uuid) +lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) { return kLwpaErrNotImpl; } -lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid *uuid) +lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid) { return kLwpaErrNotImpl; } diff --git a/src/lwpa_plat/mqx/lwpa/socket.c b/src/lwpa_plat/mqx/lwpa/socket.c index b57dcb365..c0f46f323 100644 --- a/src/lwpa_plat/mqx/lwpa/socket.c +++ b/src/lwpa_plat/mqx/lwpa/socket.c @@ -82,18 +82,18 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /* clang-format on */ -bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) +bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) { - struct sockaddr_in *sin = (struct sockaddr_in *)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sa->port = sin->sin_port; lwpaip_set_v4_address(&sa->ip, sin->sin_addr.s_addr); return true; } else if (pfsa->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sa->port = sin6->sin6_port; lwpaip_set_v6_address(&sa->ip, sin6->sin6_addr.s6_addr); return true; @@ -101,12 +101,12 @@ bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) return false; } -size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa) +size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; if (lwpaip_is_v4(&sa->ip)) { - struct sockaddr_in *sin = (struct sockaddr_in *)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sin->sin_family = AF_INET; sin->sin_port = sa->port; sin->sin_addr.s_addr = lwpaip_v4_address(&sa->ip); @@ -114,7 +114,7 @@ size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa) } else if (lwpaip_is_v6(&sa->ip)) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sin6->sin6_family = AF_INET6; sin6->sin6_port = sa->port; memcpy(sin6->sin6_addr.s6_addr, lwpaip_v6_address(&sa->ip), IPV6_BYTES); @@ -170,7 +170,7 @@ static lwpa_error_t err_plat_to_lwpa(uint32_t rtcserr) } } -lwpa_error_t lwpa_socket_init(void *platform_data) +lwpa_error_t lwpa_socket_init(void* platform_data) { /* No initialization is necessary on this platform. */ (void)platform_data; @@ -182,13 +182,13 @@ void lwpa_socket_deinit() /* No deinitialization is necessary on this platform. */ } -lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr *address, lwpa_socket_t *conn_sock) +lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { /* TODO */ return kLwpaErrNotImpl; } -lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr *address) +lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) { struct sockaddr ss; size_t sa_size; @@ -208,19 +208,19 @@ lwpa_error_t lwpa_close(lwpa_socket_t id) return err_plat_to_lwpa(closesocket(id)); } -lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr *address) +lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) { /* TODO */ return kLwpaErrNotImpl; } -lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr *address) +lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) { /* TODO */ return kLwpaErrNotImpl; } -lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr *address) +lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) { struct sockaddr ss; uint16_t size = sizeof ss; @@ -238,7 +238,7 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr *address) return err_plat_to_lwpa(res); } -lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void *option_value, size_t *option_len) +lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) { /* TODO */ return kLwpaErrNotImpl; @@ -250,13 +250,13 @@ lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) return kLwpaErrNotImpl; } -int lwpa_recv(lwpa_socket_t id, void *buffer, size_t length, int flags) +int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) { /* TODO */ return kLwpaErrNotImpl; } -int lwpa_recvfrom(lwpa_socket_t id, void *buffer, size_t length, int flags, LwpaSockaddr *address) +int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address) { int32_t res; uint32_t impl_flags = (flags & LWPA_MSG_PEEK) ? RTCS_MSG_PEEK : 0; @@ -279,13 +279,13 @@ int lwpa_recvfrom(lwpa_socket_t id, void *buffer, size_t length, int flags, Lwpa return (res == RTCS_ERROR ? err_plat_to_lwpa(RTCS_geterror(id)) : res); } -int lwpa_send(lwpa_socket_t id, const void *message, size_t length, int flags) +int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) { /* TODO */ return kLwpaErrNotImpl; } -int lwpa_sendto(lwpa_socket_t id, const void *message, size_t length, int flags, const LwpaSockaddr *dest_addr) +int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) { int32_t res; size_t ss_size; @@ -297,11 +297,11 @@ int lwpa_sendto(lwpa_socket_t id, const void *message, size_t length, int flags, if ((ss_size = sockaddr_lwpa_to_plat(&ss, dest_addr)) == 0) return kLwpaErrInvalid; - res = sendto(id, (char *)message, (uint32_t)length, 0, &ss, ss_size); + res = sendto(id, (char*)message, (uint32_t)length, 0, &ss, ss_size); return (res == RTCS_ERROR ? err_plat_to_lwpa(RTCS_geterror(id)) : res); } -lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void *option_value, size_t option_len) +lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) { uint32_t res = RTCSERR_SOCK_INVALID_OPTION; @@ -317,7 +317,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const uint32_t size = sizeof sock_type; if (RTCS_OK == getsockopt(id, SOL_SOCKET, OPT_SOCKET_TYPE, &sock_type, &size)) { - uint32_t val = (uint32_t)(*(int *)option_value); + uint32_t val = (uint32_t)(*(int*)option_value); if (sock_type == SOCK_STREAM) { res = setsockopt(id, SOL_TCP, OPT_RBSIZE, &val, sizeof val); @@ -332,35 +332,35 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const case LWPA_SO_SNDBUF: if (level == LWPA_SOL_SOCKET && option_len >= sizeof(uint32_t)) { - uint32_t val = *(int *)option_value; + uint32_t val = *(int*)option_value; res = setsockopt(id, SOL_TCP, OPT_TBSIZE, &val, sizeof val); } break; case LWPA_SO_RCVTIMEO: if (level == LWPA_SOL_SOCKET && option_len >= sizeof(uint32_t)) { - uint32_t val = (uint32_t)(*(int *)option_value); + uint32_t val = (uint32_t)(*(int*)option_value); res = setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, &val, sizeof val); } break; case LWPA_SO_SNDTIMEO: if (level == LWPA_SOL_SOCKET && option_len >= sizeof(uint32_t)) { - uint32_t val = (uint32_t)(*(int *)option_value); + uint32_t val = (uint32_t)(*(int*)option_value); res = setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, &val, sizeof val); } break; case LWPA_IP_TTL: if (level == LWPA_IPPROTO_IP && option_len >= sizeof(unsigned char)) { - unsigned char val = (unsigned char)(*(int *)option_value); + unsigned char val = (unsigned char)(*(int*)option_value); res = setsockopt(id, SOL_IP, RTCS_SO_IP_TX_TTL, &val, sizeof val); } break; case LWPA_MCAST_JOIN_GROUP: if (option_len == sizeof(LwpaMreq)) { - LwpaMreq *amreq = (LwpaMreq *)option_value; + LwpaMreq* amreq = (LwpaMreq*)option_value; if (lwpaip_is_v4(&amreq->group) && level == LWPA_IPPROTO_IP) { /* We don't need htonl -- MQX/RTCS stores IPv4s in host order. */ @@ -388,7 +388,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const case LWPA_MCAST_LEAVE_GROUP: if (option_len == sizeof(LwpaMreq)) { - LwpaMreq *amreq = (LwpaMreq *)option_value; + LwpaMreq* amreq = (LwpaMreq*)option_value; if (lwpaip_is_v4(&amreq->group) && level == LWPA_IPPROTO_IP) { /* We don't need htonl -- MQX/RTCS stores IPv4s in host order. */ @@ -418,7 +418,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const #if BSP_ENET_DEVICE_COUNT == 1 if (option_len == sizeof(LwpaIpAddr)) { - LwpaIpAddr *netint_requested = (LwpaIpAddr *)option_value; + LwpaIpAddr* netint_requested = (LwpaIpAddr*)option_value; IPCFG_IP_ADDRESS_DATA ip_data; if (ipcfg_get_ip(BSP_DEFAULT_ENET_DEVICE, &ip_data)) @@ -455,7 +455,7 @@ lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) return kLwpaErrInvalid; } -lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t *id) +lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* id) { if (id) { @@ -512,11 +512,11 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) return kLwpaErrSys; } -int lwpa_poll(LwpaPollfd *fds, size_t nfds, int timeout_ms) +int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) { rtcs_fd_set readfds; rtcs_fd_set writefds; - LwpaPollfd *fd; + LwpaPollfd* fd; int32_t nplatfds; int sel_res; int32_t nreadfds = 0, nwritefds = 0; @@ -579,11 +579,11 @@ int lwpa_poll(LwpaPollfd *fds, size_t nfds, int timeout_ms) return (int)sel_res; } -lwpa_error_t lwpa_getaddrinfo(const char *hostname, const char *service, const LwpaAddrinfo *hints, - LwpaAddrinfo *result) +lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, + LwpaAddrinfo* result) { int32_t res; - struct addrinfo *pf_res; + struct addrinfo* pf_res; struct addrinfo pf_hints; if ((!hostname && !service) || !result) @@ -609,11 +609,11 @@ lwpa_error_t lwpa_getaddrinfo(const char *hostname, const char *service, const L return err_plat_to_lwpa(res); } -bool lwpa_nextaddr(LwpaAddrinfo *ai) +bool lwpa_nextaddr(LwpaAddrinfo* ai) { if (ai && ai->pd[1]) { - struct addrinfo *pf_ai = (struct addrinfo *)ai->pd[1]; + struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; if (!sockaddr_plat_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) return false; @@ -645,13 +645,13 @@ bool lwpa_nextaddr(LwpaAddrinfo *ai) return false; } -void lwpa_freeaddrinfo(LwpaAddrinfo *ai) +void lwpa_freeaddrinfo(LwpaAddrinfo* ai) { if (ai) - freeaddrinfo((struct addrinfo *)ai->pd[0]); + freeaddrinfo((struct addrinfo*)ai->pd[0]); } -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size) +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) { if (!src || !dest) return kLwpaErrInvalid; @@ -680,7 +680,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size) } } -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char *src, LwpaIpAddr *dest) +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) { if (!src || !dest) return kLwpaErrInvalid; diff --git a/src/lwpa_plat/mqx/lwpa/thread.c b/src/lwpa_plat/mqx/lwpa/thread.c index 07a622ba1..8df48d4b2 100644 --- a/src/lwpa_plat/mqx/lwpa/thread.c +++ b/src/lwpa_plat/mqx/lwpa/thread.c @@ -24,7 +24,7 @@ static bool msec_per_tick_initted = false; static void thread_func_internal(uint32_t initial_data) { - lwpa_thread_t *thread_data = (lwpa_thread_t *)initial_data; + lwpa_thread_t* thread_data = (lwpa_thread_t*)initial_data; if (thread_data) { thread_data->fn(thread_data->arg); @@ -32,7 +32,7 @@ static void thread_func_internal(uint32_t initial_data) } } -bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void (*thread_fn)(void *), void *thread_arg) +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg) { _task_id t_id; TASK_TEMPLATE_STRUCT template; @@ -49,7 +49,7 @@ bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void template.TASK_STACKSIZE = params->stack_size; if (params->platform_data) { - LwpaThreadParamsMqx *platform_params = (LwpaThreadParamsMqx *)params->platform_data; + LwpaThreadParamsMqx* platform_params = (LwpaThreadParamsMqx*)params->platform_data; template.TASK_ATTRIBUTES = platform_params->task_attributes; template.DEFAULT_TIME_SLICE = platform_params->time_slice; } @@ -73,7 +73,7 @@ bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void return false; } -bool lwpa_thread_stop(lwpa_thread_t *id, int wait_ms) +bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms) { _mqx_uint ticks; _mqx_uint res; diff --git a/src/lwpa_plat/windows/lwpa/lock.c b/src/lwpa_plat/windows/lwpa/lock.c index b163faf35..349fa5222 100644 --- a/src/lwpa_plat/windows/lwpa/lock.c +++ b/src/lwpa_plat/windows/lwpa/lock.c @@ -21,7 +21,7 @@ #include "lwpa/int.h" #include "mmsystem.h" -bool lwpa_mutex_create(lwpa_mutex_t *id) +bool lwpa_mutex_create(lwpa_mutex_t* id) { if (id) { @@ -32,7 +32,7 @@ bool lwpa_mutex_create(lwpa_mutex_t *id) return false; } -bool lwpa_signal_create(lwpa_signal_t *id) +bool lwpa_signal_create(lwpa_signal_t* id) { if (id) { @@ -43,7 +43,7 @@ bool lwpa_signal_create(lwpa_signal_t *id) return false; } -bool lwpa_rwlock_create(lwpa_rwlock_t *id) +bool lwpa_rwlock_create(lwpa_rwlock_t* id) { if (id) { @@ -55,7 +55,7 @@ bool lwpa_rwlock_create(lwpa_rwlock_t *id) return false; } -bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms) +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms) { (void)wait_ms; if (id && id->valid) @@ -68,7 +68,7 @@ bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms) return false; } -bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms) +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms) { DWORD initial_time; diff --git a/src/lwpa_plat/windows/lwpa/netint.c b/src/lwpa_plat/windows/lwpa/netint.c index f0297354e..9875f55e1 100644 --- a/src/lwpa_plat/windows/lwpa/netint.c +++ b/src/lwpa_plat/windows/lwpa/netint.c @@ -26,37 +26,37 @@ #include #include "lwpa/int.h" -static bool mask_is_empty(const LwpaIpAddr *mask); -static bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr *mask); +static bool mask_is_empty(const LwpaIpAddr* mask); +static bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask); -static IP_ADAPTER_ADDRESSES *get_windows_adapters() +static IP_ADAPTER_ADDRESSES* get_windows_adapters() { ULONG buflen = 0; ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_GATEWAYS; /* Preallocating a buffer specifically this size is expressly recommended by the Microsoft usage * page. */ - uint8_t *buffer = malloc(15000); + uint8_t* buffer = malloc(15000); if (!buffer) return NULL; - if (ERROR_BUFFER_OVERFLOW == GetAdaptersAddresses(AF_UNSPEC, flags, NULL, (IP_ADAPTER_ADDRESSES *)buffer, &buflen)) + if (ERROR_BUFFER_OVERFLOW == GetAdaptersAddresses(AF_UNSPEC, flags, NULL, (IP_ADAPTER_ADDRESSES*)buffer, &buflen)) { free(buffer); buffer = malloc(buflen); if (buffer && - (ERROR_SUCCESS == GetAdaptersAddresses(AF_UNSPEC, flags, NULL, (IP_ADAPTER_ADDRESSES *)buffer, &buflen))) + (ERROR_SUCCESS == GetAdaptersAddresses(AF_UNSPEC, flags, NULL, (IP_ADAPTER_ADDRESSES*)buffer, &buflen))) { - return (IP_ADAPTER_ADDRESSES *)buffer; + return (IP_ADAPTER_ADDRESSES*)buffer; } } return NULL; } -static void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS *pip, IP_ADAPTER_GATEWAY_ADDRESS *pgate, LwpaNetintInfo *info) +static void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, IP_ADAPTER_GATEWAY_ADDRESS* pgate, LwpaNetintInfo* info) { - struct sockaddr_in *sin = (struct sockaddr_in *)pip->Address.lpSockaddr; - struct sockaddr_in *gw_sin = pgate ? (struct sockaddr_in *)pgate->Address.lpSockaddr : NULL; + struct sockaddr_in* sin = (struct sockaddr_in*)pip->Address.lpSockaddr; + struct sockaddr_in* gw_sin = pgate ? (struct sockaddr_in*)pgate->Address.lpSockaddr : NULL; ULONG mask = 0; ConvertLengthToIpv4Mask(pip->OnLinkPrefixLength, &mask); @@ -81,7 +81,7 @@ size_t lwpa_netint_get_num_interfaces() while (pcur) { /* If this is multihomed, there may be multiple addresses under the same adapter */ - IP_ADAPTER_UNICAST_ADDRESS *pip = pcur->FirstUnicastAddress; + IP_ADAPTER_UNICAST_ADDRESS* pip = pcur->FirstUnicastAddress; while (pip) { switch (pip->Address.lpSockaddr->sa_family) @@ -102,7 +102,7 @@ size_t lwpa_netint_get_num_interfaces() return n_ifaces; } -size_t lwpa_netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_size) +size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) { size_t n_ifaces = 0; IP_ADAPTER_ADDRESSES *padapters, *pcur; @@ -123,11 +123,11 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_ while (pcur) { /* If this is multihomed, there may be multiple addresses under the same adapter */ - IP_ADAPTER_UNICAST_ADDRESS *pip = pcur->FirstUnicastAddress; - IP_ADAPTER_GATEWAY_ADDRESS *pgate = pcur->FirstGatewayAddress; + IP_ADAPTER_UNICAST_ADDRESS* pip = pcur->FirstUnicastAddress; + IP_ADAPTER_GATEWAY_ADDRESS* pgate = pcur->FirstGatewayAddress; while (pip) { - LwpaNetintInfo *info = &netint_arr[n_ifaces]; + LwpaNetintInfo* info = &netint_arr[n_ifaces]; switch (pip->Address.lpSockaddr->sa_family) { case AF_INET: @@ -174,15 +174,15 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_ return n_ifaces; } -bool lwpa_netint_get_default_interface(LwpaNetintInfo *netint) +bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint) { DWORD def_ifindex; bool res = false; if (NO_ERROR == GetBestInterface(0, &def_ifindex)) { - IP_ADAPTER_ADDRESSES *pcur; - IP_ADAPTER_ADDRESSES *padapters = get_windows_adapters(); + IP_ADAPTER_ADDRESSES* pcur; + IP_ADAPTER_ADDRESSES* padapters = get_windows_adapters(); if (!padapters) return res; pcur = padapters; @@ -190,8 +190,8 @@ bool lwpa_netint_get_default_interface(LwpaNetintInfo *netint) while (pcur) { /* If this is multihomed, there may be multiple addresses under the same adapter */ - IP_ADAPTER_UNICAST_ADDRESS *pip = pcur->FirstUnicastAddress; - IP_ADAPTER_GATEWAY_ADDRESS *pgate = pcur->FirstGatewayAddress; + IP_ADAPTER_UNICAST_ADDRESS* pip = pcur->FirstUnicastAddress; + IP_ADAPTER_GATEWAY_ADDRESS* pgate = pcur->FirstGatewayAddress; while (pip) { if (pcur->IfIndex == def_ifindex && pip->Address.lpSockaddr->sa_family == AF_INET) @@ -221,7 +221,7 @@ bool lwpa_netint_get_default_interface(LwpaNetintInfo *netint) return res; } -bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr *mask) +bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask) { if (lwpaip_is_v4(ip1) && lwpaip_is_v4(ip2) && lwpaip_is_v4(mask)) { @@ -230,9 +230,9 @@ bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr else if (lwpaip_is_v6(ip1) && lwpaip_is_v6(ip2) && lwpaip_is_v6(mask)) { size_t i; - const uint32_t *p1 = (const uint32_t *)lwpaip_v6_address(ip1); - const uint32_t *p2 = (const uint32_t *)lwpaip_v6_address(ip2); - const uint32_t *pm = (const uint32_t *)lwpaip_v6_address(mask); + const uint32_t* p1 = (const uint32_t*)lwpaip_v6_address(ip1); + const uint32_t* p2 = (const uint32_t*)lwpaip_v6_address(ip2); + const uint32_t* pm = (const uint32_t*)lwpaip_v6_address(mask); for (i = 0; i < LWPA_IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) { @@ -244,7 +244,7 @@ bool mask_compare(const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr return false; } -bool mask_is_empty(const LwpaIpAddr *mask) +bool mask_is_empty(const LwpaIpAddr* mask) { uint32_t mask_part = 0; @@ -255,19 +255,19 @@ bool mask_is_empty(const LwpaIpAddr *mask) else if (lwpaip_is_v6(mask)) { size_t i; - const uint32_t *p = (const uint32_t *)lwpaip_v6_address(mask); + const uint32_t* p = (const uint32_t*)lwpaip_v6_address(mask); for (i = 0; i < LWPA_IPV6_BYTES / 4; ++i, ++p) mask_part |= *p; } return (mask_part == 0); } -const LwpaNetintInfo *lwpa_netint_get_iface_for_dest(const LwpaIpAddr *dest, const LwpaNetintInfo *netint_arr, +const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, size_t netint_arr_size) { - const LwpaNetintInfo *res = NULL; - const LwpaNetintInfo *def = NULL; - const LwpaNetintInfo *netint; + const LwpaNetintInfo* res = NULL; + const LwpaNetintInfo* def = NULL; + const LwpaNetintInfo* netint; if (!dest || !netint_arr || netint_arr_size == 0) return false; diff --git a/src/lwpa_plat/windows/lwpa/plat_uuid.c b/src/lwpa_plat/windows/lwpa/plat_uuid.c index 721bc545f..14d2155c5 100644 --- a/src/lwpa_plat/windows/lwpa/plat_uuid.c +++ b/src/lwpa_plat/windows/lwpa/plat_uuid.c @@ -26,7 +26,7 @@ // Use Windows APIs to generate UUIDs. // https://docs.microsoft.com/en-us/windows/desktop/api/rpcdce/nf-rpcdce-uuidcreate -lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid *uuid) +lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) { if (!uuid) return kLwpaErrInvalid; @@ -46,7 +46,7 @@ lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid *uuid) } } -lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid *uuid) +lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid) { if (!uuid) return kLwpaErrInvalid; @@ -66,7 +66,7 @@ lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid *uuid) } } -lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid *uuid) +lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid* uuid) { return lwpa_generate_v4_uuid(uuid); } \ No newline at end of file diff --git a/src/lwpa_plat/windows/lwpa/socket.c b/src/lwpa_plat/windows/lwpa/socket.c index 67c2899e7..a1d7960cd 100644 --- a/src/lwpa_plat/windows/lwpa/socket.c +++ b/src/lwpa_plat/windows/lwpa/socket.c @@ -109,28 +109,28 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = static lwpa_error_t err_plat_to_lwpa(int wsaerror); // Helper functions for the lwpa_poll API -static void init_socket_chunk(LwpaPollCtxSocket *chunk); -static LwpaPollCtxSocket *find_socket(LwpaPollContext *context, lwpa_socket_t socket); -static LwpaPollCtxSocket *find_hole(LwpaPollContext *context); -static void set_in_fd_sets(LwpaPollContext *context, const LwpaPollCtxSocket *sock); -static void clear_in_fd_sets(LwpaPollContext *context, const LwpaPollCtxSocket *sock); -static lwpa_error_t handle_select_result(LwpaPollContext *context, LwpaPollEvent *event, const LwpaPollFdSet *readfds, - const LwpaPollFdSet *writefds, const LwpaPollFdSet *exceptfds); +static void init_socket_chunk(LwpaPollCtxSocket* chunk); +static LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket); +static LwpaPollCtxSocket* find_hole(LwpaPollContext* context); +static void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock); +static void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock); +static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, const LwpaPollFdSet* readfds, + const LwpaPollFdSet* writefds, const LwpaPollFdSet* exceptfds); /*************************** Function definitions ****************************/ -bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) +bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) { - struct sockaddr_in *sin = (struct sockaddr_in *)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sa->port = ntohs(sin->sin_port); lwpaip_set_v4_address(&sa->ip, ntohl(sin->sin_addr.s_addr)); return true; } else if (pfsa->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sa->port = ntohs(sin6->sin6_port); lwpaip_set_v6_address(&sa->ip, sin6->sin6_addr.s6_addr); return true; @@ -138,12 +138,12 @@ bool sockaddr_plat_to_lwpa(LwpaSockaddr *sa, const struct sockaddr *pfsa) return false; } -size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa) +size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; if (lwpaip_is_v4(&sa->ip)) { - struct sockaddr_in *sin = (struct sockaddr_in *)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; sin->sin_port = htons(sa->port); @@ -152,7 +152,7 @@ size_t sockaddr_lwpa_to_plat(struct sockaddr *pfsa, const LwpaSockaddr *sa) } else if (lwpaip_is_v6(&sa->ip)) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; memset(sin6, 0, sizeof(struct sockaddr_in6)); sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(sa->port); @@ -242,7 +242,7 @@ lwpa_error_t err_plat_to_lwpa(int wsaerror) } } -lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr *address, lwpa_socket_t *conn_sock) +lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { struct sockaddr_storage ss; int sa_size = sizeof ss; @@ -251,11 +251,11 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr *address, lwpa_socket_t if (!conn_sock) return kLwpaErrInvalid; - res = accept(id, (struct sockaddr *)&ss, &sa_size); + res = accept(id, (struct sockaddr*)&ss, &sa_size); if (res != INVALID_SOCKET) { - if (address && !sockaddr_plat_to_lwpa(address, (struct sockaddr *)&ss)) + if (address && !sockaddr_plat_to_lwpa(address, (struct sockaddr*)&ss)) { closesocket(res); return kLwpaErrSys; @@ -266,7 +266,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr *address, lwpa_socket_t return err_plat_to_lwpa(WSAGetLastError()); } -lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr *address) +lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) { struct sockaddr_storage ss; size_t sa_size; @@ -275,11 +275,11 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr *address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_plat((struct sockaddr *)&ss, address); + sa_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, address); if (sa_size == 0) return kLwpaErrInvalid; - res = bind(id, (struct sockaddr *)&ss, (int)sa_size); + res = bind(id, (struct sockaddr*)&ss, (int)sa_size); return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); } @@ -289,7 +289,7 @@ lwpa_error_t lwpa_close(lwpa_socket_t id) return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); } -lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr *address) +lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) { struct sockaddr_storage ss; size_t sa_size; @@ -298,15 +298,15 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr *address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_plat((struct sockaddr *)&ss, address); + sa_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, address); if (sa_size == 0) return kLwpaErrInvalid; - res = connect(id, (struct sockaddr *)&ss, (int)sa_size); + res = connect(id, (struct sockaddr*)&ss, (int)sa_size); return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); } -lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr *address) +lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) { /* TODO */ (void)id; @@ -314,7 +314,7 @@ lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr *address) return kLwpaErrNotImpl; } -lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr *address) +lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) { int res; struct sockaddr_storage ss; @@ -323,17 +323,17 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr *address) if (!address) return kLwpaErrInvalid; - res = getsockname(id, (struct sockaddr *)&ss, &size); + res = getsockname(id, (struct sockaddr*)&ss, &size); if (res == 0) { - if (!sockaddr_plat_to_lwpa(address, (struct sockaddr *)&ss)) + if (!sockaddr_plat_to_lwpa(address, (struct sockaddr*)&ss)) return kLwpaErrSys; return kLwpaErrOk; } return err_plat_to_lwpa(WSAGetLastError()); } -lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void *option_value, size_t *option_len) +lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) { /* TODO */ (void)id; @@ -350,7 +350,7 @@ lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); } -int lwpa_recv(lwpa_socket_t id, void *buffer, size_t length, int flags) +int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) { int res; int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; @@ -362,7 +362,7 @@ int lwpa_recv(lwpa_socket_t id, void *buffer, size_t length, int flags) return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); } -int lwpa_recvfrom(lwpa_socket_t id, void *buffer, size_t length, int flags, LwpaSockaddr *address) +int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address) { int res; int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; @@ -372,13 +372,13 @@ int lwpa_recvfrom(lwpa_socket_t id, void *buffer, size_t length, int flags, Lwpa if (!buffer) return (int)kLwpaErrInvalid; - res = recvfrom(id, buffer, (int)length, impl_flags, (struct sockaddr *)&fromaddr, &fromlen); + res = recvfrom(id, buffer, (int)length, impl_flags, (struct sockaddr*)&fromaddr, &fromlen); if (res >= 0) { if (address && fromlen > 0) { - if (!sockaddr_plat_to_lwpa(address, (struct sockaddr *)&fromaddr)) + if (!sockaddr_plat_to_lwpa(address, (struct sockaddr*)&fromaddr)) return kLwpaErrSys; } return res; @@ -386,7 +386,7 @@ int lwpa_recvfrom(lwpa_socket_t id, void *buffer, size_t length, int flags, Lwpa return (int)err_plat_to_lwpa(WSAGetLastError()); } -int lwpa_send(lwpa_socket_t id, const void *message, size_t length, int flags) +int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) { int res; (void)flags; @@ -398,7 +398,7 @@ int lwpa_send(lwpa_socket_t id, const void *message, size_t length, int flags) return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); } -int lwpa_sendto(lwpa_socket_t id, const void *message, size_t length, int flags, const LwpaSockaddr *dest_addr) +int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) { int res = -1; size_t ss_size; @@ -408,13 +408,13 @@ int lwpa_sendto(lwpa_socket_t id, const void *message, size_t length, int flags, if (!dest_addr || !message) return (int)kLwpaErrInvalid; - if ((ss_size = sockaddr_lwpa_to_plat((struct sockaddr *)&ss, dest_addr)) > 0) - res = sendto(id, message, (int)length, 0, (struct sockaddr *)&ss, (int)ss_size); + if ((ss_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, dest_addr)) > 0) + res = sendto(id, message, (int)length, 0, (struct sockaddr*)&ss, (int)ss_size); return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); } -lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void *option_value, size_t option_len) +lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) { int res = -1; @@ -436,46 +436,46 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const case LWPA_SO_RCVTIMEO: if (option_len == sizeof(int)) { - DWORD val = (DWORD) * (int *)option_value; - res = setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, (char *)&val, sizeof val); + DWORD val = (DWORD) * (int*)option_value; + res = setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, (char*)&val, sizeof val); } break; case LWPA_SO_SNDTIMEO: if (option_len == sizeof(int)) { - DWORD val = (DWORD) * (int *)option_value; - res = setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, (char *)&val, sizeof val); + DWORD val = (DWORD) * (int*)option_value; + res = setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, (char*)&val, sizeof val); } break; case LWPA_SO_REUSEADDR: if (option_len == sizeof(int)) { - BOOL val = (BOOL) * (int *)option_value; - res = setsockopt(id, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof val); + BOOL val = (BOOL) * (int*)option_value; + res = setsockopt(id, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof val); } break; case LWPA_SO_BROADCAST: if (option_len == sizeof(int)) { - BOOL val = (BOOL) * (int *)option_value; - res = setsockopt(id, SOL_SOCKET, SO_BROADCAST, (char *)&val, sizeof val); + BOOL val = (BOOL) * (int*)option_value; + res = setsockopt(id, SOL_SOCKET, SO_BROADCAST, (char*)&val, sizeof val); } break; case LWPA_SO_KEEPALIVE: if (option_len == sizeof(int)) { - BOOL val = (BOOL) * (int *)option_value; - res = setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof val); + BOOL val = (BOOL) * (int*)option_value; + res = setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof val); } break; case LWPA_SO_LINGER: if (option_len == sizeof(LwpaLinger)) { - LwpaLinger *ll = (LwpaLinger *)option_value; + LwpaLinger* ll = (LwpaLinger*)option_value; struct linger val; val.l_onoff = (u_short)ll->onoff; val.l_linger = (u_short)ll->linger; - res = setsockopt(id, SOL_SOCKET, SO_LINGER, (char *)&val, sizeof val); + res = setsockopt(id, SOL_SOCKET, SO_LINGER, (char*)&val, sizeof val); } break; case LWPA_SO_ERROR: /* Set not supported */ @@ -490,59 +490,59 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const case LWPA_IP_TTL: if (option_len == sizeof(int)) { - DWORD val = (DWORD) * (int *)option_value; - res = setsockopt(id, IPPROTO_IP, IP_TTL, (char *)&val, sizeof val); + DWORD val = (DWORD) * (int*)option_value; + res = setsockopt(id, IPPROTO_IP, IP_TTL, (char*)&val, sizeof val); } break; case LWPA_MCAST_JOIN_GROUP: if (option_len == sizeof(LwpaMreq)) { - LwpaMreq *amreq = (LwpaMreq *)option_value; + LwpaMreq* amreq = (LwpaMreq*)option_value; if (lwpaip_is_v4(&amreq->group)) { struct ip_mreq val; val.imr_multiaddr.s_addr = htonl(lwpaip_v4_address(&amreq->group)); val.imr_interface.s_addr = htonl(lwpaip_v4_address(&amreq->netint)); - res = setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&val, sizeof val); + res = setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&val, sizeof val); } } break; case LWPA_MCAST_LEAVE_GROUP: if (option_len == sizeof(LwpaMreq)) { - LwpaMreq *amreq = (LwpaMreq *)option_value; + LwpaMreq* amreq = (LwpaMreq*)option_value; if (lwpaip_is_v4(&amreq->group)) { struct ip_mreq val; val.imr_multiaddr.s_addr = htonl(lwpaip_v4_address(&amreq->group)); val.imr_interface.s_addr = htonl(lwpaip_v4_address(&amreq->netint)); - res = setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&val, sizeof val); + res = setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&val, sizeof val); } } break; case LWPA_IP_MULTICAST_IF: if (option_len == sizeof(LwpaIpAddr)) { - LwpaIpAddr *netint = (LwpaIpAddr *)option_value; + LwpaIpAddr* netint = (LwpaIpAddr*)option_value; if (lwpaip_is_v4(netint)) { DWORD val = htonl(lwpaip_v4_address(netint)); - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char *)&val, sizeof val); + res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, sizeof val); } } break; case LWPA_IP_MULTICAST_TTL: if (option_len == sizeof(int)) { - DWORD val = (DWORD) * (int *)option_value; - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&val, sizeof val); + DWORD val = (DWORD) * (int*)option_value; + res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&val, sizeof val); } break; case LWPA_IP_MULTICAST_LOOP: if (option_len == sizeof(int)) { - DWORD val = (DWORD) * (int *)option_value; - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&val, sizeof val); + DWORD val = (DWORD) * (int*)option_value; + res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&val, sizeof val); } break; default: @@ -589,8 +589,8 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const case LWPA_IPV6_V6ONLY: if (option_len == sizeof(int)) { - DWORD val = (DWORD) * (int *)option_value; - res = setsockopt(id, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof val); + DWORD val = (DWORD) * (int*)option_value; + res = setsockopt(id, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&val, sizeof val); } break; default: /* Other IPv6 options TODO on windows. */ @@ -614,7 +614,7 @@ lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) return kLwpaErrInvalid; } -lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t *id) +lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* id) { if (id) { @@ -647,7 +647,7 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); } -lwpa_error_t lwpa_poll_context_init(LwpaPollContext *context) +lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { if (!context) return kLwpaErrInvalid; @@ -665,7 +665,7 @@ lwpa_error_t lwpa_poll_context_init(LwpaPollContext *context) return kLwpaErrOk; } -void lwpa_poll_context_deinit(LwpaPollContext *context) +void lwpa_poll_context_deinit(LwpaPollContext* context) { if (!context || !context->valid) return; @@ -678,9 +678,9 @@ void lwpa_poll_context_deinit(LwpaPollContext *context) context->valid = false; } -LwpaPollCtxSocket *find_socket(LwpaPollContext *context, lwpa_socket_t socket) +LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket) { - for (LwpaPollCtxSocket *cur = context->sockets; cur < context->sockets + context->socket_arr_size; ++cur) + for (LwpaPollCtxSocket* cur = context->sockets; cur < context->sockets + context->socket_arr_size; ++cur) { if (cur->socket == socket) return cur; @@ -688,22 +688,22 @@ LwpaPollCtxSocket *find_socket(LwpaPollContext *context, lwpa_socket_t socket) return NULL; } -void init_socket_chunk(LwpaPollCtxSocket *chunk) +void init_socket_chunk(LwpaPollCtxSocket* chunk) { - for (LwpaPollCtxSocket *cur = chunk; cur < chunk + POLL_CONTEXT_ARR_CHUNK_SIZE; ++cur) + for (LwpaPollCtxSocket* cur = chunk; cur < chunk + POLL_CONTEXT_ARR_CHUNK_SIZE; ++cur) { cur->socket = LWPA_SOCKET_INVALID; } } -LwpaPollCtxSocket *find_hole(LwpaPollContext *context) +LwpaPollCtxSocket* find_hole(LwpaPollContext* context) { - LwpaPollCtxSocket *hole = NULL; + LwpaPollCtxSocket* hole = NULL; if (!context->sockets) { // No sockets have been added yet. Create the first chunk. - context->sockets = (LwpaPollCtxSocket *)calloc(POLL_CONTEXT_ARR_CHUNK_SIZE, sizeof(LwpaPollCtxSocket)); + context->sockets = (LwpaPollCtxSocket*)calloc(POLL_CONTEXT_ARR_CHUNK_SIZE, sizeof(LwpaPollCtxSocket)); if (context->sockets) { init_socket_chunk(context->sockets); @@ -714,7 +714,7 @@ LwpaPollCtxSocket *find_hole(LwpaPollContext *context) else { // Find an invalid socket in the list - for (LwpaPollCtxSocket *cur = context->sockets; cur < context->sockets + context->socket_arr_size; ++cur) + for (LwpaPollCtxSocket* cur = context->sockets; cur < context->sockets + context->socket_arr_size; ++cur) { if (cur->socket == LWPA_SOCKET_INVALID) { @@ -727,7 +727,7 @@ LwpaPollCtxSocket *find_hole(LwpaPollContext *context) { // Expand the socket array by another chunk. size_t new_size = context->socket_arr_size + POLL_CONTEXT_ARR_CHUNK_SIZE; - context->sockets = (LwpaPollCtxSocket *)realloc(context->sockets, new_size * sizeof(LwpaPollCtxSocket)); + context->sockets = (LwpaPollCtxSocket*)realloc(context->sockets, new_size * sizeof(LwpaPollCtxSocket)); if (context->sockets) { init_socket_chunk(&context->sockets[context->socket_arr_size]); @@ -740,7 +740,7 @@ LwpaPollCtxSocket *find_hole(LwpaPollContext *context) return hole; } -void set_in_fd_sets(LwpaPollContext *context, const LwpaPollCtxSocket *sock) +void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) { if (sock->events & LWPA_POLL_IN) { @@ -756,7 +756,7 @@ void set_in_fd_sets(LwpaPollContext *context, const LwpaPollCtxSocket *sock) } } -void clear_in_fd_sets(LwpaPollContext *context, const LwpaPollCtxSocket *sock) +void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) { if (sock->events & LWPA_POLL_IN) { @@ -772,8 +772,8 @@ void clear_in_fd_sets(LwpaPollContext *context, const LwpaPollCtxSocket *sock) } } -lwpa_error_t lwpa_poll_add_socket(LwpaPollContext *context, lwpa_socket_t socket, lwpa_poll_events_t events, - void *user_data) +lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, + void* user_data) { if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) return kLwpaErrInvalid; @@ -787,7 +787,7 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext *context, lwpa_socket_t socket } else { - LwpaPollCtxSocket *new_sock = find_hole(context); + LwpaPollCtxSocket* new_sock = find_hole(context); if (new_sock) { new_sock->socket = socket; @@ -807,8 +807,8 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext *context, lwpa_socket_t socket return res; } -lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext *context, lwpa_socket_t socket, lwpa_poll_events_t new_events, - void *new_user_data) +lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, + void* new_user_data) { if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) return kLwpaErrInvalid; @@ -816,7 +816,7 @@ lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext *context, lwpa_socket_t soc lwpa_error_t res = kLwpaErrSys; if (lwpa_mutex_take(&context->lock, LWPA_WAIT_FOREVER)) { - LwpaPollCtxSocket *sock_desc = find_socket(context, socket); + LwpaPollCtxSocket* sock_desc = find_socket(context, socket); if (sock_desc) { clear_in_fd_sets(context, sock_desc); @@ -834,14 +834,14 @@ lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext *context, lwpa_socket_t soc return res; } -void lwpa_poll_remove_socket(LwpaPollContext *context, lwpa_socket_t socket) +void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) { if (!context || !context->valid || socket == LWPA_SOCKET_INVALID) return; if (lwpa_mutex_take(&context->lock, LWPA_WAIT_FOREVER)) { - LwpaPollCtxSocket *sock_desc = find_socket(context, socket); + LwpaPollCtxSocket* sock_desc = find_socket(context, socket); if (sock_desc) { clear_in_fd_sets(context, sock_desc); @@ -852,7 +852,7 @@ void lwpa_poll_remove_socket(LwpaPollContext *context, lwpa_socket_t socket) } } -lwpa_error_t lwpa_poll_wait(LwpaPollContext *context, LwpaPollEvent *event, int timeout_ms) +lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms) { if (!context || !context->valid || !event) return kLwpaErrInvalid; @@ -912,8 +912,8 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext *context, LwpaPollEvent *event, int } } -lwpa_error_t handle_select_result(LwpaPollContext *context, LwpaPollEvent *event, const LwpaPollFdSet *readfds, - const LwpaPollFdSet *writefds, const LwpaPollFdSet *exceptfds) +lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, const LwpaPollFdSet* readfds, + const LwpaPollFdSet* writefds, const LwpaPollFdSet* exceptfds) { // Init the event data. event->socket = LWPA_SOCKET_INVALID; @@ -924,7 +924,7 @@ lwpa_error_t handle_select_result(LwpaPollContext *context, LwpaPollEvent *event // gone wrong. lwpa_error_t res = kLwpaErrSys; - for (LwpaPollCtxSocket *sock_desc = context->sockets; sock_desc < context->sockets + context->socket_arr_size; + for (LwpaPollCtxSocket* sock_desc = context->sockets; sock_desc < context->sockets + context->socket_arr_size; ++sock_desc) { if (sock_desc->socket == LWPA_SOCKET_INVALID) @@ -940,7 +940,7 @@ lwpa_error_t handle_select_result(LwpaPollContext *context, LwpaPollEvent *event /* Check for errors */ int error; int error_size = sizeof(error); - if (getsockopt(sock_desc->socket, SOL_SOCKET, SO_ERROR, (char *)&error, &error_size) == 0) + if (getsockopt(sock_desc->socket, SOL_SOCKET, SO_ERROR, (char*)&error, &error_size) == 0) { if (error != 0) { @@ -978,11 +978,11 @@ lwpa_error_t handle_select_result(LwpaPollContext *context, LwpaPollEvent *event return res; } -lwpa_error_t lwpa_getaddrinfo(const char *hostname, const char *service, const LwpaAddrinfo *hints, - LwpaAddrinfo *result) +lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, + LwpaAddrinfo* result) { int res; - struct addrinfo *pf_res; + struct addrinfo* pf_res; struct addrinfo pf_hints; if ((!hostname && !service) || !result) @@ -1008,11 +1008,11 @@ lwpa_error_t lwpa_getaddrinfo(const char *hostname, const char *service, const L return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(res)); } -bool lwpa_nextaddr(LwpaAddrinfo *ai) +bool lwpa_nextaddr(LwpaAddrinfo* ai) { if (ai && ai->pd[1]) { - struct addrinfo *pf_ai = (struct addrinfo *)ai->pd[1]; + struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; if (!sockaddr_plat_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) return false; @@ -1048,15 +1048,15 @@ bool lwpa_nextaddr(LwpaAddrinfo *ai) return false; } -void lwpa_freeaddrinfo(LwpaAddrinfo *ai) +void lwpa_freeaddrinfo(LwpaAddrinfo* ai) { if (ai) - freeaddrinfo((struct addrinfo *)ai->pd[0]); + freeaddrinfo((struct addrinfo*)ai->pd[0]); } #endif /* !defined(LWPA_BUILDING_MOCK_LIB) */ -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size) +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) { if (!src || !dest) return kLwpaErrInvalid; @@ -1084,7 +1084,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr *src, char *dest, size_t size) } } -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char *src, LwpaIpAddr *dest) +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) { if (!src || !dest) return kLwpaErrInvalid; diff --git a/src/lwpa_plat/windows/lwpa/thread.c b/src/lwpa_plat/windows/lwpa/thread.c index 736c40065..6b12cb7a5 100644 --- a/src/lwpa_plat/windows/lwpa/thread.c +++ b/src/lwpa_plat/windows/lwpa/thread.c @@ -38,7 +38,7 @@ typedef struct tagTHREADNAME_INFO DWORD dwFlags; /* Reserved for future use, must be zero. */ } THREADNAME_INFO; #pragma pack(pop) -void SetThreadName(DWORD dwThreadID, const char *threadName) +void SetThreadName(DWORD dwThreadID, const char* threadName) { THREADNAME_INFO info; info.dwType = 0x1000; @@ -49,7 +49,7 @@ void SetThreadName(DWORD dwThreadID, const char *threadName) #pragma warning(disable : 6320 6322) __try { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); } __except (EXCEPTION_EXECUTE_HANDLER) { @@ -57,9 +57,9 @@ void SetThreadName(DWORD dwThreadID, const char *threadName) #pragma warning(pop) } -unsigned __stdcall thread_func_internal(void *pthread) +unsigned __stdcall thread_func_internal(void* pthread) { - lwpa_thread_t *thread_data = (lwpa_thread_t *)pthread; + lwpa_thread_t* thread_data = (lwpa_thread_t*)pthread; if (thread_data) { SetThreadName((DWORD)-1, thread_data->name); @@ -70,7 +70,7 @@ unsigned __stdcall thread_func_internal(void *pthread) return 1; } -bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void (*thread_fn)(void *), void *thread_arg) +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg) { if (!id || !params || !thread_fn) return false; @@ -87,7 +87,7 @@ bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void return true; } -bool lwpa_thread_stop(lwpa_thread_t *id, int wait_ms) +bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms) { if (id) { diff --git a/src/lwpa_plat/windows/lwpa/timer.c b/src/lwpa_plat/windows/lwpa/timer.c index c0bce251f..f3e241bb6 100644 --- a/src/lwpa_plat/windows/lwpa/timer.c +++ b/src/lwpa_plat/windows/lwpa/timer.c @@ -26,7 +26,7 @@ uint32_t lwpa_getms() return timeGetTime(); } -uint32_t lwpa_timer_remaining(const LwpaTimer *timer) +uint32_t lwpa_timer_remaining(const LwpaTimer* timer) { uint32_t res = 0; if (timer->interval != 0) diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp index 1296dac01..713970cb8 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/main.cpp @@ -28,7 +28,7 @@ // do this than using a global variable. LwpaIpAddr g_netint; -int main(int argc, char **argv) +int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); diff --git a/tests/unit/mqx/iar/test_log.c b/tests/unit/mqx/iar/test_log.c index bc4b4a3dd..4a41206ec 100644 --- a/tests/unit/mqx/iar/test_log.c +++ b/tests/unit/mqx/iar/test_log.c @@ -21,14 +21,14 @@ #include #include "lwpa_log.h" -static void *expect_context; +static void* expect_context; static bool expect_syslog_str_present, expect_human_str_present; static char expect_syslog_str[LWPA_SYSLOG_STR_MAX_LEN]; static char expect_human_str[LWPA_HUMAN_LOG_STR_MAX_LEN]; static char expect_raw_str[LWPA_LOG_MSG_MAX_LEN]; static bool log_passed_flag; -static void log_cb(void *context, const char *syslog_str, const char *human_str, const char *raw_str) +static void log_cb(void* context, const char* syslog_str, const char* human_str, const char* raw_str) { if (context != expect_context || !raw_str || 0 != strcmp(raw_str, expect_raw_str) || (expect_syslog_str_present && (!syslog_str || 0 != strcmp(syslog_str, expect_syslog_str))) || @@ -47,7 +47,7 @@ static void log_cb(void *context, const char *syslog_str, const char *human_str, LwpaLogTimeParams tparams; bool time_fn_called; -static void time_cb(void *context, LwpaLogTimeParams *time_params) +static void time_cb(void* context, LwpaLogTimeParams* time_params) { (void)context; *time_params = tparams; @@ -228,7 +228,7 @@ bool test_log_intval() // Used by the following tests. Try using lwpa_vlog() to log various combinations of syslog and // human-readable logging. -bool vlog_helper(LwpaLogParams *lparams, int pri, const char *format, ...) +bool vlog_helper(LwpaLogParams* lparams, int pri, const char* format, ...) { va_list args; va_start(args, format); @@ -346,9 +346,9 @@ bool test_log_maxlength() LwpaLogParams lparams; char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; - char *expect_syslog_str_ptr; - char *expect_human_str_ptr; - char *expect_raw_str_ptr; + char* expect_syslog_str_ptr; + char* expect_human_str_ptr; + char* expect_raw_str_ptr; init_flags(); diff --git a/tests/unit/mqx/iar/test_mempool.c b/tests/unit/mqx/iar/test_mempool.c index cd5daf990..e9427186f 100644 --- a/tests/unit/mqx/iar/test_mempool.c +++ b/tests/unit/mqx/iar/test_mempool.c @@ -30,7 +30,7 @@ struct test_elem LWPA_MEMPOOL_DEFINE(alloc_test, struct test_elem, TEST_ALLOC_MEMP_SIZE); struct alloctest { - struct test_elem *elem; + struct test_elem* elem; bool freed; } test_array[TEST_ALLOC_MEMP_SIZE]; @@ -47,7 +47,7 @@ bool test_alloc() /* Allocate the entire pool. */ for (i = 0; i < TEST_ALLOC_MEMP_SIZE; ++i) { - test_array[i].elem = (struct test_elem *)lwpa_mempool_alloc(alloc_test); + test_array[i].elem = (struct test_elem*)lwpa_mempool_alloc(alloc_test); if (!test_array[i].elem) { ok = false; @@ -80,7 +80,7 @@ bool test_alloc() /* Make sure we can allocate the entire pool again. */ for (i = 0; i < TEST_ALLOC_MEMP_SIZE; ++i) { - test_array[i].elem = (struct test_elem *)lwpa_mempool_alloc(alloc_test); + test_array[i].elem = (struct test_elem*)lwpa_mempool_alloc(alloc_test); if (!test_array[i].elem) { ok = false; diff --git a/tests/unit/mqx/iar/test_mutex.c b/tests/unit/mqx/iar/test_mutex.c index a6dad6b5d..8011dd003 100644 --- a/tests/unit/mqx/iar/test_mutex.c +++ b/tests/unit/mqx/iar/test_mutex.c @@ -65,13 +65,13 @@ static bool mt_terminated[MUTEX_TEST_NUM_THREADS]; static int g_shared_var; struct thread_data { - lwpa_mutex_t *mutex; + lwpa_mutex_t* mutex; int thread_num; }; void mutex_test_thread(uint32_t initial_data) { - struct thread_data *td = (struct thread_data *)initial_data; + struct thread_data* td = (struct thread_data*)initial_data; int i; for (i = 0; i < MUTEX_TEST_NUM_ITERATIONS; ++i) diff --git a/tests/unit/mqx/iar/test_netint.c b/tests/unit/mqx/iar/test_netint.c index 8f3693977..1aaf8c271 100644 --- a/tests/unit/mqx/iar/test_netint.c +++ b/tests/unit/mqx/iar/test_netint.c @@ -21,7 +21,7 @@ #include #include "lwpa_netint.h" -static LwpaNetintInfo *g_interfaces; +static LwpaNetintInfo* g_interfaces; static size_t g_num_interfaces; bool test_enumerate() @@ -85,7 +85,7 @@ bool test_default() bool test_route() { bool ok = true; - LwpaNetintInfo *iface; + LwpaNetintInfo* iface; for (iface = g_interfaces; iface < g_interfaces + g_num_interfaces; ++iface) { @@ -95,7 +95,7 @@ bool test_route() uint32_t remote; uint32_t mask; LwpaIpAddr dest_ip; - const LwpaNetintInfo *dest; + const LwpaNetintInfo* dest; if (lwpaip_is_v6(&iface->addr)) continue; diff --git a/tests/unit/mqx/iar/test_pack.c b/tests/unit/mqx/iar/test_pack.c index ddf12a4d4..e3b69da09 100644 --- a/tests/unit/mqx/iar/test_pack.c +++ b/tests/unit/mqx/iar/test_pack.c @@ -19,10 +19,10 @@ #include "lwpatest.h" #include "lwpa_pack.h" -bool test_pack16b(uint8_t *buffer) +bool test_pack16b(uint8_t* buffer) { const uint16_t tst = 0x1234; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint16_t)); pack_16b(buffer, tst); @@ -31,10 +31,10 @@ bool test_pack16b(uint8_t *buffer) return false; } -bool test_pack16l(uint8_t *buffer) +bool test_pack16l(uint8_t* buffer) { const uint16_t tst = 0x1234; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint16_t)); pack_16l(buffer, tst); @@ -43,7 +43,7 @@ bool test_pack16l(uint8_t *buffer) return false; } -bool test_upack16b(uint8_t *buffer) +bool test_upack16b(uint8_t* buffer) { const uint16_t tst = 0x1234; uint16_t var; @@ -56,7 +56,7 @@ bool test_upack16b(uint8_t *buffer) return false; } -bool test_upack16l(uint8_t *buffer) +bool test_upack16l(uint8_t* buffer) { const uint16_t tst = 0x1234; uint16_t var; @@ -69,10 +69,10 @@ bool test_upack16l(uint8_t *buffer) return false; } -bool test_pack32b(uint8_t *buffer) +bool test_pack32b(uint8_t* buffer) { const uint32_t tst = 0x12345678; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint32_t)); pack_32b(buffer, tst); @@ -83,10 +83,10 @@ bool test_pack32b(uint8_t *buffer) return false; } -bool test_pack32l(uint8_t *buffer) +bool test_pack32l(uint8_t* buffer) { const uint32_t tst = 0x12345678; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint32_t)); pack_32l(buffer, tst); @@ -97,7 +97,7 @@ bool test_pack32l(uint8_t *buffer) return false; } -bool test_upack32b(uint8_t *buffer) +bool test_upack32b(uint8_t* buffer) { const uint32_t tst = 0x12345678; uint32_t var; @@ -110,7 +110,7 @@ bool test_upack32b(uint8_t *buffer) return false; } -bool test_upack32l(uint8_t *buffer) +bool test_upack32l(uint8_t* buffer) { const uint32_t tst = 0x12345678; uint32_t var; @@ -123,10 +123,10 @@ bool test_upack32l(uint8_t *buffer) return false; } -bool test_pack64b(uint8_t *buffer) +bool test_pack64b(uint8_t* buffer) { const uint64_t tst = 0x1234567890abcdef; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint64_t)); pack_64b(buffer, tst); @@ -138,10 +138,10 @@ bool test_pack64b(uint8_t *buffer) return false; } -bool test_pack64l(uint8_t *buffer) +bool test_pack64l(uint8_t* buffer) { const uint64_t tst = 0x1234567890abcdef; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint64_t)); pack_64l(buffer, tst); @@ -153,7 +153,7 @@ bool test_pack64l(uint8_t *buffer) return false; } -bool test_upack64b(uint8_t *buffer) +bool test_upack64b(uint8_t* buffer) { const uint64_t tst = 0x1234567890abcdef; uint64_t var; @@ -166,7 +166,7 @@ bool test_upack64b(uint8_t *buffer) return false; } -bool test_upack64l(uint8_t *buffer) +bool test_upack64l(uint8_t* buffer) { const uint64_t tst = 0x1234567890abcdef; uint64_t var; @@ -179,7 +179,7 @@ bool test_upack64l(uint8_t *buffer) return false; } -bool test_pack16(uint8_t *buffer) +bool test_pack16(uint8_t* buffer) { int offset = 0; bool ok; @@ -203,7 +203,7 @@ bool test_pack16(uint8_t *buffer) return ok; } -bool test_pack32(uint8_t *buffer) +bool test_pack32(uint8_t* buffer) { int offset = 0; bool ok; @@ -227,7 +227,7 @@ bool test_pack32(uint8_t *buffer) return ok; } -bool test_pack64(uint8_t *buffer) +bool test_pack64(uint8_t* buffer) { int offset = 0; bool ok; diff --git a/tests/unit/mqx/iar/test_rbtree.c b/tests/unit/mqx/iar/test_rbtree.c index 3296b1ddd..874b77b4d 100644 --- a/tests/unit/mqx/iar/test_rbtree.c +++ b/tests/unit/mqx/iar/test_rbtree.c @@ -25,23 +25,23 @@ int incrementing_int_array[INT_ARRAY_SIZE]; static int g_alloc_call_count; -static LwpaRbNode *node_alloc() +static LwpaRbNode* node_alloc() { ++g_alloc_call_count; - return (LwpaRbNode *)_mem_alloc(sizeof(LwpaRbNode)); + return (LwpaRbNode*)_mem_alloc(sizeof(LwpaRbNode)); } static int g_dealloc_call_count; -static void node_dealloc(LwpaRbNode *node) +static void node_dealloc(LwpaRbNode* node) { ++g_dealloc_call_count; _mem_free(node); } -static int int_cmp(const LwpaRbTree *self, const LwpaRbNode *node_a, const LwpaRbNode *node_b) +static int int_cmp(const LwpaRbTree* self, const LwpaRbNode* node_a, const LwpaRbNode* node_b) { - int a = *(int *)node_a->value; - int b = *(int *)node_b->value; + int a = *(int*)node_a->value; + int b = *(int*)node_b->value; return a - b; } @@ -51,9 +51,9 @@ static LwpaRbNode node_pool[INT_ARRAY_SIZE]; static int g_clearfunc_call_count; bool remove_one_flag; #define MAGIC_REMOVE_VALUE (INT_ARRAY_SIZE / 2) -static void clear_func(const LwpaRbTree *self, LwpaRbNode *node) +static void clear_func(const LwpaRbTree* self, LwpaRbNode* node) { - if (remove_one_flag && *(int *)node->value == MAGIC_REMOVE_VALUE) + if (remove_one_flag && *(int*)node->value == MAGIC_REMOVE_VALUE) remove_one_flag = false; ++g_clearfunc_call_count; } @@ -80,7 +80,7 @@ bool test_insert_static() /* Now, point each node at its respective value and insert it into the tree */ for (i = 0; i < INT_ARRAY_SIZE; ++i) { - LwpaRbNode *node = &node_pool[i]; + LwpaRbNode* node = &node_pool[i]; ok = (NULL != rb_node_init(node, &intval_pool[i])); if (!ok) break; @@ -96,7 +96,7 @@ bool test_insert_static() if (ok) { int to_find = rand() / (RAND_MAX / INT_ARRAY_SIZE + 1); - int *found = (int *)rb_tree_find(&tree, &to_find); + int* found = (int*)rb_tree_find(&tree, &to_find); ok = (found != NULL && *found == to_find); } if (ok) @@ -152,7 +152,7 @@ bool test_insert_dynamic() if (ok) { int to_find = rand() / (RAND_MAX / INT_ARRAY_SIZE + 1); - int *found = (int *)rb_tree_find(&tree, &to_find); + int* found = (int*)rb_tree_find(&tree, &to_find); ok = (found != NULL && *found == to_find); } if (ok) @@ -174,7 +174,7 @@ bool test_iter() int i; LwpaRbTree tree; LwpaRbIter iter; - int *val = NULL; + int* val = NULL; bool ok; ok = (NULL != rb_tree_init(&tree, int_cmp, node_alloc, node_dealloc)); @@ -204,7 +204,7 @@ bool test_iter() ok = (NULL != rb_iter_init(&iter)); if (ok) { - val = (int *)rb_iter_first(&iter, &tree); + val = (int*)rb_iter_first(&iter, &tree); /* Although the elements were inserted in random order, the tree should be sorted so 0 should be * the first value. */ ok = (*val == 0); @@ -213,7 +213,7 @@ bool test_iter() { size_t num_iterations = 1; int last_val = *val; - while ((val = (int *)rb_iter_next(&iter))) + while ((val = (int*)rb_iter_next(&iter))) { ++num_iterations; /* Each value given by the iterator should be numerically higher than the one that came before @@ -230,7 +230,7 @@ bool test_iter() } if (ok) { - val = (int *)rb_iter_last(&iter, &tree); + val = (int*)rb_iter_last(&iter, &tree); /* Although the elements were inserted in random order, the tree should be sorted so * INT_ARRAY_SIZE - 1 should be the last value. */ ok = (*val == (INT_ARRAY_SIZE - 1)); @@ -239,7 +239,7 @@ bool test_iter() { size_t num_iterations = 1; int last_val = *val; - while ((val = (int *)rb_iter_prev(&iter))) + while ((val = (int*)rb_iter_prev(&iter))) { ++num_iterations; /* Each value given by the reverse iterator should be numerically smaller than the one that diff --git a/tests/unit/mqx/iar/test_rwlock.c b/tests/unit/mqx/iar/test_rwlock.c index 3d741cc86..4767199c3 100644 --- a/tests/unit/mqx/iar/test_rwlock.c +++ b/tests/unit/mqx/iar/test_rwlock.c @@ -118,7 +118,7 @@ bool test_rwlock_create_destroy() static int g_shared_var; struct thread_data { - lwpa_rwlock_t *rwlock; + lwpa_rwlock_t* rwlock; int thread_num; bool done; bool passed; @@ -126,7 +126,7 @@ struct thread_data void write_test_thread(uint32_t initial_data) { - struct thread_data *td = (struct thread_data *)initial_data; + struct thread_data* td = (struct thread_data*)initial_data; int i; for (i = 0; i < RWLOCK_TEST_NUM_ITERATIONS; ++i) @@ -141,7 +141,7 @@ void write_test_thread(uint32_t initial_data) void read_test_thread(uint32_t initial_data) { - struct thread_data *td = (struct thread_data *)initial_data; + struct thread_data* td = (struct thread_data*)initial_data; int i; td->passed = true; diff --git a/tests/unit/mqx/iar/test_signal.c b/tests/unit/mqx/iar/test_signal.c index 8932cd466..90eefc79b 100644 --- a/tests/unit/mqx/iar/test_signal.c +++ b/tests/unit/mqx/iar/test_signal.c @@ -67,14 +67,14 @@ bool test_signal_create_destroy() struct thread_data { - lwpa_signal_t *signal; + lwpa_signal_t* signal; int thread_num; bool passed; }; void signal_test_thread(uint32_t initial_data) { - struct thread_data *td = (struct thread_data *)initial_data; + struct thread_data* td = (struct thread_data*)initial_data; int i; for (i = 0; i < 3; ++i) diff --git a/tests/unit/mqx/iar/test_socket.c b/tests/unit/mqx/iar/test_socket.c index 4aade7f34..c914d93b8 100644 --- a/tests/unit/mqx/iar/test_socket.c +++ b/tests/unit/mqx/iar/test_socket.c @@ -28,17 +28,17 @@ bool test_inet_xtox() bool ok; LwpaIpAddr addr; char str[LWPA_INET6_ADDRSTRLEN]; - const char *test_ip4_1 = "0.0.0.0"; - const char *test_ip4_2 = "255.255.255.255"; - const char *test_ip4_fail = "256.256.256.256"; - const char *test_ip6_1 = "::"; + const char* test_ip4_1 = "0.0.0.0"; + const char* test_ip4_2 = "255.255.255.255"; + const char* test_ip4_fail = "256.256.256.256"; + const char* test_ip6_1 = "::"; const uint8_t test_ip6_1_bin[IPV6_BYTES] = {0}; - const char *test_ip6_2 = "::1"; + const char* test_ip6_2 = "::1"; const uint8_t test_ip6_2_bin[IPV6_BYTES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - const char *test_ip6_3 = "ffff:FFFF:ffff:FFFF:ffff:FFFF:ffff:FFFF"; + const char* test_ip6_3 = "ffff:FFFF:ffff:FFFF:ffff:FFFF:ffff:FFFF"; const uint8_t test_ip6_3_bin[IPV6_BYTES] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const char *test_ip6_fail = "abcd::ef01::2345"; + const char* test_ip6_fail = "abcd::ef01::2345"; /* Test lwpa_inet_pton() */ ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV4, test_ip4_1, &addr)); @@ -124,8 +124,8 @@ struct sendthread_inf void send_thread(uint32_t initial_data) { - struct sendthread_inf *inf = (struct sendthread_inf *)initial_data; - const uint8_t *send_buf = (const uint8_t *)SEND_MSG; + struct sendthread_inf* inf = (struct sendthread_inf*)initial_data; + const uint8_t* send_buf = (const uint8_t*)SEND_MSG; size_t i; for (i = 0; i < NUM_TEST_PACKETS; ++i) @@ -219,7 +219,7 @@ bool test_unicast_udp() if (!ok) break; buf[SEND_MSG_LEN] = '\0'; - ok = (0 == strcmp((char *)buf, SEND_MSG)); + ok = (0 == strcmp((char*)buf, SEND_MSG)); if (!ok) break; } @@ -344,7 +344,7 @@ bool test_multicast_udp() if (!ok) break; buf[SEND_MSG_LEN] = '\0'; - ok = (0 == strcmp((char *)buf, SEND_MSG)); + ok = (0 == strcmp((char*)buf, SEND_MSG)); if (!ok) break; } @@ -379,8 +379,8 @@ struct pt_sendthread_inf void polltest_sendthread(uint32_t initial_data) { - struct pt_sendthread_inf *inf = (struct pt_sendthread_inf *)initial_data; - const uint8_t *send_buf = (const uint8_t *)SEND_MSG; + struct pt_sendthread_inf* inf = (struct pt_sendthread_inf*)initial_data; + const uint8_t* send_buf = (const uint8_t*)SEND_MSG; lwpa_sendto(inf->send_sock, send_buf, SEND_MSG_LEN, 0, &inf->send_addr_1); lwpa_sendto(inf->send_sock, send_buf, SEND_MSG_LEN, 0, &inf->send_addr_2); @@ -482,7 +482,7 @@ bool test_poll() if (!ok) break; buf[SEND_MSG_LEN] = '\0'; - ok = (0 == strcmp((char *)buf, SEND_MSG)); + ok = (0 == strcmp((char*)buf, SEND_MSG)); if (!ok) break; } diff --git a/tests/unit/mqx/iar/test_thread.c b/tests/unit/mqx/iar/test_thread.c index 42f44e4d0..e7dcbed6a 100644 --- a/tests/unit/mqx/iar/test_thread.c +++ b/tests/unit/mqx/iar/test_thread.c @@ -21,7 +21,7 @@ static bool g_waitthread_run; -void wait_and_exit(void *param) +void wait_and_exit(void* param) { while (g_waitthread_run) lwpa_thread_sleep(50); @@ -65,14 +65,14 @@ static volatile bool spin_task_run, oneshot_task_run; static volatile bool spin_task_ran = false; static volatile bool oneshot_task_ran = false; -void increment_and_spin(void *param) +void increment_and_spin(void* param) { spin_task_ran = true; while (spin_task_run) ; } -void oneshot(void *param) +void oneshot(void* param) { if (oneshot_task_run) oneshot_task_ran = true; @@ -121,13 +121,13 @@ bool test_thread_time_slice() static int shared_var; static bool lp_thread_done, lp_thread_passed, hp_thread_done; -void low_priority_thread(void *param) +void low_priority_thread(void* param) { lp_thread_passed = (shared_var == 1000); lp_thread_done = true; } -void high_priority_thread(void *param) +void high_priority_thread(void* param) { int i; for (i = 0; i < 1000; ++i) diff --git a/tests/unit/mqx/testio.h b/tests/unit/mqx/testio.h index a3d3679b0..b75ff4d3a 100644 --- a/tests/unit/mqx/testio.h +++ b/tests/unit/mqx/testio.h @@ -14,17 +14,12 @@ #define OUTPUT_TEST_SUITE_TIMEOUT() printf("[TestSuiteTimeout]\n") -#define OUTPUT_TEST_MODULE_BEGIN(name) \ - printf("[TestModuleBegin:" name "]\n") +#define OUTPUT_TEST_MODULE_BEGIN(name) printf("[TestModuleBegin:" name "]\n") -#define OUTPUT_TEST_MODULE_END(name, did_pass) \ - printf("[TestModuleEnd:" name ":%s]\n", did_pass ? "PASS" : "FAIL") +#define OUTPUT_TEST_MODULE_END(name, did_pass) printf("[TestModuleEnd:" name ":%s]\n", did_pass ? "PASS" : "FAIL") -#define OUTPUT_TEST_BEGIN(name) \ - printf("[TestBegin:" name "]\n") +#define OUTPUT_TEST_BEGIN(name) printf("[TestBegin:" name "]\n") -#define OUTPUT_TEST_RESULT(did_pass) \ - ((did_pass) ? printf("[TestResult:PASS]\n") \ - : printf("[TestResult:FAIL]\n")) +#define OUTPUT_TEST_RESULT(did_pass) ((did_pass) ? printf("[TestResult:PASS]\n") : printf("[TestResult:FAIL]\n")) #endif /* _TEST_IO_H_ */ diff --git a/tests/unit/test_log.cpp b/tests/unit/test_log.cpp index 305e76534..11a731444 100644 --- a/tests/unit/test_log.cpp +++ b/tests/unit/test_log.cpp @@ -26,7 +26,7 @@ // Disable strcpy() warning on Windows/MSVC #ifdef _MSC_VER -#pragma warning(disable: 4996) +#pragma warning(disable : 4996) #endif using testing::Mock; @@ -34,39 +34,34 @@ using testing::Mock; class LogTest : public ::testing::Test { protected: - LogTest() - { - FillDefaultTime(cur_time); - } + LogTest() { FillDefaultTime(cur_time); } virtual ~LogTest() {} - void TestLwpaVlogHelper(std::string expect_syslog_str, std::string expect_human_str, - std::string expect_raw_str, LwpaLogParams *lparams, int pri, - const char *format, ...); + void TestLwpaVlogHelper(std::string expect_syslog_str, std::string expect_human_str, std::string expect_raw_str, + LwpaLogParams* lparams, int pri, const char* format, ...); public: - static void FillDefaultTime(LwpaLogTimeParams &tparams); + static void FillDefaultTime(LwpaLogTimeParams& tparams); - MOCK_METHOD3(VerifyLogCallback, void(std::string syslog_str, std::string human_str, - std::string raw_str)); + MOCK_METHOD3(VerifyLogCallback, void(std::string syslog_str, std::string human_str, std::string raw_str)); LwpaLogTimeParams cur_time; bool time_fn_called; }; -static void log_cb(void *context, const char *syslog_str, const char *human_str, const char *raw_str) +static void log_cb(void* context, const char* syslog_str, const char* human_str, const char* raw_str) { - LogTest *lt = static_cast(context); + LogTest* lt = static_cast(context); if (lt) { lt->VerifyLogCallback(syslog_str ? syslog_str : "", human_str ? human_str : "", raw_str ? raw_str : ""); } } -static void time_cb(void *context, LwpaLogTimeParams *time_params) +static void time_cb(void* context, LwpaLogTimeParams* time_params) { - LogTest *lt = static_cast(context); + LogTest* lt = static_cast(context); if (lt && time_params) { *time_params = lt->cur_time; @@ -74,7 +69,7 @@ static void time_cb(void *context, LwpaLogTimeParams *time_params) } } -void LogTest::FillDefaultTime(LwpaLogTimeParams &time_params) +void LogTest::FillDefaultTime(LwpaLogTimeParams& time_params) { time_params.year = 1970; // absolute year time_params.month = 1; // month of the year - [1, 12] @@ -165,7 +160,8 @@ TEST_F(LogTest, log_intval) lparams.time_fn = time_cb; lparams.context = this; - std::string expect_syslog_str = "<0>1 1970-01-01T00:00:00.000Z host?name My_App - - - Here are some int values: 1 42 4294967295"; + std::string expect_syslog_str = + "<0>1 1970-01-01T00:00:00.000Z host?name My_App - - - Here are some int values: 1 42 4294967295"; std::string expect_human_str = "1970-01-01 00:00:00.000Z Here are some int values: 1 42 4294967295"; std::string expect_raw_str = "Here are some int values: 1 42 4294967295"; @@ -207,8 +203,7 @@ TEST_F(LogTest, log_intval) // Used by the following tests. Try using lwpa_vlog() to log various combinations of syslog and // human-readable logging. void LogTest::TestLwpaVlogHelper(std::string expect_syslog_str, std::string expect_human_str, - std::string expect_raw_str, LwpaLogParams *lparams, int pri, - const char *format, ...) + std::string expect_raw_str, LwpaLogParams* lparams, int pri, const char* format, ...) { va_list args; va_start(args, format); @@ -373,6 +368,5 @@ TEST_F(LogTest, log_maxlength) // Now try the actual logging using lwpa_vlog(). lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); - TestLwpaVlogHelper(expect_syslog_str, expect_human_str, expect_raw_str, &lparams, LWPA_LOG_DEBUG, - to_log_str); + TestLwpaVlogHelper(expect_syslog_str, expect_human_str, expect_raw_str, &lparams, LWPA_LOG_DEBUG, to_log_str); } diff --git a/tests/unit/test_mempool.cpp b/tests/unit/test_mempool.cpp index 46088d2ce..b20032e48 100644 --- a/tests/unit/test_mempool.cpp +++ b/tests/unit/test_mempool.cpp @@ -38,7 +38,7 @@ class MempoolTest : public ::testing::Test LWPA_MEMPOOL_DEFINE(alloc_test, TestElem, kAllocTestMempSize); LWPA_MEMPOOL_DEFINE_ARRAY(alloc_array_test, TestElem, kAllocTestMempArraySize, kAllocTestMempSize); - std::vector test_vec; + std::vector test_vec; }; constexpr size_t MempoolTest::kAllocTestMempSize; @@ -54,7 +54,7 @@ TEST_F(MempoolTest, alloc_free) test_vec.reserve(kAllocTestMempSize); for (size_t i = 0; i < kAllocTestMempSize; ++i) { - auto elem = static_cast(lwpa_mempool_alloc(alloc_test)); + auto elem = static_cast(lwpa_mempool_alloc(alloc_test)); ASSERT_TRUE(elem != NULL); test_vec.push_back(elem); } @@ -78,7 +78,7 @@ TEST_F(MempoolTest, alloc_free) // Make sure we can allocate the entire pool again. for (size_t i = 0; i < kAllocTestMempSize; ++i) { - test_vec[i] = static_cast(lwpa_mempool_alloc(alloc_test)); + test_vec[i] = static_cast(lwpa_mempool_alloc(alloc_test)); ASSERT_TRUE(test_vec[i] != NULL); } } @@ -93,7 +93,7 @@ TEST_F(MempoolTest, alloc_free_array) test_vec.reserve(kAllocTestMempSize); for (size_t i = 0; i < kAllocTestMempSize; ++i) { - auto elem_arr = static_cast(lwpa_mempool_alloc(alloc_array_test)); + auto elem_arr = static_cast(lwpa_mempool_alloc(alloc_array_test)); ASSERT_TRUE(elem_arr != NULL); // Write to each spot in the array - failure could be caught by a segfault or similar @@ -125,7 +125,7 @@ TEST_F(MempoolTest, alloc_free_array) // Make sure we can allocate the entire pool again. for (size_t i = 0; i < kAllocTestMempSize; ++i) { - test_vec[i] = static_cast(lwpa_mempool_alloc(alloc_array_test)); + test_vec[i] = static_cast(lwpa_mempool_alloc(alloc_array_test)); // Make sure the sentinel values we set before are still there. for (size_t j = 0; j < kAllocTestMempArraySize; ++j) diff --git a/tests/unit/test_mutex.cpp b/tests/unit/test_mutex.cpp index 01d2ba1ab..df034934f 100644 --- a/tests/unit/test_mutex.cpp +++ b/tests/unit/test_mutex.cpp @@ -59,7 +59,7 @@ TEST_F(MutexTest, create_destroy) ASSERT_FALSE(lwpa_mutex_take(&mutex, LWPA_WAIT_FOREVER)); } -static void mutex_test_thread(MutexTest *fixture) +static void mutex_test_thread(MutexTest* fixture) { if (fixture) { @@ -96,7 +96,7 @@ TEST_F(MutexTest, threads) threads.push_back(std::move(thread)); } - for (auto &thread : threads) + for (auto& thread : threads) thread.join(); ASSERT_EQ(shared_var, (kNumThreads * kNumIterations)); diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index 112eb617d..aadaa8ea2 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -35,12 +35,12 @@ class NetintTest : public ::testing::Test TEST_F(NetintTest, enumerate) { ASSERT_GT(num_netints, 0u); - LwpaNetintInfo *netint_arr = new LwpaNetintInfo[num_netints]; + LwpaNetintInfo* netint_arr = new LwpaNetintInfo[num_netints]; size_t num_netints_returned = lwpa_netint_get_interfaces(netint_arr, num_netints); ASSERT_EQ(num_netints_returned, num_netints); size_t num_defaults = 0; - for (LwpaNetintInfo *netint = netint_arr; netint < netint_arr + num_netints_returned; ++netint) + for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints_returned; ++netint) { if (netint->is_default) ++num_defaults; @@ -55,14 +55,14 @@ TEST_F(NetintTest, default) ASSERT_GT(num_netints, 0u); LwpaNetintInfo def; - LwpaNetintInfo *netint_arr = new LwpaNetintInfo[num_netints]; + LwpaNetintInfo* netint_arr = new LwpaNetintInfo[num_netints]; memset(&def, 0, sizeof def); memset(netint_arr, 0, sizeof(struct LwpaNetintInfo) * num_netints); num_netints = lwpa_netint_get_interfaces(netint_arr, num_netints); ASSERT_TRUE(lwpa_netint_get_default_interface(&def)); ASSERT_TRUE(def.is_default); - for (LwpaNetintInfo *netint = netint_arr; netint < netint_arr + num_netints; ++netint) + for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) { if (netint->is_default) { @@ -77,12 +77,12 @@ TEST_F(NetintTest, IPv4routing) { ASSERT_GT(num_netints, 0u); - LwpaNetintInfo *netint_arr = new LwpaNetintInfo[num_netints]; + LwpaNetintInfo* netint_arr = new LwpaNetintInfo[num_netints]; num_netints = lwpa_netint_get_interfaces(netint_arr, num_netints); std::set nets_already_tried; - for (LwpaNetintInfo *netint = netint_arr; netint < netint_arr + num_netints; ++netint) + for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) { uint32_t net = lwpaip_v4_address(&netint->addr) & lwpaip_v4_address(&netint->mask); LwpaIpAddr test_addr; @@ -96,7 +96,7 @@ TEST_F(NetintTest, IPv4routing) LwpaIpAddr ext_addr; lwpaip_set_v4_address(&ext_addr, 0xc8dc0302); // 200.220.3.2 - const LwpaNetintInfo *def = lwpa_netint_get_iface_for_dest(&ext_addr, netint_arr, num_netints); + const LwpaNetintInfo* def = lwpa_netint_get_iface_for_dest(&ext_addr, netint_arr, num_netints); ASSERT_TRUE(def != NULL); ASSERT_TRUE(def->is_default); } diff --git a/tests/unit/test_pack.cpp b/tests/unit/test_pack.cpp index aefee93a5..65077c4cf 100644 --- a/tests/unit/test_pack.cpp +++ b/tests/unit/test_pack.cpp @@ -24,10 +24,10 @@ class PackTest : public ::testing::Test { protected: - bool test_pack16b(uint8_t *buffer) + bool test_pack16b(uint8_t* buffer) { const uint16_t tst = 0x1234; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint16_t)); lwpa_pack_16b(buffer, tst); @@ -36,10 +36,10 @@ class PackTest : public ::testing::Test return false; } - bool test_pack16l(uint8_t *buffer) + bool test_pack16l(uint8_t* buffer) { const uint16_t tst = 0x1234; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint16_t)); lwpa_pack_16l(buffer, tst); @@ -48,7 +48,7 @@ class PackTest : public ::testing::Test return false; } - bool test_upack16b(uint8_t *buffer) + bool test_upack16b(uint8_t* buffer) { const uint16_t tst = 0x1234; uint16_t var; @@ -61,7 +61,7 @@ class PackTest : public ::testing::Test return false; } - bool test_upack16l(uint8_t *buffer) + bool test_upack16l(uint8_t* buffer) { const uint16_t tst = 0x1234; uint16_t var; @@ -74,10 +74,10 @@ class PackTest : public ::testing::Test return false; } - bool test_pack32b(uint8_t *buffer) + bool test_pack32b(uint8_t* buffer) { const uint32_t tst = 0x12345678; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint32_t)); lwpa_pack_32b(buffer, tst); @@ -88,10 +88,10 @@ class PackTest : public ::testing::Test return false; } - bool test_pack32l(uint8_t *buffer) + bool test_pack32l(uint8_t* buffer) { const uint32_t tst = 0x12345678; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint32_t)); lwpa_pack_32l(buffer, tst); @@ -102,7 +102,7 @@ class PackTest : public ::testing::Test return false; } - bool test_upack32b(uint8_t *buffer) + bool test_upack32b(uint8_t* buffer) { const uint32_t tst = 0x12345678; uint32_t var; @@ -115,7 +115,7 @@ class PackTest : public ::testing::Test return false; } - bool test_upack32l(uint8_t *buffer) + bool test_upack32l(uint8_t* buffer) { const uint32_t tst = 0x12345678; uint32_t var; @@ -128,10 +128,10 @@ class PackTest : public ::testing::Test return false; } - bool test_pack64b(uint8_t *buffer) + bool test_pack64b(uint8_t* buffer) { const uint64_t tst = 0x1234567890abcdef; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint64_t)); lwpa_pack_64b(buffer, tst); @@ -143,10 +143,10 @@ class PackTest : public ::testing::Test return false; } - bool test_pack64l(uint8_t *buffer) + bool test_pack64l(uint8_t* buffer) { const uint64_t tst = 0x1234567890abcdef; - const uint8_t *ptst = (const uint8_t *)(&tst); + const uint8_t* ptst = (const uint8_t*)(&tst); memset(buffer, 0, sizeof(uint64_t)); lwpa_pack_64l(buffer, tst); @@ -158,7 +158,7 @@ class PackTest : public ::testing::Test return false; } - bool test_upack64b(uint8_t *buffer) + bool test_upack64b(uint8_t* buffer) { const uint64_t tst = 0x1234567890abcdef; uint64_t var; @@ -171,7 +171,7 @@ class PackTest : public ::testing::Test return false; } - bool test_upack64l(uint8_t *buffer) + bool test_upack64l(uint8_t* buffer) { const uint64_t tst = 0x1234567890abcdef; uint64_t var; diff --git a/tests/unit/test_rbtree.cpp b/tests/unit/test_rbtree.cpp index 843422548..554222c2d 100644 --- a/tests/unit/test_rbtree.cpp +++ b/tests/unit/test_rbtree.cpp @@ -63,32 +63,32 @@ class RbTreeTest : public ::testing::Test unsigned int RbTreeTest::alloc_call_count; unsigned int RbTreeTest::dealloc_call_count; -LwpaRbNode *node_alloc() +LwpaRbNode* node_alloc() { ++RbTreeTest::alloc_call_count; return new LwpaRbNode; } -void node_dealloc(LwpaRbNode *node) +void node_dealloc(LwpaRbNode* node) { ++RbTreeTest::dealloc_call_count; delete node; } -static int int_cmp(const LwpaRbTree *self, const LwpaRbNode *node_a, const LwpaRbNode *node_b) +static int int_cmp(const LwpaRbTree* self, const LwpaRbNode* node_a, const LwpaRbNode* node_b) { (void)self; - int a = *(int *)node_a->value; - int b = *(int *)node_b->value; + int a = *(int*)node_a->value; + int b = *(int*)node_b->value; return a - b; } -static void clear_func(const LwpaRbTree *self, LwpaRbNode *node) +static void clear_func(const LwpaRbTree* self, LwpaRbNode* node) { - RbTreeTest *rbtt = static_cast(self->info); + RbTreeTest* rbtt = static_cast(self->info); if (rbtt) { - if (rbtt->remove_one_flag && *(int *)node->value == RbTreeTest::MAGIC_REMOVE_VALUE) + if (rbtt->remove_one_flag && *(int*)node->value == RbTreeTest::MAGIC_REMOVE_VALUE) { rbtt->remove_one_flag = false; } @@ -105,7 +105,7 @@ TEST_F(RbTreeTest, insert_static) // Point each node at its respective value and insert it into the tree for (size_t i = 0; i < INT_ARRAY_SIZE; ++i) { - LwpaRbNode *node = &node_pool[i]; + LwpaRbNode* node = &node_pool[i]; ASSERT_TRUE(NULL != lwpa_rbnode_init(node, &random_int_array[i])); ASSERT_NE(0, lwpa_rbtree_insert_node(&tree, node)); } @@ -114,7 +114,7 @@ TEST_F(RbTreeTest, insert_static) // Find a random number int to_find = rand() / (RAND_MAX / INT_ARRAY_SIZE + 1); - int *found = (int *)lwpa_rbtree_find(&tree, &to_find); + int* found = (int*)lwpa_rbtree_find(&tree, &to_find); ASSERT_TRUE(found != NULL); ASSERT_EQ(*found, to_find); @@ -144,7 +144,7 @@ TEST_F(RbTreeTest, insert_dynamic) // Find a random number int to_find = rand() / (RAND_MAX / INT_ARRAY_SIZE + 1); - int *found = (int *)lwpa_rbtree_find(&tree, &to_find); + int* found = (int*)lwpa_rbtree_find(&tree, &to_find); ASSERT_TRUE(found != NULL); ASSERT_EQ(*found, to_find); @@ -173,7 +173,7 @@ TEST_F(RbTreeTest, iter) ASSERT_TRUE(NULL != lwpa_rbiter_init(&iter)); // Get the first value. - int *val = (int *)lwpa_rbiter_first(&iter, &tree); + int* val = (int*)lwpa_rbiter_first(&iter, &tree); // Although the elements were inserted in random order, the tree should be sorted so 0 should be // the first value. ASSERT_EQ(*val, 0); @@ -181,7 +181,7 @@ TEST_F(RbTreeTest, iter) // Test iterating through the tree in forward order. size_t num_iterations = 1; int last_val = *val; - while ((val = (int *)lwpa_rbiter_next(&iter)) != NULL) + while ((val = (int*)lwpa_rbiter_next(&iter)) != NULL) { ++num_iterations; // Each value given by the iterator should be numerically higher than the one that came before @@ -192,13 +192,13 @@ TEST_F(RbTreeTest, iter) ASSERT_EQ(num_iterations, INT_ARRAY_SIZE); // Get the last value. - val = (int *)lwpa_rbiter_last(&iter, &tree); + val = (int*)lwpa_rbiter_last(&iter, &tree); ASSERT_EQ(*val, static_cast(INT_ARRAY_SIZE - 1)); // Test iterating through the tree in reverse order. num_iterations = 1; last_val = *val; - while ((val = (int *)lwpa_rbiter_prev(&iter)) != NULL) + while ((val = (int*)lwpa_rbiter_prev(&iter)) != NULL) { ++num_iterations; // Each value given by the iterator should be numerically lower than the one that came before diff --git a/tests/unit/test_rwlock.cpp b/tests/unit/test_rwlock.cpp index 0d328c5a9..70ae82b5f 100644 --- a/tests/unit/test_rwlock.cpp +++ b/tests/unit/test_rwlock.cpp @@ -87,7 +87,7 @@ TEST_F(RwlockTest, create_destroy) ASSERT_FALSE(lwpa_rwlock_writelock(&rwlock, LWPA_WAIT_FOREVER)); } -static void write_test_thread(RwlockTest *fixture) +static void write_test_thread(RwlockTest* fixture) { if (fixture) { @@ -106,7 +106,7 @@ static void write_test_thread(RwlockTest *fixture) using namespace std::chrono_literals; -static void read_test_thread(RwlockTest *fixture) +static void read_test_thread(RwlockTest* fixture) { if (fixture) { @@ -156,7 +156,7 @@ TEST_F(RwlockTest, threads) threads.push_back(std::move(write_thread)); } - for (auto &thread : threads) + for (auto& thread : threads) thread.join(); ASSERT_TRUE(read_thread_pass); diff --git a/tests/unit/test_signal.cpp b/tests/unit/test_signal.cpp index 732d88c2b..4d7b4fa7c 100644 --- a/tests/unit/test_signal.cpp +++ b/tests/unit/test_signal.cpp @@ -64,7 +64,7 @@ TEST_F(SignalTest, create_destroy) ASSERT_FALSE(lwpa_signal_wait(&signal, LWPA_WAIT_FOREVER)); } -static void signal_test_thread(SignalTest *fixture) +static void signal_test_thread(SignalTest* fixture) { if (fixture) { @@ -97,7 +97,7 @@ TEST_F(SignalTest, threads) lwpa_signal_post(&signal); } - for (auto &thread : threads) + for (auto& thread : threads) thread.join(); lwpa_signal_destroy(&signal); diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 5b6e07a94..a96f2b6de 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -29,7 +29,7 @@ class SocketTest : public ::testing::Test { public: static const size_t NUM_TEST_PACKETS = 1000; - static const char *SEND_MSG; + static const char* SEND_MSG; static const size_t SEND_MSG_LEN = 12; static const uint32_t TEST_MCAST_ADDR = 0xec02054d; // 236.2.5.77 lwpa_socket_t send_sock = LWPA_SOCKET_INVALID; @@ -38,29 +38,29 @@ class SocketTest : public ::testing::Test protected: // For inet_xtox char str[LWPA_INET6_ADDRSTRLEN]; - const char *test_ip4_1 = "0.0.0.0"; - const char *test_ip4_2 = "255.255.255.255"; - const char *test_ip4_fail = "256.256.256.256"; - const char *test_ip6_1 = "::"; + const char* test_ip4_1 = "0.0.0.0"; + const char* test_ip4_2 = "255.255.255.255"; + const char* test_ip4_fail = "256.256.256.256"; + const char* test_ip6_1 = "::"; const uint8_t test_ip6_1_bin[LWPA_IPV6_BYTES] = {0}; - const char *test_ip6_2 = "::1"; + const char* test_ip6_2 = "::1"; const uint8_t test_ip6_2_bin[LWPA_IPV6_BYTES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - const char *test_ip6_3 = "ffff:FFFF:ffff:FFFF:ffff:FFFF:ffff:FFFF"; + const char* test_ip6_3 = "ffff:FFFF:ffff:FFFF:ffff:FFFF:ffff:FFFF"; const uint8_t test_ip6_3_bin[LWPA_IPV6_BYTES] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const char *test_ip6_fail = "abcd::ef01::2345"; + const char* test_ip6_fail = "abcd::ef01::2345"; // For getaddrinfo - const char *test_hostname = "www.google.com"; - const char *test_service = "http"; + const char* test_hostname = "www.google.com"; + const char* test_service = "http"; - const char *test_gai_ip_str = "10.101.1.1"; + const char* test_gai_ip_str = "10.101.1.1"; const uint32_t test_gai_ip = 0x0a650101; - const char *test_gai_port_str = "8080"; + const char* test_gai_port_str = "8080"; const uint16_t test_gai_port = 8080; }; -const char *SocketTest::SEND_MSG = "testtesttest"; +const char* SocketTest::SEND_MSG = "testtesttest"; TEST_F(SocketTest, inet_xtox) { @@ -104,11 +104,11 @@ TEST_F(SocketTest, sockopts) // TODO, need getsockopt() implemented for this } -static void send_thread(SocketTest *fixture) +static void send_thread(SocketTest* fixture) { if (fixture) { - const uint8_t *send_buf = (const uint8_t *)(SocketTest::SEND_MSG); + const uint8_t* send_buf = (const uint8_t*)(SocketTest::SEND_MSG); for (size_t i = 0; i < SocketTest::NUM_TEST_PACKETS; ++i) lwpa_sendto(fixture->send_sock, send_buf, SocketTest::SEND_MSG_LEN, 0, &fixture->send_addr_1); } @@ -166,7 +166,7 @@ TEST_F(SocketTest, unicast_udp) ASSERT_NE(from_addr.port, 8888); buf[SEND_MSG_LEN] = '\0'; - ASSERT_EQ(0, strcmp((char *)buf, SEND_MSG)); + ASSERT_EQ(0, strcmp((char*)buf, SEND_MSG)); } // recvfrom should time out because this socket is bound to a different port and we set the @@ -240,7 +240,7 @@ TEST_F(SocketTest, multicast_udp) ASSERT_NE(from_addr.port, 8888); buf[SEND_MSG_LEN] = '\0'; - ASSERT_EQ(0, strcmp((char *)buf, SEND_MSG)); + ASSERT_EQ(0, strcmp((char*)buf, SEND_MSG)); } LwpaSockaddr from_addr; uint8_t buf[SEND_MSG_LEN + 1]; diff --git a/tests/unit/test_socket_poll.cpp b/tests/unit/test_socket_poll.cpp index 64da5bd4a..7aedff9eb 100644 --- a/tests/unit/test_socket_poll.cpp +++ b/tests/unit/test_socket_poll.cpp @@ -37,7 +37,7 @@ extern LwpaIpAddr g_netint; class SocketPollTest : public ::testing::Test { protected: - static const char *SEND_MSG; + static const char* SEND_MSG; static const size_t SEND_MSG_LEN{12}; void SetUp() override { ASSERT_EQ(kLwpaErrOk, lwpa_poll_context_init(&context_)); } @@ -46,7 +46,7 @@ class SocketPollTest : public ::testing::Test LwpaPollContext context_{}; }; -const char *SocketPollTest::SEND_MSG = "testtesttest"; +const char* SocketPollTest::SEND_MSG = "testtesttest"; // Test to make sure various invalid calls to lwpa_poll_* functions fail properly. TEST_F(SocketPollTest, invalid_calls) @@ -90,8 +90,8 @@ TEST_F(SocketPollTest, invalid_calls) TEST_F(SocketPollTest, user_data) { lwpa_socket_t sock_1, sock_2; - void *user_data_1 = reinterpret_cast(1); - void *user_data_2 = reinterpret_cast(2); + void* user_data_1 = reinterpret_cast(1); + void* user_data_2 = reinterpret_cast(2); // Create two UDP sockets and poll for writability, make sure our user data gets passed back to us // intact. @@ -282,7 +282,7 @@ TEST_F(SocketPollTest, udp_in) ASSERT_NE(from_addr.port, 8888); ASSERT_NE(from_addr.port, 9999); recv_buf[SEND_MSG_LEN] = '\0'; - ASSERT_EQ(0, strcmp((char *)recv_buf.data(), SEND_MSG)); + ASSERT_EQ(0, strcmp((char*)recv_buf.data(), SEND_MSG)); lwpa_socket_t first_socket = event.socket; diff --git a/tests/unit/test_thread.cpp b/tests/unit/test_thread.cpp index b7da9dbc8..c67f4f771 100644 --- a/tests/unit/test_thread.cpp +++ b/tests/unit/test_thread.cpp @@ -38,9 +38,9 @@ class ThreadTest : public ::testing::Test volatile bool oneshot_task_ran{false}; }; -void wait_and_exit(void *param) +void wait_and_exit(void* param) { - ThreadTest *tt = static_cast(param); + ThreadTest* tt = static_cast(param); if (tt) { while (tt->waitthread_run) @@ -77,9 +77,9 @@ TEST_F(ThreadTest, create_destroy) ASSERT_TRUE(lwpa_thread_stop(&wait_thread, LWPA_WAIT_FOREVER)); } -void increment_and_spin(void *param) +void increment_and_spin(void* param) { - ThreadTest *tt = static_cast(param); + ThreadTest* tt = static_cast(param); if (tt) { tt->spin_task_ran = true; @@ -88,9 +88,9 @@ void increment_and_spin(void *param) } } -void oneshot(void *param) +void oneshot(void* param) { - ThreadTest *tt = static_cast(param); + ThreadTest* tt = static_cast(param); if (tt) { if (tt->oneshot_task_run) diff --git a/tests/unit/test_timer.cpp b/tests/unit/test_timer.cpp index 62fea194f..30103309e 100644 --- a/tests/unit/test_timer.cpp +++ b/tests/unit/test_timer.cpp @@ -29,14 +29,8 @@ extern "C" uint32_t lwpa_getms(); class TimerTest : public ::testing::Test { - void SetUp() override - { - ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_TIMERS)); - } - void TearDown() override - { - lwpa_deinit(LWPA_FEATURE_TIMERS); - } + void SetUp() override { ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_TIMERS)); } + void TearDown() override { lwpa_deinit(LWPA_FEATURE_TIMERS); } }; static bool mocking_getms; diff --git a/tests/unit/test_uuid.cpp b/tests/unit/test_uuid.cpp index f07503b1b..31d78485a 100644 --- a/tests/unit/test_uuid.cpp +++ b/tests/unit/test_uuid.cpp @@ -126,7 +126,7 @@ TEST_F(UuidTest, generate_v3) // Make sure the Variant Version bits are correct. // We should always have Variant 1, Version 3. std::vector uuid_vect{uuid1, uuid2, uuid3, uuid4, uuid1_dup}; - std::for_each(uuid_vect.begin(), uuid_vect.end(), [](const LwpaUuid &uuid) { + std::for_each(uuid_vect.begin(), uuid_vect.end(), [](const LwpaUuid& uuid) { ASSERT_EQ((uuid.data[6] & 0xf0u), 0x30u); ASSERT_EQ((uuid.data[8] & 0xc0u), 0x80u); }); From 15c83a9f3083544ee7e5014b715ee98ca915f044 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 3 Jun 2019 14:20:22 -0500 Subject: [PATCH 008/264] Move to a more consistent naming scheme: - Change 'plat' and 'platform' to 'os' as it's a more accurate representation of what lwpa targets - Make sure the os-specific sources are all prefixed with os_ --- CMakeLists.txt | 9 +- include/lwpa/lock.h | 2 +- include/lwpa/socket.h | 2 +- include/lwpa/thread.h | 2 +- include/lwpa_mock/socket.h | 4 +- .../freertos/lwpa/os_lock.h} | 6 +- .../freertos/lwpa/os_thread.h} | 6 +- .../plat_lock.h => os/linux/lwpa/os_lock.h} | 6 +- .../linux/lwpa/os_socket.h} | 18 ++-- .../linux/lwpa/os_thread.h} | 6 +- .../plat_lock.h => os/mqx/lwpa/os_lock.h} | 6 +- .../plat_socket.h => os/mqx/lwpa/os_socket.h} | 18 ++-- .../plat_thread.h => os/mqx/lwpa/os_thread.h} | 6 +- .../plat_lock.h => os/windows/lwpa/os_lock.h} | 6 +- .../windows/lwpa/os_socket.h} | 18 ++-- .../windows/lwpa/os_thread.h} | 6 +- src/CMakeLists.txt | 76 ++++++++--------- .../freertos_lwip/lwpa/os_lock.c} | 0 .../freertos_lwip/lwpa/os_netint.c} | 0 .../freertos_lwip/lwpa/os_socket.c} | 50 +++++------ .../freertos_lwip/lwpa/os_thread.c} | 0 .../freertos_lwip/lwpa/os_timer.c} | 0 .../common.c => os/linux/lwpa/os_common.c} | 0 .../lwpa/lock.c => os/linux/lwpa/os_lock.c} | 0 .../netint.c => os/linux/lwpa/os_netint.c} | 0 .../socket.c => os/linux/lwpa/os_socket.c} | 82 +++++++++---------- .../thread.c => os/linux/lwpa/os_thread.c} | 0 .../lwpa/timer.c => os/linux/lwpa/os_timer.c} | 8 +- .../plat_uuid.c => os/linux/lwpa/os_uuid.c} | 20 ++--- .../lwpa/common.c => os/mqx/lwpa/os_common.c} | 0 .../mqx/lwpa/lock.c => os/mqx/lwpa/os_lock.c} | 0 .../lwpa/netint.c => os/mqx/lwpa/os_netint.c} | 0 .../lwpa/socket.c => os/mqx/lwpa/os_socket.c} | 68 +++++++-------- .../lwpa/thread.c => os/mqx/lwpa/os_thread.c} | 0 .../lwpa/timer.c => os/mqx/lwpa/os_timer.c} | 0 .../plat_uuid.c => os/mqx/lwpa/os_uuid.c} | 0 .../common.c => os/windows/lwpa/os_common.c} | 4 +- .../lwpa/lock.c => os/windows/lwpa/os_lock.c} | 0 .../netint.c => os/windows/lwpa/os_netint.c} | 0 .../socket.c => os/windows/lwpa/os_socket.c} | 76 ++++++++--------- .../thread.c => os/windows/lwpa/os_thread.c} | 0 .../timer.c => os/windows/lwpa/os_timer.c} | 0 .../plat_uuid.c => os/windows/lwpa/os_uuid.c} | 26 +++--- tests/CMakeLists.txt | 2 +- 44 files changed, 265 insertions(+), 268 deletions(-) rename include/{lwpa_plat/freertos/lwpa/plat_lock.h => os/freertos/lwpa/os_lock.h} (95%) rename include/{lwpa_plat/freertos/lwpa/plat_thread.h => os/freertos/lwpa/os_thread.h} (95%) rename include/{lwpa_plat/linux/lwpa/plat_lock.h => os/linux/lwpa/os_lock.h} (95%) rename include/{lwpa_plat/linux/lwpa/plat_socket.h => os/linux/lwpa/os_socket.h} (63%) rename include/{lwpa_plat/linux/lwpa/plat_thread.h => os/linux/lwpa/os_thread.h} (93%) rename include/{lwpa_plat/mqx/lwpa/plat_lock.h => os/mqx/lwpa/os_lock.h} (96%) rename include/{lwpa_plat/mqx/lwpa/plat_socket.h => os/mqx/lwpa/os_socket.h} (65%) rename include/{lwpa_plat/mqx/lwpa/plat_thread.h => os/mqx/lwpa/os_thread.h} (95%) rename include/{lwpa_plat/windows/lwpa/plat_lock.h => os/windows/lwpa/os_lock.h} (98%) rename include/{lwpa_plat/windows/lwpa/plat_socket.h => os/windows/lwpa/os_socket.h} (74%) rename include/{lwpa_plat/windows/lwpa/plat_thread.h => os/windows/lwpa/os_thread.h} (95%) rename src/{lwpa_plat/freertos_lwip/lwpa/lock.c => os/freertos_lwip/lwpa/os_lock.c} (100%) rename src/{lwpa_plat/freertos_lwip/lwpa/netint.c => os/freertos_lwip/lwpa/os_netint.c} (100%) rename src/{lwpa_plat/freertos_lwip/lwpa/socket.c => os/freertos_lwip/lwpa/os_socket.c} (92%) rename src/{lwpa_plat/freertos_lwip/lwpa/thread.c => os/freertos_lwip/lwpa/os_thread.c} (100%) rename src/{lwpa_plat/freertos_lwip/lwpa/timer.c => os/freertos_lwip/lwpa/os_timer.c} (100%) rename src/{lwpa_plat/linux/lwpa/common.c => os/linux/lwpa/os_common.c} (100%) rename src/{lwpa_plat/linux/lwpa/lock.c => os/linux/lwpa/os_lock.c} (100%) rename src/{lwpa_plat/linux/lwpa/netint.c => os/linux/lwpa/os_netint.c} (100%) rename src/{lwpa_plat/linux/lwpa/socket.c => os/linux/lwpa/os_socket.c} (89%) rename src/{lwpa_plat/linux/lwpa/thread.c => os/linux/lwpa/os_thread.c} (100%) rename src/{lwpa_plat/linux/lwpa/timer.c => os/linux/lwpa/os_timer.c} (85%) rename src/{lwpa_plat/linux/lwpa/plat_uuid.c => os/linux/lwpa/os_uuid.c} (82%) rename src/{lwpa_plat/mqx/lwpa/common.c => os/mqx/lwpa/os_common.c} (100%) rename src/{lwpa_plat/mqx/lwpa/lock.c => os/mqx/lwpa/os_lock.c} (100%) rename src/{lwpa_plat/mqx/lwpa/netint.c => os/mqx/lwpa/os_netint.c} (100%) rename src/{lwpa_plat/mqx/lwpa/socket.c => os/mqx/lwpa/os_socket.c} (91%) rename src/{lwpa_plat/mqx/lwpa/thread.c => os/mqx/lwpa/os_thread.c} (100%) rename src/{lwpa_plat/mqx/lwpa/timer.c => os/mqx/lwpa/os_timer.c} (100%) rename src/{lwpa_plat/mqx/lwpa/plat_uuid.c => os/mqx/lwpa/os_uuid.c} (100%) rename src/{lwpa_plat/windows/lwpa/common.c => os/windows/lwpa/os_common.c} (95%) rename src/{lwpa_plat/windows/lwpa/lock.c => os/windows/lwpa/os_lock.c} (100%) rename src/{lwpa_plat/windows/lwpa/netint.c => os/windows/lwpa/os_netint.c} (100%) rename src/{lwpa_plat/windows/lwpa/socket.c => os/windows/lwpa/os_socket.c} (92%) rename src/{lwpa_plat/windows/lwpa/thread.c => os/windows/lwpa/os_thread.c} (100%) rename src/{lwpa_plat/windows/lwpa/timer.c => os/windows/lwpa/os_timer.c} (100%) rename src/{lwpa_plat/windows/lwpa/plat_uuid.c => os/windows/lwpa/os_uuid.c} (74%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18cc755fa..478d92023 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,9 @@ if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) endif() list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/tools/cmake) + set(OPTION_DEFAULTS ON) +else() + set(OPTION_DEFAULTS OFF) endif() option(LWPA_BUILD_MOCK_LIB "Build the lwpa_mock library" OFF) @@ -28,12 +31,6 @@ endif() add_subdirectory(src) -if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - set(OPTION_DEFAULTS ON) -else() - set(OPTION_DEFAULTS OFF) -endif() - # Tests option(LWPA_BUILD_TESTS "Build the lwpa unit tests" ${OPTION_DEFAULTS}) diff --git a/include/lwpa/lock.h b/include/lwpa/lock.h index b44c29f9a..19876148c 100644 --- a/include/lwpa/lock.h +++ b/include/lwpa/lock.h @@ -20,7 +20,7 @@ #ifndef _LWPA_LOCK_H_ #define _LWPA_LOCK_H_ -#include "lwpa/plat_lock.h" +#include "lwpa/os_lock.h" #if defined(__cplusplus) || defined(DOXYGEN) // C++ extras defined if including lwpa in a C++ application. diff --git a/include/lwpa/socket.h b/include/lwpa/socket.h index ea9a4ab9a..73b42cdb7 100644 --- a/include/lwpa/socket.h +++ b/include/lwpa/socket.h @@ -44,7 +44,7 @@ /*! Event flags for the lwpa_poll_*() API functions. */ typedef uint32_t lwpa_poll_events_t; -#include "lwpa/plat_socket.h" /* The platform-specific socket definitions */ +#include "lwpa/os_socket.h" /* The os-specific socket definitions */ /* clang-format off */ diff --git a/include/lwpa/thread.h b/include/lwpa/thread.h index 28d0d5e4c..255f3cef5 100644 --- a/include/lwpa/thread.h +++ b/include/lwpa/thread.h @@ -28,6 +28,6 @@ typedef struct LwpaThreadParams void* platform_data; } LwpaThreadParams; -#include "lwpa/plat_thread.h" +#include "lwpa/os_thread.h" #endif /* _LWPA_THREAD_H_ */ diff --git a/include/lwpa_mock/socket.h b/include/lwpa_mock/socket.h index 54c4d3ea0..8e5984723 100644 --- a/include/lwpa_mock/socket.h +++ b/include/lwpa_mock/socket.h @@ -27,8 +27,8 @@ // We don't mock: // lwpa_inet_pton() // lwpa_inet_ntop() -// sockaddr_plat_to_lwpa() -// sockaddr_lwpa_to_plat() +// sockaddr_os_to_lwpa() +// sockaddr_lwpa_to_os() #ifdef __cplusplus extern "C" { diff --git a/include/lwpa_plat/freertos/lwpa/plat_lock.h b/include/os/freertos/lwpa/os_lock.h similarity index 95% rename from include/lwpa_plat/freertos/lwpa/plat_lock.h rename to include/os/freertos/lwpa/os_lock.h index a5fc5f47a..eea128200 100644 --- a/include/lwpa_plat/freertos/lwpa/plat_lock.h +++ b/include/os/freertos/lwpa/os_lock.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_LOCK_H_ -#define _LWPA_PLAT_LOCK_H_ +#ifndef _LWPA_OS_LOCK_H_ +#define _LWPA_OS_LOCK_H_ #include "FreeRTOS.h" #include "semphr.h" @@ -60,4 +60,4 @@ void lwpa_rwlock_destroy(lwpa_rwlock_t* id); } #endif -#endif /* _LWPA_PLAT_LOCK_H_ */ +#endif /* _LWPA_OS_LOCK_H_ */ diff --git a/include/lwpa_plat/freertos/lwpa/plat_thread.h b/include/os/freertos/lwpa/os_thread.h similarity index 95% rename from include/lwpa_plat/freertos/lwpa/plat_thread.h rename to include/os/freertos/lwpa/os_thread.h index e407a14a3..8143cb56a 100644 --- a/include/lwpa_plat/freertos/lwpa/plat_thread.h +++ b/include/os/freertos/lwpa/os_thread.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_THREAD_H_ -#define _LWPA_PLAT_THREAD_H_ +#ifndef _LWPA_OS_THREAD_H_ +#define _LWPA_OS_THREAD_H_ #include "FreeRTOS.h" #include "task.h" @@ -58,4 +58,4 @@ bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); } #endif -#endif /* LWPA_PLAT_THREAD_H_ */ +#endif /* _LWPA_OS_THREAD_H_ */ diff --git a/include/lwpa_plat/linux/lwpa/plat_lock.h b/include/os/linux/lwpa/os_lock.h similarity index 95% rename from include/lwpa_plat/linux/lwpa/plat_lock.h rename to include/os/linux/lwpa/os_lock.h index 079443d98..aca4a8f6b 100644 --- a/include/lwpa_plat/linux/lwpa/plat_lock.h +++ b/include/os/linux/lwpa/os_lock.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_LOCK_H_ -#define _LWPA_PLAT_LOCK_H_ +#ifndef _LWPA_OS_LOCK_H_ +#define _LWPA_OS_LOCK_H_ #include #include "lwpa/bool.h" @@ -49,4 +49,4 @@ typedef pthread_rwlock_t lwpa_rwlock_t; #define lwpa_rwlock_writeunlock(idptr) #define lwpa_rwlock_destroy(idptr) -#endif /* _LWPA_PLAT_LOCK_H_ */ \ No newline at end of file +#endif /* _LWPA_OS_LOCK_H_ */ \ No newline at end of file diff --git a/include/lwpa_plat/linux/lwpa/plat_socket.h b/include/os/linux/lwpa/os_socket.h similarity index 63% rename from include/lwpa_plat/linux/lwpa/plat_socket.h rename to include/os/linux/lwpa/os_socket.h index af8abd85a..ca03a71b0 100644 --- a/include/lwpa_plat/linux/lwpa/plat_socket.h +++ b/include/os/linux/lwpa/os_socket.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_SOCKET_H_ -#define _LWPA_PLAT_SOCKET_H_ +#ifndef _LWPA_OS_SOCKET_H_ +#define _LWPA_OS_SOCKET_H_ #include #include @@ -30,20 +30,20 @@ typedef int lwpa_socket_t; #define LWPA_SOCKET_MAX_POLL_SIZE FD_SETSIZE -#define ip_plat_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), ntohl((pfipptr)->s_addr)) -#define ip_lwpa_to_plat_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(lwpaip_v4_address(lwpaipptr))) -#define ip_plat_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) -#define ip_lwpa_to_plat_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) +#define ip_os_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), ntohl((pfipptr)->s_addr)) +#define ip_lwpa_to_os_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(lwpaip_v4_address(lwpaipptr))) +#define ip_os_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) +#define ip_lwpa_to_os_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) #ifdef __cplusplus extern "C" { #endif -bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); -size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa); +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); #ifdef __cplusplus } #endif -#endif /* _LWPA_PLAT_SOCKET_H_ */ +#endif /* _LWPA_OS_SOCKET_H_ */ diff --git a/include/lwpa_plat/linux/lwpa/plat_thread.h b/include/os/linux/lwpa/os_thread.h similarity index 93% rename from include/lwpa_plat/linux/lwpa/plat_thread.h rename to include/os/linux/lwpa/os_thread.h index 612c61da1..628a13133 100644 --- a/include/lwpa_plat/linux/lwpa/plat_thread.h +++ b/include/os/linux/lwpa/os_thread.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_THREAD_H_ -#define _LWPA_PLAT_THREAD_H_ +#ifndef _LWPA_OS_THREAD_H_ +#define _LWPA_OS_THREAD_H_ #include @@ -35,4 +35,4 @@ typedef pthread_t lwpa_thread_t; #define lwpa_thread_stop(idptr, wait_ms) false #define lwpa_thread_sleep(sleep_ms) -#endif /* _LWPA_PLAT_THREAD_H_ */ \ No newline at end of file +#endif /* _LWPA_OS_THREAD_H_ */ \ No newline at end of file diff --git a/include/lwpa_plat/mqx/lwpa/plat_lock.h b/include/os/mqx/lwpa/os_lock.h similarity index 96% rename from include/lwpa_plat/mqx/lwpa/plat_lock.h rename to include/os/mqx/lwpa/os_lock.h index 3a51a5e16..a3626343e 100644 --- a/include/lwpa_plat/mqx/lwpa/plat_lock.h +++ b/include/os/mqx/lwpa/os_lock.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_LOCK_H_ -#define _LWPA_PLAT_LOCK_H_ +#ifndef _LWPA_OS_LOCK_H_ +#define _LWPA_OS_LOCK_H_ #include #include @@ -60,4 +60,4 @@ void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); } #endif -#endif /* _LWPA_PLAT_LOCK_H_ */ +#endif /* _LWPA_OS_LOCK_H_ */ diff --git a/include/lwpa_plat/mqx/lwpa/plat_socket.h b/include/os/mqx/lwpa/os_socket.h similarity index 65% rename from include/lwpa_plat/mqx/lwpa/plat_socket.h rename to include/os/mqx/lwpa/os_socket.h index bde7ea873..f0f74a339 100644 --- a/include/lwpa_plat/mqx/lwpa/plat_socket.h +++ b/include/os/mqx/lwpa/os_socket.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_SOCKET_H_ -#define _LWPA_PLAT_SOCKET_H_ +#ifndef _LWPA_OS_SOCKET_H_ +#define _LWPA_OS_SOCKET_H_ #include #include "lwpa/inet.h" @@ -34,16 +34,16 @@ typedef uint32_t lwpa_socket_t; extern "C" { #endif -#define ip_plat_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), (pfipptr)->s_addr) -#define ip_lwpa_to_plat_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = lwpaip_v4_address(lwpaipptr)) -#define ip_plat_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) -#define ip_lwpa_to_plat_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) +#define ip_os_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), (pfipptr)->s_addr) +#define ip_lwpa_to_os_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = lwpaip_v4_address(lwpaipptr)) +#define ip_os_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) +#define ip_lwpa_to_os_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) -bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); -size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa); +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); #ifdef __cplusplus } #endif -#endif /* _LWPA_PLAT_SOCKET_H_ */ +#endif /* _LWPA_OS_SOCKET_H_ */ diff --git a/include/lwpa_plat/mqx/lwpa/plat_thread.h b/include/os/mqx/lwpa/os_thread.h similarity index 95% rename from include/lwpa_plat/mqx/lwpa/plat_thread.h rename to include/os/mqx/lwpa/os_thread.h index e9bd670c0..535c28c40 100644 --- a/include/lwpa_plat/mqx/lwpa/plat_thread.h +++ b/include/os/mqx/lwpa/os_thread.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_THREAD_H_ -#define _LWPA_PLAT_THREAD_H_ +#ifndef _LWPA_OS_THREAD_H_ +#define _LWPA_OS_THREAD_H_ #include #include "lwpa/common.h" @@ -64,4 +64,4 @@ bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); } #endif -#endif /* LWPA_PLAT_THREAD_H_ */ +#endif /* _LWPA_OS_THREAD_H_ */ diff --git a/include/lwpa_plat/windows/lwpa/plat_lock.h b/include/os/windows/lwpa/os_lock.h similarity index 98% rename from include/lwpa_plat/windows/lwpa/plat_lock.h rename to include/os/windows/lwpa/os_lock.h index 8de00d994..31cf42d24 100644 --- a/include/lwpa_plat/windows/lwpa/plat_lock.h +++ b/include/os/windows/lwpa/os_lock.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_LOCK_H_ -#define _LWPA_PLAT_LOCK_H_ +#ifndef _LWPA_OS_LOCK_H_ +#define _LWPA_OS_LOCK_H_ #ifndef NOMINMAX #define NOMINMAX 1 /* Suppress some conflicting definitions in the Windows headers */ @@ -120,4 +120,4 @@ bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms); } #endif -#endif /* _LWPA_PLAT_LOCK_H_ */ +#endif /* _LWPA_OS_LOCK_H_ */ diff --git a/include/lwpa_plat/windows/lwpa/plat_socket.h b/include/os/windows/lwpa/os_socket.h similarity index 74% rename from include/lwpa_plat/windows/lwpa/plat_socket.h rename to include/os/windows/lwpa/os_socket.h index 966c57f57..e29061926 100644 --- a/include/lwpa_plat/windows/lwpa/plat_socket.h +++ b/include/os/windows/lwpa/os_socket.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_WINDOWS_SOCKET_H_ -#define _LWPA_WINDOWS_SOCKET_H_ +#ifndef _LWPA_OS_SOCKET_H_ +#define _LWPA_OS_SOCKET_H_ #ifndef NOMINMAX #define NOMINMAX 1 /* Suppress some conflicting definitions in the Windows headers */ @@ -73,16 +73,16 @@ typedef struct LwpaPollContext extern "C" { #endif -#define ip_plat_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), ntohl((pfipptr)->s_addr)) -#define ip_lwpa_to_plat_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(lwpaip_v4_address(lwpaipptr))) -#define ip_plat_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) -#define ip_lwpa_to_plat_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) +#define ip_os_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), ntohl((pfipptr)->s_addr)) +#define ip_lwpa_to_os_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(lwpaip_v4_address(lwpaipptr))) +#define ip_os_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) +#define ip_lwpa_to_os_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) -bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); -size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa); +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); #ifdef __cplusplus } #endif -#endif /* _LWPA_WINDOWS_SOCKET_H_ */ +#endif /* _LWPA_OS_SOCKET_H_ */ diff --git a/include/lwpa_plat/windows/lwpa/plat_thread.h b/include/os/windows/lwpa/os_thread.h similarity index 95% rename from include/lwpa_plat/windows/lwpa/plat_thread.h rename to include/os/windows/lwpa/os_thread.h index cfa086b80..755d075a8 100644 --- a/include/lwpa_plat/windows/lwpa/plat_thread.h +++ b/include/os/windows/lwpa/os_thread.h @@ -17,8 +17,8 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PLAT_THREAD_H_ -#define _LWPA_PLAT_THREAD_H_ +#ifndef _LWPA_OS_THREAD_H_ +#define _LWPA_OS_THREAD_H_ #ifndef NOMINMAX #define NOMINMAX 1 /* Suppress some conflicting definitions in the Windows headers */ @@ -61,4 +61,4 @@ bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); } #endif -#endif /* LWPA_PLAT_THREAD_H_ */ +#endif /* _LWPA_OS_THREAD_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7791ece29..4e2bac9aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,36 +5,36 @@ if(DEFINED LWPA_CONFIG) set(${LWPA_HAVE_CONFIG_H} LWPA_HAVE_CONFIG_H) endif() -# The set of supported platforms -set(VALID_LWPA_PLATFORMS +# The set of supported target OS +set(VALID_LWPA_TARGETS windows linux mqx ) -if(NOT DEFINED LWPA_PLATFORM) - message(STATUS "LWPA_PLATFORM not supplied, assuming native compile by default...") +if(NOT DEFINED LWPA_TARGET_OS) + message(STATUS "LWPA_TARGET_OS not supplied, assuming native compile by default...") if(WIN32) - set(LWPA_PLATFORM windows) + set(LWPA_TARGET_OS windows) elseif(UNIX AND NOT APPLE) - set(LWPA_PLATFORM linux) + set(LWPA_TARGET_OS linux) else() - message(FATAL_ERROR "lwpa is not ported for this platform.") + message(FATAL_ERROR "lwpa is not ported for this target OS.") endif() endif() -if(NOT ${LWPA_PLATFORM} IN_LIST VALID_LWPA_PLATFORMS) - message(FATAL_ERROR "${LWPA_PLATFORM} is not a valid platform.") +if(NOT ${LWPA_TARGET_OS} IN_LIST VALID_LWPA_TARGETS) + message(FATAL_ERROR "${LWPA_TARGET_OS} is not a valid target OS.") endif() -# MQX platform support -if(LWPA_PLATFORM STREQUAL mqx) +# MQX compilation support +if(LWPA_TARGET_OS STREQUAL mqx) if(NOT DEFINED MQX_BOARD_DIR) message(FATAL_ERROR "You must provide a variable MQX_BOARD_DIR to indicate the location of your MQX libraries.") endif() endif() -set(LWPA_PLATFORM ${LWPA_PLATFORM} PARENT_SCOPE) +set(LWPA_TARGET_OS ${LWPA_TARGET_OS} PARENT_SCOPE) ############################################################################### # Core lwpa library @@ -61,9 +61,9 @@ add_library(lwpa ${LWPA_ROOT}/include/lwpa/root_layer_pdu.h ${LWPA_ROOT}/include/lwpa/socket.h ${LWPA_ROOT}/include/lwpa/timer.h - ${LWPA_ROOT}/include/lwpa_plat/${LWPA_PLATFORM}/lwpa/plat_lock.h - ${LWPA_ROOT}/include/lwpa_plat/${LWPA_PLATFORM}/lwpa/plat_thread.h - ${LWPA_ROOT}/include/lwpa_plat/${LWPA_PLATFORM}/lwpa/plat_socket.h + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_lock.h + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_thread.h + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_socket.h # lwpa sources ${LWPA_ROOT}/src/lwpa/uuid.c ${LWPA_ROOT}/src/lwpa/error.c @@ -74,29 +74,29 @@ add_library(lwpa ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/md5.h ${LWPA_ROOT}/src/lwpa/md5c.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/common.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/lock.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/netint.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/plat_uuid.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/socket.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/thread.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/timer.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_common.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_uuid.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_socket.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_thread.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_timer.c ) # lwpa public include directories and library dependencies target_include_directories(lwpa PUBLIC ${LWPA_ROOT}/include - ${LWPA_ROOT}/include/lwpa_plat/${LWPA_PLATFORM} + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS} ${LWPA_CONFIG_LOC} ) target_compile_definitions(lwpa PUBLIC ${LWPA_HAVE_CONFIG_H}) -# Add include paths and library dependencies based on platform for which we are being compiled -if(LWPA_PLATFORM STREQUAL windows) +# Add include paths and library dependencies based on OS for which we are being compiled +if(LWPA_TARGET_OS STREQUAL windows) target_link_libraries(lwpa PUBLIC winmm ws2_32 Iphlpapi Rpcrt4) -elseif(LWPA_PLATFORM STREQUAL linux) +elseif(LWPA_TARGET_OS STREQUAL linux) target_link_libraries(lwpa PUBLIC uuid) -elseif(LWPA_PLATFORM STREQUAL mqx) +elseif(LWPA_TARGET_OS STREQUAL mqx) # Include the debug versions of the MQX libs if a Debug configuration is specified. # I think there's probably a better way of doing this and I'm missing something here. if(CMAKE_BUILD_TYPE STREQUAL Debug) @@ -143,9 +143,9 @@ if(LWPA_BUILD_MOCK_LIB) ${LWPA_ROOT}/include/lwpa/root_layer_pdu.h ${LWPA_ROOT}/include/lwpa/socket.h ${LWPA_ROOT}/include/lwpa/timer.h - ${LWPA_ROOT}/include/lwpa_plat/${LWPA_PLATFORM}/lwpa/plat_lock.h - ${LWPA_ROOT}/include/lwpa_plat/${LWPA_PLATFORM}/lwpa/plat_socket.h - ${LWPA_ROOT}/include/lwpa_plat/${LWPA_PLATFORM}/lwpa/plat_thread.h + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_lock.h + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_socket.h + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_thread.h ${LWPA_ROOT}/include/lwpa_mock/socket.h @@ -160,22 +160,22 @@ if(LWPA_BUILD_MOCK_LIB) ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/md5.h ${LWPA_ROOT}/src/lwpa/md5c.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/lock.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/netint.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/plat_uuid.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/socket.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/thread.c - ${LWPA_ROOT}/src/lwpa_plat/${LWPA_PLATFORM}/lwpa/timer.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/lock.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/netint.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_uuid.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/socket.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/thread.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/timer.c ${LWPA_ROOT}/src/lwpa_mock/socket.c ) target_include_directories(lwpa_mock PUBLIC ${LWPA_ROOT}/include - ${LWPA_ROOT}/include/lwpa_plat/${LWPA_PLATFORM} + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS} ) target_compile_definitions(lwpa_mock PRIVATE LWPA_BUILDING_MOCK_LIB) target_link_libraries(lwpa_mock PUBLIC meekrosoft::fff) - if(LWPA_PLATFORM STREQUAL windows) + if(LWPA_TARGET_OS STREQUAL windows) target_link_libraries(lwpa_mock PUBLIC winmm ws2_32 Iphlpapi Rpcrt4) endif() set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) diff --git a/src/lwpa_plat/freertos_lwip/lwpa/lock.c b/src/os/freertos_lwip/lwpa/os_lock.c similarity index 100% rename from src/lwpa_plat/freertos_lwip/lwpa/lock.c rename to src/os/freertos_lwip/lwpa/os_lock.c diff --git a/src/lwpa_plat/freertos_lwip/lwpa/netint.c b/src/os/freertos_lwip/lwpa/os_netint.c similarity index 100% rename from src/lwpa_plat/freertos_lwip/lwpa/netint.c rename to src/os/freertos_lwip/lwpa/os_netint.c diff --git a/src/lwpa_plat/freertos_lwip/lwpa/socket.c b/src/os/freertos_lwip/lwpa/os_socket.c similarity index 92% rename from src/lwpa_plat/freertos_lwip/lwpa/socket.c rename to src/os/freertos_lwip/lwpa/os_socket.c index 0e3edec20..8b02961ca 100644 --- a/src/lwpa_plat/freertos_lwip/lwpa/socket.c +++ b/src/os/freertos_lwip/lwpa/os_socket.c @@ -85,7 +85,7 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /* clang-format on */ -static bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) +static bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) { @@ -112,7 +112,7 @@ static bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) return false; } -static socklen_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) +static socklen_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) { socklen_t ret = 0; if (lwpaip_is_v4(&sa->ip)) @@ -138,16 +138,16 @@ static socklen_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr return ret; } -lwpa_error_t lwpa_socket_init(void* platform_data) +lwpa_error_t lwpa_socket_init(void* os_data) { - /* No initialization is necessary on this platform. */ - (void)platform_data; + /* No initialization is necessary on this os. */ + (void)os_data; return kLwpaErrOk; } void lwpa_socket_deinit() { - /* No deinitialization is necessary on this platform. */ + /* No deinitialization is necessary on this os. */ } int lwpa_accept(void* id, LwpaSockaddr* address) @@ -162,7 +162,7 @@ int lwpa_bind(void* id, const LwpaSockaddr* address) if (address) { struct sockaddr_storage ss; - socklen_t sa_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, address); + socklen_t sa_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); if (sa_size > 0) res = bind((int)id, (struct sockaddr*)&ss, sa_size); } @@ -195,7 +195,7 @@ int lwpa_getsockname(void* id, LwpaSockaddr* address) socklen_t size = sizeof ss; if (0 == getsockname((int)id, (struct sockaddr*)&ss, &size)) { - if (sockaddr_plat_to_lwpa(address, (struct sockaddr*)&ss)) + if (sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) res = 0; } } @@ -236,7 +236,7 @@ int lwpa_recvfrom(void* id, void* buffer, size_t length, int flags, LwpaSockaddr { if (address && fromlen > 0) { - if (!sockaddr_plat_to_lwpa(address, (struct sockaddr*)&fromaddr)) + if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) res = -1; } } @@ -259,7 +259,7 @@ int lwpa_sendto(void* id, const void* message, size_t length, int flags, const L if (!dest_addr || !message) return res; - if ((ss_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, dest_addr)) > 0) + if ((ss_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr)) > 0) res = sendto((int)id, message, length, 0, (struct sockaddr*)&ss, ss_size); return res; } @@ -271,7 +271,7 @@ int lwpa_setsockopt(void* id, int level, int option_name, const void* option_val if (!option_value) return res; - /* TODO this platform implementation could be simplified by use of socket + /* TODO this os implementation could be simplified by use of socket * option lookup arrays. */ switch (level) { @@ -449,7 +449,7 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* else { *id = LWPA_SOCKET_INVALID; - return err_plat_to_lwpa(errno); + return err_os_to_lwpa(errno); } } else @@ -465,10 +465,10 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) fd_set readfds; fd_set writefds; LwpaPollfd* fd; - int nplatfds; + int nosfds; int sel_res; int nreadfds = 0, nwritefds = 0; - struct timeval plat_timeout; + struct timeval os_timeout; if (fds && nfds > 0) { @@ -487,23 +487,23 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) FD_SET((int)fd->fd, &writefds); nwritefds++; } - /* LWPA_POLLPRI/exceptfds is not handled properly on this platform */ + /* LWPA_POLLPRI/exceptfds is not handled properly on this os */ } } if (timeout_ms == 0) { - plat_timeout.tv_sec = 0; - plat_timeout.tv_usec = 0; + os_timeout.tv_sec = 0; + os_timeout.tv_usec = 0; } else if (timeout_ms != LWPA_WAIT_FOREVER) { - plat_timeout.tv_sec = timeout_ms / 1000; - plat_timeout.tv_usec = (timeout_ms % 1000) * 1000; + os_timeout.tv_sec = timeout_ms / 1000; + os_timeout.tv_usec = (timeout_ms % 1000) * 1000; } - nplatfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; - sel_res = select(nplatfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, NULL, - timeout_ms == LWPA_WAIT_FOREVER ? NULL : &plat_timeout); + nosfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; + sel_res = select(nosfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, NULL, + timeout_ms == LWPA_WAIT_FOREVER ? NULL : &os_timeout); if (sel_res < 0) return -1; @@ -521,7 +521,7 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) fd->revents |= LWPA_POLLOUT; } /* LWPA_POLLPRI/exceptfds is not handled properly on this - * platform */ + * os */ } } return sel_res; @@ -562,10 +562,10 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) { struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; - if (!sockaddr_plat_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) return false; /* Can't use reverse maps, because we have no guarantee of the numeric - * values of the platform constants. Ugh. */ + * values of the os constants. Ugh. */ if (pf_ai->ai_family == AF_INET) ai->ai_family = LWPA_AF_INET; else if (pf_ai->ai_family == AF_INET6) diff --git a/src/lwpa_plat/freertos_lwip/lwpa/thread.c b/src/os/freertos_lwip/lwpa/os_thread.c similarity index 100% rename from src/lwpa_plat/freertos_lwip/lwpa/thread.c rename to src/os/freertos_lwip/lwpa/os_thread.c diff --git a/src/lwpa_plat/freertos_lwip/lwpa/timer.c b/src/os/freertos_lwip/lwpa/os_timer.c similarity index 100% rename from src/lwpa_plat/freertos_lwip/lwpa/timer.c rename to src/os/freertos_lwip/lwpa/os_timer.c diff --git a/src/lwpa_plat/linux/lwpa/common.c b/src/os/linux/lwpa/os_common.c similarity index 100% rename from src/lwpa_plat/linux/lwpa/common.c rename to src/os/linux/lwpa/os_common.c diff --git a/src/lwpa_plat/linux/lwpa/lock.c b/src/os/linux/lwpa/os_lock.c similarity index 100% rename from src/lwpa_plat/linux/lwpa/lock.c rename to src/os/linux/lwpa/os_lock.c diff --git a/src/lwpa_plat/linux/lwpa/netint.c b/src/os/linux/lwpa/os_netint.c similarity index 100% rename from src/lwpa_plat/linux/lwpa/netint.c rename to src/os/linux/lwpa/os_netint.c diff --git a/src/lwpa_plat/linux/lwpa/socket.c b/src/os/linux/lwpa/os_socket.c similarity index 89% rename from src/lwpa_plat/linux/lwpa/socket.c rename to src/os/linux/lwpa/os_socket.c index b77fe7ac7..b1e2ad003 100644 --- a/src/lwpa_plat/linux/lwpa/socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -22,7 +22,7 @@ #include #include -bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) { @@ -41,7 +41,7 @@ bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) return false; } -size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; if (lwpaip_is_v4(&sa->ip)) @@ -64,7 +64,7 @@ size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) } /* -static lwpa_error_t err_plat_to_lwpa(int wsaerror) +static lwpa_error_t err_os_to_lwpa(int wsaerror) { switch (wsaerror) { @@ -140,7 +140,7 @@ static lwpa_error_t err_plat_to_lwpa(int wsaerror) } */ -lwpa_error_t lwpa_socket_init(void* platform_data) +lwpa_error_t lwpa_socket_init(void* os_data) { return kLwpaErrNotImpl; } @@ -163,7 +163,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* if (res != INVALID_SOCKET) { - if (address && !sockaddr_plat_to_lwpa(address, (struct sockaddr *)&ss)) + if (address && !sockaddr_os_to_lwpa(address, (struct sockaddr *)&ss)) { closesocket(res); return kLwpaErrSys; @@ -171,7 +171,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* *conn_sock = res; return kLwpaErrOk; } - return err_plat_to_lwpa(WSAGetLastError()); + return err_os_to_lwpa(WSAGetLastError()); */ return kLwpaErrNotImpl; } @@ -186,12 +186,12 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_plat((struct sockaddr *)&ss, address); + sa_size = sockaddr_lwpa_to_os((struct sockaddr *)&ss, address); if (sa_size == 0) return kLwpaErrInvalid; res = bind(id, (struct sockaddr *)&ss, (int)sa_size); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); */ return kLwpaErrNotImpl; } @@ -200,7 +200,7 @@ lwpa_error_t lwpa_close(lwpa_socket_t id) { /* int res = closesocket(id); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); */ return kLwpaErrNotImpl; } @@ -215,12 +215,12 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_plat((struct sockaddr *)&ss, address); + sa_size = sockaddr_lwpa_to_os((struct sockaddr *)&ss, address); if (sa_size == 0) return kLwpaErrInvalid; res = connect(id, (struct sockaddr *)&ss, (int)sa_size); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); */ return kLwpaErrNotImpl; } @@ -246,11 +246,11 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) res = getsockname(id, (struct sockaddr *)&ss, &size); if (res == 0) { - if (!sockaddr_plat_to_lwpa(address, (struct sockaddr *)&ss)) + if (!sockaddr_os_to_lwpa(address, (struct sockaddr *)&ss)) return kLwpaErrSys; return kLwpaErrOk; } - return err_plat_to_lwpa(WSAGetLastError()); + return err_os_to_lwpa(WSAGetLastError()); */ return kLwpaErrNotImpl; } @@ -270,7 +270,7 @@ lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) { /* int res = listen(id, backlog); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); */ return kLwpaErrNotImpl; } @@ -285,7 +285,7 @@ int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) return kLwpaErrInvalid; res = recv(id, buffer, (int)length, impl_flags); - return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); */ return kLwpaErrNotImpl; } @@ -307,12 +307,12 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa { if (address && fromlen > 0) { - if (!sockaddr_plat_to_lwpa(address, (struct sockaddr *)&fromaddr)) + if (!sockaddr_os_to_lwpa(address, (struct sockaddr *)&fromaddr)) return kLwpaErrSys; } return res; } - return (int)err_plat_to_lwpa(WSAGetLastError()); + return (int)err_os_to_lwpa(WSAGetLastError()); */ return kLwpaErrNotImpl; } @@ -327,7 +327,7 @@ int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) return kLwpaErrInvalid; res = send(id, message, (int)length, 0); - return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); */ return kLwpaErrNotImpl; } @@ -343,10 +343,10 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, if (!dest_addr || !message) return (int)kLwpaErrInvalid; - if ((ss_size = sockaddr_lwpa_to_plat((struct sockaddr *)&ss, dest_addr)) > 0) + if ((ss_size = sockaddr_lwpa_to_os((struct sockaddr *)&ss, dest_addr)) > 0) res = sendto(id, message, (int)length, 0, (struct sockaddr *)&ss, (int)ss_size); - return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); */ return kLwpaErrNotImpl; } @@ -358,7 +358,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const // if (!option_value) // return kLwpaErrInvalid; // - // /* TODO this platform implementation could be simplified by use of socket option lookup arrays. */ + // /* TODO this OS implementation could be simplified by use of socket option lookup arrays. */ // switch (level) // { // case LWPA_SOL_SOCKET: @@ -527,11 +527,11 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const // return kLwpaErrInvalid; // } // break; - // case LWPA_SO_REUSEPORT: /* Not supported on this platform. */ + // case LWPA_SO_REUSEPORT: /* Not supported on this OS. */ // default: // return kLwpaErrInvalid; // } - // return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + // return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); return kLwpaErrNotImpl; } @@ -541,7 +541,7 @@ lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) if (how >= 0 && how < LWPA_NUM_SHUT) { int res = shutdown(id, shutmap[how]); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); } return kLwpaErrInvalid; */ @@ -562,7 +562,7 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) /* unsigned long val = (blocking ? 0 : 1); int res = ioctlsocket(id, FIONBIO, &val); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); */ return kLwpaErrNotImpl; } @@ -572,10 +572,10 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) { // fd_set readfds, writefds, exceptfds; // LwpaPollfd *fd; - // int nplatfds; + // int nosfds; // int sel_res; // int nreadfds = 0, nwritefds = 0, nexceptfds = 0; - // struct timeval plat_timeout; + // struct timeval os_timeout; // // if (fds && nfds > 0) // { @@ -605,23 +605,23 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) // // if (timeout_ms == 0) // { - // plat_timeout.tv_sec = 0; - // plat_timeout.tv_usec = 0; + // os_timeout.tv_sec = 0; + // os_timeout.tv_usec = 0; // } // else if (timeout_ms != LWPA_WAIT_FOREVER) // { - // plat_timeout.tv_sec = timeout_ms / 1000; - // plat_timeout.tv_usec = (timeout_ms % 1000) * 1000; + // os_timeout.tv_sec = timeout_ms / 1000; + // os_timeout.tv_usec = (timeout_ms % 1000) * 1000; // } - // nplatfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; - // nplatfds = (nexceptfds > nplatfds) ? nexceptfds : nplatfds; - // sel_res = select(nplatfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, nexceptfds ? &exceptfds : + // nosfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; + // nosfds = (nexceptfds > nosfds) ? nexceptfds : nosfds; + // sel_res = select(nosfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, nexceptfds ? &exceptfds : // NULL, - // timeout_ms == LWPA_WAIT_FOREVER ? NULL : &plat_timeout); + // timeout_ms == LWPA_WAIT_FOREVER ? NULL : &os_timeout); // // if (sel_res < 0) // { - // return err_plat_to_lwpa(WSAGetLastError()); + // return err_os_to_lwpa(WSAGetLastError()); // } // else if (sel_res == 0) // { @@ -643,11 +643,11 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) // if (error != 0) // { // fd->revents |= LWPA_POLLERR; - // fd->err = err_plat_to_lwpa(error); + // fd->err = err_os_to_lwpa(error); // } // } // else - // return (int)err_plat_to_lwpa(WSAGetLastError()); + // return (int)err_os_to_lwpa(WSAGetLastError()); // } // if (nreadfds && (fd->events & LWPA_POLLIN) && FD_ISSET(fd->fd, &readfds)) // { @@ -695,7 +695,7 @@ lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const L if (!lwpa_nextaddr(result)) res = -1; } - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(res)); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(res)); */ return kLwpaErrNotImpl; } @@ -706,9 +706,9 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) // { // struct addrinfo *pf_ai = (struct addrinfo *)ai->pd[1]; // ai->ai_flags = 0; - // if (!sockaddr_plat_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + // if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) // return false; - // /* Can't use reverse maps, because we have no guarantee of the numeric values of the platform + // /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS // * constants. Ugh. */ // if (pf_ai->ai_family == AF_INET) // ai->ai_family = LWPA_AF_INET; diff --git a/src/lwpa_plat/linux/lwpa/thread.c b/src/os/linux/lwpa/os_thread.c similarity index 100% rename from src/lwpa_plat/linux/lwpa/thread.c rename to src/os/linux/lwpa/os_thread.c diff --git a/src/lwpa_plat/linux/lwpa/timer.c b/src/os/linux/lwpa/os_timer.c similarity index 85% rename from src/lwpa_plat/linux/lwpa/timer.c rename to src/os/linux/lwpa/os_timer.c index 696ac13aa..813c97007 100644 --- a/src/lwpa_plat/linux/lwpa/timer.c +++ b/src/os/linux/lwpa/os_timer.c @@ -23,10 +23,10 @@ uint32_t lwpa_getms() { - struct timespec plat_time; - if (0 == clock_gettime(CLOCK_MONOTONIC, &plat_time)) + struct timespec os_time; + if (0 == clock_gettime(CLOCK_MONOTONIC, &os_time)) { - return (uint32_t)(plat_time.tv_sec * 1000 + (plat_time.tv_nsec / 1000000)); + return (uint32_t)(os_time.tv_sec * 1000 + (os_time.tv_nsec / 1000000)); } return 0; -} \ No newline at end of file +} diff --git a/src/lwpa_plat/linux/lwpa/plat_uuid.c b/src/os/linux/lwpa/os_uuid.c similarity index 82% rename from src/lwpa_plat/linux/lwpa/plat_uuid.c rename to src/os/linux/lwpa/os_uuid.c index 5a39fa00d..5ccdad271 100644 --- a/src/lwpa_plat/linux/lwpa/plat_uuid.c +++ b/src/os/linux/lwpa/os_uuid.c @@ -29,9 +29,9 @@ lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) if (!uuid) return kLwpaErrInvalid; - uuid_t plat_uuid; - uuid_generate_time(plat_uuid); - memcpy(uuid->data, plat_uuid, LWPA_UUID_BYTES); + uuid_t os_uuid; + uuid_generate_time(os_uuid); + memcpy(uuid->data, os_uuid, LWPA_UUID_BYTES); return kLwpaErrOk; } @@ -40,9 +40,9 @@ lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid) if (!uuid) return kLwpaErrInvalid; - uuid_t plat_uuid; - uuid_generate_random(plat_uuid); - memcpy(uuid->data, plat_uuid, LWPA_UUID_BYTES); + uuid_t os_uuid; + uuid_generate_random(os_uuid); + memcpy(uuid->data, os_uuid, LWPA_UUID_BYTES); return kLwpaErrOk; } @@ -51,8 +51,8 @@ lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid* uuid) if (!uuid) return kLwpaErrInvalid; - uuid_t plat_uuid; - uuid_generate(plat_uuid); - memcpy(uuid->data, plat_uuid, LWPA_UUID_BYTES); + uuid_t os_uuid; + uuid_generate(os_uuid); + memcpy(uuid->data, os_uuid, LWPA_UUID_BYTES); return kLwpaErrOk; -} \ No newline at end of file +} diff --git a/src/lwpa_plat/mqx/lwpa/common.c b/src/os/mqx/lwpa/os_common.c similarity index 100% rename from src/lwpa_plat/mqx/lwpa/common.c rename to src/os/mqx/lwpa/os_common.c diff --git a/src/lwpa_plat/mqx/lwpa/lock.c b/src/os/mqx/lwpa/os_lock.c similarity index 100% rename from src/lwpa_plat/mqx/lwpa/lock.c rename to src/os/mqx/lwpa/os_lock.c diff --git a/src/lwpa_plat/mqx/lwpa/netint.c b/src/os/mqx/lwpa/os_netint.c similarity index 100% rename from src/lwpa_plat/mqx/lwpa/netint.c rename to src/os/mqx/lwpa/os_netint.c diff --git a/src/lwpa_plat/mqx/lwpa/socket.c b/src/os/mqx/lwpa/os_socket.c similarity index 91% rename from src/lwpa_plat/mqx/lwpa/socket.c rename to src/os/mqx/lwpa/os_socket.c index c0f46f323..767d7cac7 100644 --- a/src/lwpa_plat/mqx/lwpa/socket.c +++ b/src/os/mqx/lwpa/os_socket.c @@ -82,7 +82,7 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /* clang-format on */ -bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) { @@ -101,7 +101,7 @@ bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) return false; } -size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; if (lwpaip_is_v4(&sa->ip)) @@ -123,7 +123,7 @@ size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) return ret; } -static lwpa_error_t err_plat_to_lwpa(uint32_t rtcserr) +static lwpa_error_t err_os_to_lwpa(uint32_t rtcserr) { switch (rtcserr) { @@ -170,16 +170,16 @@ static lwpa_error_t err_plat_to_lwpa(uint32_t rtcserr) } } -lwpa_error_t lwpa_socket_init(void* platform_data) +lwpa_error_t lwpa_socket_init(void* os_data) { - /* No initialization is necessary on this platform. */ - (void)platform_data; + /* No initialization is necessary on this os. */ + (void)os_data; return kLwpaErrOk; } void lwpa_socket_deinit() { - /* No deinitialization is necessary on this platform. */ + /* No deinitialization is necessary on this os. */ } lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) @@ -196,16 +196,16 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_plat(&ss, address); + sa_size = sockaddr_lwpa_to_os(&ss, address); if (sa_size == 0) return kLwpaErrInvalid; - return err_plat_to_lwpa(bind(id, &ss, sa_size)); + return err_os_to_lwpa(bind(id, &ss, sa_size)); } lwpa_error_t lwpa_close(lwpa_socket_t id) { - return err_plat_to_lwpa(closesocket(id)); + return err_os_to_lwpa(closesocket(id)); } lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) @@ -232,10 +232,10 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) res = getsockname(id, &ss, &size); if (res == RTCS_OK) { - if (!sockaddr_plat_to_lwpa(address, &ss)) + if (!sockaddr_os_to_lwpa(address, &ss)) return kLwpaErrSys; } - return err_plat_to_lwpa(res); + return err_os_to_lwpa(res); } lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) @@ -272,11 +272,11 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa { if (address && fromlen > 0) { - if (!sockaddr_plat_to_lwpa(address, &fromaddr)) + if (!sockaddr_os_to_lwpa(address, &fromaddr)) return kLwpaErrInvalid; } } - return (res == RTCS_ERROR ? err_plat_to_lwpa(RTCS_geterror(id)) : res); + return (res == RTCS_ERROR ? err_os_to_lwpa(RTCS_geterror(id)) : res); } int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) @@ -294,11 +294,11 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, if (!dest_addr || !message) return kLwpaErrInvalid; - if ((ss_size = sockaddr_lwpa_to_plat(&ss, dest_addr)) == 0) + if ((ss_size = sockaddr_lwpa_to_os(&ss, dest_addr)) == 0) return kLwpaErrInvalid; res = sendto(id, (char*)message, (uint32_t)length, 0, &ss, ss_size); - return (res == RTCS_ERROR ? err_plat_to_lwpa(RTCS_geterror(id)) : res); + return (res == RTCS_ERROR ? err_os_to_lwpa(RTCS_geterror(id)) : res); } lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) @@ -414,7 +414,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const case LWPA_IP_MULTICAST_IF: /* This one is a bit tricky. The stack doesn't actually support this functionality, but for * systems with only one network interface we want to pretend that it does if called - * correctly. This makes the behavior for platform-neutral calling code more consistent. */ + * correctly. This makes the behavior for os-neutral calling code more consistent. */ #if BSP_ENET_DEVICE_COUNT == 1 if (option_len == sizeof(LwpaIpAddr)) { @@ -443,14 +443,14 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const break; } - return err_plat_to_lwpa(res); + return err_os_to_lwpa(res); } lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) { if (how >= 0 && how < LWPA_NUM_SHUT) { - return err_plat_to_lwpa(shutdownsocket(id, (int32_t)shutmap[how])); + return err_os_to_lwpa(shutdownsocket(id, (int32_t)shutmap[how])); } return kLwpaErrInvalid; } @@ -495,14 +495,14 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) res = setsockopt(id, SOL_TCP, OPT_RECEIVE_NOWAIT, &opt_value, uint32_size); if (res == RTCS_OK) res = setsockopt(id, SOL_TCP, OPT_SEND_NOWAIT, &opt_value, uint32_size); - return err_plat_to_lwpa(res); + return err_os_to_lwpa(res); } else if (sock_type == SOCK_DGRAM) { res = setsockopt(id, SOL_UDP, OPT_RECEIVE_NOWAIT, &opt_value, uint32_size); if (res == RTCS_OK) res = setsockopt(id, SOL_UDP, OPT_SEND_NOWAIT, &opt_value, uint32_size); - return err_plat_to_lwpa(res); + return err_os_to_lwpa(res); } else { @@ -517,10 +517,10 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) rtcs_fd_set readfds; rtcs_fd_set writefds; LwpaPollfd* fd; - int32_t nplatfds; + int32_t nosfds; int sel_res; int32_t nreadfds = 0, nwritefds = 0; - uint32_t plat_timeout; + uint32_t os_timeout; if (fds && nfds > 0) { @@ -539,22 +539,22 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) RTCS_FD_SET(fd->fd, &writefds); nwritefds++; } - /* LWPA_POLLPRI/exceptfds is not handled properly on this platform */ + /* LWPA_POLLPRI/exceptfds is not handled properly on this OS */ } } if (timeout_ms == LWPA_WAIT_FOREVER) - plat_timeout = 0; + os_timeout = 0; else if (timeout_ms == 0) - plat_timeout = 0xffffffff; + os_timeout = 0xffffffff; else - plat_timeout = (uint32_t)timeout_ms; - nplatfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; - sel_res = select(nplatfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, NULL, plat_timeout); + os_timeout = (uint32_t)timeout_ms; + nosfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; + sel_res = select(nosfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, NULL, os_timeout); if (sel_res == RTCS_ERROR) { - return err_plat_to_lwpa(RTCS_get_errno()); + return err_os_to_lwpa(RTCS_get_errno()); } else if (sel_res == 0) { @@ -573,7 +573,7 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) { fd->revents |= LWPA_POLLOUT; } - /* LWPA_POLLPRI/exceptfds is not handled properly on this platform */ + /* LWPA_POLLPRI/exceptfds is not handled properly on this OS */ } } return (int)sel_res; @@ -606,7 +606,7 @@ lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const L if (!lwpa_nextaddr(result)) return kLwpaErrSys; } - return err_plat_to_lwpa(res); + return err_os_to_lwpa(res); } bool lwpa_nextaddr(LwpaAddrinfo* ai) @@ -615,9 +615,9 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) { struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; - if (!sockaddr_plat_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) return false; - /* Can't use reverse maps, because we have no guarantee of the numeric values of the platform + /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS * constants. Ugh. */ if (pf_ai->ai_family == AF_INET) ai->ai_family = LWPA_AF_INET; diff --git a/src/lwpa_plat/mqx/lwpa/thread.c b/src/os/mqx/lwpa/os_thread.c similarity index 100% rename from src/lwpa_plat/mqx/lwpa/thread.c rename to src/os/mqx/lwpa/os_thread.c diff --git a/src/lwpa_plat/mqx/lwpa/timer.c b/src/os/mqx/lwpa/os_timer.c similarity index 100% rename from src/lwpa_plat/mqx/lwpa/timer.c rename to src/os/mqx/lwpa/os_timer.c diff --git a/src/lwpa_plat/mqx/lwpa/plat_uuid.c b/src/os/mqx/lwpa/os_uuid.c similarity index 100% rename from src/lwpa_plat/mqx/lwpa/plat_uuid.c rename to src/os/mqx/lwpa/os_uuid.c diff --git a/src/lwpa_plat/windows/lwpa/common.c b/src/os/windows/lwpa/os_common.c similarity index 95% rename from src/lwpa_plat/windows/lwpa/common.c rename to src/os/windows/lwpa/os_common.c index db63b9150..8cf1066a7 100644 --- a/src/lwpa_plat/windows/lwpa/common.c +++ b/src/os/windows/lwpa/os_common.c @@ -24,7 +24,7 @@ #define LWPA_WINDOWS_TIMER_RESOLUTION 1 // ms -static lwpa_error_t err_plat_to_lwpa(int wsaerror) +static lwpa_error_t err_os_to_lwpa(int wsaerror) { // Only dealing with the possible errors from WSAStartup() below. switch (wsaerror) @@ -62,7 +62,7 @@ lwpa_error_t lwpa_init(lwpa_features_t features) { if (timer_initted) timeEndPeriod(LWPA_WINDOWS_TIMER_RESOLUTION); - return err_plat_to_lwpa(startup_res); + return err_os_to_lwpa(startup_res); } } return kLwpaErrOk; diff --git a/src/lwpa_plat/windows/lwpa/lock.c b/src/os/windows/lwpa/os_lock.c similarity index 100% rename from src/lwpa_plat/windows/lwpa/lock.c rename to src/os/windows/lwpa/os_lock.c diff --git a/src/lwpa_plat/windows/lwpa/netint.c b/src/os/windows/lwpa/os_netint.c similarity index 100% rename from src/lwpa_plat/windows/lwpa/netint.c rename to src/os/windows/lwpa/os_netint.c diff --git a/src/lwpa_plat/windows/lwpa/socket.c b/src/os/windows/lwpa/os_socket.c similarity index 92% rename from src/lwpa_plat/windows/lwpa/socket.c rename to src/os/windows/lwpa/os_socket.c index a1d7960cd..0562573dc 100644 --- a/src/lwpa_plat/windows/lwpa/socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -106,7 +106,7 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /*********************** Private function prototypes *************************/ // Convert Windows sockets errors to lwpa_error_t values. -static lwpa_error_t err_plat_to_lwpa(int wsaerror); +static lwpa_error_t err_os_to_lwpa(int wsaerror); // Helper functions for the lwpa_poll API static void init_socket_chunk(LwpaPollCtxSocket* chunk); @@ -119,7 +119,7 @@ static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent /*************************** Function definitions ****************************/ -bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) { @@ -138,7 +138,7 @@ bool sockaddr_plat_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) return false; } -size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; if (lwpaip_is_v4(&sa->ip)) @@ -165,7 +165,7 @@ size_t sockaddr_lwpa_to_plat(struct sockaddr* pfsa, const LwpaSockaddr* sa) #if !defined(LWPA_BUILDING_MOCK_LIB) -lwpa_error_t err_plat_to_lwpa(int wsaerror) +lwpa_error_t err_os_to_lwpa(int wsaerror) { /* The Winsock error codes are not even close to contiguous in defined value, * so a giant switch statement is the only solution here... */ @@ -255,7 +255,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* if (res != INVALID_SOCKET) { - if (address && !sockaddr_plat_to_lwpa(address, (struct sockaddr*)&ss)) + if (address && !sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) { closesocket(res); return kLwpaErrSys; @@ -263,7 +263,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* *conn_sock = res; return kLwpaErrOk; } - return err_plat_to_lwpa(WSAGetLastError()); + return err_os_to_lwpa(WSAGetLastError()); } lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) @@ -275,18 +275,18 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, address); + sa_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); if (sa_size == 0) return kLwpaErrInvalid; res = bind(id, (struct sockaddr*)&ss, (int)sa_size); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_close(lwpa_socket_t id) { int res = closesocket(id); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) @@ -298,12 +298,12 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, address); + sa_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); if (sa_size == 0) return kLwpaErrInvalid; res = connect(id, (struct sockaddr*)&ss, (int)sa_size); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) @@ -326,11 +326,11 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) res = getsockname(id, (struct sockaddr*)&ss, &size); if (res == 0) { - if (!sockaddr_plat_to_lwpa(address, (struct sockaddr*)&ss)) + if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) return kLwpaErrSys; return kLwpaErrOk; } - return err_plat_to_lwpa(WSAGetLastError()); + return err_os_to_lwpa(WSAGetLastError()); } lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) @@ -347,7 +347,7 @@ lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) { int res = listen(id, backlog); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); } int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) @@ -359,7 +359,7 @@ int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) return kLwpaErrInvalid; res = recv(id, buffer, (int)length, impl_flags); - return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); } int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address) @@ -378,12 +378,12 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa { if (address && fromlen > 0) { - if (!sockaddr_plat_to_lwpa(address, (struct sockaddr*)&fromaddr)) + if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) return kLwpaErrSys; } return res; } - return (int)err_plat_to_lwpa(WSAGetLastError()); + return (int)err_os_to_lwpa(WSAGetLastError()); } int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) @@ -395,7 +395,7 @@ int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) return kLwpaErrInvalid; res = send(id, message, (int)length, 0); - return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); } int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) @@ -408,10 +408,10 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, if (!dest_addr || !message) return (int)kLwpaErrInvalid; - if ((ss_size = sockaddr_lwpa_to_plat((struct sockaddr*)&ss, dest_addr)) > 0) + if ((ss_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr)) > 0) res = sendto(id, message, (int)length, 0, (struct sockaddr*)&ss, (int)ss_size); - return (res >= 0 ? res : (int)err_plat_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) @@ -421,7 +421,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (!option_value) return kLwpaErrInvalid; - /* TODO this platform implementation could be simplified by use of socket option lookup arrays. */ + /* TODO this OS implementation could be simplified by use of socket option lookup arrays. */ switch (level) { case LWPA_SOL_SOCKET: @@ -597,11 +597,11 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const return kLwpaErrInvalid; } break; - case LWPA_SO_REUSEPORT: /* Not supported on this platform. */ + case LWPA_SO_REUSEPORT: /* Not supported on this OS. */ default: return kLwpaErrInvalid; } - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) @@ -609,7 +609,7 @@ lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) if (how >= 0 && how < LWPA_NUM_SHUT) { int res = shutdown(id, shutmap[how]); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); } return kLwpaErrInvalid; } @@ -629,7 +629,7 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* else { *id = LWPA_SOCKET_INVALID; - return err_plat_to_lwpa(WSAGetLastError()); + return err_os_to_lwpa(WSAGetLastError()); } } else @@ -644,7 +644,7 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) { unsigned long val = (blocking ? 0 : 1); int res = ioctlsocket(id, FIONBIO, &val); - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) @@ -877,24 +877,24 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int if (!readfds.count && !writefds.count && !exceptfds.count) return kLwpaErrNoSockets; - struct timeval plat_timeout; + struct timeval os_timeout; if (timeout_ms == 0) { - plat_timeout.tv_sec = 0; - plat_timeout.tv_usec = 0; + os_timeout.tv_sec = 0; + os_timeout.tv_usec = 0; } else if (timeout_ms != LWPA_WAIT_FOREVER) { - plat_timeout.tv_sec = timeout_ms / 1000; - plat_timeout.tv_usec = (timeout_ms % 1000) * 1000; + os_timeout.tv_sec = timeout_ms / 1000; + os_timeout.tv_usec = (timeout_ms % 1000) * 1000; } int sel_res = select(0, readfds.count ? &readfds.set : NULL, writefds.count ? &writefds.set : NULL, - exceptfds.count ? &exceptfds.set : NULL, timeout_ms == LWPA_WAIT_FOREVER ? NULL : &plat_timeout); + exceptfds.count ? &exceptfds.set : NULL, timeout_ms == LWPA_WAIT_FOREVER ? NULL : &os_timeout); if (sel_res < 0) { - return err_plat_to_lwpa(WSAGetLastError()); + return err_os_to_lwpa(WSAGetLastError()); } else if (sel_res == 0) { @@ -945,12 +945,12 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event if (error != 0) { event->events |= LWPA_POLL_ERR; - event->err = err_plat_to_lwpa(error); + event->err = err_os_to_lwpa(error); } } else { - res = err_plat_to_lwpa(WSAGetLastError()); + res = err_os_to_lwpa(WSAGetLastError()); break; } if (LWPA_FD_ISSET(sock_desc->socket, readfds)) @@ -1005,7 +1005,7 @@ lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const L if (!lwpa_nextaddr(result)) res = -1; } - return (res == 0 ? kLwpaErrOk : err_plat_to_lwpa(res)); + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(res)); } bool lwpa_nextaddr(LwpaAddrinfo* ai) @@ -1014,10 +1014,10 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) { struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; - if (!sockaddr_plat_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) return false; - /* Can't use reverse maps, because we have no guarantee of the numeric values of the platform + /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS * constants. Ugh. */ if (pf_ai->ai_family == AF_INET) ai->ai_family = LWPA_AF_INET; diff --git a/src/lwpa_plat/windows/lwpa/thread.c b/src/os/windows/lwpa/os_thread.c similarity index 100% rename from src/lwpa_plat/windows/lwpa/thread.c rename to src/os/windows/lwpa/os_thread.c diff --git a/src/lwpa_plat/windows/lwpa/timer.c b/src/os/windows/lwpa/os_timer.c similarity index 100% rename from src/lwpa_plat/windows/lwpa/timer.c rename to src/os/windows/lwpa/os_timer.c diff --git a/src/lwpa_plat/windows/lwpa/plat_uuid.c b/src/os/windows/lwpa/os_uuid.c similarity index 74% rename from src/lwpa_plat/windows/lwpa/plat_uuid.c rename to src/os/windows/lwpa/os_uuid.c index 14d2155c5..630e0b9e4 100644 --- a/src/lwpa_plat/windows/lwpa/plat_uuid.c +++ b/src/os/windows/lwpa/os_uuid.c @@ -31,13 +31,13 @@ lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) if (!uuid) return kLwpaErrInvalid; - UUID plat_uuid; - if (RPC_S_OK == UuidCreateSequential(&plat_uuid)) + UUID os_uuid; + if (RPC_S_OK == UuidCreateSequential(&os_uuid)) { - lwpa_pack_32b(&uuid->data[0], plat_uuid.Data1); - lwpa_pack_16b(&uuid->data[4], plat_uuid.Data2); - lwpa_pack_16b(&uuid->data[6], plat_uuid.Data3); - memcpy(&uuid->data[8], plat_uuid.Data4, 8); + lwpa_pack_32b(&uuid->data[0], os_uuid.Data1); + lwpa_pack_16b(&uuid->data[4], os_uuid.Data2); + lwpa_pack_16b(&uuid->data[6], os_uuid.Data3); + memcpy(&uuid->data[8], os_uuid.Data4, 8); return kLwpaErrOk; } else @@ -51,13 +51,13 @@ lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid) if (!uuid) return kLwpaErrInvalid; - UUID plat_uuid; - if (RPC_S_OK == UuidCreate(&plat_uuid)) + UUID os_uuid; + if (RPC_S_OK == UuidCreate(&os_uuid)) { - lwpa_pack_32b(&uuid->data[0], plat_uuid.Data1); - lwpa_pack_16b(&uuid->data[4], plat_uuid.Data2); - lwpa_pack_16b(&uuid->data[6], plat_uuid.Data3); - memcpy(&uuid->data[8], plat_uuid.Data4, 8); + lwpa_pack_32b(&uuid->data[0], os_uuid.Data1); + lwpa_pack_16b(&uuid->data[4], os_uuid.Data2); + lwpa_pack_16b(&uuid->data[6], os_uuid.Data3); + memcpy(&uuid->data[8], os_uuid.Data4, 8); return kLwpaErrOk; } else @@ -69,4 +69,4 @@ lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid) lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid* uuid) { return lwpa_generate_v4_uuid(uuid); -} \ No newline at end of file +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 38f68933a..35fe4c0b9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,6 @@ ################################### testing ################################### -if(LWPA_PLATFORM STREQUAL windows OR LWPA_PLATFORM STREQUAL linux) +if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL linux) message(STATUS "Adding GoogleTest dependency...") include(AddGoogleTest) From d88aa605fdae510abc152acc3f08d6d0713f34a2 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 3 Jun 2019 14:40:53 -0500 Subject: [PATCH 009/264] Some fixes related to renaming --- src/CMakeLists.txt | 16 +++++++++------- .../{freertos_lwip => freertos}/lwpa/os_lock.c | 0 .../{freertos_lwip => freertos}/lwpa/os_thread.c | 0 .../{freertos_lwip => freertos}/lwpa/os_timer.c | 0 src/os/{freertos_lwip => lwip}/lwpa/os_netint.c | 0 src/os/{freertos_lwip => lwip}/lwpa/os_socket.c | 0 .../codewarrior-kinetis-mqx.cmake | 2 +- .../cmake/cross-toolchains/iar-kinetis-mqx.cmake | 2 +- 8 files changed, 11 insertions(+), 9 deletions(-) rename src/os/{freertos_lwip => freertos}/lwpa/os_lock.c (100%) rename src/os/{freertos_lwip => freertos}/lwpa/os_thread.c (100%) rename src/os/{freertos_lwip => freertos}/lwpa/os_timer.c (100%) rename src/os/{freertos_lwip => lwip}/lwpa/os_netint.c (100%) rename src/os/{freertos_lwip => lwip}/lwpa/os_socket.c (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4e2bac9aa..c454a8b4a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,12 +19,14 @@ if(NOT DEFINED LWPA_TARGET_OS) elseif(UNIX AND NOT APPLE) set(LWPA_TARGET_OS linux) else() - message(FATAL_ERROR "lwpa is not ported for this target OS.") + # The error check below will catch this and print the fatal error. + set(LWPA_TARGET_OS ${CMAKE_HOST_SYSTEM_NAME}) endif() endif() if(NOT ${LWPA_TARGET_OS} IN_LIST VALID_LWPA_TARGETS) - message(FATAL_ERROR "${LWPA_TARGET_OS} is not a valid target OS.") + message(FATAL_ERROR "${LWPA_TARGET_OS} is not a valid target OS. " + "Specify LWPA_TARGET_OS from these options: ${VALID_LWPA_TARGETS}") endif() # MQX compilation support @@ -160,12 +162,12 @@ if(LWPA_BUILD_MOCK_LIB) ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/md5.h ${LWPA_ROOT}/src/lwpa/md5c.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/lock.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/netint.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_uuid.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/socket.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/thread.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/timer.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_socket.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_thread.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_timer.c ${LWPA_ROOT}/src/lwpa_mock/socket.c ) diff --git a/src/os/freertos_lwip/lwpa/os_lock.c b/src/os/freertos/lwpa/os_lock.c similarity index 100% rename from src/os/freertos_lwip/lwpa/os_lock.c rename to src/os/freertos/lwpa/os_lock.c diff --git a/src/os/freertos_lwip/lwpa/os_thread.c b/src/os/freertos/lwpa/os_thread.c similarity index 100% rename from src/os/freertos_lwip/lwpa/os_thread.c rename to src/os/freertos/lwpa/os_thread.c diff --git a/src/os/freertos_lwip/lwpa/os_timer.c b/src/os/freertos/lwpa/os_timer.c similarity index 100% rename from src/os/freertos_lwip/lwpa/os_timer.c rename to src/os/freertos/lwpa/os_timer.c diff --git a/src/os/freertos_lwip/lwpa/os_netint.c b/src/os/lwip/lwpa/os_netint.c similarity index 100% rename from src/os/freertos_lwip/lwpa/os_netint.c rename to src/os/lwip/lwpa/os_netint.c diff --git a/src/os/freertos_lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c similarity index 100% rename from src/os/freertos_lwip/lwpa/os_socket.c rename to src/os/lwip/lwpa/os_socket.c diff --git a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake index e2d51b656..f6db5d15f 100644 --- a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake +++ b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake @@ -23,7 +23,7 @@ set(TOOLS_DIR ${CODEWARRIOR_INSTALL_DIR}/Cross_Tools/arm-none-eabi-gcc-4_7_3) set(CMAKE_C_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-gcc.exe) set(CMAKE_CXX_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-g++.exe) -set(LWPA_PLATFORM mqx) +set(LWPA_TARGET_OS mqx) add_compile_options( -nostdinc -ffunction-sections diff --git a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake index c7619d375..01fdcc279 100644 --- a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake +++ b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake @@ -22,7 +22,7 @@ endif() set(CMAKE_C_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe) set(CMAKE_CXX_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe) -set(LWPA_PLATFORM mqx) +set(LWPA_TARGET_OS mqx) add_compile_options( --endian=little --cpu=Cortex-M4 From 8f6880c2c00d543a0d9651afce0531ef202c2742 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 3 Jun 2019 14:44:37 -0500 Subject: [PATCH 010/264] Fix md5 names - back to original --- ThirdPartySoftware.txt | 4 ++-- port/mqx/cw10gcc/.project | 4 ++-- port/mqx/iar/lwpa.ewp | 2 +- src/CMakeLists.txt | 4 ++-- src/lwpa/{md5c.c => md5.c} | 0 src/lwpa/md5.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) rename src/lwpa/{md5c.c => md5.c} (100%) diff --git a/ThirdPartySoftware.txt b/ThirdPartySoftware.txt index db58f6a33..6660a1d47 100644 --- a/ThirdPartySoftware.txt +++ b/ThirdPartySoftware.txt @@ -12,7 +12,7 @@ The following sources in this repository are derived from the RSA Data Security, Inc. MD5 Message-Digest algorithm: src/md5.h -src/md5c.c +src/md5.c See the license information at the top of those source files for more details. @@ -27,4 +27,4 @@ mirek/rb_tree: include/lwpa/rbtree.h src/lwpa_rbtree.c -See the license information at the top of those source files for more details. \ No newline at end of file +See the license information at the top of those source files for more details. diff --git a/port/mqx/cw10gcc/.project b/port/mqx/cw10gcc/.project index 00cfdc1c4..e4c3508fb 100644 --- a/port/mqx/cw10gcc/.project +++ b/port/mqx/cw10gcc/.project @@ -271,9 +271,9 @@ PARENT-3-PROJECT_LOC/src/lwpa_uid.c - src/md5c.c + src/md5.c 1 - PARENT-3-PROJECT_LOC/src/md5c.c + PARENT-3-PROJECT_LOC/src/md5.c diff --git a/port/mqx/iar/lwpa.ewp b/port/mqx/iar/lwpa.ewp index 04a7319e8..b7a1274c9 100644 --- a/port/mqx/iar/lwpa.ewp +++ b/port/mqx/iar/lwpa.ewp @@ -2056,7 +2056,7 @@ $PROJ_DIR$\..\..\..\src\lwpa_uid.c - $PROJ_DIR$\..\..\..\src\md5c.c + $PROJ_DIR$\..\..\..\src\md5.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c454a8b4a..ca06f0ab4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,7 +75,7 @@ add_library(lwpa ${LWPA_ROOT}/src/lwpa/rbtree.c ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/md5.h - ${LWPA_ROOT}/src/lwpa/md5c.c + ${LWPA_ROOT}/src/lwpa/md5.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_common.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c @@ -161,7 +161,7 @@ if(LWPA_BUILD_MOCK_LIB) ${LWPA_ROOT}/src/lwpa/rbtree.c ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/md5.h - ${LWPA_ROOT}/src/lwpa/md5c.c + ${LWPA_ROOT}/src/lwpa/md5.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_uuid.c diff --git a/src/lwpa/md5c.c b/src/lwpa/md5.c similarity index 100% rename from src/lwpa/md5c.c rename to src/lwpa/md5.c diff --git a/src/lwpa/md5.h b/src/lwpa/md5.h index 2712c73ce..720054c0a 100644 --- a/src/lwpa/md5.h +++ b/src/lwpa/md5.h @@ -1,4 +1,4 @@ -/* MD5.H - header file for MD5C.C +/* MD5.H - header file for MD5.C */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All From 4aac740dd4c08529a9d4d8f23b41e6cebce69e4c Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 3 Jun 2019 14:51:54 -0500 Subject: [PATCH 011/264] It helps to save files before committing --- src/lwpa/md5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lwpa/md5.c b/src/lwpa/md5.c index 819350592..714cf4a71 100644 --- a/src/lwpa/md5.c +++ b/src/lwpa/md5.c @@ -1,4 +1,4 @@ -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm +/* MD5.C - RSA Data Security, Inc., MD5 message-digest algorithm */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All From 7c5f190016e98e3f604cfd2f31798369d4387e64 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 3 Jun 2019 16:59:48 -0500 Subject: [PATCH 012/264] Checking in current WIP not compiling --- docs/mainpage.md | 4 +- include/lwpa/common.h | 1 + include/os/linux/lwpa/os_socket.h | 15 ++- include/os/windows/lwpa/os_socket.h | 8 +- src/CMakeLists.txt | 1 + src/lwpa/common.c | 52 ++++++++++ src/lwpa/log.c | 147 +++++++++++++++++++++------- src/lwpa/private/common.h | 28 ++++++ src/lwpa/private/log.h | 28 ++++++ src/os/linux/lwpa/os_common.c | 7 +- src/os/linux/lwpa/os_socket.c | 30 +++++- src/os/linux/lwpa/os_uuid.c | 2 +- tests/CMakeLists.txt | 2 +- tests/unit/main.cpp | 2 - tests/unit/test_rbtree.cpp | 63 ++++++------ tests/unit/test_rwlock.cpp | 9 +- tests/unit/test_signal.cpp | 5 - tests/unit/test_thread.cpp | 1 - 18 files changed, 303 insertions(+), 102 deletions(-) create mode 100644 src/lwpa/common.c create mode 100644 src/lwpa/private/common.h create mode 100644 src/lwpa/private/log.h diff --git a/docs/mainpage.md b/docs/mainpage.md index 72f708ce5..658e92170 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -40,6 +40,7 @@ identical interface, as documented in that module's documentation. lwpa is currently ported for the following platforms: + Microsoft Windows ++ Linux + MQX RTOS ### Building lwpa for Your Platform @@ -98,4 +99,5 @@ The platform ports of lwpa have the following dependencies: + MQX RTOS - MQX 4.2.0 + Linux - - libuuid (`sudo apt-get install uuid-dev`) + - libuuid (if compiling lwpa, use `sudo apt-get install uuid-dev` or the + equivalent method for your distribution) diff --git a/include/lwpa/common.h b/include/lwpa/common.h index a498e93f1..ccf9cd2f9 100644 --- a/include/lwpa/common.h +++ b/include/lwpa/common.h @@ -43,6 +43,7 @@ #define LWPA_FEATURE_SOCKETS 0x00000001u #define LWPA_FEATURE_TIMERS 0x00000002u +#define LWPA_FEATURE_LOGGING 0x00000004u #define LWPA_FEATURES_ALL 0xffffffffu typedef uint32_t lwpa_features_t; diff --git a/include/os/linux/lwpa/os_socket.h b/include/os/linux/lwpa/os_socket.h index ca03a71b0..45ababa40 100644 --- a/include/os/linux/lwpa/os_socket.h +++ b/include/os/linux/lwpa/os_socket.h @@ -24,21 +24,26 @@ #include #include "lwpa/inet.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef int lwpa_socket_t; #define LWPA_SOCKET_INVALID -1 -#define LWPA_SOCKET_MAX_POLL_SIZE FD_SETSIZE +#define LWPA_SOCKET_MAX_POLL_SIZE -1 + +typedef struct LwpaPollContext +{ + int epoll_fd; +} LwpaPollContext; #define ip_os_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), ntohl((pfipptr)->s_addr)) #define ip_lwpa_to_os_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(lwpaip_v4_address(lwpaipptr))) #define ip_os_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) #define ip_lwpa_to_os_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) -#ifdef __cplusplus -extern "C" { -#endif - bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); diff --git a/include/os/windows/lwpa/os_socket.h b/include/os/windows/lwpa/os_socket.h index e29061926..3d2e25a85 100644 --- a/include/os/windows/lwpa/os_socket.h +++ b/include/os/windows/lwpa/os_socket.h @@ -33,6 +33,10 @@ #include "lwpa/inet.h" #include "lwpa/lock.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef SOCKET lwpa_socket_t; /*! An identifier for an invalid socket handle. The ONLY invalid socket descriptor is @@ -69,10 +73,6 @@ typedef struct LwpaPollContext } LwpaPollContext; -#ifdef __cplusplus -extern "C" { -#endif - #define ip_os_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), ntohl((pfipptr)->s_addr)) #define ip_lwpa_to_os_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(lwpaip_v4_address(lwpaipptr))) #define ip_os_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca06f0ab4..529eaf253 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -91,6 +91,7 @@ target_include_directories(lwpa PUBLIC ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS} ${LWPA_CONFIG_LOC} ) +target_include_directories(lwpa PRIVATE ${LWPA_ROOT}/src) target_compile_definitions(lwpa PUBLIC ${LWPA_HAVE_CONFIG_H}) # Add include paths and library dependencies based on OS for which we are being compiled diff --git a/src/lwpa/common.c b/src/lwpa/common.c new file mode 100644 index 000000000..3218dd8d3 --- /dev/null +++ b/src/lwpa/common.c @@ -0,0 +1,52 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/common.h" +#include "lwpa/private/common.h" +#include "lwpa/private/log.h" + +lwpa_error_t lwpa_init(lwpa_features_t features) +{ + // Step 1: OS-specific init + lwpa_error_t res = lwpa_os_init(features); + if (res != kLwpaErrOk) + return res; + + // Step 2: OS-neutral init + if (features & LWPA_FEATURE_LOGGING) + { + res = lwpa_log_init(); + if (res != kLwpaErrOk) + { + lwpa_os_deinit(features); + } + } + return res; +} + +void lwpa_deinit(lwpa_features_t features) +{ + // Step 1: OS-neutral deinit + if (features & LWPA_FEATURE_LOGGING) + { + lwpa_log_deinit(); + } + + lwpa_os_deinit(features); +} diff --git a/src/lwpa/log.c b/src/lwpa/log.c index 12fbe0c4c..8883eac26 100644 --- a/src/lwpa/log.c +++ b/src/lwpa/log.c @@ -25,12 +25,29 @@ #include #include #include "lwpa/bool.h" +#include "lwpa/lock.h" +#include "lwpa/mempool.h" +#include "lwpa/private/log.h" -/* Suppress strncpy() and gmtime() warnings on Windows/MSVC. */ #ifdef _MSC_VER +/* Suppress strncpy() warnings on Windows/MSVC. */ #pragma warning(disable : 4996) + +/* Provide va_copy() in pre-VS2013 environments. */ +#if _MSC_VER < 1800 +#define va_copy(dest, src) (dest = src) +#endif #endif +/* This module uses some C99 features: + * - vsnprintf() + * - va_copy() + * These additional exceptions to the normal C89 rules are permissible here because there are + * workarounds for VS. + */ + +/*************************** Private constants *******************************/ + #define SYSLOG_PROT_VERSION 1 /*RFC 5424, sec. 6.2.2 */ #define NILVALUE_STR "-" #define MSGID_STR NILVALUE_STR @@ -38,12 +55,47 @@ /* LOG_LOCAL1 seems to be one that's lightly used */ #define DEFAULT_FACILITY LWPA_LOG_LOCAL1 +/**************************** Private variables ******************************/ + +static bool module_initialized; +static lwpa_mutex_t buf_lock; + +/*********************** Private function prototypes *************************/ + +static void sanitize_str(char* str); + +/*************************** Function definitions ****************************/ + +/* Initialize the lwpa_log module. Creates the mutex which locks the static buffers that log + * messages are written into. */ +lwpa_error_t lwpa_log_init() +{ + if (!module_initialized) + { + if (!lwpa_mutex_create(&buf_lock)) + { + return kLwpaErrSys; + } + module_initialized = true; + } + return kLwpaErrOk; +} + +/* Deinitialize the lwpa_log module. */ +void lwpa_log_deinit() +{ + if (module_initialized) + { + lwpa_mutex_destroy(&buf_lock); + module_initialized = false; + } +} + /* Replace non-printing characters and spaces with '_'. Replace characters above 127 with '?'. */ -static void sanitize_str(char* str) +void sanitize_str(char* str) { - /* C library functions like isprint()/isgraph() are not used here because their behavior is not - * well-defined in the presence of non-ASCII characters. - */ + // C library functions like isprint()/isgraph() are not used here because their behavior is not + // well-defined in the presence of non-ASCII characters. unsigned char* cp; for (cp = (unsigned char*)str; *cp != '\0'; ++cp) { @@ -111,7 +163,7 @@ static void make_timestamp(const LwpaLogTimeParams* tparams, char* buf, bool hum if (tparams && validate_time(tparams)) { - /* Print the basic timestamp */ + // Print the basic timestamp int print_res = snprintf( buf, LWPA_LOG_TIMESTAMP_LEN, human_readable ? "%04d-%02d-%02d %02d:%02d:%02d.%03d" : "%04d-%02d-%02dT%02d:%02d:%02d.%03d", tparams->year, @@ -119,7 +171,7 @@ static void make_timestamp(const LwpaLogTimeParams* tparams, char* buf, bool hum if (print_res > 0 && print_res < LWPA_LOG_TIMESTAMP_LEN - 1) { - /* Add the UTC offset */ + // Add the UTC offset if (tparams->utc_offset == 0) { buf[print_res] = 'Z'; @@ -154,7 +206,9 @@ static bool get_time(const LwpaLogParams* params, LwpaLogTimeParams* time_params return true; } else + { return false; + } } /* Create a log message with syslog header given the appropriate va_list. Returns a pointer to the @@ -177,10 +231,8 @@ static char* lwpa_vcreate_syslog_str(char* buf, size_t buflen, const LwpaLogTime if (syslog_header_size >= 0) { - /* Copy in the message */ - /* Making an exception to the strict C89 rule here for safety. We have not found a toolchain that - * doesn't support vsnprintf. vsnprintf will write up to count - 1 bytes and always - * null-terminates. This allows LWPA_LOG_MSG_MAX_LEN valid bytes to be written. */ + // Copy in the message. vsnprintf will write up to count - 1 bytes and always null-terminates. + // This allows LWPA_LOG_MSG_MAX_LEN valid bytes to be written. vsnprintf(&buf[syslog_header_size], buflen - (size_t)syslog_header_size, format, args); return &buf[syslog_header_size]; } @@ -233,10 +285,8 @@ static char* lwpa_vcreate_human_log_str(char* buf, size_t buflen, const LwpaLogT if (human_header_size >= 0) { - /* Copy in the message */ - /* Making an exception to the strict C89 rule here for safety. We have not found a toolchain that - * doesn't support vsnprintf. vsnprintf will write up to count - 1 bytes and always - * null-terminates. This allows LWPA_LOG_MSG_MAX_LEN valid bytes to be written. */ + // Copy in the message. vsnprintf will write up to count - 1 bytes and always null-terminates. + // This allows LWPA_LOG_MSG_MAX_LEN valid bytes to be written. vsnprintf(&buf[human_header_size], buflen - (size_t)human_header_size, format, args); return &buf[human_header_size]; } @@ -297,37 +347,58 @@ void lwpa_log(const LwpaLogParams* params, int pri, const char* format, ...) */ void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list args) { - char syslogmsg[LWPA_SYSLOG_STR_MAX_LEN + 1]; - char humanlogmsg[LWPA_HUMAN_LOG_STR_MAX_LEN + 1]; - char* syslog_msg_ptr = NULL; - char* humanlog_msg_ptr = NULL; - char* raw_msg_ptr = NULL; - LwpaLogTimeParams time_params; - bool have_time; - if (!params || !params->log_fn || !format || !(LWPA_LOG_MASK(pri) & params->log_mask)) return; - have_time = get_time(params, &time_params); + LwpaLogTimeParams time_params; + bool have_time = get_time(params, &time_params); - if (params->action == kLwpaLogCreateBoth || params->action == kLwpaLogCreateSyslog) + if (lwpa_mutex_take(&buf_lock, LWPA_WAIT_FOREVER)) { - raw_msg_ptr = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, - ¶ms->syslog_params, pri, format, args); - if (raw_msg_ptr) + static char syslogmsg[LWPA_SYSLOG_STR_MAX_LEN + 1]; + static char humanlogmsg[LWPA_HUMAN_LOG_STR_MAX_LEN + 1]; + char* syslog_msg_ptr = NULL; + char* humanlog_msg_ptr = NULL; + char* raw_msg_ptr = NULL; + + // If we are calling both vcreate functions, we will need to copy the va_list. + // For more info on using a va_list multiple times, see: + // https://wiki.sei.cmu.edu/confluence/display/c/MSC39-C.+Do+not+call+va_arg%28%29+on+a+va_list+that+has+an+indeterminate+value + // https://stackoverflow.com/a/26919307 + va_list args_copy; + bool args_copied = false; + if (params->action == kLwpaLogCreateBoth) { - syslog_msg_ptr = syslogmsg; + va_copy(args_copy, args); + args_copied = true; } - } - if (params->action == kLwpaLogCreateBoth || params->action == kLwpaLogCreateHumanReadableLog) - { - raw_msg_ptr = lwpa_vcreate_human_log_str(humanlogmsg, LWPA_HUMAN_LOG_STR_MAX_LEN + 1, - have_time ? &time_params : NULL, format, args); - if (raw_msg_ptr) + + if (params->action == kLwpaLogCreateBoth || params->action == kLwpaLogCreateSyslog) { - humanlog_msg_ptr = humanlogmsg; + raw_msg_ptr = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, + ¶ms->syslog_params, pri, format, args_copied ? args_copy : args); + if (raw_msg_ptr) + { + syslog_msg_ptr = syslogmsg; + } + if (args_copied) + { + va_end(args_copy); + } + } + + if (params->action == kLwpaLogCreateBoth || params->action == kLwpaLogCreateHumanReadableLog) + { + raw_msg_ptr = lwpa_vcreate_human_log_str(humanlogmsg, LWPA_HUMAN_LOG_STR_MAX_LEN + 1, + have_time ? &time_params : NULL, format, args); + if (raw_msg_ptr) + { + humanlog_msg_ptr = humanlogmsg; + } } - } - params->log_fn(params->context, syslog_msg_ptr, humanlog_msg_ptr, raw_msg_ptr); + params->log_fn(params->context, syslog_msg_ptr, humanlog_msg_ptr, raw_msg_ptr); + + lwpa_mutex_give(&buf_lock); + } } diff --git a/src/lwpa/private/common.h b/src/lwpa/private/common.h new file mode 100644 index 000000000..1c0fe8f07 --- /dev/null +++ b/src/lwpa/private/common.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_PRIVATE_COMMON_H_ +#define _LWPA_PRIVATE_COMMON_H_ + +#include "lwpa/common.h" + +lwpa_error_t lwpa_os_init(lwpa_features_t features); +void lwpa_os_deinit(lwpa_features_t features); + +#endif /* _LWPA_PRIVATE_COMMON_H_ */ diff --git a/src/lwpa/private/log.h b/src/lwpa/private/log.h new file mode 100644 index 000000000..83585e5bd --- /dev/null +++ b/src/lwpa/private/log.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_PRIVATE_LOG_H_ +#define _LWPA_PRIVATE_LOG_H_ + +#include "lwpa/error.h" + +lwpa_error_t lwpa_log_init(); +void lwpa_log_deinit(); + +#endif /* _LWPA_PRIVATE_LOG_H_ */ diff --git a/src/os/linux/lwpa/os_common.c b/src/os/linux/lwpa/os_common.c index e16a62a36..7e1de52d0 100644 --- a/src/os/linux/lwpa/os_common.c +++ b/src/os/linux/lwpa/os_common.c @@ -18,10 +18,11 @@ ******************************************************************************/ #include "lwpa/common.h" +#include "lwpa/private/common.h" #include -lwpa_error_t lwpa_init(lwpa_features_t features) +lwpa_error_t lwpa_os_init(lwpa_features_t features) { if (features & LWPA_FEATURE_TIMERS) { @@ -31,7 +32,7 @@ lwpa_error_t lwpa_init(lwpa_features_t features) return kLwpaErrOk; } -void lwpa_deinit(lwpa_features_t features) +void lwpa_os_deinit(lwpa_features_t features) { (void)features; -} \ No newline at end of file +} diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index b1e2ad003..78f8726eb 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -567,8 +567,32 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) return kLwpaErrNotImpl; } -/* TODO move to an overlapped IO implementation on Windows for better performance. */ -int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) +lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) +{ + return kLwpaErrNotImpl; +} + +void lwpa_poll_context_deinit(LwpaPollContext* context) +{ +} + +lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, + void* user_data) +{ + return kLwpaErrNotImpl; +} + +lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, + void* new_user_data) +{ + return kLwpaErrNotImpl; +} + +void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) +{ +} + +lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms) { // fd_set readfds, writefds, exceptfds; // LwpaPollfd *fd; @@ -664,7 +688,7 @@ int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) // } // } // return sel_res; - return (int)kLwpaErrNotImpl; + return kLwpaErrNotImpl; } lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, diff --git a/src/os/linux/lwpa/os_uuid.c b/src/os/linux/lwpa/os_uuid.c index 5ccdad271..dbd03ce8d 100644 --- a/src/os/linux/lwpa/os_uuid.c +++ b/src/os/linux/lwpa/os_uuid.c @@ -21,7 +21,7 @@ #include -// Use Linux APIs to generate UUIDs. +// Use libuuid on Linux to generate UUIDs. // https://linux.die.net/man/3/uuid_generate lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 35fe4c0b9..beadd4013 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,6 +24,6 @@ if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL linux) ${TEST_SRC_DIR}/test_timer.cpp ${TEST_SRC_DIR}/test_uuid.cpp ) - + set_target_properties(test_lwpa PROPERTIES CXX_STANDARD 14) target_link_libraries(test_lwpa lwpa gmock) endif() diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp index 713970cb8..4dc6028c3 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/main.cpp @@ -32,8 +32,6 @@ int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); - ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURES_ALL)); - // Only check our custom argument if we haven't been given the "list_tests" flag if (!testing::GTEST_FLAG(list_tests)) { diff --git a/tests/unit/test_rbtree.cpp b/tests/unit/test_rbtree.cpp index 554222c2d..dec0424c6 100644 --- a/tests/unit/test_rbtree.cpp +++ b/tests/unit/test_rbtree.cpp @@ -36,7 +36,7 @@ class RbTreeTest : public ::testing::Test dealloc_call_count = 0; // Initialize an array of monotonically increasing ints - for (int i = 0; i < INT_ARRAY_SIZE; ++i) + for (int i = 0; i < kIntArraySize; ++i) incrementing_int_array[i] = i; // Copy and shuffle the integer array @@ -46,10 +46,10 @@ class RbTreeTest : public ::testing::Test std::shuffle(random_int_array.begin(), random_int_array.end(), rand); } - static constexpr size_t INT_ARRAY_SIZE = 100; - std::array incrementing_int_array; - std::array random_int_array; - std::array node_pool; + static constexpr size_t kIntArraySize = 100; + std::array incrementing_int_array; + std::array random_int_array; + std::array node_pool; public: static unsigned int alloc_call_count; @@ -57,11 +57,12 @@ class RbTreeTest : public ::testing::Test unsigned int clearfunc_call_count; bool remove_one_flag; - static const int MAGIC_REMOVE_VALUE = INT_ARRAY_SIZE / 2; + static const int kMagicRemoveValue = kIntArraySize / 2; }; unsigned int RbTreeTest::alloc_call_count; unsigned int RbTreeTest::dealloc_call_count; +constexpr size_t RbTreeTest::kIntArraySize; LwpaRbNode* node_alloc() { @@ -88,7 +89,7 @@ static void clear_func(const LwpaRbTree* self, LwpaRbNode* node) RbTreeTest* rbtt = static_cast(self->info); if (rbtt) { - if (rbtt->remove_one_flag && *(int*)node->value == RbTreeTest::MAGIC_REMOVE_VALUE) + if (rbtt->remove_one_flag && *(int*)node->value == RbTreeTest::kMagicRemoveValue) { rbtt->remove_one_flag = false; } @@ -103,31 +104,31 @@ TEST_F(RbTreeTest, insert_static) tree.info = this; // Point each node at its respective value and insert it into the tree - for (size_t i = 0; i < INT_ARRAY_SIZE; ++i) + for (size_t i = 0; i < kIntArraySize; ++i) { LwpaRbNode* node = &node_pool[i]; ASSERT_TRUE(NULL != lwpa_rbnode_init(node, &random_int_array[i])); ASSERT_NE(0, lwpa_rbtree_insert_node(&tree, node)); } - ASSERT_EQ(INT_ARRAY_SIZE, lwpa_rbtree_size(&tree)); + ASSERT_EQ(kIntArraySize, lwpa_rbtree_size(&tree)); ASSERT_NE(0, lwpa_rbtree_test(&tree, tree.root)); // Find a random number - int to_find = rand() / (RAND_MAX / INT_ARRAY_SIZE + 1); + int to_find = rand() / (RAND_MAX / kIntArraySize + 1); int* found = (int*)lwpa_rbtree_find(&tree, &to_find); ASSERT_TRUE(found != NULL); ASSERT_EQ(*found, to_find); // Try removing one item remove_one_flag = true; - int to_remove = MAGIC_REMOVE_VALUE; + int to_remove = kMagicRemoveValue; ASSERT_NE(0, lwpa_rbtree_remove_with_cb(&tree, &to_remove, clear_func)); ASSERT_FALSE(remove_one_flag); - // Clear the tree + // Clear the tre ASSERT_NE(0, lwpa_rbtree_clear_with_cb(&tree, clear_func)); ASSERT_EQ(0u, lwpa_rbtree_size(&tree)); - ASSERT_EQ(clearfunc_call_count, INT_ARRAY_SIZE); + ASSERT_EQ(clearfunc_call_count, kIntArraySize); } TEST_F(RbTreeTest, insert_dynamic) @@ -136,26 +137,26 @@ TEST_F(RbTreeTest, insert_dynamic) ASSERT_TRUE(NULL != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); // Insert each value into the tree; dynamic alloc functions should be called. - for (size_t i = 0; i < INT_ARRAY_SIZE; ++i) + for (size_t i = 0; i < kIntArraySize; ++i) ASSERT_NE(0, lwpa_rbtree_insert(&tree, &random_int_array[i])); - ASSERT_EQ(INT_ARRAY_SIZE, lwpa_rbtree_size(&tree)); - ASSERT_EQ(INT_ARRAY_SIZE, alloc_call_count); + ASSERT_EQ(kIntArraySize, lwpa_rbtree_size(&tree)); + ASSERT_EQ(kIntArraySize, alloc_call_count); ASSERT_NE(0, lwpa_rbtree_test(&tree, tree.root)); // Find a random number - int to_find = rand() / (RAND_MAX / INT_ARRAY_SIZE + 1); + int to_find = rand() / (RAND_MAX / kIntArraySize + 1); int* found = (int*)lwpa_rbtree_find(&tree, &to_find); ASSERT_TRUE(found != NULL); ASSERT_EQ(*found, to_find); // Make sure removing something that wasn't in the tree fails. - int not_in_tree = INT_ARRAY_SIZE + 1; + int not_in_tree = kIntArraySize + 1; ASSERT_EQ(0, lwpa_rbtree_remove(&tree, ¬_in_tree)); // Clear the tree ASSERT_NE(0, lwpa_rbtree_clear(&tree)); ASSERT_EQ(0u, lwpa_rbtree_size(&tree)); - ASSERT_EQ(dealloc_call_count, INT_ARRAY_SIZE); + ASSERT_EQ(dealloc_call_count, kIntArraySize); } TEST_F(RbTreeTest, iter) @@ -164,9 +165,9 @@ TEST_F(RbTreeTest, iter) ASSERT_TRUE(NULL != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); // Insert each value into the tree; dynamic alloc functions should be called. - for (size_t i = 0; i < INT_ARRAY_SIZE; ++i) + for (size_t i = 0; i < kIntArraySize; ++i) ASSERT_NE(0, lwpa_rbtree_insert(&tree, &random_int_array[i])); - ASSERT_EQ(INT_ARRAY_SIZE, lwpa_rbtree_size(&tree)); + ASSERT_EQ(kIntArraySize, lwpa_rbtree_size(&tree)); // Initialize an iterator LwpaRbIter iter; @@ -189,11 +190,11 @@ TEST_F(RbTreeTest, iter) ASSERT_GT(*val, last_val); last_val = *val; } - ASSERT_EQ(num_iterations, INT_ARRAY_SIZE); + ASSERT_EQ(num_iterations, kIntArraySize); // Get the last value. val = (int*)lwpa_rbiter_last(&iter, &tree); - ASSERT_EQ(*val, static_cast(INT_ARRAY_SIZE - 1)); + ASSERT_EQ(*val, static_cast(kIntArraySize - 1)); // Test iterating through the tree in reverse order. num_iterations = 1; @@ -206,12 +207,12 @@ TEST_F(RbTreeTest, iter) ASSERT_LT(*val, last_val); last_val = *val; } - ASSERT_EQ(num_iterations, INT_ARRAY_SIZE); + ASSERT_EQ(num_iterations, kIntArraySize); // Clear the tree. ASSERT_NE(0, lwpa_rbtree_clear(&tree)); ASSERT_EQ(0u, lwpa_rbtree_size(&tree)); - ASSERT_EQ(INT_ARRAY_SIZE, dealloc_call_count); + ASSERT_EQ(kIntArraySize, dealloc_call_count); } TEST_F(RbTreeTest, max_height) @@ -219,11 +220,11 @@ TEST_F(RbTreeTest, max_height) LwpaRbTree tree; ASSERT_TRUE(NULL != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); // Insert monotonically incrementing values into the tree. In a traditional binary tree, this - // would result in a worst-case unbalanced tree of height INT_ARRAY_SIZE. In the red-black tree, - // the maximum height should be determined by the formula 2 * log2(INT_ARRAY_SIZE + 1). - for (size_t i = 0; i < INT_ARRAY_SIZE; ++i) + // would result in a worst-case unbalanced tree of height kIntArraySize. In the red-black tree, + // the maximum height should be determined by the formula 2 * log2(kIntArraySize + 1). + for (size_t i = 0; i < kIntArraySize; ++i) ASSERT_NE(0, lwpa_rbtree_insert(&tree, &incrementing_int_array[i])); - ASSERT_EQ(INT_ARRAY_SIZE, lwpa_rbtree_size(&tree)); + ASSERT_EQ(kIntArraySize, lwpa_rbtree_size(&tree)); // Get the height of the tree and compare it against the theoretical maximum. LwpaRbIter iter; @@ -238,11 +239,11 @@ TEST_F(RbTreeTest, max_height) } while (NULL != lwpa_rbiter_next(&iter)); max_height += 1; // http://www.doctrina.org/maximum-height-of-red-black-tree.html - theoretical_max_height = 2 * (size_t)(log(INT_ARRAY_SIZE + 1) / log(2)); + theoretical_max_height = 2 * (size_t)(log(kIntArraySize + 1) / log(2)); ASSERT_LE(max_height, theoretical_max_height); // Clear the tree ASSERT_NE(0, lwpa_rbtree_clear(&tree)); ASSERT_EQ(0u, lwpa_rbtree_size(&tree)); - ASSERT_EQ(INT_ARRAY_SIZE, dealloc_call_count); + ASSERT_EQ(kIntArraySize, dealloc_call_count); } diff --git a/tests/unit/test_rwlock.cpp b/tests/unit/test_rwlock.cpp index 70ae82b5f..70d3403e4 100644 --- a/tests/unit/test_rwlock.cpp +++ b/tests/unit/test_rwlock.cpp @@ -29,11 +29,6 @@ static_assert(std::ratio_less_equal::value, "This platform does not have access to a millisecond-resolution clock. This test cannot be run."); -static_assert(std::chrono::high_resolution_clock::is_steady, "No"); class ThreadTest : public ::testing::Test { From f32836a659bf631e453e2fb50a55c0b5acfab2f8 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 3 Jun 2019 18:02:29 -0500 Subject: [PATCH 013/264] More WIP --- CHANGELOG.md | 11 ++++ docs/mainpage.md | 16 +++--- include/lwpa/common.h | 7 ++- src/CMakeLists.txt | 7 +-- src/lwpa/common.c | 34 +++++++++--- src/lwpa/log.c | 2 +- src/lwpa/private/netint.h | 28 ++++++++++ src/os/linux/lwpa/os_error.c | 97 +++++++++++++++++++++++++++++++++++ src/os/linux/lwpa/os_error.h | 27 ++++++++++ src/os/linux/lwpa/os_netint.c | 55 ++++++++++++++++++++ src/os/linux/lwpa/os_socket.c | 78 +--------------------------- 11 files changed, 266 insertions(+), 96 deletions(-) create mode 100644 src/lwpa/private/netint.h create mode 100644 src/os/linux/lwpa/os_error.c create mode 100644 src/os/linux/lwpa/os_error.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 41b7002d1..3023133cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to the lwpa library will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Added +- OS port: Linux + +### Changed +- Naming: 'operating system' and 'platform' are used somewhat interchangably by + this library, but operating system more correctly refers to what lwpa targets. + Plus, 'os' makes for nicer names than 'plat'. A pass is made for consistency. + +### Removed + ## [0.2.0] - 2019-05-29 ### Added - This CHANGELOG file. diff --git a/docs/mainpage.md b/docs/mainpage.md index 658e92170..b0abc983e 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -19,25 +19,27 @@ To jump right into the documentation, check out the the sources for lwpa are located in the heirarchy: ``` src/ - [platform_name]/ - [platform-specific lwpa sources] + os/ + [OS name]/ + [platform-specific lwpa sources] [platform-neutral lwpa sources] ``` The includes are in the heirarchy: ``` include/ - [platform_name]/ - [platform-specific lwpa headers] + os/ + [OS name]/ + [platform-specific lwpa headers] [platform-neutral lwpa headers] ``` -Some lwpa headers are platform-specific and duplicated for each platform. +Some lwpa headers are platform-specific and duplicated for each OS. Platform-specific headers for the same module will always conform to an identical interface, as documented in that module's documentation. -## Platforms +## Supported Platforms -lwpa is currently ported for the following platforms: +lwpa is currently ported for the following operating systems: + Microsoft Windows + Linux diff --git a/include/lwpa/common.h b/include/lwpa/common.h index ccf9cd2f9..f5900191c 100644 --- a/include/lwpa/common.h +++ b/include/lwpa/common.h @@ -42,10 +42,13 @@ #define LWPA_WAIT_FOREVER -1 #define LWPA_FEATURE_SOCKETS 0x00000001u -#define LWPA_FEATURE_TIMERS 0x00000002u -#define LWPA_FEATURE_LOGGING 0x00000004u +#define LWPA_FEATURE_NETINTS 0x00000002u +#define LWPA_FEATURE_TIMERS 0x00000004u +#define LWPA_FEATURE_LOGGING 0x00000008u #define LWPA_FEATURES_ALL 0xffffffffu +#define LWPA_FEATURES_ALL_BUT(mask) (((uint32_t)LWPA_FEATURES_ALL) & ((uint32_t)(~((uint32_t)(mask))))) + typedef uint32_t lwpa_features_t; #ifdef __cplusplus diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 529eaf253..fbdb7b956 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,15 +67,16 @@ add_library(lwpa ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_thread.h ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_socket.h # lwpa sources - ${LWPA_ROOT}/src/lwpa/uuid.c + ${LWPA_ROOT}/src/lwpa/common.c ${LWPA_ROOT}/src/lwpa/error.c ${LWPA_ROOT}/src/lwpa/log.c + ${LWPA_ROOT}/src/lwpa/md5.h + ${LWPA_ROOT}/src/lwpa/md5.c ${LWPA_ROOT}/src/lwpa/mempool.c ${LWPA_ROOT}/src/lwpa/pdu.c ${LWPA_ROOT}/src/lwpa/rbtree.c ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c - ${LWPA_ROOT}/src/lwpa/md5.h - ${LWPA_ROOT}/src/lwpa/md5.c + ${LWPA_ROOT}/src/lwpa/uuid.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_common.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c diff --git a/src/lwpa/common.c b/src/lwpa/common.c index 3218dd8d3..1e8f55b09 100644 --- a/src/lwpa/common.c +++ b/src/lwpa/common.c @@ -18,31 +18,53 @@ ******************************************************************************/ #include "lwpa/common.h" + +#include "lwpa/bool.h" #include "lwpa/private/common.h" #include "lwpa/private/log.h" +#include "lwpa/private/netint.h" lwpa_error_t lwpa_init(lwpa_features_t features) { + bool os_initted = false; + bool logging_initted = false; + // Step 1: OS-specific init lwpa_error_t res = lwpa_os_init(features); - if (res != kLwpaErrOk) - return res; + os_initted = (res == kLwpaErrOk); // Step 2: OS-neutral init - if (features & LWPA_FEATURE_LOGGING) + if (res == kLwpaErrOk) { - res = lwpa_log_init(); - if (res != kLwpaErrOk) + if (features & LWPA_FEATURE_LOGGING) { - lwpa_os_deinit(features); + logging_initted = ((res = lwpa_log_init()) == kLwpaErrOk); } } + + if (features & LWPA_FEATURE_NETINTS) + { + res = lwpa_netint_init(); + } + + if (res != kLwpaErrOk) + { + // Clean up on failure + if (logging_initted) + lwpa_log_deinit(); + if (os_initted) + lwpa_os_deinit(features); + } return res; } void lwpa_deinit(lwpa_features_t features) { // Step 1: OS-neutral deinit + if (features & LWPA_FEATURE_NETINTS) + { + lwpa_netint_deinit(); + } if (features & LWPA_FEATURE_LOGGING) { lwpa_log_deinit(); diff --git a/src/lwpa/log.c b/src/lwpa/log.c index 8883eac26..f29dac3a6 100644 --- a/src/lwpa/log.c +++ b/src/lwpa/log.c @@ -347,7 +347,7 @@ void lwpa_log(const LwpaLogParams* params, int pri, const char* format, ...) */ void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list args) { - if (!params || !params->log_fn || !format || !(LWPA_LOG_MASK(pri) & params->log_mask)) + if (!module_initialized || !params || !params->log_fn || !format || !(LWPA_LOG_MASK(pri) & params->log_mask)) return; LwpaLogTimeParams time_params; diff --git a/src/lwpa/private/netint.h b/src/lwpa/private/netint.h new file mode 100644 index 000000000..11ffbad61 --- /dev/null +++ b/src/lwpa/private/netint.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_PRIVATE_NETINT_H_ +#define _LWPA_PRIVATE_NETINT_H_ + +#include "lwpa/error.h" + +lwpa_error_t lwpa_netint_init(); +void lwpa_netint_deinit(); + +#endif /* _LWPA_PRIVATE_NETINT_H_ */ diff --git a/src/os/linux/lwpa/os_error.c b/src/os/linux/lwpa/os_error.c new file mode 100644 index 000000000..02844ea0f --- /dev/null +++ b/src/os/linux/lwpa/os_error.c @@ -0,0 +1,97 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "os_error.h" + +lwpa_error_t err_os_to_lwpa(int errno) +{ + switch (errno) + { + /* + case WSAEBADF: + case WSAENOTSOCK: + case WSATYPE_NOT_FOUND: + case WSAHOST_NOT_FOUND: + case WSAESTALE: + return kLwpaErrNotFound; + case WSA_INVALID_HANDLE: + case WSA_INVALID_PARAMETER: + case WSAEFAULT: + case WSAEINVAL: + case WSAEDESTADDRREQ: + case WSAENOPROTOOPT: + return kLwpaErrInvalid; + case WSA_NOT_ENOUGH_MEMORY: + case WSAEMFILE: + case WSAETOOMANYREFS: + case WSAEPROCLIM: + case WSAEUSERS: + return kLwpaErrNoMem; + case WSA_IO_PENDING: + case WSAEINPROGRESS: + return kLwpaErrInProgress; + case WSA_IO_INCOMPLETE: + case WSAEALREADY: + return kLwpaErrAlready; + case WSAEWOULDBLOCK: + return kLwpaErrWouldBlock; + case WSAEMSGSIZE: + return kLwpaErrMsgSize; + case WSAEADDRINUSE: + return kLwpaErrAddrInUse; + case WSAEADDRNOTAVAIL: + return kLwpaErrAddrNotAvail; + case WSAENETDOWN: + case WSAENETUNREACH: + case WSAENETRESET: + case WSAEHOSTDOWN: + case WSAEHOSTUNREACH: + return kLwpaErrNetwork; + case WSAECONNRESET: + case WSAECONNABORTED: + return kLwpaErrConnReset; + case WSAEISCONN: + return kLwpaErrIsConn; + case WSAENOTCONN: + return kLwpaErrNotConn; + case WSAESHUTDOWN: + return kLwpaErrShutdown; + case WSAETIMEDOUT: + return kLwpaErrTimedOut; + case WSAECONNREFUSED: + return kLwpaErrConnRefused; + case WSAENOBUFS: + return kLwpaErrBufSize; + case WSANOTIMPLIALISED: + case WSASYSNOTREADY: + return kLwpaErrNotImpl; + case WSAEACCES: + case WSA_OPERATION_ABORTED: + case WSAEPROTOTYPE: + case WSAEPROTONOSUPPORT: + case WSAESOCKTNOSUPPORT: + case WSAEOPNOTSUPP: + case WSAEPFNOSUPPORT: + case WSAEAFNOSUPPORT: + case WSASYSCALLFAILURE: + */ + default: + return kLwpaErrSys; + } +} diff --git a/src/os/linux/lwpa/os_error.h b/src/os/linux/lwpa/os_error.h new file mode 100644 index 000000000..1875747c8 --- /dev/null +++ b/src/os/linux/lwpa/os_error.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_ERROR_H_ +#define _LWPA_OS_ERROR_H_ + +#include "lwpa/error.h" + +lwpa_error_t errno_os_to_lwpa(int errno); + +#endif /* _LWPA_OS_ERROR_H_ */ diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 654bba7fa..766fcf78d 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -18,3 +18,58 @@ ******************************************************************************/ #include "lwpa/netint.h" + +#include +#include +#include +#include "lwpa/private/netint.h" +#include "os_error.h" + +/**************************** Private variables ******************************/ + +bool module_initialized; +struct ifaddrs* os_addrs; +size_t num_addrs; + +/*********************** Private function prototypes *************************/ + +static lwpa_error_t re_enumerate_os_addrs(); + +/*************************** Function definitions ****************************/ + +lwpa_error_t lwpa_netint_init() +{ + lwpa_error_t res = kLwpaErrOk; + if (!module_initialized) + { + res = re_enumerate_os_addrs(); + if (res == kLwpaErrOk) + module_initialized = true; + } + return res; +} + +void lwpa_netint_deinit() +{ + if (module_initialized) + { + freeifaddrs(os_addrs); + module_initialized = false; + } +} + +lwpa_error_t re_enumerate_os_addrs() +{ + if (getifaddrs(&os_addrs) < 0) + { + return errno_os_to_lwpa(errno); + } + + num_addrs = 0; + for (struct ifaddrs* ifaddr = os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + { + // TODO more logic... + ++num_addrs; + } + return kLwpaErrOk; +} diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 78f8726eb..8d2bb2041 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -21,6 +21,7 @@ #include #include #include +#include "os_error.h" bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { @@ -63,83 +64,6 @@ size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) return ret; } -/* -static lwpa_error_t err_os_to_lwpa(int wsaerror) -{ - switch (wsaerror) - { - case WSAEBADF: - case WSAENOTSOCK: - case WSATYPE_NOT_FOUND: - case WSAHOST_NOT_FOUND: - case WSAESTALE: - return kLwpaErrNotFound; - case WSA_INVALID_HANDLE: - case WSA_INVALID_PARAMETER: - case WSAEFAULT: - case WSAEINVAL: - case WSAEDESTADDRREQ: - case WSAENOPROTOOPT: - return kLwpaErrInvalid; - case WSA_NOT_ENOUGH_MEMORY: - case WSAEMFILE: - case WSAETOOMANYREFS: - case WSAEPROCLIM: - case WSAEUSERS: - return kLwpaErrNoMem; - case WSA_IO_PENDING: - case WSAEINPROGRESS: - return kLwpaErrInProgress; - case WSA_IO_INCOMPLETE: - case WSAEALREADY: - return kLwpaErrAlready; - case WSAEWOULDBLOCK: - return kLwpaErrWouldBlock; - case WSAEMSGSIZE: - return kLwpaErrMsgSize; - case WSAEADDRINUSE: - return kLwpaErrAddrInUse; - case WSAEADDRNOTAVAIL: - return kLwpaErrAddrNotAvail; - case WSAENETDOWN: - case WSAENETUNREACH: - case WSAENETRESET: - case WSAEHOSTDOWN: - case WSAEHOSTUNREACH: - return kLwpaErrNetwork; - case WSAECONNRESET: - case WSAECONNABORTED: - return kLwpaErrConnReset; - case WSAEISCONN: - return kLwpaErrIsConn; - case WSAENOTCONN: - return kLwpaErrNotConn; - case WSAESHUTDOWN: - return kLwpaErrShutdown; - case WSAETIMEDOUT: - return kLwpaErrTimedOut; - case WSAECONNREFUSED: - return kLwpaErrConnRefused; - case WSAENOBUFS: - return kLwpaErrBufSize; - case WSANOTIMPLIALISED: - case WSASYSNOTREADY: - return kLwpaErrNotImpl; - case WSAEACCES: - case WSA_OPERATION_ABORTED: - case WSAEPROTOTYPE: - case WSAEPROTONOSUPPORT: - case WSAESOCKTNOSUPPORT: - case WSAEOPNOTSUPP: - case WSAEPFNOSUPPORT: - case WSAEAFNOSUPPORT: - case WSASYSCALLFAILURE: - default: - return kLwpaErrSys; - } -} -*/ - lwpa_error_t lwpa_socket_init(void* os_data) { return kLwpaErrNotImpl; From b47da9b5d6555e10382fcd0b10f95665d9994fa6 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 4 Jun 2019 17:34:48 -0500 Subject: [PATCH 014/264] Still working on netints --- src/os/linux/lwpa/os_netint.c | 221 +++++++++++++++++++++++++++++++--- 1 file changed, 205 insertions(+), 16 deletions(-) diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 766fcf78d..16c764606 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -19,57 +19,246 @@ #include "lwpa/netint.h" -#include +#include #include #include +#include +#include +#include +#include +#include + +#include "lwpa/socket.h" #include "lwpa/private/netint.h" #include "os_error.h" +/***************************** Private types *********************************/ + +typedef struct RoutingTableEntry +{ + LwpaIpAddr addr; + LwpaIpAddr mask; + int interface_index; +} RoutingTableEntry; + /**************************** Private variables ******************************/ -bool module_initialized; -struct ifaddrs* os_addrs; -size_t num_addrs; +static struct LwpaNetintState +{ + bool initialized; + + RoutingTableEntry* routing_table_v4; + RoutingTableEntry* routing_table_v6; + + struct ifaddrs* os_addrs; + size_t num_addrs; + LwpaNetintInfo* lwpa_addrs; +} state; /*********************** Private function prototypes *************************/ -static lwpa_error_t re_enumerate_os_addrs(); +static lwpa_error_t build_routing_tables(); +static lwpa_error_t build_routing_table(int family, RoutingTableEntry** table); +static void free_routing_tables(); + +static lwpa_error_t enumerate_os_addrs(); +static void free_os_addrs(); /*************************** Function definitions ****************************/ lwpa_error_t lwpa_netint_init() { lwpa_error_t res = kLwpaErrOk; - if (!module_initialized) + if (!state.initialized) { res = re_enumerate_os_addrs(); if (res == kLwpaErrOk) - module_initialized = true; + state.initialized = true; } return res; } void lwpa_netint_deinit() { - if (module_initialized) + if (state.initialized) { - freeifaddrs(os_addrs); - module_initialized = false; + free_os_addrs(); + state.initialized = false; + } +} + +size_t lwpa_netint_get_num_interfaces() +{ + return state.num_addrs; +} + +size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) +{ + if (!netint_arr || netint_arr_size == 0) + return 0; + + size_t addrs_copied = (netint_arr_size < state.num_addrs ? netint_arr_size : state.num_addrs); + memcpy(netint_arr, state.lwpa_addrs, addrs_copied * sizeof(LwpaNetintInfo)); + return addrs_copied; +} + +lwpa_error_t build_routing_tables() +{ + state.routing_table_v4 = NULL; + state.routing_table_v6 = NULL; + + lwpa_error_t res = build_routing_table(AF_INET, &state.routing_table_v4); + if (res == kLwpaErrOk) + { + res = build_routing_table(AF_INET6, &state.routing_table_v6); + } + + if (res != kLwpaErrOk) + free_routing_tables(); + + return res; +} + +lwpa_error_t build_routing_table(int family, RoutingTableEntry** table) +{ + // Create a netlink socket, send a netlink request to get the routing table, and receive the + // reply. If the buffer was not big enough, repeat (cannot reuse the same socket because there + // could be issues with p + + lwpa_error_t result = kLwpaErrOk; + bool done = false; + size_t recvbufsize = 2048; // Tests show this is usually enough for small routing tables + while (result == kLwpaErrOk && !done) + { + struct sockaddr_nl addr; + memset(&addr, 0, sizeof(struct sockaddr_nl)); + addr.nl_family = AF_NETLINK; + + int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (sock == -1) + result = errno_os_to_lwpa(errno); + + if (result == kLwpaErrOk) + { + if (0 != bind(sock, (struct sockaddr*)&addr, sizeof(addr))) + result = errno_os_to_lwpa(errno); + } + + if (result) + result = create_send_request(sock, family); + + if (result) + { + result = recv_parse_reply(sock, recvbufsize); + switch (result) + { + case kLwpaErrOk: + done = true; + break; + case kLwpaErrBufSize: + recvbufsize *= 2; + break; + default: + } + } + + close(sock); } + return result; +} + +/* Quick helper for re_enumerate_os_addrs() to determine entries to skip in the linked list. */ +static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) +{ + // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. + return (!ifaddr->ifa_addr || (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6)); } -lwpa_error_t re_enumerate_os_addrs() +lwpa_error_t enumerate_os_addrs() { - if (getifaddrs(&os_addrs) < 0) + lwpa_error_t res = build_routing_tables(); + if (res != kLwpaErrOk) + return res; + + if (getifaddrs(&state.os_addrs) < 0) { return errno_os_to_lwpa(errno); } - num_addrs = 0; - for (struct ifaddrs* ifaddr = os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + // Pass 1: Total the number of addresses + state.num_addrs = 0; + for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + { + if (should_skip_ifaddr(ifaddr)) + continue; + + ++state.num_addrs; + } + + if (state.num_addrs == 0) { - // TODO more logic... - ++num_addrs; + freeifaddrs(state.os_addrs); + return kLwpaErrNoNetints; } + + // Allocate our interface array + state.lwpa_addrs = calloc(state.num_addrs, sizeof(LwpaNetintInfo)); + if (!state.lwpa_addrs) + { + freeifaddrs(state.os_addrs); + return kLwpaErrNoMem; + } + + // Pass 2: Fill in all the info about each address + size_t current_lwpa_index = 0; + for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + { + if (should_skip_ifaddr(ifaddr)) + continue; + + LwpaNetintInfo* current_info = &state.lwpa_addrs[current_lwpa_index]; + + // Interface name + strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); + current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; + + // Interface address + LwpaSockaddr temp_sockaddr; + sockaddr_os_to_lwpa(&temp_sockaddr, &ifaddr->ifa_addr); + current_info->addr = temp_sockaddr.ip; + + // Interface netmask + sockaddr_os_to_lwpa(&temp_sockaddr, &ifaddr->ifa_netmask); + current_info->mask = temp_sockaddr.ip; + } + return kLwpaErrOk; } + +void free_routing_tables() +{ + if (state.routing_table_v4) + { + free(state.routing_table_v4); + state.routing_table_v4 = NULL; + } + if (state.routing_table_v6) + { + free(state.routing_table_v6); + state.routing_table_v6 = NULL; + } +} + +void free_os_addrs() +{ + if (state.os_addrs) + { + freeifaddrs(state.os_addrs); + state.os_addrs = NULL; + } + if (state.lwpa_addrs) + { + free(state.lwpa_addrs); + state.lwpa_addrs = NULL; + } +} From 1e04f7cd79abc643efb60b0f603cc68eb4b148c1 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 5 Jun 2019 16:26:14 -0500 Subject: [PATCH 015/264] Push up WIP to continue on Windows --- docs/mainpage.md | 2 + include/lwpa/inet.h | 101 ++++------- include/lwpa/netint.h | 5 - src/CMakeLists.txt | 1 + src/lwpa/inet.c | 261 +++++++++++++++++++++++++++ src/os/linux/lwpa/os_error.h | 2 +- src/os/linux/lwpa/os_netint.c | 302 +++++++++++++++++++++++++++++--- src/os/linux/lwpa/os_socket.c | 46 ++--- src/os/windows/lwpa/os_netint.c | 45 +---- 9 files changed, 599 insertions(+), 166 deletions(-) create mode 100644 src/lwpa/inet.c diff --git a/docs/mainpage.md b/docs/mainpage.md index b0abc983e..9f3471b6e 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -103,3 +103,5 @@ The platform ports of lwpa have the following dependencies: + Linux - libuuid (if compiling lwpa, use `sudo apt-get install uuid-dev` or the equivalent method for your distribution) + - Optional Features: + * lwpa_netint (Network Interfaces): Linux 2.2, glibc 2.3.3 diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index deb970725..6374c4b77 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -34,6 +34,10 @@ * @{ */ +#ifdef __cplusplus +extern "C" { +#endif + /*! Used to identify the type of IP address contained in a LwpaIpAddr. */ typedef enum { @@ -72,39 +76,39 @@ typedef struct LwpaIpAddr /*! Determine whether a LwpaIpAddr contains an IPv4 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \return true (contains an IPv4 address) or false (does not contain an IPv4 address). */ -#define lwpaip_is_v4(lwpa_ip_ptr) ((lwpa_ip_ptr)->type == kLwpaIpTypeV4) +#define LWPA_IP_IS_V4(lwpa_ip_ptr) ((lwpa_ip_ptr)->type == kLwpaIpTypeV4) /*! Determine whether a LwpaIpAddr contains an IPv6 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \return true (contains an IPv6 address) or false (does not contain an IPv6 address). */ -#define lwpaip_is_v6(lwpa_ip_ptr) ((lwpa_ip_ptr)->type == kLwpaIpTypeV6) +#define LWPA_IP_IS_V6(lwpa_ip_ptr) ((lwpa_ip_ptr)->type == kLwpaIpTypeV6) /*! Determine whether a LwpaIpAddr contains an invalid address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \return true (is invalid) or false (is not invalid). */ -#define lwpaip_is_invalid(lwpa_ip_ptr) ((lwpa_ip_ptr)->type == kLwpaIpTypeInvalid) +#define LWPA_IP_IS_INVALID(lwpa_ip_ptr) ((lwpa_ip_ptr)->type == kLwpaIpTypeInvalid) /*! Get the IPv4 address from a LwpaIpAddr. It is recommended to first use lwpaip_is_v4() to make * sure this LwpaIpAddr contains a valid IPv4 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \return The IPv4 address (uint32_t). */ -#define lwpaip_v4_address(lwpa_ip_ptr) ((lwpa_ip_ptr)->addr.v4) +#define LWPA_IP_V4_ADDRESS(lwpa_ip_ptr) ((lwpa_ip_ptr)->addr.v4) /*! Get the IPv6 address from a LwpaIpAddr. It is recommended to first use lwpaip_is_v6() to make * sure this LwpaIpAddr contains a valid IPv6 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \return The IPv6 address (uint8_t[]). */ -#define lwpaip_v6_address(lwpa_ip_ptr) ((lwpa_ip_ptr)->addr.v6) +#define LWPA_IP_V6_ADDRESS(lwpa_ip_ptr) ((lwpa_ip_ptr)->addr.v6) /*! Set the IPv4 address in a LwpaIpAddr. Also sets the type field to indicate that this LwpaIpAddr * contains an IPv4 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \param val IPv4 address to set (uint32_t). */ -#define lwpaip_set_v4_address(lwpa_ip_ptr, val) \ - do \ - { \ - (lwpa_ip_ptr)->type = kLwpaIpTypeV4; \ - (lwpa_ip_ptr)->addr.v4 = val; \ +#define LWPA_IP_SET_V4_ADDRESS(lwpa_ip_ptr, val) \ + do \ + { \ + (lwpa_ip_ptr)->type = kLwpaIpTypeV4; \ + (lwpa_ip_ptr)->addr.v4 = val; \ } while (0) /*! Set the IPv6 address in a LwpaIpAddr. Also sets the type field to indicate that this LwpaIpAddr @@ -112,7 +116,7 @@ typedef struct LwpaIpAddr * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \param val IPv6 address to set (uint8_t[]). Must be at least of length LWPA_IPV6_BYTES. Gets * copied into the struct. */ -#define lwpaip_set_v6_address(lwpa_ip_ptr, val) \ +#define LWPA_IP_SET_V6_ADDRESS(lwpa_ip_ptr, val) \ do \ { \ (lwpa_ip_ptr)->type = kLwpaIpTypeV6; \ @@ -121,55 +125,7 @@ typedef struct LwpaIpAddr /*! Set the type field in a LwpaIpAddr to indicate that it does not contain a valid address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. */ -#define lwpaip_set_invalid(lwpa_ip_ptr) ((lwpa_ip_ptr)->type = kLwpaIpTypeInvalid) - -/*! Determine whether a LwpaIpAddr contains a multicast address. Works for either an IPv4 or an - * IPv6 address. - * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. - * \return true (contains a multicast address) or false (does not contain a multicast address). */ -#define lwpaip_is_multicast(lwpa_ip_ptr) \ - (((lwpa_ip_ptr)->type == kLwpaIpTypeV4) \ - ? (((lwpa_ip_ptr)->addr.v4 > 0xe0000000) && ((lwpa_ip_ptr)->addr.v4 < 0xefffffff)) \ - : ((lwpa_ip_ptr)->addr.v6[0] == 0xff)) - -/*! Determine whether two instances of LwpaIpAddr contain identical addresses. The type (IPv4 or - * IPv6) must be the same, as well as the value of the relevant address. - * \param ipptr1 Pointer to the first LwpaIpAddr to compare. - * \param ipptr2 Pointer to the second LwpaIpAddr to compare. - * \return true (IPs are identical) or false (IPs are not identical). */ -#define lwpaip_equal(ipptr1, ipptr2) \ - (((ipptr1)->type == (ipptr2)->type) \ - ? (((ipptr1)->type == kLwpaIpTypeV4) ? ((ipptr1)->addr.v4 == (ipptr2)->addr.v4) \ - : (0 == memcmp((ipptr1)->addr.v6, (ipptr2)->addr.v6, LWPA_IPV6_BYTES))) \ - : false) - -/*! A comparison algorithm for lwpa_ip addresses. All IPv4 addresses are considered to be < all - * IPv6 addresses. For matching types, the numerical address value is compared. - * \param ipptr1 Pointer to the first LwpaIpAddr to compare. - * \param ipptr2 Pointer to the second LwpaIpAddr to compare. - * \return < 0 (ipptr1 < ipptr2), 0 (ipptr1 == ipptr2), > 0 (ipptr1 > ipptr2) - */ -#define lwpaip_cmp(ipptr1, ipptr2) \ - (((ipptr1)->type != (ipptr2)->type) \ - ? ((ipptr1)->type - (ipptr2)->type) \ - : (((ipptr1)->type == kLwpaIpTypeV4) ? ((int)(ipptr1)->addr.v4 - (int)(ipptr2)->addr.v4) \ - : memcmp((ipptr1)->addr.v6, (ipptr2)->addr.v6, LWPA_IPV6_BYTES))) - -#define LWPA_INADDR_ANY 0 - -/*! Set a LwpaIpAddr to the IPv4 wildcard address. Use this macro; do not use LWPA_INADDR_ANY - * directly. - * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. */ -#define lwpaip_make_any_v4(lwpa_ip_ptr) lwpaip_set_v4_address(lwpa_ip_ptr, LWPA_INADDR_ANY) - -/*! Set a LwpaIpAddr to the IPv6 wildcard address. - * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. */ -#define lwpaip_make_any_v6(lwpa_ip_ptr) \ - do \ - { \ - (lwpa_ip_ptr)->type = kLwpaIpTypeV6; \ - memset(lwpaip_v6_address(lwpa_ip_ptr), 0, LWPA_IPV6_BYTES); \ - } while (0) +#define LWPA_IP_SET_INVALID(lwpa_ip_ptr) ((lwpa_ip_ptr)->type = kLwpaIpTypeInvalid) /*! @} */ @@ -181,14 +137,6 @@ typedef struct LwpaSockaddr uint32_t scope_id; /*!< IPv6 scope ID. */ } LwpaSockaddr; -/*! Determine whether two instances of LwpaSockaddr contain identical IP addresses and ports. - * \param sockptr1 Pointer to first LwpaSockaddr to compare. - * \param sockptr2 Pointer to second LwpaSockaddr to compare. - * \return true (the IP address and port are identical) or false (the IP address and port are not - * identical). */ -#define lwpasock_ip_port_equal(sockptr1, sockptr2) \ - (lwpaip_equal(&(sockptr1)->ip, &(sockptr2)->ip) && ((sockptr1)->port == (sockptr2)->port)) - #define LWPA_NETINTINFO_MAC_LEN 6 #define LWPA_NETINTINFO_NAME_LEN 64 @@ -212,6 +160,23 @@ typedef struct LwpaNetintInfo bool is_default; } LwpaNetintInfo; +bool lwpa_ip_is_multicast(const LwpaIpAddr* ip); +bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip); +void lwpa_ip_set_wildcard(LwpaIpAddr* ip, lwpa_iptype_t type); + +bool lwpa_ip_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2); +int lwpa_ip_cmp(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2); +bool lwpa_ip_and_port_equal(const LwpaSockaddr* sock1, const LwpaSockaddr* sock2); + +unsigned int lwpa_ip_mask_length(const LwpaIpAddr* netmask); +LwpaIpAddr lwpa_ipv4_mask_from_length(unsigned int mask_length); +LwpaIpAddr lwpa_ipv6_mask_from_length(unsigned int mask_length); +bool lwpa_ip_network_portions_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* netmask); + +#ifdef __cplusplus +} +#endif + /*! @} */ #endif /* _LWPA_INET_H_ */ diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index 20153d049..6aea9f9fc 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -44,11 +44,6 @@ bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint); const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, size_t netint_arr_size); -// typedef void (*netint_change_notification)(void *context); - -// int netint_register_change_cb(netint_change_notification fn, void -// *context); void netint_unregister_change_cb(int handle); - #ifdef __cplusplus } #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fbdb7b956..dea678b6d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -69,6 +69,7 @@ add_library(lwpa # lwpa sources ${LWPA_ROOT}/src/lwpa/common.c ${LWPA_ROOT}/src/lwpa/error.c + ${LWPA_ROOT}/src/lwpa/inet.c ${LWPA_ROOT}/src/lwpa/log.c ${LWPA_ROOT}/src/lwpa/md5.h ${LWPA_ROOT}/src/lwpa/md5.c diff --git a/src/lwpa/inet.c b/src/lwpa/inet.c new file mode 100644 index 000000000..211ae46d6 --- /dev/null +++ b/src/lwpa/inet.c @@ -0,0 +1,261 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/inet.h" + +/*! \brief Determine whether a LwpaIpAddr contains a multicast address. + * + * Works for both IPv4 and IPv6 addresses. + * + * \param[in] ip Address to check. + * \return true: ip contains a multicast address. + * \return false: ip does not contain a multicast address. + */ +bool lwpa_ip_is_multicast(const LwpaIpAddr* ip) +{ + if (ip) + { + if (LWPA_IP_IS_V4(ip)) + { + return (LWPA_IP_V4_ADDRESS(ip) > 0xe0000000 && LWPA_IP_V4_ADDRESS(ip) < 0xefffffff); + } + else if (LWPA_IP_IS_V6(ip)) + { + return (LWPA_IP_V6_ADDRESS(ip)[0] == 0xff); + } + } + return false; +} + +// Static storage causes this to be initialized to our desired value (all 0's) automatically +static const uint8_t v6_wildcard[LWPA_IPV6_BYTES]; + +bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip) +{ + if (ip) + { + if (LWPA_IP_IS_V4(ip)) + { + return (LWPA_IP_V4_ADDRESS(ip) == 0); + } + else if (LWPA_IP_IS_V6(ip)) + { + return (0 == memcmp(LWPA_IP_V6_ADDRESS(ip), v6_wildcard, LWPA_IPV6_BYTES)); + } + } + return false; +} + +void lwpa_ip_set_wildcard(LwpaIpAddr* ip, lwpa_iptype_t type) +{ + if (ip) + { + if (LWPA_IP_IS_V4(ip)) + { + LWPA_IP_SET_V4_ADDRESS(ip, 0); + } + else if (LWPA_IP_IS_V6(ip)) + { + LWPA_IP_SET_V6_ADDRESS(ip, v6_wildcard); + } + } +} + +/*! \brief Determine whether two instances of LwpaIpAddr contain identical addresses. + * + * The type (IPv4 or IPv6) must be the same, as well as the value of the relevant address. + * + * \param[in] ip1 First LwpaIpAddr to compare. + * \param[in] ip2 Second LwpaIpAddr to compare. + * \return true: IPs are identical. + * \return false: IPs are not identical. + */ +bool lwpa_ip_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2) +{ + if (ip1 && ip2 && ip1->type == ip2->type) + { + if (ip1->type == kLwpaIpTypeV4) + { + return LWPA_IP_V4_ADDRESS(ip1) == LWPA_IP_V4_ADDRESS(ip2); + } + else + { + return (0 == memcmp(LWPA_IP_V6_ADDRESS(ip1), LWPA_IP_V6_ADDRESS(ip2), LWPA_IPV6_BYTES)); + } + } + return false; +} + +/*! Compare two LwpaIpAddrs. + * + * Rules for comparison: + * * All Invalid addresses are considered to be equal to each other and < all IPv4 and IPv6 + * addresses + * * All IPv4 addresses are considered to be < all IPv6 addresses + * * For two IPv4 or IPv6 addresses, the numerical address value is compared + * + * \param ip1 First LwpaIpAddr to compare. + * \param ip2 Second LwpaIpAddr to compare. + * \return < 0: ip1 < ip2 + * \return 0: ip1 == ip2 + * \return > 0: ip1 > ip2 + */ +int lwpa_ip_cmp(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2) +{ + if (ip1 && ip2) + { + if (ip1->type != ip2->type) + { + return (int)(ip1->type - ip2->type); + } + else if (ip1->type == kLwpaIpTypeV4) + { + return ((int)LWPA_IP_V4_ADDRESS(ip1) - (int)LWPA_IP_V4_ADDRESS(ip2)); + } + else if (ip1->type == kLwpaIpTypeV6) + { + return memcmp(LWPA_IP_V6_ADDRESS(ip1), LWPA_IP_V6_ADDRESS(ip2), LWPA_IPV6_BYTES); + } + } + return 0; +} + +/*! \brief Determine whether two instances of LwpaSockaddr contain identical IP addresses and ports. + * \param[in] sock1 First LwpaSockaddr to compare. + * \param[in] sock2 Second LwpaSockaddr to compare. + * \return true: the IP address and port are identical. + * \return false: the IP address and port are not identical. + */ +bool lwpa_ip_and_port_equal(const LwpaSockaddr* sock1, const LwpaSockaddr* sock2) +{ + if (sock1 && sock2) + return (lwpa_ip_equal(&sock1->ip, &sock2->ip) && sock1->port == sock2->port); + else + return false; +} + +/*! \brief Get the length in bits of a netmask. + * + * Counts the number of set ('1') bits in the netmask, starting from the MSB. Works for both IPv4 + * and IPv6 netmasks. + * + * For example: + * netmask = 255.255.0.0 (0xffff0000); result = 16 + * netmask = ffff:ffff:ffff:ffff::; result = 64 + * + * \param[in] netmask Netmask to count. + * \return Number of set bits in the netmask. + */ +unsigned int lwpa_ip_mask_length(const LwpaIpAddr* netmask) +{ + unsigned int length = 0; + + if (netmask) + { + if (LWPA_IP_IS_V4(netmask)) + { + uint32_t addr_val = LWPA_IP_V4_ADDRESS(netmask); + while (addr_val & 0x8000) + { + ++length; + addr_val >>= 1; + } + } + else if (LWPA_IP_IS_V6(netmask)) + { + const uint8_t* addr_buf = LWPA_IP_V6_ADDRESS(netmask); + for (size_t i = 0; i < LWPA_IPV6_BYTES; ++i) + { + uint8_t addr_val = addr_buf[i]; + bool break_early = false; + for (size_t j = 0; j < 8; ++j, ++length) + { + if (!(addr_val & 0x80)) + { + break_early = true; + break; + } + } + if (break_early) + break; + } + } + } + + return length; +} + +LwpaIpAddr lwpa_ipv4_mask_from_length(unsigned int mask_length) +{ + LwpaIpAddr result; + LWPA_IP_SET_INVALID(&result); + + return result; +} + +LwpaIpAddr lwpa_ipv6_mask_from_length(unsigned int mask_length) +{ + LwpaIpAddr result; + LWPA_IP_SET_INVALID(&result); + + return result; +} + +/*! \brief Compare the network portions of two IP addresses using a netmask. + * + * Returns true if the _network_ portions of the IP addresses match. The host portions are + * disregarded. + * + * Some examples: + * ip1 = 192.168.0.1; ip2 = 192.168.0.2; netmask = 255.255.0.0 (/16); result = true + * ip1 = 192.168.0.1; ip2 = 192.168.1.1; netmask = 255.255.255.0 (/24); result = false + * ip1 = 2001:db8::1; ip2 = 2001:db8::2; netmask = ffff:ffff:ffff:ffff:: (/64); result = true + * ip1 = 2001:db8:1::1; ip2 = 2001:db8:2::1; netmask = ffff:ffff:ffff:ffff:: (/64); result = false + * + * \param[in] ip1 First LwpaIpAddr to compare. + * \param[in] ip2 Second LwpaIpAddr to compare. + * \param[in] netmask The netmask to use for the comparison. This mask is used to determine the + * network portion of each address. The lwpa_ip_mask_from_length() function can + * be used to turn a mask or prefix bit length into a mask. + * \return true: The network portions of the IP addresses are equal. + * \return false: The network portions are not equal. + */ +bool lwpa_ip_network_portions_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* netmask) +{ + if (LWPA_IP_IS_V4(ip1) && LWPA_IP_IS_V4(ip2) && LWPA_IP_IS_V4(netmask)) + { + return ((LWPA_IP_V4_ADDRESS(ip1) & LWPA_IP_V4_ADDRESS(netmask)) == + (LWPA_IP_V4_ADDRESS(ip2) & LWPA_IP_V4_ADDRESS(netmask))); + } + else if (LWPA_IP_IS_V6(ip1) && LWPA_IP_IS_V6(ip2) && LWPA_IP_IS_V6(netmask)) + { + size_t i; + const uint32_t* p1 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip1); + const uint32_t* p2 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip2); + const uint32_t* pm = (const uint32_t*)LWPA_IP_V6_ADDRESS(netmask); + + for (i = 0; i < LWPA_IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) + { + if ((*p1 & *pm) != (*p2 & *pm)) + return false; + } + return true; + } + return false; +} diff --git a/src/os/linux/lwpa/os_error.h b/src/os/linux/lwpa/os_error.h index 1875747c8..9978a07ef 100644 --- a/src/os/linux/lwpa/os_error.h +++ b/src/os/linux/lwpa/os_error.h @@ -22,6 +22,6 @@ #include "lwpa/error.h" -lwpa_error_t errno_os_to_lwpa(int errno); +lwpa_error_t errno_os_to_lwpa(int os_errno); #endif /* _LWPA_OS_ERROR_H_ */ diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 16c764606..8e56d13d7 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -17,9 +17,25 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ +/* The os_netint implementation for Linux. + * + * Uses getifaddrs() to get an initial list of network interfaces. More info: + * http://man7.org/linux/man-pages/man3/getifaddrs.3.html + * + * Then uses netlink sockets (specifically RTNETLINK) to fill out missing information about each + * interface. More info: + * + * Netlink sockets: http://man7.org/linux/man-pages/man7/netlink.7.html + * Netlink macros, for decoding netlink messages: http://man7.org/linux/man-pages/man3/netlink.3.html + * RtNetlink sockets: http://man7.org/linux/man-pages/man7/rtnetlink.7.html + * Some sample RtNetlink code: https://www.linuxjournal.com/article/8498 + */ + #include "lwpa/netint.h" #include +#include + #include #include #include @@ -27,6 +43,7 @@ #include #include #include +#include #include "lwpa/socket.h" #include "lwpa/private/netint.h" @@ -38,17 +55,32 @@ typedef struct RoutingTableEntry { LwpaIpAddr addr; LwpaIpAddr mask; + LwpaIpAddr gateway; int interface_index; + int metric; } RoutingTableEntry; +typedef struct RoutingTable +{ + RoutingTableEntry* entries; + size_t size; +} RoutingTable; + +/* A composite struct representing an RT_NETLINK request sent over a netlink socket. */ +typedef struct RtNetlinkRequest +{ + struct nlmsghdr nl_header; + struct rtmsg rt_msg; +} RtNetlinkRequest; + /**************************** Private variables ******************************/ static struct LwpaNetintState { bool initialized; - RoutingTableEntry* routing_table_v4; - RoutingTableEntry* routing_table_v6; + RoutingTable routing_table_v4; + RoutingTable routing_table_v6; struct ifaddrs* os_addrs; size_t num_addrs; @@ -57,10 +89,23 @@ static struct LwpaNetintState /*********************** Private function prototypes *************************/ +// Functions for building the routing tables static lwpa_error_t build_routing_tables(); -static lwpa_error_t build_routing_table(int family, RoutingTableEntry** table); +static lwpa_error_t build_routing_table(int family, RoutingTable* table); static void free_routing_tables(); +static void free_routing_table(RoutingTable* table); +// Interacting with RTNETLINK +static lwpa_error_t send_netlink_route_request(int socket, int family); +static lwpa_error_t receive_netlink_route_reply(int sock, size_t buf_size, RoutingTable* table); +static void cidr_length_to_v4_mask(unsigned char length, LwpaIpAddr* v4_mask); +static void cidr_length_to_v6_mask(unsigned char length, LwpaIpAddr* v6_mask); + +// Manipulating +static void init_routing_table_entry(RoutingTableEntry* entry); +static int compare_routing_table_entries(const void* a, const void* b); + +// Functions for enumerating the interfaces static lwpa_error_t enumerate_os_addrs(); static void free_os_addrs(); @@ -71,7 +116,7 @@ lwpa_error_t lwpa_netint_init() lwpa_error_t res = kLwpaErrOk; if (!state.initialized) { - res = re_enumerate_os_addrs(); + res = enumerate_os_addrs(); if (res == kLwpaErrOk) state.initialized = true; } @@ -104,9 +149,6 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ lwpa_error_t build_routing_tables() { - state.routing_table_v4 = NULL; - state.routing_table_v6 = NULL; - lwpa_error_t res = build_routing_table(AF_INET, &state.routing_table_v4); if (res == kLwpaErrOk) { @@ -119,15 +161,15 @@ lwpa_error_t build_routing_tables() return res; } -lwpa_error_t build_routing_table(int family, RoutingTableEntry** table) +lwpa_error_t build_routing_table(int family, RoutingTable* table) { // Create a netlink socket, send a netlink request to get the routing table, and receive the - // reply. If the buffer was not big enough, repeat (cannot reuse the same socket because there - // could be issues with p + // reply. If the buffer was not big enough, repeat (cannot reuse the same socket because we've + // often received partial messages that must be discarded) lwpa_error_t result = kLwpaErrOk; bool done = false; - size_t recvbufsize = 2048; // Tests show this is usually enough for small routing tables + size_t recv_buf_size = 2048; // Tests show this is usually enough for small routing tables while (result == kLwpaErrOk && !done) { struct sockaddr_nl addr; @@ -145,20 +187,22 @@ lwpa_error_t build_routing_table(int family, RoutingTableEntry** table) } if (result) - result = create_send_request(sock, family); + result = send_netlink_route_request(sock, family); if (result) { - result = recv_parse_reply(sock, recvbufsize); + result = receive_netlink_route_reply(sock, recv_buf_size, table); switch (result) { case kLwpaErrOk: done = true; break; case kLwpaErrBufSize: - recvbufsize *= 2; + recv_buf_size *= 2; + result = kLwpaErrOk; break; default: + break; } } @@ -167,7 +211,213 @@ lwpa_error_t build_routing_table(int family, RoutingTableEntry** table) return result; } -/* Quick helper for re_enumerate_os_addrs() to determine entries to skip in the linked list. */ +lwpa_error_t send_netlink_route_request(int socket, int family) +{ + // Build the request + RtNetlinkRequest req; + memset(&req, 0, sizeof(req)); + req.nl_header.nlmsg_len = NLMSG_LENGTH(sizeof(RtNetlinkRequest)); + req.nl_header.nlmsg_type = RTM_GETROUTE; + req.nl_header.nlmsg_flags = (__u16)(NLM_F_REQUEST | NLM_F_DUMP); + req.nl_header.nlmsg_pid = (__u32)getpid(); + req.rt_msg.rtm_family = (unsigned char)family; + req.rt_msg.rtm_table = RT_TABLE_MAIN; + + // Send it to the kernel + struct sockaddr_nl naddr; + memset(&naddr, 0, sizeof(naddr)); + naddr.nl_family = AF_NETLINK; + + if (sendto(socket, &req.nl_header, req.nl_header.nlmsg_len, 0, (struct sockaddr*)&naddr, sizeof(naddr)) >= 0) + return kLwpaErrOk; + else + return errno_os_to_lwpa(errno); +} + +lwpa_error_t receive_netlink_route_reply(int sock, size_t buf_size, RoutingTable* table) +{ + // Allocate slightly larger than buf_size, so we can detect when more room is needed + size_t real_size = buf_size + 20; + char* buffer = (char*)malloc(real_size); + if (!buffer) + return kLwpaErrNoMem; + memset(buffer, 0, real_size); + + struct nlmsghdr* nl_header; + char* cur_ptr = buffer; + size_t nl_msg_size = 0; + + // Read from the socket until the NLMSG_DONE is returned in the type of the RTNETLINK message + while (1) + { + // While we are receiving with real_size, checking against buf_size will detect when we've + // passed the limit given by the app + if (buf_size <= nl_msg_size) + { + free(buffer); + return kLwpaErrBufSize; + } + + ssize_t recv_res = recv(sock, cur_ptr, real_size - nl_msg_size, 0); + if (recv_res == -1) + { + free(buffer); + return errno_os_to_lwpa(errno); + } + + nl_header = (struct nlmsghdr*)cur_ptr; + + if (nl_header->nlmsg_type == NLMSG_DONE) + break; + + // Each message represents one route + ++table->size; + + // Adjust our position in the buffer and size received + cur_ptr += recv_res; + nl_msg_size += (size_t)recv_res; + } + + table->entries = calloc(table->size, sizeof(RoutingTableEntry)); + if (!table->entries) + { + table->size = 0; + free(buffer); + return kLwpaErrNoMem; + } + + // Parse the result + // outer loop: loops thru all the NETLINK headers that also include the route entry header + nl_header = (struct nlmsghdr*)buffer; + RoutingTableEntry* entry = table->entries; + for (; NLMSG_OK(nl_header, nl_msg_size); nl_header = NLMSG_NEXT(nl_header, nl_msg_size)) + { + init_routing_table_entry(entry); + + struct rtmsg* rt_message; + int rt_attr_size; + struct rtattr* rt_attributes; + + // get route entry header + rt_message = (struct rtmsg*)NLMSG_DATA(nl_header); + + // inner loop: loop thru all the attributes of one route entry. + rt_attributes = (struct rtattr*)RTM_RTA(rt_message); + rt_attr_size = (int)RTM_PAYLOAD(nl_header); + for (; RTA_OK(rt_attributes, rt_attr_size); rt_attributes = RTA_NEXT(rt_attributes, rt_attr_size)) + { + // We only care about the gateway and DST attribute + if (rt_attributes->rta_type == RTA_DST) + { + if (rt_attributes->rta_len == sizeof(struct in6_addr)) + LWPA_IP_SET_V6_ADDRESS(&entry->addr, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); + else + LWPA_IP_SET_V4_ADDRESS(&entry->addr, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); + } + else if (rt_attributes->rta_type == RTA_GATEWAY) + { + if (rt_attributes->rta_len == sizeof(struct in6_addr)) + LWPA_IP_SET_V6_ADDRESS(&entry->gateway, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); + else + LWPA_IP_SET_V4_ADDRESS(&entry->gateway, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); + } + else if (rt_attributes->rta_type == RTA_OIF) + { + entry->interface_index = *((int*)RTA_DATA(rt_attributes)); + } + else if (rt_attributes->rta_type == RTA_METRICS) + { + entry->metric = *((int*)RTA_DATA(rt_attributes)); + } + } + + if (LWPA_IP_IS_V4(&entry->addr)) + { + cidr_length_to_v4_mask(rt_message->rtm_dst_len, &entry->mask); + } + else if (LWPA_IP_IS_V6(&entry->addr)) + { + cidr_length_to_v6_mask(rt_message->rtm_dst_len, &entry->mask); + } + + ++entry; + } + + if (buffer) + free(buffer); + + qsort(table->entries, table->size, sizeof(RoutingTableEntry), compare_routing_table_entries); + + return kLwpaErrOk; +} + +void init_routing_table_entry(RoutingTableEntry* entry) +{ + LWPA_IP_SET_INVALID(&entry->addr); + LWPA_IP_SET_INVALID(&entry->mask); + LWPA_IP_SET_INVALID(&entry->gateway); + entry->interface_index = -1; + entry->metric = INT_MAX; +} + +int compare_routing_table_entries(const void* a, const void* b) +{ + RoutingTableEntry* e1 = (RoutingTableEntry*)a; + RoutingTableEntry* e2 = (RoutingTableEntry*)b; + + unsigned int mask_length_1 = lwpa_ip_mask_length(&e1->mask); + unsigned int mask_length_2 = lwpa_ip_mask_length(&e2->mask); + if (mask_length_1 > mask_length_2) + return 1; + else if (mask_length_1 == mask_length_2) + return 0; + else + return -1; +} + +void cidr_length_to_v4_mask(unsigned char length, LwpaIpAddr* v4_mask) +{ + unsigned char length_remaining = length; + uint32_t mask_val = 0; + uint32_t bit_to_set = 0x8000; + + // Cannot rely on signed/arithmetic shifts here because that behavior is implementation-defined + // in ANSI C + for (; length_remaining > 0; --length_remaining) + { + mask_val |= bit_to_set; + bit_to_set >>= 1; + } + + LWPA_IP_SET_V4_ADDRESS(v4_mask, mask_val); +} + +void cidr_length_to_v6_mask(unsigned char length, LwpaIpAddr* v6_mask) +{ + uint8_t mask_buf[LWPA_IPV6_BYTES]; + size_t mask_buf_index = 0; + unsigned char length_remaining = length; + uint8_t bit_to_set = 0x80; + + // Cannot rely on signed/arithmetic shifts here because that behavior is implementation-defined + // in ANSI C + for (; length_remaining > 0; --length_remaining) + { + mask_buf[mask_buf_index] |= bit_to_set; + bit_to_set >>= 1; + if (bit_to_set == 0) + { + if (++mask_buf_index >= LWPA_IPV6_BYTES) + break; + + bit_to_set = 0x80; + } + } + + LWPA_IP_SET_V6_ADDRESS(v6_mask, mask_buf); +} + +/* Quick helper for enumerate_os_addrs() to determine entries to skip in the linked list. */ static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) { // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. @@ -224,11 +474,11 @@ lwpa_error_t enumerate_os_addrs() // Interface address LwpaSockaddr temp_sockaddr; - sockaddr_os_to_lwpa(&temp_sockaddr, &ifaddr->ifa_addr); + sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_addr); current_info->addr = temp_sockaddr.ip; // Interface netmask - sockaddr_os_to_lwpa(&temp_sockaddr, &ifaddr->ifa_netmask); + sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); current_info->mask = temp_sockaddr.ip; } @@ -237,16 +487,18 @@ lwpa_error_t enumerate_os_addrs() void free_routing_tables() { - if (state.routing_table_v4) - { - free(state.routing_table_v4); - state.routing_table_v4 = NULL; - } - if (state.routing_table_v6) + free_routing_table(&state.routing_table_v4); + free_routing_table(&state.routing_table_v6); +} + +void free_routing_table(RoutingTable* table) +{ + if (table->entries) { - free(state.routing_table_v6); - state.routing_table_v6 = NULL; + free(table->entries); + table->entries = NULL; } + table->size = 0; } void free_os_addrs() diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 8d2bb2041..6ca99832d 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -29,14 +29,14 @@ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sa->port = ntohs(sin->sin_port); - lwpaip_set_v4_address(&sa->ip, ntohl(sin->sin_addr.s_addr)); + LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); return true; } else if (pfsa->sa_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sa->port = ntohs(sin6->sin6_port); - lwpaip_set_v6_address(&sa->ip, sin6->sin6_addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); return true; } return false; @@ -45,20 +45,20 @@ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; - if (lwpaip_is_v4(&sa->ip)) + if (LWPA_IP_IS_V4(&sa->ip)) { struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sin->sin_family = AF_INET; sin->sin_port = htons(sa->port); - sin->sin_addr.s_addr = htonl(lwpaip_v4_address(&sa->ip)); + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); ret = sizeof(struct sockaddr_in); } - else if (lwpaip_is_v6(&sa->ip)) + else if (LWPA_IP_IS_V6(&sa->ip)) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(sa->port); - memcpy(sin6->sin6_addr.s6_addr, lwpaip_v6_address(&sa->ip), LWPA_IPV6_BYTES); + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); ret = sizeof(struct sockaddr_in6); } return ret; @@ -91,7 +91,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* { closesocket(res); return kLwpaErrSys; - } +} *conn_sock = res; return kLwpaErrOk; } @@ -359,11 +359,11 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const // if (option_len == sizeof(LwpaMreq)) // { // LwpaMreq *amreq = (LwpaMreq *)option_value; - // if (lwpaip_is_v4(&amreq->group)) + // if (LWPA_IP_IS_V4(&amreq->group)) // { // struct ip_mreq val; - // val.imr_multiaddr.s_addr = htonl(lwpaip_v4_address(&amreq->group)); - // val.imr_interface.s_addr = htonl(lwpaip_v4_address(&amreq->netint)); + // val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + // val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); // res = setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&val, sizeof val); // } // } @@ -372,11 +372,11 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const // if (option_len == sizeof(LwpaMreq)) // { // LwpaMreq *amreq = (LwpaMreq *)option_value; - // if (lwpaip_is_v4(&amreq->group)) + // if (LWPA_IP_IS_V4(&amreq->group)) // { // struct ip_mreq val; - // val.imr_multiaddr.s_addr = htonl(lwpaip_v4_address(&amreq->group)); - // val.imr_interface.s_addr = htonl(lwpaip_v4_address(&amreq->netint)); + // val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + // val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); // res = setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&val, sizeof val); // } // } @@ -385,9 +385,9 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const // if (option_len == sizeof(LwpaIpAddr)) // { // LwpaIpAddr *netint = (LwpaIpAddr *)option_value; - // if (lwpaip_is_v4(netint)) + // if (LWPA_IP_IS_V4(netint)) // { - // DWORD val = htonl(lwpaip_v4_address(netint)); + // DWORD val = htonl(LWPA_IP_V4_ADDRESS(netint)); // res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char *)&val, sizeof val); // } // } @@ -418,12 +418,12 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const // if (option_len == sizeof(struct lwpa_mreq)) // { // LwpaMreq *amreq = (LwpaMreq *)option_value; - // if (lwpaip_is_v6(&amreq->group)) + // if (LWPA_IP_IS_V6(&amreq->group)) // { // struct ipv6_mreq val; // val.ipv6imr_interface = 0; // memcpy(&val.ipv6imr_multiaddr.s6_addr, - // lwpaip_v6_address(&amreq->group), LWPA_IPV6_BYTES); + // LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); // res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, // sizeof val); // } @@ -435,12 +435,12 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const // if (option_len == sizeof(struct lwpa_mreq)) // { // LwpaMreq *amreq = (LwpaMreq *)option_value; - // if (lwpaip_is_v6(&amreq->group)) + // if (LWPA_IP_IS_V6(&amreq->group)) // { // struct ipv6_mreq val; // val.ipv6imr_interface = 0; // memcpy(&val.ipv6imr_multiaddr.s6_addr, - // lwpaip_v6_address(&amreq->group), LWPA_IPV6_BYTES); + // LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); // res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, // sizeof val); // } @@ -702,7 +702,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) case kLwpaIpTypeV4: { struct in_addr addr; - addr.s_addr = htonl(lwpaip_v4_address(src)); + addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); if (NULL != inet_ntop(AF_INET, &addr, dest, (socklen_t)size)) return kLwpaErrOk; return kLwpaErrSys; @@ -710,7 +710,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) case kLwpaIpTypeV6: { struct in6_addr addr; - memcpy(addr.s6_addr, lwpaip_v6_address(src), LWPA_IPV6_BYTES); + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); if (NULL != inet_ntop(AF_INET6, &addr, dest, (socklen_t)size)) return kLwpaErrOk; return kLwpaErrSys; @@ -732,7 +732,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des struct in_addr addr; if (1 != inet_pton(AF_INET, src, &addr)) return kLwpaErrSys; - lwpaip_set_v4_address(dest, ntohl(addr.s_addr)); + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); return kLwpaErrOk; } case kLwpaIpTypeV6: @@ -740,7 +740,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des struct in6_addr addr; if (1 != inet_pton(AF_INET6, src, &addr)) return kLwpaErrSys; - lwpaip_set_v6_address(dest, addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); return kLwpaErrOk; } default: diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index 9875f55e1..9257bdf17 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -221,29 +221,6 @@ bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint) return res; } -bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask) -{ - if (lwpaip_is_v4(ip1) && lwpaip_is_v4(ip2) && lwpaip_is_v4(mask)) - { - return ((lwpaip_v4_address(ip1) & lwpaip_v4_address(mask)) == (lwpaip_v4_address(ip2) & lwpaip_v4_address(mask))); - } - else if (lwpaip_is_v6(ip1) && lwpaip_is_v6(ip2) && lwpaip_is_v6(mask)) - { - size_t i; - const uint32_t* p1 = (const uint32_t*)lwpaip_v6_address(ip1); - const uint32_t* p2 = (const uint32_t*)lwpaip_v6_address(ip2); - const uint32_t* pm = (const uint32_t*)lwpaip_v6_address(mask); - - for (i = 0; i < LWPA_IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) - { - if ((*p1 & *pm) != (*p2 & *pm)) - return false; - } - return true; - } - return false; -} - bool mask_is_empty(const LwpaIpAddr* mask) { uint32_t mask_part = 0; @@ -276,7 +253,7 @@ const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, con { if (netint->is_default) def = netint; - if (!mask_is_empty(&netint->mask) && mask_compare(&netint->addr, dest, &netint->mask)) + if (!lwpa_ip_is_wildcard(&netint->mask) && lwpa_ip_network_portions_equal(&netint->addr, dest, &netint->mask)) { res = netint; break; @@ -286,23 +263,3 @@ const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, con res = def; return res; } - -// static struct change_cb -//{ -// netint_change_notification fn; -// void *context; -// int handle; -// struct change_cb *next; -//} *change_cb_head; -// int next_handle; - -// int -// netint_register_change_cb(netint_change_notification fn, void *context) -//{ -// return -1; -//} - -// void netint_unregister_change_cb(int handle) -//{ - -//} From 0ee5f4130483544e1a02f6c34d944f18e9ba876b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 5 Jun 2019 18:27:21 -0500 Subject: [PATCH 016/264] Get things working on Windows again --- include/lwpa/inet.h | 6 +- include/lwpa/log.h | 1 + include/lwpa/netint.h | 1 + include/os/linux/lwpa/os_socket.h | 8 +- include/os/mqx/lwpa/os_socket.h | 8 +- include/os/windows/lwpa/os_socket.h | 8 +- src/CMakeLists.txt | 9 + src/lwpa/inet.c | 26 ++- src/os/linux/lwpa/os_netint.c | 42 ++-- src/os/lwip/lwpa/os_netint.c | 26 +-- src/os/lwip/lwpa/os_socket.c | 44 ++-- src/os/mqx/lwpa/os_netint.c | 26 +-- src/os/mqx/lwpa/os_socket.c | 44 ++-- src/os/windows/lwpa/os_common.c | 25 +-- src/os/windows/lwpa/os_netint.c | 315 +++++++++++++++------------- src/os/windows/lwpa/os_socket.c | 162 ++++---------- src/os/windows/lwpa/winsock_error.c | 102 +++++++++ src/os/windows/lwpa/winsock_error.h | 28 +++ tests/unit/main.cpp | 46 ++-- tests/unit/mqx/iar/test_netint.c | 12 +- tests/unit/mqx/iar/test_socket.c | 38 ++-- tests/unit/test_inet.cpp | 36 ++-- tests/unit/test_log.cpp | 12 +- tests/unit/test_netint.cpp | 20 +- tests/unit/test_socket.cpp | 57 ++--- tests/unit/test_socket_poll.cpp | 31 ++- 26 files changed, 614 insertions(+), 519 deletions(-) create mode 100644 src/os/windows/lwpa/winsock_error.c create mode 100644 src/os/windows/lwpa/winsock_error.h diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index 6374c4b77..50f19e0bc 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -88,13 +88,13 @@ typedef struct LwpaIpAddr * \return true (is invalid) or false (is not invalid). */ #define LWPA_IP_IS_INVALID(lwpa_ip_ptr) ((lwpa_ip_ptr)->type == kLwpaIpTypeInvalid) -/*! Get the IPv4 address from a LwpaIpAddr. It is recommended to first use lwpaip_is_v4() to make +/*! Get the IPv4 address from a LwpaIpAddr. It is recommended to first use LWPA_IP_IS_V4() to make * sure this LwpaIpAddr contains a valid IPv4 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \return The IPv4 address (uint32_t). */ #define LWPA_IP_V4_ADDRESS(lwpa_ip_ptr) ((lwpa_ip_ptr)->addr.v4) -/*! Get the IPv6 address from a LwpaIpAddr. It is recommended to first use lwpaip_is_v6() to make +/*! Get the IPv6 address from a LwpaIpAddr. It is recommended to first use LWPA_IP_IS_V6() to make * sure this LwpaIpAddr contains a valid IPv6 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \return The IPv6 address (uint8_t[]). */ @@ -162,7 +162,7 @@ typedef struct LwpaNetintInfo bool lwpa_ip_is_multicast(const LwpaIpAddr* ip); bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip); -void lwpa_ip_set_wildcard(LwpaIpAddr* ip, lwpa_iptype_t type); +void lwpa_ip_set_wildcard(lwpa_iptype_t type, LwpaIpAddr *ip); bool lwpa_ip_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2); int lwpa_ip_cmp(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2); diff --git a/include/lwpa/log.h b/include/lwpa/log.h index d318beae1..13f9367a6 100644 --- a/include/lwpa/log.h +++ b/include/lwpa/log.h @@ -24,6 +24,7 @@ #include #include #include "lwpa/bool.h" +#include "lwpa/common.h" /*! \defgroup lwpa_log lwpa_log * \ingroup lwpa diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index 6aea9f9fc..38b25d5f5 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -23,6 +23,7 @@ #include #include "lwpa/bool.h" +#include "lwpa/common.h" #include "lwpa/inet.h" /*! \defgroup lwpa_netint lwpa_netint diff --git a/include/os/linux/lwpa/os_socket.h b/include/os/linux/lwpa/os_socket.h index 45ababa40..ccace63eb 100644 --- a/include/os/linux/lwpa/os_socket.h +++ b/include/os/linux/lwpa/os_socket.h @@ -39,10 +39,10 @@ typedef struct LwpaPollContext int epoll_fd; } LwpaPollContext; -#define ip_os_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), ntohl((pfipptr)->s_addr)) -#define ip_lwpa_to_os_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(lwpaip_v4_address(lwpaipptr))) -#define ip_os_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) -#define ip_lwpa_to_os_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) +#define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), ntohl((pfipptr)->s_addr)) +#define IP_LWPA_TO_OS_V4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(LWPA_IP_V4_ADDRESS(lwpaipptr))) +#define IP_OS_TO_LWPA_V6(lwpaipptr, pfipptr) LWPA_IP_SET_V6_ADDRESS((lwpaipptr), (pfipptr)->s6_addr) +#define IP_LWPA_TO_OS_V6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, LWPA_IP_V6_ADDRESS(lwpaipptr), IPV6_BYTES) bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); diff --git a/include/os/mqx/lwpa/os_socket.h b/include/os/mqx/lwpa/os_socket.h index f0f74a339..8aeb7894f 100644 --- a/include/os/mqx/lwpa/os_socket.h +++ b/include/os/mqx/lwpa/os_socket.h @@ -34,10 +34,10 @@ typedef uint32_t lwpa_socket_t; extern "C" { #endif -#define ip_os_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), (pfipptr)->s_addr) -#define ip_lwpa_to_os_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = lwpaip_v4_address(lwpaipptr)) -#define ip_os_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) -#define ip_lwpa_to_os_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) +#define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), (pfipptr)->s_addr) +#define IP_LWPA_TO_OS_V4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = LWPA_IP_V4_ADDRESS(lwpaipptr)) +#define IP_OS_TO_LWPA_V6(lwpaipptr, pfipptr) LWPA_IP_SET_V6_ADDRESS((lwpaipptr), (pfipptr)->s6_addr) +#define IP_LWPA_TO_OS_V6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, LWPA_IP_V6_ADDRESS(lwpaipptr), IPV6_BYTES) bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); diff --git a/include/os/windows/lwpa/os_socket.h b/include/os/windows/lwpa/os_socket.h index 3d2e25a85..70eb842c5 100644 --- a/include/os/windows/lwpa/os_socket.h +++ b/include/os/windows/lwpa/os_socket.h @@ -73,10 +73,10 @@ typedef struct LwpaPollContext } LwpaPollContext; -#define ip_os_to_lwpa_v4(lwpaipptr, pfipptr) lwpaip_set_v4_address((lwpaipptr), ntohl((pfipptr)->s_addr)) -#define ip_lwpa_to_os_v4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(lwpaip_v4_address(lwpaipptr))) -#define ip_os_to_lwpa_v6(lwpaipptr, pfipptr) lwpaip_set_v6_address((lwpaipptr), (pfipptr)->s6_addr) -#define ip_lwpa_to_os_v6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, lwpaip_v6_address(lwpaipptr), IPV6_BYTES) +#define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), ntohl((pfipptr)->s_addr)) +#define IP_LWPA_TO_OS_V4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(LWPA_IP_V4_ADDRESS(lwpaipptr))) +#define IP_OS_TO_LWPA_V6(lwpaipptr, pfipptr) LWPA_IP_SET_V6_ADDRESS((lwpaipptr), (pfipptr)->s6_addr) +#define IP_LWPA_TO_OS_V6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, LWPA_IP_V6_ADDRESS(lwpaipptr), IPV6_BYTES) bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dea678b6d..3af960206 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -98,9 +98,17 @@ target_compile_definitions(lwpa PUBLIC ${LWPA_HAVE_CONFIG_H}) # Add include paths and library dependencies based on OS for which we are being compiled if(LWPA_TARGET_OS STREQUAL windows) + target_sources(lwpa PRIVATE + ${LWPA_ROOT}/src/os/windows/lwpa/winsock_error.h + ${LWPA_ROOT}/src/os/windows/lwpa/winsock_error.c + ) target_link_libraries(lwpa PUBLIC winmm ws2_32 Iphlpapi Rpcrt4) elseif(LWPA_TARGET_OS STREQUAL linux) target_link_libraries(lwpa PUBLIC uuid) + target_sources(lwpa PRIVATE + ${LWPA_ROOT}/src/os/linux/lwpa/os_error.h + ${LWPA_ROOT}/src/os/linux/lwpa/os_error.c + ) elseif(LWPA_TARGET_OS STREQUAL mqx) # Include the debug versions of the MQX libs if a Debug configuration is specified. # I think there's probably a better way of doing this and I'm missing something here. @@ -178,6 +186,7 @@ if(LWPA_BUILD_MOCK_LIB) ${LWPA_ROOT}/include ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS} ) + target_include_directories(lwpa_mock PRIVATE ${LWPA_ROOT}/src) target_compile_definitions(lwpa_mock PRIVATE LWPA_BUILDING_MOCK_LIB) target_link_libraries(lwpa_mock PUBLIC meekrosoft::fff) if(LWPA_TARGET_OS STREQUAL windows) diff --git a/src/lwpa/inet.c b/src/lwpa/inet.c index 211ae46d6..7c87ed8c9 100644 --- a/src/lwpa/inet.c +++ b/src/lwpa/inet.c @@ -19,6 +19,12 @@ #include "lwpa/inet.h" +/**************************** Private variables ******************************/ + +static const uint8_t v6_wildcard[LWPA_IPV6_BYTES] = {0}; + +/*************************** Function definitions ****************************/ + /*! \brief Determine whether a LwpaIpAddr contains a multicast address. * * Works for both IPv4 and IPv6 addresses. @@ -43,9 +49,6 @@ bool lwpa_ip_is_multicast(const LwpaIpAddr* ip) return false; } -// Static storage causes this to be initialized to our desired value (all 0's) automatically -static const uint8_t v6_wildcard[LWPA_IPV6_BYTES]; - bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip) { if (ip) @@ -62,17 +65,20 @@ bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip) return false; } -void lwpa_ip_set_wildcard(LwpaIpAddr* ip, lwpa_iptype_t type) +void lwpa_ip_set_wildcard(lwpa_iptype_t type, LwpaIpAddr* ip) { if (ip) { - if (LWPA_IP_IS_V4(ip)) - { - LWPA_IP_SET_V4_ADDRESS(ip, 0); - } - else if (LWPA_IP_IS_V6(ip)) + switch (type) { - LWPA_IP_SET_V6_ADDRESS(ip, v6_wildcard); + case kLwpaIpTypeV4: + LWPA_IP_SET_V4_ADDRESS(ip, 0); + break; + case kLwpaIpTypeV6: + LWPA_IP_SET_V6_ADDRESS(ip, v6_wildcard); + break; + default: + break; } } } diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 8e56d13d7..704b7502f 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -83,8 +83,8 @@ static struct LwpaNetintState RoutingTable routing_table_v6; struct ifaddrs* os_addrs; - size_t num_addrs; - LwpaNetintInfo* lwpa_addrs; + size_t num_netints; + LwpaNetintInfo* lwpa_netints; } state; /*********************** Private function prototypes *************************/ @@ -106,8 +106,8 @@ static void init_routing_table_entry(RoutingTableEntry* entry); static int compare_routing_table_entries(const void* a, const void* b); // Functions for enumerating the interfaces -static lwpa_error_t enumerate_os_addrs(); -static void free_os_addrs(); +static lwpa_error_t enumerate_netints(); +static void free_netints(); /*************************** Function definitions ****************************/ @@ -116,7 +116,7 @@ lwpa_error_t lwpa_netint_init() lwpa_error_t res = kLwpaErrOk; if (!state.initialized) { - res = enumerate_os_addrs(); + res = enumerate_netints(); if (res == kLwpaErrOk) state.initialized = true; } @@ -127,14 +127,14 @@ void lwpa_netint_deinit() { if (state.initialized) { - free_os_addrs(); + free_netints(); state.initialized = false; } } size_t lwpa_netint_get_num_interfaces() { - return state.num_addrs; + return state.num_netints; } size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) @@ -142,8 +142,8 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ if (!netint_arr || netint_arr_size == 0) return 0; - size_t addrs_copied = (netint_arr_size < state.num_addrs ? netint_arr_size : state.num_addrs); - memcpy(netint_arr, state.lwpa_addrs, addrs_copied * sizeof(LwpaNetintInfo)); + size_t addrs_copied = (netint_arr_size < state.num_netints ? netint_arr_size : state.num_netints); + memcpy(netint_arr, state.lwpa_netints, addrs_copied * sizeof(LwpaNetintInfo)); return addrs_copied; } @@ -417,14 +417,14 @@ void cidr_length_to_v6_mask(unsigned char length, LwpaIpAddr* v6_mask) LWPA_IP_SET_V6_ADDRESS(v6_mask, mask_buf); } -/* Quick helper for enumerate_os_addrs() to determine entries to skip in the linked list. */ +/* Quick helper for enumerate_netints() to determine entries to skip in the linked list. */ static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) { // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. return (!ifaddr->ifa_addr || (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6)); } -lwpa_error_t enumerate_os_addrs() +lwpa_error_t enumerate_netints() { lwpa_error_t res = build_routing_tables(); if (res != kLwpaErrOk) @@ -436,24 +436,24 @@ lwpa_error_t enumerate_os_addrs() } // Pass 1: Total the number of addresses - state.num_addrs = 0; + state.num_netints = 0; for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) { if (should_skip_ifaddr(ifaddr)) continue; - ++state.num_addrs; + ++state.num_netints; } - if (state.num_addrs == 0) + if (state.num_netints == 0) { freeifaddrs(state.os_addrs); return kLwpaErrNoNetints; } // Allocate our interface array - state.lwpa_addrs = calloc(state.num_addrs, sizeof(LwpaNetintInfo)); - if (!state.lwpa_addrs) + state.lwpa_netints = calloc(state.num_netints, sizeof(LwpaNetintInfo)); + if (!state.lwpa_netints) { freeifaddrs(state.os_addrs); return kLwpaErrNoMem; @@ -466,7 +466,7 @@ lwpa_error_t enumerate_os_addrs() if (should_skip_ifaddr(ifaddr)) continue; - LwpaNetintInfo* current_info = &state.lwpa_addrs[current_lwpa_index]; + LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; // Interface name strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); @@ -501,16 +501,16 @@ void free_routing_table(RoutingTable* table) table->size = 0; } -void free_os_addrs() +void free_netints() { if (state.os_addrs) { freeifaddrs(state.os_addrs); state.os_addrs = NULL; } - if (state.lwpa_addrs) + if (state.lwpa_netints) { - free(state.lwpa_addrs); - state.lwpa_addrs = NULL; + free(state.lwpa_netints); + state.lwpa_netints = NULL; } } diff --git a/src/os/lwip/lwpa/os_netint.c b/src/os/lwip/lwpa/os_netint.c index 34a80a822..2fc425ad8 100644 --- a/src/os/lwip/lwpa/os_netint.c +++ b/src/os/lwip/lwpa/os_netint.c @@ -46,9 +46,9 @@ static void copy_interface_info(struct netif* lwip_netint, LwpaNetintInfo* netin #if LWIP_IPV4 if (!ip_addr_isany(netif_ip_addr4(lwip_netint))) { - lwpaip_set_v4_address(&netint->addr, ntohl(netif_ip4_addr(lwip_netint)->addr)); - lwpaip_set_v4_address(&netint->mask, ntohl(netif_ip4_netmask(lwip_netint)->addr)); - lwpaip_set_v4_address(&netint->gate, ntohl(netif_ip4_gw(lwip_netint)->addr)); + LWPA_IP_SET_V4_ADDRESS(&netint->addr, ntohl(netif_ip4_addr(lwip_netint)->addr)); + LWPA_IP_SET_V4_ADDRESS(&netint->mask, ntohl(netif_ip4_netmask(lwip_netint)->addr)); + LWPA_IP_SET_V4_ADDRESS(&netint->gate, ntohl(netif_ip4_gw(lwip_netint)->addr)); } #endif #if 0 @@ -128,16 +128,16 @@ bool netint_get_default_interface(LwpaNetintInfo* netint) bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask) { - if (lwpaip_is_v4(ip1) && lwpaip_is_v4(ip2) && lwpaip_is_v4(mask)) + if (LWPA_IP_IS_V4(ip1) && LWPA_IP_IS_V4(ip2) && LWPA_IP_IS_V4(mask)) { - return ((lwpaip_v4_address(ip1) & lwpaip_v4_address(mask)) == (lwpaip_v4_address(ip2) & lwpaip_v4_address(mask))); + return ((LWPA_IP_V4_ADDRESS(ip1) & LWPA_IP_V4_ADDRESS(mask)) == (LWPA_IP_V4_ADDRESS(ip2) & LWPA_IP_V4_ADDRESS(mask))); } - else if (lwpaip_is_v6(ip1) && lwpaip_is_v6(ip2) && lwpaip_is_v6(mask)) + else if (LWPA_IP_IS_V6(ip1) && LWPA_IP_IS_V6(ip2) && LWPA_IP_IS_V6(mask)) { size_t i; - const uint32_t* p1 = (const uint32_t*)lwpaip_v6_address(ip1); - const uint32_t* p2 = (const uint32_t*)lwpaip_v6_address(ip2); - const uint32_t* pm = (const uint32_t*)lwpaip_v6_address(mask); + const uint32_t* p1 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip1); + const uint32_t* p2 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip2); + const uint32_t* pm = (const uint32_t*)LWPA_IP_V6_ADDRESS(mask); for (i = 0; i < IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) { @@ -153,12 +153,12 @@ bool mask_is_empty(const LwpaIpAddr* mask) { uint32_t mask_part = 0; - if (lwpaip_is_v4(mask)) - mask_part = lwpaip_v4_address(mask); - else if (lwpaip_is_v6(mask)) + if (LWPA_IP_IS_V4(mask)) + mask_part = LWPA_IP_V4_ADDRESS(mask); + else if (LWPA_IP_IS_V6(mask)) { size_t i; - const uint32_t* p = (const uint32_t*)lwpaip_v6_address(mask); + const uint32_t* p = (const uint32_t*)LWPA_IP_V6_ADDRESS(mask); for (i = 0; i < IPV6_BYTES / 4; ++i, ++p) mask_part |= *p; } diff --git a/src/os/lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c index 8b02961ca..ee1e63722 100644 --- a/src/os/lwip/lwpa/os_socket.c +++ b/src/os/lwip/lwpa/os_socket.c @@ -92,7 +92,7 @@ static bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) #if LWIP_IPV4 struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sa->port = ntohs(sin->sin_port); - lwpaip_set_v4_address(&sa->ip, ntohl(sin->sin_addr.s_addr)); + LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); return true; #else return false; @@ -103,7 +103,7 @@ static bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) #if LWIP_IPV6 struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sa->port = ntohs(sin6->sin6_port); - lwpaip_set_v6_address(&sa->ip, sin6->sin6_addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); return true; #else return false; @@ -115,23 +115,23 @@ static bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) static socklen_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) { socklen_t ret = 0; - if (lwpaip_is_v4(&sa->ip)) + if (LWPA_IP_IS_V4(&sa->ip)) { #if LWIP_IPV4 struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sin->sin_family = AF_INET; sin->sin_port = htons(sa->port); - sin->sin_addr.s_addr = htonl(lwpaip_v4_address(&sa->ip)); + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); ret = sizeof(struct sockaddr_in); #endif } - else if (lwpaip_is_v6(&sa->ip)) + else if (LWPA_IP_IS_V6(&sa->ip)) { #if LWIP_IPV6 struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(sa->port); - memcpy(sin6->sin6_addr.s6_addr, lwpaip_v6_address(&sa->ip), IPV6_BYTES); + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), IPV6_BYTES); ret = sizeof(struct sockaddr_in6); #endif } @@ -329,11 +329,11 @@ int lwpa_setsockopt(void* id, int level, int option_name, const void* option_val if (option_len == sizeof(struct lwpa_mreq)) { LwpaMreq* amreq = (LwpaMreq*)option_value; - if (lwpaip_is_v4(&amreq->group)) + if (LWPA_IP_IS_V4(&amreq->group)) { struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(lwpaip_v4_address(&amreq->group)); - val.imr_interface.s_addr = htonl(lwpaip_v4_address(&amreq->netint)); + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); res = setsockopt((int)id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &val, sizeof val); } } @@ -342,11 +342,11 @@ int lwpa_setsockopt(void* id, int level, int option_name, const void* option_val if (option_len == sizeof(struct lwpa_mreq)) { LwpaMreq* amreq = (LwpaMreq*)option_value; - if (lwpaip_is_v4(&amreq->group)) + if (LWPA_IP_IS_V4(&amreq->group)) { struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(lwpaip_v4_address(&amreq->group)); - val.imr_interface.s_addr = htonl(lwpaip_v4_address(&amreq->netint)); + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); res = setsockopt((int)id, IPPROTO_IP, IP_DROP_MEMBERSHIP, &val, sizeof val); } } @@ -355,10 +355,10 @@ int lwpa_setsockopt(void* id, int level, int option_name, const void* option_val if (option_len == sizeof(struct lwpa_ip)) { LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (lwpaip_is_v4(netint)) + if (LWPA_IP_IS_V4(netint)) { struct in_addr val; - val.s_addr = htonl(lwpaip_v4_address(netint)); + val.s_addr = htonl(LWPA_IP_V4_ADDRESS(netint)); res = setsockopt((int)id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); } } @@ -387,12 +387,12 @@ int lwpa_setsockopt(void* id, int level, int option_name, const void* option_val if (option_len == sizeof(struct lwpa_mreq)) { LwpaMreq *amreq = (LwpaMreq *)option_value; - if (lwpaip_is_v6(&amreq->group)) + if (LWPA_IP_IS_V6(&amreq->group)) { struct ipv6_mreq val; val.ipv6imr_interface = 0; memcpy(&val.ipv6imr_multiaddr.s6_addr, - lwpaip_v6_address(&amreq->group), IPV6_BYTES); + LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); res = setsockopt((int)id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, sizeof val); } @@ -404,12 +404,12 @@ int lwpa_setsockopt(void* id, int level, int option_name, const void* option_val if (option_len == sizeof(struct lwpa_mreq)) { LwpaMreq *amreq = (LwpaMreq *)option_value; - if (lwpaip_is_v6(&amreq->group)) + if (LWPA_IP_IS_V6(&amreq->group)) { struct ipv6_mreq val; val.ipv6imr_interface = 0; memcpy(&val.ipv6imr_multiaddr.s6_addr, - lwpaip_v6_address(&amreq->group), IPV6_BYTES); + LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); res = setsockopt((int)id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, sizeof val); } @@ -608,7 +608,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) case LWPA_IPV4: { struct in_addr addr; - addr.s_addr = htonl(lwpaip_v4_address(src)); + addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); if (NULL != inet_ntop(AF_INET, &addr, dest, size)) return kLwpaErrOk; return kLwpaErrSys; @@ -616,7 +616,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) case LWPA_IPV6: { struct in6_addr addr; - memcpy(addr.s6_addr, lwpaip_v6_address(src), IPV6_BYTES); + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), IPV6_BYTES); if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) return kLwpaErrOk; return kLwpaErrSys; @@ -638,7 +638,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des struct in_addr addr; if (1 != inet_pton(AF_INET, src, &addr)) return kLwpaErrSys; - lwpaip_set_v4_address(dest, ntohl(addr.s_addr)); + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); return kLwpaErrOk; } case LWPA_IPV6: @@ -646,7 +646,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des struct in6_addr addr; if (1 != inet_pton(AF_INET6, src, &addr)) return kLwpaErrSys; - lwpaip_set_v6_address(dest, addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); return kLwpaErrOk; } default: diff --git a/src/os/mqx/lwpa/os_netint.c b/src/os/mqx/lwpa/os_netint.c index 602176d6a..d8dc721fc 100644 --- a/src/os/mqx/lwpa/os_netint.c +++ b/src/os/mqx/lwpa/os_netint.c @@ -39,9 +39,9 @@ static void copy_interface_info(size_t mqx_index, LwpaNetintInfo* netint) netint->ifindex = (int)RTCS_if_get_handle(mqx_index); ipcfg_get_ip(mqx_index, &ip_data); - lwpaip_set_v4_address(&netint->addr, ip_data.ip); - lwpaip_set_v4_address(&netint->mask, ip_data.mask); - lwpaip_set_v4_address(&netint->gate, ip_data.gateway); + LWPA_IP_SET_V4_ADDRESS(&netint->addr, ip_data.ip); + LWPA_IP_SET_V4_ADDRESS(&netint->mask, ip_data.mask); + LWPA_IP_SET_V4_ADDRESS(&netint->gate, ip_data.gateway); ipcfg_get_mac(mqx_index, netint->mac); sprintf(netint->name, "en%d", mqx_index); @@ -84,16 +84,16 @@ bool netint_get_default_interface(LwpaNetintInfo* netint) bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask) { - if (lwpaip_is_v4(ip1) && lwpaip_is_v4(ip2) && lwpaip_is_v4(mask)) + if (LWPA_IP_IS_V4(ip1) && LWPA_IP_IS_V4(ip2) && LWPA_IP_IS_V4(mask)) { - return ((lwpaip_v4_address(ip1) & lwpaip_v4_address(mask)) == (lwpaip_v4_address(ip2) & lwpaip_v4_address(mask))); + return ((LWPA_IP_V4_ADDRESS(ip1) & LWPA_IP_V4_ADDRESS(mask)) == (LWPA_IP_V4_ADDRESS(ip2) & LWPA_IP_V4_ADDRESS(mask))); } - else if (lwpaip_is_v6(ip1) && lwpaip_is_v6(ip2) && lwpaip_is_v6(mask)) + else if (LWPA_IP_IS_V6(ip1) && LWPA_IP_IS_V6(ip2) && LWPA_IP_IS_V6(mask)) { size_t i; - const uint32_t* p1 = (const uint32_t*)lwpaip_v6_address(ip1); - const uint32_t* p2 = (const uint32_t*)lwpaip_v6_address(ip2); - const uint32_t* pm = (const uint32_t*)lwpaip_v6_address(mask); + const uint32_t* p1 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip1); + const uint32_t* p2 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip2); + const uint32_t* pm = (const uint32_t*)LWPA_IP_V6_ADDRESS(mask); for (i = 0; i < IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) { @@ -109,12 +109,12 @@ bool mask_is_empty(const LwpaIpAddr* mask) { uint32_t mask_part = 0; - if (lwpaip_is_v4(mask)) - mask_part = lwpaip_v4_address(mask); - else if (lwpaip_is_v6(mask)) + if (LWPA_IP_IS_V4(mask)) + mask_part = LWPA_IP_V4_ADDRESS(mask); + else if (LWPA_IP_IS_V6(mask)) { size_t i; - const uint32_t* p = (const uint32_t*)lwpaip_v6_address(mask); + const uint32_t* p = (const uint32_t*)LWPA_IP_V6_ADDRESS(mask); for (i = 0; i < IPV6_BYTES / 4; ++i, ++p) mask_part |= *p; } diff --git a/src/os/mqx/lwpa/os_socket.c b/src/os/mqx/lwpa/os_socket.c index 767d7cac7..0353519d0 100644 --- a/src/os/mqx/lwpa/os_socket.c +++ b/src/os/mqx/lwpa/os_socket.c @@ -88,14 +88,14 @@ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sa->port = sin->sin_port; - lwpaip_set_v4_address(&sa->ip, sin->sin_addr.s_addr); + LWPA_IP_SET_V4_ADDRESS(&sa->ip, sin->sin_addr.s_addr); return true; } else if (pfsa->sa_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sa->port = sin6->sin6_port; - lwpaip_set_v6_address(&sa->ip, sin6->sin6_addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); return true; } return false; @@ -104,20 +104,20 @@ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; - if (lwpaip_is_v4(&sa->ip)) + if (LWPA_IP_IS_V4(&sa->ip)) { struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sin->sin_family = AF_INET; sin->sin_port = sa->port; - sin->sin_addr.s_addr = lwpaip_v4_address(&sa->ip); + sin->sin_addr.s_addr = LWPA_IP_V4_ADDRESS(&sa->ip); ret = sizeof(struct sockaddr_in); } - else if (lwpaip_is_v6(&sa->ip)) + else if (LWPA_IP_IS_V6(&sa->ip)) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sin6->sin6_family = AF_INET6; sin6->sin6_port = sa->port; - memcpy(sin6->sin6_addr.s6_addr, lwpaip_v6_address(&sa->ip), IPV6_BYTES); + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), IPV6_BYTES); ret = sizeof(struct sockaddr_in6); } return ret; @@ -361,12 +361,12 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (option_len == sizeof(LwpaMreq)) { LwpaMreq* amreq = (LwpaMreq*)option_value; - if (lwpaip_is_v4(&amreq->group) && level == LWPA_IPPROTO_IP) + if (LWPA_IP_IS_V4(&amreq->group) && level == LWPA_IPPROTO_IP) { /* We don't need htonl -- MQX/RTCS stores IPv4s in host order. */ struct ip_mreq val; - val.imr_multiaddr.s_addr = lwpaip_v4_address(&amreq->group); - val.imr_interface.s_addr = lwpaip_v4_address(&amreq->netint); + val.imr_multiaddr.s_addr = LWPA_IP_V4_ADDRESS(&amreq->group); + val.imr_interface.s_addr = LWPA_IP_V4_ADDRESS(&amreq->netint); res = setsockopt(id, SOL_IGMP, RTCS_SO_IGMP_ADD_MEMBERSHIP, &val, sizeof val); if (res == RTCS_OK) { @@ -376,11 +376,11 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const setsockopt(id, SOL_IGMP, RTCS_SO_IGMP_ADD_MEMBERSHIP, &val, sizeof val); } } - else if (lwpaip_is_v6(&amreq->group) && level == LWPA_IPPROTO_IPV6) + else if (LWPA_IP_IS_V6(&amreq->group) && level == LWPA_IPPROTO_IPV6) { struct ipv6_mreq val; val.ipv6imr_interface = 0; /* TODO find out what MQX does with interface indexes */ - memcpy(&val.ipv6imr_multiaddr.s6_addr, lwpaip_v6_address(&amreq->group), IPV6_BYTES); + memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); res = setsockopt(id, SOL_IP6, RTCS_SO_IP6_JOIN_GROUP, &val, sizeof val); } } @@ -389,19 +389,19 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (option_len == sizeof(LwpaMreq)) { LwpaMreq* amreq = (LwpaMreq*)option_value; - if (lwpaip_is_v4(&amreq->group) && level == LWPA_IPPROTO_IP) + if (LWPA_IP_IS_V4(&amreq->group) && level == LWPA_IPPROTO_IP) { /* We don't need htonl -- MQX/RTCS stores IPv4s in host order. */ struct ip_mreq val; - val.imr_multiaddr.s_addr = lwpaip_v4_address(&amreq->group); - val.imr_interface.s_addr = lwpaip_v4_address(&amreq->netint); + val.imr_multiaddr.s_addr = LWPA_IP_V4_ADDRESS(&amreq->group); + val.imr_interface.s_addr = LWPA_IP_V4_ADDRESS(&amreq->netint); res = setsockopt(id, SOL_IGMP, RTCS_SO_IGMP_DROP_MEMBERSHIP, &val, sizeof val); } - else if (lwpaip_is_v6(&amreq->group) && level == LWPA_IPPROTO_IPV6) + else if (LWPA_IP_IS_V6(&amreq->group) && level == LWPA_IPPROTO_IPV6) { struct ipv6_mreq val; val.ipv6imr_interface = 0; /* TODO find out what MQX does with interface indexes */ - memcpy(&val.ipv6imr_multiaddr.s6_addr, lwpaip_v6_address(&amreq->group), IPV6_BYTES); + memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); res = setsockopt(id, SOL_IP6, RTCS_SO_IP6_LEAVE_GROUP, &val, sizeof val); } } @@ -425,8 +425,8 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const { LwpaIpAddr default_netint_ip; - lwpaip_set_v4_address(&default_netint_ip, ip_data.ip); - if (lwpaip_equal(netint_requested, &default_netint_ip)) + LWPA_IP_SET_V4_ADDRESS(&default_netint_ip, ip_data.ip); + if (lwpa_ip_equal(netint_requested, &default_netint_ip)) res = kLwpaErrOk; } } @@ -662,7 +662,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) { struct in_addr addr; /* RTCS expects host byte order in their in_addrs. Thus no htonl is needed. */ - addr.s_addr = lwpaip_v4_address(src); + addr.s_addr = LWPA_IP_V4_ADDRESS(src); if (NULL != inet_ntop(AF_INET, &addr, dest, size)) return kLwpaErrOk; return kLwpaErrSys; @@ -670,7 +670,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) case LWPA_IPV6: { struct in6_addr addr; - memcpy(addr.s6_addr, lwpaip_v6_address(src), IPV6_BYTES); + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), IPV6_BYTES); if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) return kLwpaErrOk; return kLwpaErrSys; @@ -693,7 +693,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des if (RTCS_OK != inet_pton(AF_INET, src, &addr, sizeof addr)) return kLwpaErrSys; /* RTCS gives us host byte order in their in_addrs. Thus no htonl is needed. */ - lwpaip_set_v4_address(dest, addr.s_addr); + LWPA_IP_SET_V4_ADDRESS(dest, addr.s_addr); return kLwpaErrOk; } case LWPA_IPV6: @@ -701,7 +701,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des struct in6_addr addr; if (RTCS_OK != inet_pton(AF_INET6, src, &addr, sizeof addr)) return kLwpaErrSys; - lwpaip_set_v6_address(dest, addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); return kLwpaErrOk; } default: diff --git a/src/os/windows/lwpa/os_common.c b/src/os/windows/lwpa/os_common.c index 8cf1066a7..1959a7b1d 100644 --- a/src/os/windows/lwpa/os_common.c +++ b/src/os/windows/lwpa/os_common.c @@ -21,28 +21,11 @@ #include #include "lwpa/bool.h" +#include "winsock_error.h" #define LWPA_WINDOWS_TIMER_RESOLUTION 1 // ms -static lwpa_error_t err_os_to_lwpa(int wsaerror) -{ - // Only dealing with the possible errors from WSAStartup() below. - switch (wsaerror) - { - case WSAEPROCLIM: - return kLwpaErrNoMem; - case WSAEINPROGRESS: - return kLwpaErrInProgress; - case WSASYSNOTREADY: - return kLwpaErrNotInit; - case WSAVERNOTSUPPORTED: - case WSAEFAULT: - default: - return kLwpaErrSys; - } -} - -lwpa_error_t lwpa_init(lwpa_features_t features) +lwpa_error_t lwpa_os_init(lwpa_features_t features) { bool timer_initted = false; @@ -62,13 +45,13 @@ lwpa_error_t lwpa_init(lwpa_features_t features) { if (timer_initted) timeEndPeriod(LWPA_WINDOWS_TIMER_RESOLUTION); - return err_os_to_lwpa(startup_res); + return err_winsock_to_lwpa(startup_res); } } return kLwpaErrOk; } -void lwpa_deinit(lwpa_features_t features) +void lwpa_os_deinit(lwpa_features_t features) { if (features & LWPA_FEATURE_TIMERS) { diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index 9257bdf17..de5ee1e4d 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -20,114 +20,222 @@ #include "lwpa/netint.h" #include -#include -#include -#include + +#include +#include +#include #include + #include "lwpa/int.h" +#include "lwpa/private/netint.h" -static bool mask_is_empty(const LwpaIpAddr* mask); -static bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask); +/**************************** Private variables ******************************/ -static IP_ADAPTER_ADDRESSES* get_windows_adapters() +static struct LwpaNetintState { - ULONG buflen = 0; - ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_GATEWAYS; + bool initialized; - /* Preallocating a buffer specifically this size is expressly recommended by the Microsoft usage - * page. */ - uint8_t* buffer = malloc(15000); - if (!buffer) - return NULL; + size_t num_netints; + LwpaNetintInfo* lwpa_netints; + bool have_default_netint_index; + size_t default_netint_index; +} state; - if (ERROR_BUFFER_OVERFLOW == GetAdaptersAddresses(AF_UNSPEC, flags, NULL, (IP_ADAPTER_ADDRESSES*)buffer, &buflen)) +/*********************** Private function prototypes *************************/ + +static IP_ADAPTER_ADDRESSES* get_windows_adapters(); +static void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, IP_ADAPTER_GATEWAY_ADDRESS* pgate, LwpaNetintInfo* info); +static void copy_all_netint_info(IP_ADAPTER_ADDRESSES *adapters); +static lwpa_error_t enumerate_netints(); +static void free_netints(); + +/*************************** Function definitions ****************************/ + +lwpa_error_t lwpa_netint_init() +{ + lwpa_error_t res = kLwpaErrOk; + if (!state.initialized) { - free(buffer); - buffer = malloc(buflen); - if (buffer && - (ERROR_SUCCESS == GetAdaptersAddresses(AF_UNSPEC, flags, NULL, (IP_ADAPTER_ADDRESSES*)buffer, &buflen))) - { - return (IP_ADAPTER_ADDRESSES*)buffer; - } + res = enumerate_netints(); + if (res == kLwpaErrOk) + state.initialized = true; } - return NULL; + return res; } -static void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, IP_ADAPTER_GATEWAY_ADDRESS* pgate, LwpaNetintInfo* info) +void lwpa_netint_deinit() { - struct sockaddr_in* sin = (struct sockaddr_in*)pip->Address.lpSockaddr; - struct sockaddr_in* gw_sin = pgate ? (struct sockaddr_in*)pgate->Address.lpSockaddr : NULL; - ULONG mask = 0; - - ConvertLengthToIpv4Mask(pip->OnLinkPrefixLength, &mask); - lwpaip_set_v4_address(&info->addr, ntohl(sin->sin_addr.s_addr)); - lwpaip_set_v4_address(&info->mask, ntohl((uint32_t)mask)); - if (pgate) - lwpaip_set_v4_address(&info->gate, ntohl(gw_sin->sin_addr.s_addr)); - else - lwpaip_set_v4_address(&info->gate, 0u); + if (state.initialized) + { + free_netints(); + memset(&state, 0, sizeof(state)); + } } size_t lwpa_netint_get_num_interfaces() +{ + return state.num_netints; +} + +size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) +{ + if (!netint_arr || netint_arr_size == 0) + return 0; + + size_t addrs_copied = (netint_arr_size < state.num_netints ? netint_arr_size : state.num_netints); + memcpy(netint_arr, state.lwpa_netints, addrs_copied * sizeof(LwpaNetintInfo)); + return addrs_copied; +} + +bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint) +{ + if (netint && state.have_default_netint_index) + { + *netint = state.lwpa_netints[state.default_netint_index]; + return true; + } + return false; +} + +const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, + size_t netint_arr_size) +{ + const LwpaNetintInfo* res = NULL; + const LwpaNetintInfo* def = NULL; + const LwpaNetintInfo* netint; + + if (!dest || !netint_arr || netint_arr_size == 0) + return false; + + for (netint = netint_arr; netint < netint_arr + netint_arr_size; ++netint) + { + if (netint->is_default) + def = netint; + if (!lwpa_ip_is_wildcard(&netint->mask) && lwpa_ip_network_portions_equal(&netint->addr, dest, &netint->mask)) + { + res = netint; + break; + } + } + if (!res) + res = def; + return res; +} + +lwpa_error_t enumerate_netints() { IP_ADAPTER_ADDRESSES *padapters, *pcur; - size_t n_ifaces = 0; padapters = get_windows_adapters(); if (!padapters) - return 0; + return kLwpaErrSys; pcur = padapters; + state.num_netints = 0; while (pcur) { - /* If this is multihomed, there may be multiple addresses under the same adapter */ + // If this is multihomed, there may be multiple addresses under the same adapter IP_ADAPTER_UNICAST_ADDRESS* pip = pcur->FirstUnicastAddress; while (pip) { switch (pip->Address.lpSockaddr->sa_family) { case AF_INET: - ++n_ifaces; + ++state.num_netints; break; case AF_INET6: default: - /* TODO IPv6 */ + // TODO IPv6 break; } pip = pip->Next; } pcur = pcur->Next; } + + if (state.num_netints == 0) + { + free(padapters); + return kLwpaErrNoNetints; + } + + state.lwpa_netints = calloc(state.num_netints, sizeof(LwpaNetintInfo)); + if (!state.lwpa_netints) + { + free(padapters); + return kLwpaErrNoMem; + } + + copy_all_netint_info(padapters); free(padapters); - return n_ifaces; + return kLwpaErrOk; } -size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) +void free_netints() { - size_t n_ifaces = 0; - IP_ADAPTER_ADDRESSES *padapters, *pcur; - DWORD def_ifindex; - bool have_def_index = false; + if (state.lwpa_netints) + { + free(state.lwpa_netints); + state.lwpa_netints = NULL; + } +} - if (!netint_arr || netint_arr_size == 0) - return 0; +IP_ADAPTER_ADDRESSES* get_windows_adapters() +{ + ULONG buflen = 0; + ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_GATEWAYS; - padapters = get_windows_adapters(); - if (!padapters) - return 0; - pcur = padapters; + // Preallocating a buffer specifically this size is expressly recommended by the Microsoft usage + // page. + uint8_t* buffer = malloc(15000); + if (!buffer) + return NULL; + if (ERROR_BUFFER_OVERFLOW == GetAdaptersAddresses(AF_UNSPEC, flags, NULL, (IP_ADAPTER_ADDRESSES*)buffer, &buflen)) + { + free(buffer); + buffer = malloc(buflen); + if (buffer && + (ERROR_SUCCESS == GetAdaptersAddresses(AF_UNSPEC, flags, NULL, (IP_ADAPTER_ADDRESSES*)buffer, &buflen))) + { + return (IP_ADAPTER_ADDRESSES*)buffer; + } + } + return NULL; +} + +void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, IP_ADAPTER_GATEWAY_ADDRESS* pgate, LwpaNetintInfo* info) +{ + struct sockaddr_in* sin = (struct sockaddr_in*)pip->Address.lpSockaddr; + struct sockaddr_in* gw_sin = pgate ? (struct sockaddr_in*)pgate->Address.lpSockaddr : NULL; + ULONG mask = 0; + + ConvertLengthToIpv4Mask(pip->OnLinkPrefixLength, &mask); + LWPA_IP_SET_V4_ADDRESS(&info->addr, ntohl(sin->sin_addr.s_addr)); + LWPA_IP_SET_V4_ADDRESS(&info->mask, ntohl((uint32_t)mask)); + if (pgate) + LWPA_IP_SET_V4_ADDRESS(&info->gate, ntohl(gw_sin->sin_addr.s_addr)); + else + LWPA_IP_SET_V4_ADDRESS(&info->gate, 0u); +} + +void copy_all_netint_info(IP_ADAPTER_ADDRESSES *adapters) +{ + IP_ADAPTER_ADDRESSES *pcur = adapters; + DWORD def_ifindex; + bool have_def_index = false; if (NO_ERROR == GetBestInterface(0, &def_ifindex)) have_def_index = true; + size_t netint_index = 0; while (pcur) { - /* If this is multihomed, there may be multiple addresses under the same adapter */ + // If this is multihomed, there may be multiple addresses under the same adapter IP_ADAPTER_UNICAST_ADDRESS* pip = pcur->FirstUnicastAddress; IP_ADAPTER_GATEWAY_ADDRESS* pgate = pcur->FirstGatewayAddress; while (pip) { - LwpaNetintInfo* info = &netint_arr[n_ifaces]; + LwpaNetintInfo* info = &state.lwpa_netints[netint_index]; switch (pip->Address.lpSockaddr->sa_family) { case AF_INET: @@ -146,6 +254,8 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ if (have_def_index && pcur->IfIndex == def_ifindex) { info->is_default = true; + state.have_default_netint_index = true; + state.default_netint_index = netint_index; have_def_index = false; } else @@ -158,108 +268,13 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ else memset(info->mac, 0, LWPA_NETINTINFO_MAC_LEN); - if (++n_ifaces >= netint_arr_size) - break; + ++netint_index; pip = pip->Next; - /* Just in case there's only ever one gateway but more addrs (probably not possible) */ + // Just in case there's only ever one gateway but more addrs (probably not possible) if (pgate && pgate->Next) pgate = pgate->Next; } - if (n_ifaces >= netint_arr_size) - break; pcur = pcur->Next; } - free(padapters); - return n_ifaces; -} - -bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint) -{ - DWORD def_ifindex; - bool res = false; - - if (NO_ERROR == GetBestInterface(0, &def_ifindex)) - { - IP_ADAPTER_ADDRESSES* pcur; - IP_ADAPTER_ADDRESSES* padapters = get_windows_adapters(); - if (!padapters) - return res; - pcur = padapters; - - while (pcur) - { - /* If this is multihomed, there may be multiple addresses under the same adapter */ - IP_ADAPTER_UNICAST_ADDRESS* pip = pcur->FirstUnicastAddress; - IP_ADAPTER_GATEWAY_ADDRESS* pgate = pcur->FirstGatewayAddress; - while (pip) - { - if (pcur->IfIndex == def_ifindex && pip->Address.lpSockaddr->sa_family == AF_INET) - { - copy_ipv4_info(pip, pgate, netint); - netint->ifindex = def_ifindex; - netint->is_default = true; - strncpy_s(netint->name, LWPA_NETINTINFO_NAME_LEN, pcur->AdapterName, _TRUNCATE); - if (pcur->PhysicalAddressLength == LWPA_NETINTINFO_MAC_LEN) - memcpy(netint->mac, pcur->PhysicalAddress, LWPA_NETINTINFO_MAC_LEN); - else - memset(netint->mac, 0, LWPA_NETINTINFO_MAC_LEN); - res = true; - break; - } - pip = pip->Next; - /* Just in case there's only ever one gateway but more addrs (probably not possible) */ - if (pgate && pgate->Next) - pgate = pgate->Next; - } - if (res == true) - break; - pcur = pcur->Next; - } - free(padapters); - } - return res; -} - -bool mask_is_empty(const LwpaIpAddr* mask) -{ - uint32_t mask_part = 0; - - if (lwpaip_is_v4(mask)) - { - mask_part = lwpaip_v4_address(mask); - } - else if (lwpaip_is_v6(mask)) - { - size_t i; - const uint32_t* p = (const uint32_t*)lwpaip_v6_address(mask); - for (i = 0; i < LWPA_IPV6_BYTES / 4; ++i, ++p) - mask_part |= *p; - } - return (mask_part == 0); -} - -const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, - size_t netint_arr_size) -{ - const LwpaNetintInfo* res = NULL; - const LwpaNetintInfo* def = NULL; - const LwpaNetintInfo* netint; - - if (!dest || !netint_arr || netint_arr_size == 0) - return false; - - for (netint = netint_arr; netint < netint_arr + netint_arr_size; ++netint) - { - if (netint->is_default) - def = netint; - if (!lwpa_ip_is_wildcard(&netint->mask) && lwpa_ip_network_portions_equal(&netint->addr, dest, &netint->mask)) - { - res = netint; - break; - } - } - if (!res) - res = def; - return res; } diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index 0562573dc..f4a1825b7 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -25,6 +25,8 @@ #include #include +#include "winsock_error.h" + /*************************** Private constants *******************************/ #define POLL_CONTEXT_ARR_CHUNK_SIZE 10 @@ -105,9 +107,6 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /*********************** Private function prototypes *************************/ -// Convert Windows sockets errors to lwpa_error_t values. -static lwpa_error_t err_os_to_lwpa(int wsaerror); - // Helper functions for the lwpa_poll API static void init_socket_chunk(LwpaPollCtxSocket* chunk); static LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket); @@ -125,14 +124,14 @@ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; sa->port = ntohs(sin->sin_port); - lwpaip_set_v4_address(&sa->ip, ntohl(sin->sin_addr.s_addr)); + LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); return true; } else if (pfsa->sa_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; sa->port = ntohs(sin6->sin6_port); - lwpaip_set_v6_address(&sa->ip, sin6->sin6_addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); return true; } return false; @@ -141,22 +140,22 @@ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) { size_t ret = 0; - if (lwpaip_is_v4(&sa->ip)) + if (LWPA_IP_IS_V4(&sa->ip)) { struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; sin->sin_port = htons(sa->port); - sin->sin_addr.s_addr = htonl(lwpaip_v4_address(&sa->ip)); + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); ret = sizeof(struct sockaddr_in); } - else if (lwpaip_is_v6(&sa->ip)) + else if (LWPA_IP_IS_V6(&sa->ip)) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; memset(sin6, 0, sizeof(struct sockaddr_in6)); sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(sa->port); - memcpy(sin6->sin6_addr.s6_addr, lwpaip_v6_address(&sa->ip), LWPA_IPV6_BYTES); + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); ret = sizeof(struct sockaddr_in6); in6addr_any; } @@ -165,83 +164,6 @@ size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) #if !defined(LWPA_BUILDING_MOCK_LIB) -lwpa_error_t err_os_to_lwpa(int wsaerror) -{ - /* The Winsock error codes are not even close to contiguous in defined value, - * so a giant switch statement is the only solution here... */ - switch (wsaerror) - { - case WSAEBADF: - case WSAENOTSOCK: - case WSATYPE_NOT_FOUND: - case WSAHOST_NOT_FOUND: - case WSAESTALE: - return kLwpaErrNotFound; - case WSA_INVALID_HANDLE: - case WSA_INVALID_PARAMETER: - case WSAEFAULT: - case WSAEINVAL: - case WSAEDESTADDRREQ: - case WSAENOPROTOOPT: - return kLwpaErrInvalid; - case WSA_NOT_ENOUGH_MEMORY: - case WSAEMFILE: - case WSAETOOMANYREFS: - case WSAEPROCLIM: - case WSAEUSERS: - return kLwpaErrNoMem; - case WSA_IO_PENDING: - case WSAEINPROGRESS: - return kLwpaErrInProgress; - case WSA_IO_INCOMPLETE: - case WSAEALREADY: - return kLwpaErrAlready; - case WSAEWOULDBLOCK: - return kLwpaErrWouldBlock; - case WSAEMSGSIZE: - return kLwpaErrMsgSize; - case WSAEADDRINUSE: - return kLwpaErrAddrInUse; - case WSAEADDRNOTAVAIL: - return kLwpaErrAddrNotAvail; - case WSAENETDOWN: - case WSAENETUNREACH: - case WSAENETRESET: - case WSAEHOSTDOWN: - case WSAEHOSTUNREACH: - return kLwpaErrNetwork; - case WSAECONNRESET: - case WSAECONNABORTED: - return kLwpaErrConnReset; - case WSAEISCONN: - return kLwpaErrIsConn; - case WSAENOTCONN: - return kLwpaErrNotConn; - case WSAESHUTDOWN: - return kLwpaErrShutdown; - case WSAETIMEDOUT: - return kLwpaErrTimedOut; - case WSAECONNREFUSED: - return kLwpaErrConnRefused; - case WSAENOBUFS: - return kLwpaErrBufSize; - case WSANOTINITIALISED: - case WSASYSNOTREADY: - return kLwpaErrNotInit; - case WSAEACCES: - case WSA_OPERATION_ABORTED: - case WSAEPROTOTYPE: - case WSAEPROTONOSUPPORT: - case WSAESOCKTNOSUPPORT: - case WSAEOPNOTSUPP: - case WSAEPFNOSUPPORT: - case WSAEAFNOSUPPORT: - case WSASYSCALLFAILURE: - default: - return kLwpaErrSys; - } -} - lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { struct sockaddr_storage ss; @@ -263,7 +185,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* *conn_sock = res; return kLwpaErrOk; } - return err_os_to_lwpa(WSAGetLastError()); + return err_winsock_to_lwpa(WSAGetLastError()); } lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) @@ -280,13 +202,13 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) return kLwpaErrInvalid; res = bind(id, (struct sockaddr*)&ss, (int)sa_size); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_close(lwpa_socket_t id) { int res = closesocket(id); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) @@ -303,7 +225,7 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) return kLwpaErrInvalid; res = connect(id, (struct sockaddr*)&ss, (int)sa_size); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) @@ -330,7 +252,7 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) return kLwpaErrSys; return kLwpaErrOk; } - return err_os_to_lwpa(WSAGetLastError()); + return err_winsock_to_lwpa(WSAGetLastError()); } lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) @@ -347,7 +269,7 @@ lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) { int res = listen(id, backlog); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); } int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) @@ -359,7 +281,7 @@ int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) return kLwpaErrInvalid; res = recv(id, buffer, (int)length, impl_flags); - return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_winsock_to_lwpa(WSAGetLastError())); } int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address) @@ -383,7 +305,7 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa } return res; } - return (int)err_os_to_lwpa(WSAGetLastError()); + return (int)err_winsock_to_lwpa(WSAGetLastError()); } int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) @@ -395,7 +317,7 @@ int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) return kLwpaErrInvalid; res = send(id, message, (int)length, 0); - return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_winsock_to_lwpa(WSAGetLastError())); } int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) @@ -411,7 +333,7 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, if ((ss_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr)) > 0) res = sendto(id, message, (int)length, 0, (struct sockaddr*)&ss, (int)ss_size); - return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); + return (res >= 0 ? res : (int)err_winsock_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) @@ -498,11 +420,11 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (option_len == sizeof(LwpaMreq)) { LwpaMreq* amreq = (LwpaMreq*)option_value; - if (lwpaip_is_v4(&amreq->group)) + if (LWPA_IP_IS_V4(&amreq->group)) { struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(lwpaip_v4_address(&amreq->group)); - val.imr_interface.s_addr = htonl(lwpaip_v4_address(&amreq->netint)); + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); res = setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&val, sizeof val); } } @@ -511,11 +433,11 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (option_len == sizeof(LwpaMreq)) { LwpaMreq* amreq = (LwpaMreq*)option_value; - if (lwpaip_is_v4(&amreq->group)) + if (LWPA_IP_IS_V4(&amreq->group)) { struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(lwpaip_v4_address(&amreq->group)); - val.imr_interface.s_addr = htonl(lwpaip_v4_address(&amreq->netint)); + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); res = setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&val, sizeof val); } } @@ -524,9 +446,9 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (option_len == sizeof(LwpaIpAddr)) { LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (lwpaip_is_v4(netint)) + if (LWPA_IP_IS_V4(netint)) { - DWORD val = htonl(lwpaip_v4_address(netint)); + DWORD val = htonl(LWPA_IP_V4_ADDRESS(netint)); res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, sizeof val); } } @@ -557,12 +479,12 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (option_len == sizeof(struct lwpa_mreq)) { LwpaMreq *amreq = (LwpaMreq *)option_value; - if (lwpaip_is_v6(&amreq->group)) + if (LWPA_IP_IS_V6(&amreq->group)) { struct ipv6_mreq val; val.ipv6imr_interface = 0; memcpy(&val.ipv6imr_multiaddr.s6_addr, - lwpaip_v6_address(&amreq->group), LWPA_IPV6_BYTES); + LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, sizeof val); } @@ -574,12 +496,12 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (option_len == sizeof(struct lwpa_mreq)) { LwpaMreq *amreq = (LwpaMreq *)option_value; - if (lwpaip_is_v6(&amreq->group)) + if (LWPA_IP_IS_V6(&amreq->group)) { struct ipv6_mreq val; val.ipv6imr_interface = 0; memcpy(&val.ipv6imr_multiaddr.s6_addr, - lwpaip_v6_address(&amreq->group), LWPA_IPV6_BYTES); + LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, sizeof val); } @@ -601,7 +523,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const default: return kLwpaErrInvalid; } - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) @@ -609,7 +531,7 @@ lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) if (how >= 0 && how < LWPA_NUM_SHUT) { int res = shutdown(id, shutmap[how]); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); } return kLwpaErrInvalid; } @@ -629,7 +551,7 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* else { *id = LWPA_SOCKET_INVALID; - return err_os_to_lwpa(WSAGetLastError()); + return err_winsock_to_lwpa(WSAGetLastError()); } } else @@ -644,7 +566,7 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) { unsigned long val = (blocking ? 0 : 1); int res = ioctlsocket(id, FIONBIO, &val); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); } lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) @@ -894,7 +816,7 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int if (sel_res < 0) { - return err_os_to_lwpa(WSAGetLastError()); + return err_winsock_to_lwpa(WSAGetLastError()); } else if (sel_res == 0) { @@ -945,12 +867,12 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event if (error != 0) { event->events |= LWPA_POLL_ERR; - event->err = err_os_to_lwpa(error); + event->err = err_winsock_to_lwpa(error); } } else { - res = err_os_to_lwpa(WSAGetLastError()); + res = err_winsock_to_lwpa(WSAGetLastError()); break; } if (LWPA_FD_ISSET(sock_desc->socket, readfds)) @@ -1005,7 +927,7 @@ lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const L if (!lwpa_nextaddr(result)) res = -1; } - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(res)); + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(res)); } bool lwpa_nextaddr(LwpaAddrinfo* ai) @@ -1066,7 +988,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) case kLwpaIpTypeV4: { struct in_addr addr; - addr.s_addr = htonl(lwpaip_v4_address(src)); + addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); if (NULL != inet_ntop(AF_INET, &addr, dest, size)) return kLwpaErrOk; return kLwpaErrSys; @@ -1074,7 +996,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) case kLwpaIpTypeV6: { struct in6_addr addr; - memcpy(addr.s6_addr, lwpaip_v6_address(src), LWPA_IPV6_BYTES); + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) return kLwpaErrOk; return kLwpaErrSys; @@ -1096,7 +1018,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des struct in_addr addr; if (1 != inet_pton(AF_INET, src, &addr)) return kLwpaErrSys; - lwpaip_set_v4_address(dest, ntohl(addr.s_addr)); + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); return kLwpaErrOk; } case kLwpaIpTypeV6: @@ -1104,7 +1026,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des struct in6_addr addr; if (1 != inet_pton(AF_INET6, src, &addr)) return kLwpaErrSys; - lwpaip_set_v6_address(dest, addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); return kLwpaErrOk; } default: diff --git a/src/os/windows/lwpa/winsock_error.c b/src/os/windows/lwpa/winsock_error.c new file mode 100644 index 000000000..b77833b91 --- /dev/null +++ b/src/os/windows/lwpa/winsock_error.c @@ -0,0 +1,102 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "winsock_error.h" + +#include +#include + +// Convert Windows sockets errors to lwpa_error_t values. +lwpa_error_t err_winsock_to_lwpa(int wsaerror) +{ + // The Winsock error codes are not even close to contiguous in defined value, so a giant switch + // statement is the only solution here... + switch (wsaerror) + { + case WSAEBADF: + case WSAENOTSOCK: + case WSATYPE_NOT_FOUND: + case WSAHOST_NOT_FOUND: + case WSAESTALE: + return kLwpaErrNotFound; + case WSA_INVALID_HANDLE: + case WSA_INVALID_PARAMETER: + case WSAEFAULT: + case WSAEINVAL: + case WSAEDESTADDRREQ: + case WSAENOPROTOOPT: + return kLwpaErrInvalid; + case WSA_NOT_ENOUGH_MEMORY: + case WSAEMFILE: + case WSAETOOMANYREFS: + case WSAEPROCLIM: + case WSAEUSERS: + return kLwpaErrNoMem; + case WSA_IO_PENDING: + case WSAEINPROGRESS: + return kLwpaErrInProgress; + case WSA_IO_INCOMPLETE: + case WSAEALREADY: + return kLwpaErrAlready; + case WSAEWOULDBLOCK: + return kLwpaErrWouldBlock; + case WSAEMSGSIZE: + return kLwpaErrMsgSize; + case WSAEADDRINUSE: + return kLwpaErrAddrInUse; + case WSAEADDRNOTAVAIL: + return kLwpaErrAddrNotAvail; + case WSAENETDOWN: + case WSAENETUNREACH: + case WSAENETRESET: + case WSAEHOSTDOWN: + case WSAEHOSTUNREACH: + return kLwpaErrNetwork; + case WSAECONNRESET: + case WSAECONNABORTED: + return kLwpaErrConnReset; + case WSAEISCONN: + return kLwpaErrIsConn; + case WSAENOTCONN: + return kLwpaErrNotConn; + case WSAESHUTDOWN: + return kLwpaErrShutdown; + case WSAETIMEDOUT: + return kLwpaErrTimedOut; + case WSAECONNREFUSED: + return kLwpaErrConnRefused; + case WSAENOBUFS: + return kLwpaErrBufSize; + case WSANOTINITIALISED: + case WSASYSNOTREADY: + return kLwpaErrNotInit; + case WSAEACCES: + case WSA_OPERATION_ABORTED: + case WSAEPROTOTYPE: + case WSAEPROTONOSUPPORT: + case WSAESOCKTNOSUPPORT: + case WSAEOPNOTSUPP: + case WSAEPFNOSUPPORT: + case WSAEAFNOSUPPORT: + case WSASYSCALLFAILURE: + default: + return kLwpaErrSys; + } +} + diff --git a/src/os/windows/lwpa/winsock_error.h b/src/os/windows/lwpa/winsock_error.h new file mode 100644 index 000000000..d2a6e8baf --- /dev/null +++ b/src/os/windows/lwpa/winsock_error.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_ERROR_H_ +#define _LWPA_OS_ERROR_H_ + +#include "lwpa/error.h" + +lwpa_error_t err_winsock_to_lwpa(int wsaerror); + +#endif /* _LWPA_OS_ERROR_H_ */ + diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp index 4dc6028c3..3233ddbf3 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/main.cpp @@ -24,36 +24,34 @@ #include "lwpa/socket.h" #include "lwpa/common.h" -// Need to pass this from the command line to a test case; there doesn't seem to be a better way to -// do this than using a global variable. -LwpaIpAddr g_netint; +//LwpaIpAddr g_netint; int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); // Only check our custom argument if we haven't been given the "list_tests" flag - if (!testing::GTEST_FLAG(list_tests)) - { - if (argc == 2) - { - if (0 >= lwpa_inet_pton(kLwpaIpTypeV4, argv[1], &g_netint)) - { - printf( - "Usage: %s \n" - " interface_addr: IP address of network interface to use for test.\n", - argv[0]); - - return 1; - } - } - else - { - LwpaNetintInfo default_netint; - lwpa_netint_get_default_interface(&default_netint); - g_netint = default_netint.addr; - } - } +// if (!testing::GTEST_FLAG(list_tests)) +// { +// if (argc == 2) +// { +// if (0 >= lwpa_inet_pton(kLwpaIpTypeV4, argv[1], &g_netint)) +// { +// printf( +// "Usage: %s \n" +// " interface_addr: IP address of network interface to use for test.\n", +// argv[0]); +// +// return 1; +// } +// } +// else +// { +// LwpaNetintInfo default_netint; +// lwpa_netint_get_default_interface(&default_netint); +// g_netint = default_netint.addr; +// } +// } return RUN_ALL_TESTS(); } diff --git a/tests/unit/mqx/iar/test_netint.c b/tests/unit/mqx/iar/test_netint.c index 1aaf8c271..bf6a783e7 100644 --- a/tests/unit/mqx/iar/test_netint.c +++ b/tests/unit/mqx/iar/test_netint.c @@ -97,12 +97,12 @@ bool test_route() LwpaIpAddr dest_ip; const LwpaNetintInfo* dest; - if (lwpaip_is_v6(&iface->addr)) + if (LWPA_IP_IS_V6(&iface->addr)) continue; - mask = lwpaip_v4_address(&iface->mask); - host = lwpaip_v4_address(&iface->addr) & (~mask); - net = lwpaip_v4_address(&iface->addr) & mask; + mask = LWPA_IP_V4_ADDRESS(&iface->mask); + host = LWPA_IP_V4_ADDRESS(&iface->addr) & (~mask); + net = LWPA_IP_V4_ADDRESS(&iface->addr) & mask; /* Simulate another host on the same subnet. */ neighbor = net | ((host + 1) & (~mask)); @@ -111,14 +111,14 @@ bool test_route() remote = 0x1u | (net ^ ((~mask) + 1)); /* Test the local neighbor */ - lwpaip_set_v4_address(&dest_ip, neighbor); + LWPA_IP_SET_V4_ADDRESS(&dest_ip, neighbor); dest = netint_get_iface_for_dest(&dest_ip, g_interfaces, g_num_interfaces); ok = (dest == iface); if (!ok) break; /* Test the remote host */ - lwpaip_set_v4_address(&dest_ip, remote); + LWPA_IP_SET_V4_ADDRESS(&dest_ip, remote); dest = netint_get_iface_for_dest(&dest_ip, g_interfaces, g_num_interfaces); ok = (dest->is_default); if (!ok) diff --git a/tests/unit/mqx/iar/test_socket.c b/tests/unit/mqx/iar/test_socket.c index c914d93b8..c3081cbf8 100644 --- a/tests/unit/mqx/iar/test_socket.c +++ b/tests/unit/mqx/iar/test_socket.c @@ -43,60 +43,60 @@ bool test_inet_xtox() /* Test lwpa_inet_pton() */ ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV4, test_ip4_1, &addr)); if (ok) - ok = (lwpaip_v4_address(&addr) == 0); + ok = (LWPA_IP_V4_ADDRESS(&addr) == 0); if (ok) ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV4, test_ip4_2, &addr)); if (ok) - ok = (lwpaip_v4_address(&addr) == 0xffffffff); + ok = (LWPA_IP_V4_ADDRESS(&addr) == 0xffffffff); if (ok) ok = (kLwpaErrOk != lwpa_inet_pton(LWPA_IPV4, test_ip4_fail, &addr)); if (ok) ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV6, test_ip6_1, &addr)); if (ok) - ok = (0 == memcmp(lwpaip_v6_address(&addr), test_ip6_1_bin, IPV6_BYTES)); + ok = (0 == memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_1_bin, IPV6_BYTES)); if (ok) ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV6, test_ip6_2, &addr)); if (ok) - ok = (0 == memcmp(lwpaip_v6_address(&addr), test_ip6_2_bin, IPV6_BYTES)); + ok = (0 == memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_2_bin, IPV6_BYTES)); if (ok) ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV6, test_ip6_3, &addr)); if (ok) - ok = (0 == memcmp(lwpaip_v6_address(&addr), test_ip6_3_bin, IPV6_BYTES)); + ok = (0 == memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_3_bin, IPV6_BYTES)); if (ok) ok = (kLwpaErrOk != lwpa_inet_pton(LWPA_IPV6, test_ip6_fail, &addr)); /* Test lwpa_inet_ntop() */ if (ok) { - lwpaip_set_v4_address(&addr, 0); + LWPA_IP_SET_V4_ADDRESS(&addr, 0); ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); } if (ok) ok = (0 == strcmp(str, test_ip4_1)); if (ok) { - lwpaip_set_v4_address(&addr, 0xffffffff); + LWPA_IP_SET_V4_ADDRESS(&addr, 0xffffffff); ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); } if (ok) ok = (0 == strcmp(str, test_ip4_2)); if (ok) { - lwpaip_set_v6_address(&addr, test_ip6_1_bin); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_1_bin); ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); } if (ok) ok = (0 == strcmp(str, test_ip6_1)); if (ok) { - lwpaip_set_v6_address(&addr, test_ip6_2_bin); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_2_bin); ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); } if (ok) ok = (0 == strcmp(str, test_ip6_2)); if (ok) { - lwpaip_set_v6_address(&addr, test_ip6_3_bin); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_3_bin); ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); } if (ok) @@ -190,7 +190,7 @@ bool test_unicast_udp() } if (ok) { - lwpaip_set_v4_address(&stinf.send_addr.ip, ip_data.ip); + LWPA_IP_SET_V4_ADDRESS(&stinf.send_addr.ip, ip_data.ip); stinf.send_addr.port = 8888; /* Start the send thread. */ @@ -215,7 +215,7 @@ bool test_unicast_udp() ok = (SEND_MSG_LEN == lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr)); if (!ok) break; - ok = (lwpaip_equal(&stinf.send_addr.ip, &from_addr.ip) && (from_addr.port != 8888)); + ok = (lwpa_ip_equal(&stinf.send_addr.ip, &from_addr.ip) && (from_addr.port != 8888)); if (!ok) break; buf[SEND_MSG_LEN] = '\0'; @@ -290,7 +290,7 @@ bool test_multicast_udp() if (ok) { /* Bind socket 1 to the multicast address and port 8888. */ - lwpaip_set_v4_address(&bind_addr.ip, TEST_MCAST_ADDR); + LWPA_IP_SET_V4_ADDRESS(&bind_addr.ip, TEST_MCAST_ADDR); bind_addr.port = 8888; ok = (0 == lwpa_bind(rcvsock1, &bind_addr)); } @@ -304,8 +304,8 @@ bool test_multicast_udp() { /* Subscribe socket 1 to the multicast address. */ LwpaMreq mreq; - lwpaip_set_v4_address(&mreq.netint, ip_data.ip); - lwpaip_set_v4_address(&mreq.group, TEST_MCAST_ADDR); + LWPA_IP_SET_V4_ADDRESS(&mreq.netint, ip_data.ip); + LWPA_IP_SET_V4_ADDRESS(&mreq.group, TEST_MCAST_ADDR); ok = (0 == lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &mreq, sizeof mreq)); /* Subscribe socket 2 to the multicast address */ if (ok) @@ -315,7 +315,7 @@ bool test_multicast_udp() } if (ok) { - lwpaip_set_v4_address(&stinf.send_addr.ip, TEST_MCAST_ADDR); + LWPA_IP_SET_V4_ADDRESS(&stinf.send_addr.ip, TEST_MCAST_ADDR); stinf.send_addr.port = 8888; /* Start the send thread. */ @@ -436,8 +436,8 @@ bool test_poll() } if (ok) { - lwpaip_set_v4_address(&stinf.send_addr_1.ip, ip_data.ip); - lwpaip_set_v4_address(&stinf.send_addr_2.ip, ip_data.ip); + LWPA_IP_SET_V4_ADDRESS(&stinf.send_addr_1.ip, ip_data.ip); + LWPA_IP_SET_V4_ADDRESS(&stinf.send_addr_2.ip, ip_data.ip); stinf.send_addr_1.port = 8888; stinf.send_addr_2.port = 9999; @@ -478,7 +478,7 @@ bool test_poll() ok = (SEND_MSG_LEN == lwpa_recvfrom(pfds[i].fd, buf, SEND_MSG_LEN, 0, &from_addr)); if (!ok) break; - ok = (lwpaip_equal(&stinf.send_addr_1.ip, &from_addr.ip) && (from_addr.port != 8888)); + ok = (lwpa_ip_equal(&stinf.send_addr_1.ip, &from_addr.ip) && (from_addr.port != 8888)); if (!ok) break; buf[SEND_MSG_LEN] = '\0'; diff --git a/tests/unit/test_inet.cpp b/tests/unit/test_inet.cpp index 7e30f528e..8bf58e649 100644 --- a/tests/unit/test_inet.cpp +++ b/tests/unit/test_inet.cpp @@ -29,41 +29,41 @@ TEST_F(InetTest, ip_addr) { LwpaIpAddr v4; - lwpaip_set_v4_address(&v4, 0x01020304); - ASSERT_TRUE(lwpaip_is_v4(&v4)); - ASSERT_EQ(lwpaip_v4_address(&v4), 0x01020304u); + LWPA_IP_SET_V4_ADDRESS(&v4, 0x01020304); + ASSERT_TRUE(LWPA_IP_IS_V4(&v4)); + ASSERT_EQ(LWPA_IP_V4_ADDRESS(&v4), 0x01020304u); // Copied address should compare equal LwpaIpAddr v4_copy = v4; - ASSERT_TRUE(lwpaip_equal(&v4_copy, &v4)); - ASSERT_EQ(0, lwpaip_cmp(&v4_copy, &v4)); + ASSERT_TRUE(lwpa_ip_equal(&v4_copy, &v4)); + ASSERT_EQ(0, lwpa_ip_cmp(&v4_copy, &v4)); LwpaIpAddr v6; std::array v6_data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - lwpaip_set_v6_address(&v6, v6_data.data()); - ASSERT_TRUE(lwpaip_is_v6(&v6)); - ASSERT_EQ(0, memcmp(lwpaip_v6_address(&v6), v6_data.data(), LWPA_IPV6_BYTES)); + LWPA_IP_SET_V6_ADDRESS(&v6, v6_data.data()); + ASSERT_TRUE(LWPA_IP_IS_V6(&v6)); + ASSERT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&v6), v6_data.data(), LWPA_IPV6_BYTES)); // Copied address should compare equal LwpaIpAddr v6_copy = v6; - ASSERT_TRUE(lwpaip_equal(&v6_copy, &v6)); - ASSERT_EQ(0, lwpaip_cmp(&v6_copy, &v6)); + ASSERT_TRUE(lwpa_ip_equal(&v6_copy, &v6)); + ASSERT_EQ(0, lwpa_ip_cmp(&v6_copy, &v6)); // The v4 and v6 should not be equal, and per the comparison algorithm the v4 should be less than // the v6 - ASSERT_FALSE(lwpaip_equal(&v4, &v6)); - ASSERT_LT(lwpaip_cmp(&v4, &v6), 0); + ASSERT_FALSE(lwpa_ip_equal(&v4, &v6)); + ASSERT_LT(lwpa_ip_cmp(&v4, &v6), 0); - // Further test the lwpaip_cmp() macro, with like address types + // Further test the lwpa_ip_cmp() macro, with like address types LwpaIpAddr v4_less; - lwpaip_set_v4_address(&v4_less, 0x01020303); + LWPA_IP_SET_V4_ADDRESS(&v4_less, 0x01020303); LwpaIpAddr v6_less; auto v6_data_less = v6_data; v6_data_less[15] = 14; - lwpaip_set_v6_address(&v6_less, v6_data_less.data()); + LWPA_IP_SET_V6_ADDRESS(&v6_less, v6_data_less.data()); - ASSERT_LT(lwpaip_cmp(&v4_less, &v4), 0); - ASSERT_LT(lwpaip_cmp(&v6_less, &v6), 0); -} \ No newline at end of file + ASSERT_LT(lwpa_ip_cmp(&v4_less, &v4), 0); + ASSERT_LT(lwpa_ip_cmp(&v6_less, &v6), 0); +} diff --git a/tests/unit/test_log.cpp b/tests/unit/test_log.cpp index 11a731444..dd5707825 100644 --- a/tests/unit/test_log.cpp +++ b/tests/unit/test_log.cpp @@ -34,9 +34,15 @@ using testing::Mock; class LogTest : public ::testing::Test { protected: - LogTest() { FillDefaultTime(cur_time); } - - virtual ~LogTest() {} + LogTest() + { + lwpa_init(LWPA_FEATURE_LOGGING); + FillDefaultTime(cur_time); + } + ~LogTest() + { + lwpa_deinit(LWPA_FEATURE_LOGGING); + } void TestLwpaVlogHelper(std::string expect_syslog_str, std::string expect_human_str, std::string expect_raw_str, LwpaLogParams* lparams, int pri, const char* format, ...); diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index aadaa8ea2..61b4c46fc 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -25,11 +25,17 @@ class NetintTest : public ::testing::Test { protected: - NetintTest() : num_netints(0) { num_netints = lwpa_netint_get_num_interfaces(); } - - virtual ~NetintTest() {} + NetintTest() + { + lwpa_init(LWPA_FEATURE_NETINTS); + num_netints = lwpa_netint_get_num_interfaces(); + } + ~NetintTest() + { + lwpa_deinit(LWPA_FEATURE_NETINTS); + } - size_t num_netints; + size_t num_netints{0}; }; TEST_F(NetintTest, enumerate) @@ -84,18 +90,18 @@ TEST_F(NetintTest, IPv4routing) for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) { - uint32_t net = lwpaip_v4_address(&netint->addr) & lwpaip_v4_address(&netint->mask); + uint32_t net = LWPA_IP_V4_ADDRESS(&netint->addr) & LWPA_IP_V4_ADDRESS(&netint->mask); LwpaIpAddr test_addr; if (nets_already_tried.find(net) != nets_already_tried.end()) continue; nets_already_tried.insert(net); - lwpaip_set_v4_address(&test_addr, net + 1); + LWPA_IP_SET_V4_ADDRESS(&test_addr, net + 1); ASSERT_EQ(lwpa_netint_get_iface_for_dest(&test_addr, netint_arr, num_netints), netint); } LwpaIpAddr ext_addr; - lwpaip_set_v4_address(&ext_addr, 0xc8dc0302); // 200.220.3.2 + LWPA_IP_SET_V4_ADDRESS(&ext_addr, 0xc8dc0302); // 200.220.3.2 const LwpaNetintInfo* def = lwpa_netint_get_iface_for_dest(&ext_addr, netint_arr, num_netints); ASSERT_TRUE(def != NULL); ASSERT_TRUE(def->is_default); diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index a96f2b6de..2ef39240a 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -17,14 +17,11 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/socket.h" +#include "lwpa/netint.h" #include "gtest/gtest.h" #include #include -// Need to pass this from the command line to a test case; there doesn't seem to be a better way to -// do this than using a global variable. -extern LwpaIpAddr g_netint; - class SocketTest : public ::testing::Test { public: @@ -36,6 +33,18 @@ class SocketTest : public ::testing::Test LwpaSockaddr send_addr_1; protected: + SocketTest() + { + lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); + lwpa_netint_get_default_interface(&default_netint_); + } + ~SocketTest() + { + lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); + } + + LwpaNetintInfo default_netint_; + // For inet_xtox char str[LWPA_INET6_ADDRSTRLEN]; const char* test_ip4_1 = "0.0.0.0"; @@ -68,32 +77,32 @@ TEST_F(SocketTest, inet_xtox) // Test lwpa_inet_pton() ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_1, &addr)); - ASSERT_EQ(lwpaip_v4_address(&addr), 0u); + ASSERT_EQ(LWPA_IP_V4_ADDRESS(&addr), 0u); ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_2, &addr)); - ASSERT_EQ(lwpaip_v4_address(&addr), 0xffffffffu); + ASSERT_EQ(LWPA_IP_V4_ADDRESS(&addr), 0xffffffffu); ASSERT_NE(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_fail, &addr)); ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_1, &addr)); - ASSERT_EQ(0, memcmp(lwpaip_v6_address(&addr), test_ip6_1_bin, LWPA_IPV6_BYTES)); + ASSERT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_1_bin, LWPA_IPV6_BYTES)); ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_2, &addr)); - ASSERT_EQ(0, memcmp(lwpaip_v6_address(&addr), test_ip6_2_bin, LWPA_IPV6_BYTES)); + ASSERT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_2_bin, LWPA_IPV6_BYTES)); ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_3, &addr)); - ASSERT_EQ(0, memcmp(lwpaip_v6_address(&addr), test_ip6_3_bin, LWPA_IPV6_BYTES)); + ASSERT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_3_bin, LWPA_IPV6_BYTES)); ASSERT_NE(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_fail, &addr)); // Test lwpa_inet_ntop() - lwpaip_set_v4_address(&addr, 0); + LWPA_IP_SET_V4_ADDRESS(&addr, 0); ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); ASSERT_EQ(0, strcmp(str, test_ip4_1)); - lwpaip_set_v4_address(&addr, 0xffffffff); + LWPA_IP_SET_V4_ADDRESS(&addr, 0xffffffff); ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); ASSERT_EQ(0, strcmp(str, test_ip4_2)); - lwpaip_set_v6_address(&addr, test_ip6_1_bin); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_1_bin); ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); ASSERT_EQ(0, strcmp(str, test_ip6_1)); - lwpaip_set_v6_address(&addr, test_ip6_2_bin); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_2_bin); ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); ASSERT_EQ(0, strcmp(str, test_ip6_2)); - lwpaip_set_v6_address(&addr, test_ip6_3_bin); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_3_bin); ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); ASSERT_TRUE((0 == strcmp(str, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) || (0 == strcmp(str, "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"))); @@ -140,7 +149,7 @@ TEST_F(SocketTest, unicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock3)); - lwpaip_make_any_v4(&bind_addr.ip); + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); bind_addr.port = 8888; // Shouldn't be able to bind to a closed socket. ASSERT_NE(kLwpaErrOk, lwpa_bind(rcvsock3, &bind_addr)); @@ -150,7 +159,7 @@ TEST_F(SocketTest, unicast_udp) bind_addr.port = 9999; ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); - lwpaip_set_v4_address(&send_addr_1.ip, 0x7f000001u); + LWPA_IP_SET_V4_ADDRESS(&send_addr_1.ip, 0x7f000001u); send_addr_1.port = 8888; std::thread send_thr(send_thread, this); @@ -162,7 +171,7 @@ TEST_F(SocketTest, unicast_udp) uint8_t buf[SEND_MSG_LEN + 1]; ASSERT_EQ(SEND_MSG_LEN, (size_t)lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr)); - ASSERT_TRUE(lwpaip_equal(&send_addr_1.ip, &from_addr.ip)); + ASSERT_TRUE(lwpa_ip_equal(&send_addr_1.ip, &from_addr.ip)); ASSERT_NE(from_addr.port, 8888); buf[SEND_MSG_LEN] = '\0'; @@ -207,7 +216,7 @@ TEST_F(SocketTest, multicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); // Bind socket 1 to the wildcard address and port 8888. - lwpaip_make_any_v4(&bind_addr.ip); + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); bind_addr.port = 8888; ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); @@ -217,14 +226,14 @@ TEST_F(SocketTest, multicast_udp) // Subscribe socket 1 to the multicast address. LwpaMreq mreq; - mreq.netint = g_netint; - lwpaip_set_v4_address(&mreq.group, TEST_MCAST_ADDR); + mreq.netint = default_netint_.addr; + LWPA_IP_SET_V4_ADDRESS(&mreq.group, TEST_MCAST_ADDR); ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &mreq, sizeof mreq)); // Subscribe socket 2 to the multicast address ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &mreq, sizeof mreq)); - lwpaip_set_v4_address(&send_addr_1.ip, TEST_MCAST_ADDR); + LWPA_IP_SET_V4_ADDRESS(&send_addr_1.ip, TEST_MCAST_ADDR); send_addr_1.port = 8888; // Start the send thread. @@ -264,12 +273,12 @@ TEST_F(SocketTest, getaddrinfo) memset(&ai_hints, 0, sizeof ai_hints); ai_hints.ai_family = LWPA_AF_INET; ASSERT_EQ(kLwpaErrOk, lwpa_getaddrinfo(test_hostname, test_service, &ai_hints, &ai)); - ASSERT_TRUE(lwpaip_is_v4(&ai.ai_addr.ip)); + ASSERT_TRUE(LWPA_IP_IS_V4(&ai.ai_addr.ip)); lwpa_freeaddrinfo(&ai); ai_hints.ai_flags = LWPA_AI_NUMERICHOST; ASSERT_EQ(kLwpaErrOk, lwpa_getaddrinfo(test_gai_ip_str, test_gai_port_str, &ai_hints, &ai)); - ASSERT_TRUE(lwpaip_is_v4(&ai.ai_addr.ip)); - ASSERT_EQ(lwpaip_v4_address(&ai.ai_addr.ip), test_gai_ip); + ASSERT_TRUE(LWPA_IP_IS_V4(&ai.ai_addr.ip)); + ASSERT_EQ(LWPA_IP_V4_ADDRESS(&ai.ai_addr.ip), test_gai_ip); ASSERT_EQ(ai.ai_addr.port, test_gai_port); } diff --git a/tests/unit/test_socket_poll.cpp b/tests/unit/test_socket_poll.cpp index 7aedff9eb..f1108b55e 100644 --- a/tests/unit/test_socket_poll.cpp +++ b/tests/unit/test_socket_poll.cpp @@ -21,6 +21,7 @@ #include #include "lwpa/socket.h" +#include "lwpa/netint.h" #include "gtest/gtest.h" #if LWPA_SOCKET_MAX_POLL_SIZE <= 0 || LWPA_SOCKET_MAX_POLL_SIZE > 1024 @@ -30,13 +31,21 @@ #define BULK_POLL_TEST_NUM_SOCKETS LWPA_SOCKET_MAX_POLL_SIZE #endif -// Need to pass this from the command line to a test case; there doesn't seem to be a better way to -// do this than using a global variable. -extern LwpaIpAddr g_netint; - class SocketPollTest : public ::testing::Test { protected: + SocketPollTest() + { + lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); + lwpa_netint_get_default_interface(&default_netint_); + } + ~SocketPollTest() + { + lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); + } + + LwpaNetintInfo default_netint_; + static const char* SEND_MSG; static const size_t SEND_MSG_LEN{12}; @@ -133,7 +142,7 @@ TEST_F(SocketPollTest, modify) // Bind the socket to the wildcard address and port 8888. LwpaSockaddr bind_addr; - lwpaip_make_any_v4(&bind_addr.ip); + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); bind_addr.port = 8888; ASSERT_EQ(kLwpaErrOk, lwpa_bind(sock, &bind_addr)); @@ -155,7 +164,7 @@ TEST_F(SocketPollTest, modify) // Send data to socket LwpaSockaddr send_addr; - send_addr.ip = g_netint; + send_addr.ip = default_netint_.addr; send_addr.port = 8888; lwpa_sendto(sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); @@ -185,7 +194,7 @@ TEST_F(SocketPollTest, bulk_poll) if (i < BULK_POLL_TEST_NUM_SOCKETS) { LwpaSockaddr bind_addr; - lwpaip_make_any_v4(&bind_addr.ip); + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); bind_addr.port = 0; ASSERT_EQ(kLwpaErrOk, lwpa_bind(socket_arr[i], &bind_addr)) << "Failed on iteration " << i; ASSERT_EQ(kLwpaErrOk, lwpa_getsockname(socket_arr[i], &bind_addr)) << "Failed on iteration " << i; @@ -203,7 +212,7 @@ TEST_F(SocketPollTest, bulk_poll) ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); LwpaSockaddr send_addr; - lwpaip_set_v4_address(&send_addr.ip, 0x7f000001); + LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, 0x7f000001); for (size_t i = 0; i < BULK_POLL_TEST_NUM_SOCKETS; ++i) { // Send to each socket in turn and make sure poll works for it @@ -244,7 +253,7 @@ TEST_F(SocketPollTest, udp_in) // Bind socket 1 to the wildcard address and port 8888. LwpaSockaddr bind_addr; - lwpaip_make_any_v4(&bind_addr.ip); + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); bind_addr.port = 8888; ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); @@ -261,7 +270,7 @@ TEST_F(SocketPollTest, udp_in) ASSERT_EQ(kLwpaErrTimedOut, lwpa_poll_wait(&context_, &event, 100)); LwpaSockaddr send_addr; - send_addr.ip = g_netint; + send_addr.ip = default_netint_.addr; send_addr.port = 8888; lwpa_sendto(send_sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); @@ -278,7 +287,7 @@ TEST_F(SocketPollTest, udp_in) std::array recv_buf; LwpaSockaddr from_addr; ASSERT_EQ(SEND_MSG_LEN, (size_t)lwpa_recvfrom(event.socket, recv_buf.data(), SEND_MSG_LEN, 0, &from_addr)); - ASSERT_TRUE(lwpaip_equal(&send_addr.ip, &from_addr.ip)); + ASSERT_TRUE(lwpa_ip_equal(&send_addr.ip, &from_addr.ip)); ASSERT_NE(from_addr.port, 8888); ASSERT_NE(from_addr.port, 9999); recv_buf[SEND_MSG_LEN] = '\0'; From bb071cd5a4d96b523db9b03354d7e0b7385092ce Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 5 Jun 2019 22:00:02 -0500 Subject: [PATCH 017/264] Finish up some API changes on Windows, moving back to Linux --- include/lwpa/inet.h | 3 +- include/lwpa/netint.h | 3 +- src/lwpa/inet.c | 115 +++++++++++++---- src/os/windows/lwpa/os_netint.c | 37 +++--- tests/unit/test_inet.cpp | 214 +++++++++++++++++++++++++++++--- tests/unit/test_netint.cpp | 20 +-- 6 files changed, 325 insertions(+), 67 deletions(-) diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index 50f19e0bc..7178fe0ec 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -169,8 +169,7 @@ int lwpa_ip_cmp(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2); bool lwpa_ip_and_port_equal(const LwpaSockaddr* sock1, const LwpaSockaddr* sock2); unsigned int lwpa_ip_mask_length(const LwpaIpAddr* netmask); -LwpaIpAddr lwpa_ipv4_mask_from_length(unsigned int mask_length); -LwpaIpAddr lwpa_ipv6_mask_from_length(unsigned int mask_length); +LwpaIpAddr lwpa_ip_mask_from_length(lwpa_iptype_t type, unsigned int mask_length); bool lwpa_ip_network_portions_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* netmask); #ifdef __cplusplus diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index 38b25d5f5..2f57ae246 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -42,8 +42,7 @@ extern "C" { size_t lwpa_netint_get_num_interfaces(); size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size); bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint); -const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, - size_t netint_arr_size); +lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint); #ifdef __cplusplus } diff --git a/src/lwpa/inet.c b/src/lwpa/inet.c index 7c87ed8c9..9e04f4916 100644 --- a/src/lwpa/inet.c +++ b/src/lwpa/inet.c @@ -39,7 +39,7 @@ bool lwpa_ip_is_multicast(const LwpaIpAddr* ip) { if (LWPA_IP_IS_V4(ip)) { - return (LWPA_IP_V4_ADDRESS(ip) > 0xe0000000 && LWPA_IP_V4_ADDRESS(ip) < 0xefffffff); + return (LWPA_IP_V4_ADDRESS(ip) >= 0xe0000000 && LWPA_IP_V4_ADDRESS(ip) <= 0xefffffff); } else if (LWPA_IP_IS_V6(ip)) { @@ -49,6 +49,17 @@ bool lwpa_ip_is_multicast(const LwpaIpAddr* ip) return false; } +/*! \brief Determine whether a LwpaIpAddr contains a wildcard address. + * + * Works for both IPv4 and IPv6 addresses. The wildcard address is used as an argument to + * lwpa_bind() to indicate that a socket should be bound to all available network interfaces. It + * should not be used as a placeholder or invalid address - use LWPA_IP_SET_INVALID() and + * LWPA_IP_IS_INVALID() for that. + * + * \param[in] ip Address to check. + * \return true: ip contains a wildcard address. + * \return false: ip does not contain a wildcard address. + */ bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip) { if (ip) @@ -65,6 +76,16 @@ bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip) return false; } +/*! \brief Initialize a LwpaIpAddr with a wildcard address. + * + * Works for both IPv4 and IPv6 addresses. The wildcard address is used as an argument to + * lwpa_bind() to indicate that a socket should be bound to all available network interfaces. It + * should not be used as a placeholder or invalid address - use LWPA_IP_SET_INVALID() and + * LWPA_IP_IS_INVALID() for that. + * + * \param[in] type Type of wildcard to create, either IPv4 or IPv6. + * \param[out] ip Address in which to store the wildcard value. + */ void lwpa_ip_set_wildcard(lwpa_iptype_t type, LwpaIpAddr* ip) { if (ip) @@ -78,6 +99,7 @@ void lwpa_ip_set_wildcard(lwpa_iptype_t type, LwpaIpAddr* ip) LWPA_IP_SET_V6_ADDRESS(ip, v6_wildcard); break; default: + LWPA_IP_SET_INVALID(ip); break; } } @@ -116,8 +138,8 @@ bool lwpa_ip_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2) * * All IPv4 addresses are considered to be < all IPv6 addresses * * For two IPv4 or IPv6 addresses, the numerical address value is compared * - * \param ip1 First LwpaIpAddr to compare. - * \param ip2 Second LwpaIpAddr to compare. + * \param[in] ip1 First LwpaIpAddr to compare. + * \param[in] ip2 Second LwpaIpAddr to compare. * \return < 0: ip1 < ip2 * \return 0: ip1 == ip2 * \return > 0: ip1 > ip2 @@ -177,29 +199,32 @@ unsigned int lwpa_ip_mask_length(const LwpaIpAddr* netmask) if (LWPA_IP_IS_V4(netmask)) { uint32_t addr_val = LWPA_IP_V4_ADDRESS(netmask); - while (addr_val & 0x8000) + uint32_t bit_mask = 0x80000000u; + while (addr_val & bit_mask) { ++length; - addr_val >>= 1; + bit_mask >>= 1; } } else if (LWPA_IP_IS_V6(netmask)) { const uint8_t* addr_buf = LWPA_IP_V6_ADDRESS(netmask); - for (size_t i = 0; i < LWPA_IPV6_BYTES; ++i) + size_t addr_index = 0; + while (addr_buf[addr_index] == 0xff && addr_index < LWPA_IPV6_BYTES) { - uint8_t addr_val = addr_buf[i]; - bool break_early = false; - for (size_t j = 0; j < 8; ++j, ++length) + length += 8; + addr_index++; + } + + if (addr_index < LWPA_IPV6_BYTES) + { + uint8_t addr_val = addr_buf[addr_index]; + uint8_t bit_mask = 0x80u; + for (; bit_mask != 0; bit_mask >>= 1, ++length) { - if (!(addr_val & 0x80)) - { - break_early = true; + if (!(addr_val & bit_mask)) break; - } } - if (break_early) - break; } } } @@ -207,19 +232,63 @@ unsigned int lwpa_ip_mask_length(const LwpaIpAddr* netmask) return length; } -LwpaIpAddr lwpa_ipv4_mask_from_length(unsigned int mask_length) +/*! \brief Create a netmask given a length in bits. + * + * Creates either an IPv4 or IPv6 netmask, setting the most-significant mask_length bits. + * + * For example: + * type = kLwpaIpTypeV4; mask_length = 16; result = 255.255.0.0 + * type = kLwpaIpTypeV6; mask_length = 64; result = ffff:ffff:ffff:ffff:: + * + * \param[in] type Type of netmask to create, either IPv4 or IPv6. + * \param[in] mask_length Length in bits of the mask, counting from the MSB. + * \return LwpaIpAddr containing the netmask. + */ +LwpaIpAddr lwpa_ip_mask_from_length(lwpa_iptype_t type, unsigned int mask_length) { LwpaIpAddr result; - LWPA_IP_SET_INVALID(&result); - return result; -} + if (type == kLwpaIpTypeV4) + { + uint32_t mask_val = 0; + uint32_t bit_mask = 0x80000000u; + unsigned int adjusted_length = (mask_length > 32 ? 32 : mask_length); + for (unsigned int i = 0; i < adjusted_length; ++i, bit_mask >>= 1) + { + mask_val |= bit_mask; + } -LwpaIpAddr lwpa_ipv6_mask_from_length(unsigned int mask_length) -{ - LwpaIpAddr result; - LWPA_IP_SET_INVALID(&result); + LWPA_IP_SET_V4_ADDRESS(&result, mask_val); + } + else if (type == kLwpaIpTypeV6) + { + uint8_t mask_buf[LWPA_IPV6_BYTES]; + memset(mask_buf, 0, sizeof(mask_buf)); + unsigned int adjusted_length = (mask_length > 128 ? 128 : mask_length); + + size_t mask_index = 0; + while (adjusted_length / 8 > 0) + { + mask_buf[mask_index++] = 0xff; + adjusted_length -= 8; + } + + uint8_t bit_mask = 0x80u; + do + { + if (adjusted_length == 0) + break; + mask_buf[mask_index] |= bit_mask; + --adjusted_length; + bit_mask >>= 1; + } while (bit_mask != 0); + LWPA_IP_SET_V6_ADDRESS(&result, mask_buf); + } + else + { + LWPA_IP_SET_INVALID(&result); + } return result; } diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index de5ee1e4d..c0b63ae16 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -45,7 +45,7 @@ static struct LwpaNetintState static IP_ADAPTER_ADDRESSES* get_windows_adapters(); static void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, IP_ADAPTER_GATEWAY_ADDRESS* pgate, LwpaNetintInfo* info); -static void copy_all_netint_info(IP_ADAPTER_ADDRESSES *adapters); +static void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters); static lwpa_error_t enumerate_netints(); static void free_netints(); @@ -97,29 +97,38 @@ bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint) return false; } -const LwpaNetintInfo* lwpa_netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, - size_t netint_arr_size) +lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) { const LwpaNetintInfo* res = NULL; const LwpaNetintInfo* def = NULL; - const LwpaNetintInfo* netint; - if (!dest || !netint_arr || netint_arr_size == 0) - return false; + if (!dest || !netint) + return kLwpaErrInvalid; - for (netint = netint_arr; netint < netint_arr + netint_arr_size; ++netint) + for (const LwpaNetintInfo* netint_entry = state.lwpa_netints; netint_entry < state.lwpa_netints + state.num_netints; + ++netint_entry) { - if (netint->is_default) - def = netint; - if (!lwpa_ip_is_wildcard(&netint->mask) && lwpa_ip_network_portions_equal(&netint->addr, dest, &netint->mask)) + if (netint_entry->is_default) + def = netint_entry; + if (!lwpa_ip_is_wildcard(&netint_entry->mask) && + lwpa_ip_network_portions_equal(&netint_entry->addr, dest, &netint_entry->mask)) { - res = netint; + res = netint_entry; break; } } if (!res) res = def; - return res; + + if (res) + { + *netint = *res; + return kLwpaErrOk; + } + else + { + return kLwpaErrNotFound; + } } lwpa_error_t enumerate_netints() @@ -219,9 +228,9 @@ void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, IP_ADAPTER_GATEWAY_ADDRESS* LWPA_IP_SET_V4_ADDRESS(&info->gate, 0u); } -void copy_all_netint_info(IP_ADAPTER_ADDRESSES *adapters) +void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) { - IP_ADAPTER_ADDRESSES *pcur = adapters; + IP_ADAPTER_ADDRESSES* pcur = adapters; DWORD def_ifindex; bool have_def_index = false; if (NO_ERROR == GetBestInterface(0, &def_ifindex)) diff --git a/tests/unit/test_inet.cpp b/tests/unit/test_inet.cpp index 8bf58e649..aba24e824 100644 --- a/tests/unit/test_inet.cpp +++ b/tests/unit/test_inet.cpp @@ -19,43 +19,109 @@ #include "lwpa/inet.h" #include "gtest/gtest.h" #include +#include +#include class InetTest : public ::testing::Test { }; // Test the LwpaIpAddr struct and macros -TEST_F(InetTest, ip_addr) +TEST_F(InetTest, addr_macros) { - LwpaIpAddr v4; + LwpaIpAddr test_addr; + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x01020304); + EXPECT_TRUE(LWPA_IP_IS_V4(&test_addr)); + EXPECT_EQ(LWPA_IP_V4_ADDRESS(&test_addr), 0x01020304u); + + std::array v6_data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); + EXPECT_TRUE(LWPA_IP_IS_V6(&test_addr)); + EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&test_addr), v6_data.data(), LWPA_IPV6_BYTES)); + + LWPA_IP_SET_INVALID(&test_addr); + EXPECT_TRUE(LWPA_IP_IS_INVALID(&test_addr)); +} + +TEST_F(InetTest, multicast) +{ + LwpaIpAddr test_addr; + + // An invalid IP is not multicast + LWPA_IP_SET_INVALID(&test_addr); + EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); + + // Test the edges of the IPv4 multicast range + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xdfffffff); + EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xe0000000); + EXPECT_TRUE(lwpa_ip_is_multicast(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xefffffff); + EXPECT_TRUE(lwpa_ip_is_multicast(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xf0000000); + EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xffffffff); + EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); + + // Test the edges of the IPv6 multicast range + std::array v6_data = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); + EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); + + v6_data = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); + EXPECT_TRUE(lwpa_ip_is_multicast(&test_addr)); + + v6_data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); + EXPECT_TRUE(lwpa_ip_is_multicast(&test_addr)); +} + +// Just tests reflexivity of the wildcard functions, we don't rely on the wildcard address to be +// any specific value. +TEST_F(InetTest, wildcard) +{ + LwpaIpAddr test_addr; + + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &test_addr); + EXPECT_TRUE(lwpa_ip_is_wildcard(&test_addr)); + + lwpa_ip_set_wildcard(kLwpaIpTypeV6, &test_addr); + EXPECT_TRUE(lwpa_ip_is_wildcard(&test_addr)); +} + +// Test the lwpa_ip_equal() and lwpa_ip_cmp() functions +TEST_F(InetTest, compare) +{ + LwpaIpAddr v4; LWPA_IP_SET_V4_ADDRESS(&v4, 0x01020304); - ASSERT_TRUE(LWPA_IP_IS_V4(&v4)); - ASSERT_EQ(LWPA_IP_V4_ADDRESS(&v4), 0x01020304u); // Copied address should compare equal LwpaIpAddr v4_copy = v4; - ASSERT_TRUE(lwpa_ip_equal(&v4_copy, &v4)); - ASSERT_EQ(0, lwpa_ip_cmp(&v4_copy, &v4)); + EXPECT_TRUE(lwpa_ip_equal(&v4_copy, &v4)); + EXPECT_EQ(0, lwpa_ip_cmp(&v4_copy, &v4)); LwpaIpAddr v6; - std::array v6_data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; LWPA_IP_SET_V6_ADDRESS(&v6, v6_data.data()); - ASSERT_TRUE(LWPA_IP_IS_V6(&v6)); - ASSERT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&v6), v6_data.data(), LWPA_IPV6_BYTES)); // Copied address should compare equal LwpaIpAddr v6_copy = v6; - ASSERT_TRUE(lwpa_ip_equal(&v6_copy, &v6)); - ASSERT_EQ(0, lwpa_ip_cmp(&v6_copy, &v6)); + EXPECT_TRUE(lwpa_ip_equal(&v6_copy, &v6)); + EXPECT_EQ(0, lwpa_ip_cmp(&v6_copy, &v6)); // The v4 and v6 should not be equal, and per the comparison algorithm the v4 should be less than // the v6 - ASSERT_FALSE(lwpa_ip_equal(&v4, &v6)); - ASSERT_LT(lwpa_ip_cmp(&v4, &v6), 0); + EXPECT_FALSE(lwpa_ip_equal(&v4, &v6)); + EXPECT_LT(lwpa_ip_cmp(&v4, &v6), 0); - // Further test the lwpa_ip_cmp() macro, with like address types + // Further test the lwpa_ip_cmp() function, with like address types LwpaIpAddr v4_less; LWPA_IP_SET_V4_ADDRESS(&v4_less, 0x01020303); @@ -64,6 +130,122 @@ TEST_F(InetTest, ip_addr) v6_data_less[15] = 14; LWPA_IP_SET_V6_ADDRESS(&v6_less, v6_data_less.data()); - ASSERT_LT(lwpa_ip_cmp(&v4_less, &v4), 0); - ASSERT_LT(lwpa_ip_cmp(&v6_less, &v6), 0); + EXPECT_LT(lwpa_ip_cmp(&v4_less, &v4), 0); + EXPECT_LT(lwpa_ip_cmp(&v6_less, &v6), 0); } + +// Test the lwpa_ip_mask_length() function +TEST_F(InetTest, mask_length) +{ + LwpaIpAddr test_mask; + + // Test mask: Invalid or null IP + EXPECT_EQ(0u, lwpa_ip_mask_length(nullptr)); + LWPA_IP_SET_INVALID(&test_mask); + EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /0, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0); + EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /7, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xfe000000u); + EXPECT_EQ(7u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /25, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xffffff80u); + EXPECT_EQ(25u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /32, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xffffffffu); + EXPECT_EQ(32u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: nonzero but with leading zeroes, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0x7fffffff); + EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /0, V6 + std::array test_v6_val{}; + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); + EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /64, V6 + test_v6_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}; + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); + EXPECT_EQ(64u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /77, V6 + test_v6_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0, 0, 0, 0, 0, 0}; + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); + EXPECT_EQ(77u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /128, V6 + test_v6_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); + EXPECT_EQ(128u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: nonzero but with leading zeroes, V6 + test_v6_val = {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); + EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); +} + +// Test the lwpa_ip_mask_from_length() function +TEST_F(InetTest, mask_from_length) +{ + // Test mask: /0, V4 + LwpaIpAddr mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 0); + EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); + EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0u); + + // Test mask: /7, V4 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 7); + EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); + EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0xfe000000u); + + // Test mask: /25, V4 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 25); + EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); + EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffff80u); + + // Test mask: /32, V4 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 32); + EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); + EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffffffu); + + // Test mask: Greater than /32, V4 + // Should truncate to 32 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, UINT_MAX); + EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); + EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffffffu); + + // Test mask: /0, V6 + std::array v6_compare_val{}; + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 0); + EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); + EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); + + // Test mask: /64, V6 + v6_compare_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}; + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 64); + EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); + EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); + + // Test mask: /77, V6 + v6_compare_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0, 0, 0, 0, 0, 0}; + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 77); + EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); + EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); + + // Test mask: /128, V6 + v6_compare_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 128); + EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); + EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); + + // Test mask: Greater than /128, V6 + // Should truncate to 128 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, UINT_MAX); + EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); + EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); +} \ No newline at end of file diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index 61b4c46fc..d628e9831 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -26,14 +26,11 @@ class NetintTest : public ::testing::Test { protected: NetintTest() - { + { lwpa_init(LWPA_FEATURE_NETINTS); num_netints = lwpa_netint_get_num_interfaces(); } - ~NetintTest() - { - lwpa_deinit(LWPA_FEATURE_NETINTS); - } + ~NetintTest() { lwpa_deinit(LWPA_FEATURE_NETINTS); } size_t num_netints{0}; }; @@ -79,7 +76,7 @@ TEST_F(NetintTest, default) delete[] netint_arr; } -TEST_F(NetintTest, IPv4routing) +TEST_F(NetintTest, ipv4_routing) { ASSERT_GT(num_netints, 0u); @@ -97,12 +94,15 @@ TEST_F(NetintTest, IPv4routing) continue; nets_already_tried.insert(net); LWPA_IP_SET_V4_ADDRESS(&test_addr, net + 1); - ASSERT_EQ(lwpa_netint_get_iface_for_dest(&test_addr, netint_arr, num_netints), netint); + + LwpaNetintInfo netint_res; + ASSERT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&test_addr, &netint_res)); + EXPECT_TRUE(lwpa_ip_equal(&netint_res.addr, &netint->addr)); } LwpaIpAddr ext_addr; LWPA_IP_SET_V4_ADDRESS(&ext_addr, 0xc8dc0302); // 200.220.3.2 - const LwpaNetintInfo* def = lwpa_netint_get_iface_for_dest(&ext_addr, netint_arr, num_netints); - ASSERT_TRUE(def != NULL); - ASSERT_TRUE(def->is_default); + LwpaNetintInfo def; + ASSERT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&ext_addr, &def)); + ASSERT_TRUE(def.is_default); } From a2e8d5d64be03c15e8b44fb5eb66aaa0b1a47c6f Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 6 Jun 2019 18:13:32 -0500 Subject: [PATCH 018/264] Routing table now working. --- CMakeLists.txt | 11 +- examples/CMakeLists.txt | 1 + examples/netint/CMakeLists.txt | 6 + examples/netint/netint_example.c | 69 +++++++++ include/lwpa/inet.h | 3 +- src/CMakeLists.txt | 3 + src/lwpa/inet.c | 25 ++++ src/os/linux/lwpa/os_error.c | 2 +- src/os/linux/lwpa/os_netint.c | 241 +++++++++++++++++-------------- 9 files changed, 250 insertions(+), 111 deletions(-) create mode 100644 examples/CMakeLists.txt create mode 100644 examples/netint/CMakeLists.txt create mode 100644 examples/netint/netint_example.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 478d92023..d2adc1b8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,14 +27,21 @@ if(LWPA_BUILD_MOCK_LIB) add_subdirectory(external/fff) endif() -# Main library +################################# Main library ################################ add_subdirectory(src) -# Tests +#################################### Tests #################################### option(LWPA_BUILD_TESTS "Build the lwpa unit tests" ${OPTION_DEFAULTS}) if(LWPA_BUILD_TESTS) enable_testing() add_subdirectory(tests) endif() + +################################## Examples ################################### + +option(LWPA_BUILD_EXAMPLES "Build the lwpa example apps" ${OPTION_DEFAULTS}) +if(LWPA_BUILD_EXAMPLES) + add_subdirectory(examples) +endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 000000000..d7adcf57f --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(netint) diff --git a/examples/netint/CMakeLists.txt b/examples/netint/CMakeLists.txt new file mode 100644 index 000000000..fdff24808 --- /dev/null +++ b/examples/netint/CMakeLists.txt @@ -0,0 +1,6 @@ +############################# lwpa_netint example ############################# + +add_executable(netint_example + netint_example.c +) +target_link_libraries(netint_example PRIVATE lwpa) diff --git a/examples/netint/netint_example.c b/examples/netint/netint_example.c new file mode 100644 index 000000000..bc17c7c2c --- /dev/null +++ b/examples/netint/netint_example.c @@ -0,0 +1,69 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +/* An example application showing usage of the lwpa_netint functions. + * This example will print information about each network interface on your machine. It is + * platform-neutral. + */ + +#include +#include +#include +#include "lwpa/netint.h" +#include "lwpa/socket.h" + +int main() +{ + lwpa_error_t init_res = lwpa_init(LWPA_FEATURE_NETINTS); + if (init_res != kLwpaErrOk) + { + printf("lwpa_init() failed with error: '%s'\n", lwpa_strerror(init_res)); + return 1; + } + + size_t num_interfaces = lwpa_netint_get_num_interfaces(); + if (num_interfaces == 0) + { + printf("Error: No network interfaces found on system.\n"); + lwpa_deinit(LWPA_FEATURE_NETINTS); + return 1; + } + + LwpaNetintInfo* netint_arr = (LwpaNetintInfo*)calloc(num_interfaces, sizeof(LwpaNetintInfo)); + assert(netint_arr); + num_interfaces = lwpa_netint_get_interfaces(netint_arr, num_interfaces); + + printf("Network interfaces found:\n"); + printf("%-46s %-46s %-46s %s", "Address", "Netmask", "Gateway", "OS Index\n"); + for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_interfaces; ++netint) + { + char addr_str[LWPA_INET6_ADDRSTRLEN]; + char netmask_str[LWPA_INET6_ADDRSTRLEN]; + char gw_str[LWPA_INET6_ADDRSTRLEN]; + lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); + lwpa_inet_ntop(&netint->mask, netmask_str, LWPA_INET6_ADDRSTRLEN); + lwpa_inet_ntop(&netint->gate, gw_str, LWPA_INET6_ADDRSTRLEN); + + printf("%-46s %-46s %-46s %8d\n", addr_str, netmask_str, gw_str, netint->ifindex); + } + + lwpa_deinit(LWPA_FEATURE_NETINTS); + + return 0; +} diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index 7178fe0ec..ea4c36f81 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -160,9 +160,10 @@ typedef struct LwpaNetintInfo bool is_default; } LwpaNetintInfo; +bool lwpa_ip_is_loopback(const LwpaIpAddr* ip); bool lwpa_ip_is_multicast(const LwpaIpAddr* ip); bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip); -void lwpa_ip_set_wildcard(lwpa_iptype_t type, LwpaIpAddr *ip); +void lwpa_ip_set_wildcard(lwpa_iptype_t type, LwpaIpAddr* ip); bool lwpa_ip_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2); int lwpa_ip_cmp(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3af960206..1fb522fd8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -95,6 +95,9 @@ target_include_directories(lwpa PUBLIC ) target_include_directories(lwpa PRIVATE ${LWPA_ROOT}/src) target_compile_definitions(lwpa PUBLIC ${LWPA_HAVE_CONFIG_H}) +if(LWPA_NETINT_DEBUG_OUTPUT) + target_compile_definitions(lwpa PRIVATE LWPA_NETINT_DEBUG_OUTPUT) +endif() # Add include paths and library dependencies based on OS for which we are being compiled if(LWPA_TARGET_OS STREQUAL windows) diff --git a/src/lwpa/inet.c b/src/lwpa/inet.c index 9e04f4916..64ec8221d 100644 --- a/src/lwpa/inet.c +++ b/src/lwpa/inet.c @@ -22,9 +22,34 @@ /**************************** Private variables ******************************/ static const uint8_t v6_wildcard[LWPA_IPV6_BYTES] = {0}; +static const uint8_t v6_loopback[LWPA_IPV6_BYTES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; /*************************** Function definitions ****************************/ +/*! \brief Determine whether a LwpaIpAddr contains a loopback address. + * + * Works for both IPv4 and IPv6 addresses. + * + * \param[in] ip Address to check. + * \return true: ip contains a loopback address. + * \return false: ip does not contain a loopback address. + */ +bool lwpa_ip_is_loopback(const LwpaIpAddr* ip) +{ + if (ip) + { + if (LWPA_IP_IS_V4(ip)) + { + return ((LWPA_IP_V4_ADDRESS(ip) & 0xff000000u) == 0x7f000000u); + } + else if (LWPA_IP_IS_V6(ip)) + { + return (0 == memcmp(LWPA_IP_V6_ADDRESS(ip), v6_loopback, LWPA_IPV6_BYTES)); + } + } + return false; +} + /*! \brief Determine whether a LwpaIpAddr contains a multicast address. * * Works for both IPv4 and IPv6 addresses. diff --git a/src/os/linux/lwpa/os_error.c b/src/os/linux/lwpa/os_error.c index 02844ea0f..2f4a6980e 100644 --- a/src/os/linux/lwpa/os_error.c +++ b/src/os/linux/lwpa/os_error.c @@ -19,7 +19,7 @@ #include "os_error.h" -lwpa_error_t err_os_to_lwpa(int errno) +lwpa_error_t errno_os_to_lwpa(int errno) { switch (errno) { diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 704b7502f..316d30b37 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -36,6 +36,11 @@ #include #include +#ifdef LWPA_NETINT_DEBUG_OUTPUT +#include +#include +#endif + #include #include #include @@ -97,9 +102,8 @@ static void free_routing_table(RoutingTable* table); // Interacting with RTNETLINK static lwpa_error_t send_netlink_route_request(int socket, int family); -static lwpa_error_t receive_netlink_route_reply(int sock, size_t buf_size, RoutingTable* table); -static void cidr_length_to_v4_mask(unsigned char length, LwpaIpAddr* v4_mask); -static void cidr_length_to_v6_mask(unsigned char length, LwpaIpAddr* v6_mask); +static lwpa_error_t receive_netlink_route_reply(int sock, int family, size_t buf_size, RoutingTable* table); +static lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl_msg_size, RoutingTable* table); // Manipulating static void init_routing_table_entry(RoutingTableEntry* entry); @@ -109,6 +113,10 @@ static int compare_routing_table_entries(const void* a, const void* b); static lwpa_error_t enumerate_netints(); static void free_netints(); +#if LWPA_NETINT_DEBUG_OUTPUT +static void debug_print_routing_table(RoutingTable* table); +#endif + /*************************** Function definitions ****************************/ lwpa_error_t lwpa_netint_init() @@ -158,6 +166,11 @@ lwpa_error_t build_routing_tables() if (res != kLwpaErrOk) free_routing_tables(); +#if LWPA_NETINT_DEBUG_OUTPUT + debug_print_routing_table(&state.routing_table_v4); + debug_print_routing_table(&state.routing_table_v6); +#endif + return res; } @@ -186,12 +199,12 @@ lwpa_error_t build_routing_table(int family, RoutingTable* table) result = errno_os_to_lwpa(errno); } - if (result) + if (result == kLwpaErrOk) result = send_netlink_route_request(sock, family); - if (result) + if (result == kLwpaErrOk) { - result = receive_netlink_route_reply(sock, recv_buf_size, table); + result = receive_netlink_route_reply(sock, family, recv_buf_size, table); switch (result) { case kLwpaErrOk: @@ -234,7 +247,7 @@ lwpa_error_t send_netlink_route_request(int socket, int family) return errno_os_to_lwpa(errno); } -lwpa_error_t receive_netlink_route_reply(int sock, size_t buf_size, RoutingTable* table) +lwpa_error_t receive_netlink_route_reply(int sock, int family, size_t buf_size, RoutingTable* table) { // Allocate slightly larger than buf_size, so we can detect when more room is needed size_t real_size = buf_size + 20; @@ -243,7 +256,6 @@ lwpa_error_t receive_netlink_route_reply(int sock, size_t buf_size, RoutingTable return kLwpaErrNoMem; memset(buffer, 0, real_size); - struct nlmsghdr* nl_header; char* cur_ptr = buffer; size_t nl_msg_size = 0; @@ -265,90 +277,106 @@ lwpa_error_t receive_netlink_route_reply(int sock, size_t buf_size, RoutingTable return errno_os_to_lwpa(errno); } - nl_header = (struct nlmsghdr*)cur_ptr; + struct nlmsghdr* nl_header = (struct nlmsghdr*)cur_ptr; if (nl_header->nlmsg_type == NLMSG_DONE) break; - // Each message represents one route - ++table->size; - // Adjust our position in the buffer and size received cur_ptr += recv_res; nl_msg_size += (size_t)recv_res; } - table->entries = calloc(table->size, sizeof(RoutingTableEntry)); - if (!table->entries) - { - table->size = 0; - free(buffer); - return kLwpaErrNoMem; - } + lwpa_error_t parse_res = parse_netlink_route_reply(family, buffer, nl_msg_size, table); + + free(buffer); + return parse_res; +} + +lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl_msg_size, RoutingTable* table) +{ + table->size = 0; + table->entries = NULL; // Parse the result // outer loop: loops thru all the NETLINK headers that also include the route entry header - nl_header = (struct nlmsghdr*)buffer; - RoutingTableEntry* entry = table->entries; + struct nlmsghdr* nl_header = (struct nlmsghdr*)buffer; for (; NLMSG_OK(nl_header, nl_msg_size); nl_header = NLMSG_NEXT(nl_header, nl_msg_size)) { - init_routing_table_entry(entry); + RoutingTableEntry new_entry; + init_routing_table_entry(&new_entry); - struct rtmsg* rt_message; - int rt_attr_size; - struct rtattr* rt_attributes; + bool new_entry_valid = true; // get route entry header - rt_message = (struct rtmsg*)NLMSG_DATA(nl_header); + struct rtmsg* rt_message = (struct rtmsg*)NLMSG_DATA(nl_header); - // inner loop: loop thru all the attributes of one route entry. - rt_attributes = (struct rtattr*)RTM_RTA(rt_message); - rt_attr_size = (int)RTM_PAYLOAD(nl_header); - for (; RTA_OK(rt_attributes, rt_attr_size); rt_attributes = RTA_NEXT(rt_attributes, rt_attr_size)) + // Filter out entries from the local routing table. Netlink seems to give us those even though + // we only asked for the main one. + if (rt_message->rtm_type != RTN_LOCAL && rt_message->rtm_type != RTN_BROADCAST && + rt_message->rtm_type != RTN_ANYCAST) { - // We only care about the gateway and DST attribute - if (rt_attributes->rta_type == RTA_DST) + // inner loop: loop thru all the attributes of one route entry. + struct rtattr* rt_attributes = (struct rtattr*)RTM_RTA(rt_message); + int rt_attr_size = (int)RTM_PAYLOAD(nl_header); + for (; RTA_OK(rt_attributes, rt_attr_size); rt_attributes = RTA_NEXT(rt_attributes, rt_attr_size)) { - if (rt_attributes->rta_len == sizeof(struct in6_addr)) - LWPA_IP_SET_V6_ADDRESS(&entry->addr, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); - else - LWPA_IP_SET_V4_ADDRESS(&entry->addr, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); - } - else if (rt_attributes->rta_type == RTA_GATEWAY) - { - if (rt_attributes->rta_len == sizeof(struct in6_addr)) - LWPA_IP_SET_V6_ADDRESS(&entry->gateway, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); - else - LWPA_IP_SET_V4_ADDRESS(&entry->gateway, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); - } - else if (rt_attributes->rta_type == RTA_OIF) - { - entry->interface_index = *((int*)RTA_DATA(rt_attributes)); - } - else if (rt_attributes->rta_type == RTA_METRICS) - { - entry->metric = *((int*)RTA_DATA(rt_attributes)); + // We only care about the gateway and DST attribute + if (rt_attributes->rta_type == RTA_DST) + { + if (family == AF_INET6) + LWPA_IP_SET_V6_ADDRESS(&new_entry.addr, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); + else + LWPA_IP_SET_V4_ADDRESS(&new_entry.addr, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); + } + else if (rt_attributes->rta_type == RTA_GATEWAY) + { + if (family == AF_INET6) + LWPA_IP_SET_V6_ADDRESS(&new_entry.gateway, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); + else + LWPA_IP_SET_V4_ADDRESS(&new_entry.gateway, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); + } + else if (rt_attributes->rta_type == RTA_OIF) + { + new_entry.interface_index = *((int*)RTA_DATA(rt_attributes)); + } + else if (rt_attributes->rta_type == RTA_PRIORITY) + { + new_entry.metric = *((int*)RTA_DATA(rt_attributes)); + } } } - - if (LWPA_IP_IS_V4(&entry->addr)) + else { - cidr_length_to_v4_mask(rt_message->rtm_dst_len, &entry->mask); + new_entry_valid = false; } - else if (LWPA_IP_IS_V6(&entry->addr)) + + if (!LWPA_IP_IS_INVALID(&new_entry.addr)) { - cidr_length_to_v6_mask(rt_message->rtm_dst_len, &entry->mask); + new_entry.mask = lwpa_ip_mask_from_length(new_entry.addr.type, rt_message->rtm_dst_len); } - ++entry; + // Insert the new entry into the list + if (new_entry_valid) + { + ++table->size; + if (table->entries) + table->entries = (RoutingTableEntry*)realloc(table->entries, table->size * sizeof(RoutingTableEntry)); + else + table->entries = (RoutingTableEntry*)malloc(sizeof(RoutingTableEntry)); + table->entries[table->size - 1] = new_entry; + } } - if (buffer) - free(buffer); - - qsort(table->entries, table->size, sizeof(RoutingTableEntry), compare_routing_table_entries); - - return kLwpaErrOk; + if (table->size > 0) + { + qsort(table->entries, table->size, sizeof(RoutingTableEntry), compare_routing_table_entries); + return kLwpaErrOk; + } + else + { + return kLwpaErrSys; + } } void init_routing_table_entry(RoutingTableEntry* entry) @@ -368,53 +396,22 @@ int compare_routing_table_entries(const void* a, const void* b) unsigned int mask_length_1 = lwpa_ip_mask_length(&e1->mask); unsigned int mask_length_2 = lwpa_ip_mask_length(&e2->mask); if (mask_length_1 > mask_length_2) - return 1; - else if (mask_length_1 == mask_length_2) - return 0; - else + { return -1; -} - -void cidr_length_to_v4_mask(unsigned char length, LwpaIpAddr* v4_mask) -{ - unsigned char length_remaining = length; - uint32_t mask_val = 0; - uint32_t bit_to_set = 0x8000; - - // Cannot rely on signed/arithmetic shifts here because that behavior is implementation-defined - // in ANSI C - for (; length_remaining > 0; --length_remaining) + } + else if (mask_length_1 < mask_length_2) { - mask_val |= bit_to_set; - bit_to_set >>= 1; + return 1; } - - LWPA_IP_SET_V4_ADDRESS(v4_mask, mask_val); -} - -void cidr_length_to_v6_mask(unsigned char length, LwpaIpAddr* v6_mask) -{ - uint8_t mask_buf[LWPA_IPV6_BYTES]; - size_t mask_buf_index = 0; - unsigned char length_remaining = length; - uint8_t bit_to_set = 0x80; - - // Cannot rely on signed/arithmetic shifts here because that behavior is implementation-defined - // in ANSI C - for (; length_remaining > 0; --length_remaining) + else { - mask_buf[mask_buf_index] |= bit_to_set; - bit_to_set >>= 1; - if (bit_to_set == 0) - { - if (++mask_buf_index >= LWPA_IPV6_BYTES) - break; - - bit_to_set = 0x80; - } + if (e1->metric < e2->metric) + return -1; + else if (e1->metric > e2->metric) + return 1; + else + return 0; } - - LWPA_IP_SET_V6_ADDRESS(v6_mask, mask_buf); } /* Quick helper for enumerate_netints() to determine entries to skip in the linked list. */ @@ -452,7 +449,7 @@ lwpa_error_t enumerate_netints() } // Allocate our interface array - state.lwpa_netints = calloc(state.num_netints, sizeof(LwpaNetintInfo)); + state.lwpa_netints = (LwpaNetintInfo*)calloc(state.num_netints, sizeof(LwpaNetintInfo)); if (!state.lwpa_netints) { freeifaddrs(state.os_addrs); @@ -466,7 +463,7 @@ lwpa_error_t enumerate_netints() if (should_skip_ifaddr(ifaddr)) continue; - LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; + LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index++]; // Interface name strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); @@ -514,3 +511,33 @@ void free_netints() state.lwpa_netints = NULL; } } + +#if LWPA_NETINT_DEBUG_OUTPUT +void debug_print_routing_table(RoutingTable* table) +{ + printf("%-40s %-40s %-40s %s %s\n", "Address", "Mask", "Gateway", "Metric", "Index"); + for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) + { + char addr_str[LWPA_INET6_ADDRSTRLEN]; + char mask_str[LWPA_INET6_ADDRSTRLEN]; + char gw_str[LWPA_INET6_ADDRSTRLEN]; + + if (!LWPA_IP_IS_INVALID(&entry->addr)) + lwpa_inet_ntop(&entry->addr, addr_str, LWPA_INET6_ADDRSTRLEN); + else + strcpy(addr_str, "0.0.0.0"); + + if (!LWPA_IP_IS_INVALID(&entry->mask)) + lwpa_inet_ntop(&entry->mask, mask_str, LWPA_INET6_ADDRSTRLEN); + else + strcpy(mask_str, "0.0.0.0"); + + if (!LWPA_IP_IS_INVALID(&entry->gateway)) + lwpa_inet_ntop(&entry->gateway, gw_str, LWPA_INET6_ADDRSTRLEN); + else + strcpy(gw_str, "0.0.0.0"); + + printf("%-40s %-40s %-40s %d %d\n", addr_str, mask_str, gw_str, entry->metric, entry->interface_index); + } +} +#endif From ec89346917538b8adbbc666cbb45940f0a1aabda Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 6 Jun 2019 21:20:38 -0500 Subject: [PATCH 019/264] Improve netint and example. Gateway code does not quite work as expected yet - need to troubleshoot --- examples/netint/netint_example.c | 76 +++++++++++++++++++++++++++++--- src/os/linux/lwpa/os_netint.c | 54 ++++++++++++++++++++++- 2 files changed, 123 insertions(+), 7 deletions(-) diff --git a/examples/netint/netint_example.c b/examples/netint/netint_example.c index bc17c7c2c..2c5918db4 100644 --- a/examples/netint/netint_example.c +++ b/examples/netint/netint_example.c @@ -28,6 +28,66 @@ #include "lwpa/netint.h" #include "lwpa/socket.h" +#define FORMAT_BUF_SIZE 50 + +static char header_format[FORMAT_BUF_SIZE]; +static char line_format[FORMAT_BUF_SIZE]; + +#define NAME_COL_HEADER "Name" +#define ADDR_COL_HEADER "Address" +#define NETMASK_COL_HEADER "Netmask" +#define GATEWAY_COL_HEADER "Gateway" +#define MAC_COL_HEADER "MAC" +#define INDEX_COL_HEADER "OS Index" + +// Create a format string for printf based on the column width of the longest entry in each column +void create_format_strings(const LwpaNetintInfo* netint_arr, size_t num_interfaces) +{ + size_t longest_name = 0; + size_t longest_addr = 0; + size_t longest_netmask = 0; + size_t longest_gateway = 0; + + for (const LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_interfaces; ++netint) + { + char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; + char netmask_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; + char gw_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; + + lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); + lwpa_inet_ntop(&netint->mask, netmask_str, LWPA_INET6_ADDRSTRLEN); + lwpa_inet_ntop(&netint->gate, gw_str, LWPA_INET6_ADDRSTRLEN); + + size_t name_len = strlen(netint->name); + size_t addr_len = strlen(addr_str); + size_t netmask_len = strlen(netmask_str); + size_t gw_len = strlen(gw_str); + + if (name_len > longest_name) + longest_name = name_len; + if (addr_len > longest_addr) + longest_addr = addr_len; + if (netmask_len > longest_netmask) + longest_netmask = netmask_len; + if (gw_len > longest_gateway) + longest_gateway = gw_len; + } + + if (longest_name < sizeof(NAME_COL_HEADER)) + longest_name = sizeof(NAME_COL_HEADER); + if (longest_addr < sizeof(ADDR_COL_HEADER)) + longest_addr = sizeof(ADDR_COL_HEADER); + if (longest_netmask < sizeof(NETMASK_COL_HEADER)) + longest_netmask = sizeof(NETMASK_COL_HEADER); + if (longest_gateway < sizeof(GATEWAY_COL_HEADER)) + longest_gateway = sizeof(GATEWAY_COL_HEADER); + + snprintf(header_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-%zus %%-17s %%s\n", longest_name, longest_addr, + longest_netmask, longest_gateway); + snprintf(line_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-%zus %%-17s %%8d\n", longest_name, longest_addr, + longest_netmask, longest_gateway); +} + int main() { lwpa_error_t init_res = lwpa_init(LWPA_FEATURE_NETINTS); @@ -49,18 +109,24 @@ int main() assert(netint_arr); num_interfaces = lwpa_netint_get_interfaces(netint_arr, num_interfaces); + create_format_strings(netint_arr, num_interfaces); + printf("Network interfaces found:\n"); - printf("%-46s %-46s %-46s %s", "Address", "Netmask", "Gateway", "OS Index\n"); + printf(header_format, NAME_COL_HEADER, ADDR_COL_HEADER, NETMASK_COL_HEADER, GATEWAY_COL_HEADER, MAC_COL_HEADER, + INDEX_COL_HEADER); for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_interfaces; ++netint) { - char addr_str[LWPA_INET6_ADDRSTRLEN]; - char netmask_str[LWPA_INET6_ADDRSTRLEN]; - char gw_str[LWPA_INET6_ADDRSTRLEN]; + char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; + char netmask_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; + char gw_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; + char mac_str[18]; lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); lwpa_inet_ntop(&netint->mask, netmask_str, LWPA_INET6_ADDRSTRLEN); lwpa_inet_ntop(&netint->gate, gw_str, LWPA_INET6_ADDRSTRLEN); + snprintf(mac_str, 18, "%02x:%02x:%02x:%02x:%02x:%02x", netint->mac[0], netint->mac[1], netint->mac[2], + netint->mac[3], netint->mac[4], netint->mac[5]); - printf("%-46s %-46s %-46s %8d\n", addr_str, netmask_str, gw_str, netint->ifindex); + printf(line_format, netint->name, addr_str, netmask_str, gw_str, mac_str, netint->ifindex); } lwpa_deinit(LWPA_FEATURE_NETINTS); diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 316d30b37..6f45583de 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -35,10 +35,10 @@ #include #include +#include #ifdef LWPA_NETINT_DEBUG_OUTPUT #include -#include #endif #include @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include #include @@ -105,12 +107,13 @@ static lwpa_error_t send_netlink_route_request(int socket, int family); static lwpa_error_t receive_netlink_route_reply(int sock, int family, size_t buf_size, RoutingTable* table); static lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl_msg_size, RoutingTable* table); -// Manipulating +// Manipulating routing table entries static void init_routing_table_entry(RoutingTableEntry* entry); static int compare_routing_table_entries(const void* a, const void* b); // Functions for enumerating the interfaces static lwpa_error_t enumerate_netints(); +static void get_default_gateway(LwpaNetintInfo* netint); static void free_netints(); #if LWPA_NETINT_DEBUG_OUTPUT @@ -427,8 +430,13 @@ lwpa_error_t enumerate_netints() if (res != kLwpaErrOk) return res; + int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (ioctl_sock == -1) + return errno_os_to_lwpa(errno); + if (getifaddrs(&state.os_addrs) < 0) { + close(ioctl_sock); return errno_os_to_lwpa(errno); } @@ -445,6 +453,7 @@ lwpa_error_t enumerate_netints() if (state.num_netints == 0) { freeifaddrs(state.os_addrs); + close(ioctl_sock); return kLwpaErrNoNetints; } @@ -453,6 +462,7 @@ lwpa_error_t enumerate_netints() if (!state.lwpa_netints) { freeifaddrs(state.os_addrs); + close(ioctl_sock); return kLwpaErrNoMem; } @@ -477,11 +487,49 @@ lwpa_error_t enumerate_netints() // Interface netmask sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); current_info->mask = temp_sockaddr.ip; + + // Default gateway + get_default_gateway(current_info); + + // Struct ifreq to use with ioctl() calls + struct ifreq if_req; + strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); + + // Hardware address + int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); + if (ioctl_res == 0) + memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); + else + memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); + + // Interface index + ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); + if (ioctl_res == 0) + current_info->ifindex = if_req.ifr_ifindex; + else + current_info->ifindex = -1; } return kLwpaErrOk; } +void get_default_gateway(LwpaNetintInfo* netint) +{ + RoutingTable* table_to_use = (LWPA_IP_IS_V6(&netint->addr) ? &state.routing_table_v6 : &state.routing_table_v4); + + for (RoutingTableEntry* entry = table_to_use->entries; entry < table_to_use->entries + table_to_use->size; ++entry) + { + if (!LWPA_IP_IS_INVALID(&entry->gateway) && + lwpa_ip_network_portions_equal(&entry->addr, &netint->addr, &netint->mask)) + { + netint->gate = entry->gateway; + return; + } + } + // Reached the end of the routing table - no default gateway + LWPA_IP_SET_INVALID(&netint->gate); +} + void free_routing_tables() { free_routing_table(&state.routing_table_v4); @@ -510,6 +558,8 @@ void free_netints() free(state.lwpa_netints); state.lwpa_netints = NULL; } + + free_routing_tables(); } #if LWPA_NETINT_DEBUG_OUTPUT From b036a017819380f83d57b55431b77d507e345996 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 6 Jun 2019 21:37:10 -0500 Subject: [PATCH 020/264] Add unit test for is_loopback function --- tests/unit/test_inet.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/unit/test_inet.cpp b/tests/unit/test_inet.cpp index aba24e824..8bcab8855 100644 --- a/tests/unit/test_inet.cpp +++ b/tests/unit/test_inet.cpp @@ -44,6 +44,39 @@ TEST_F(InetTest, addr_macros) EXPECT_TRUE(LWPA_IP_IS_INVALID(&test_addr)); } +// Test the lwpa_ip_is_loopback() function +TEST_F(InetTest, loopback) +{ + LwpaIpAddr test_addr; + + // An invalid IP is not loopback + LWPA_IP_SET_INVALID(&test_addr); + EXPECT_FALSE(lwpa_ip_is_loopback(&test_addr)); + + // Test the edges of the IPv4 loopback range + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7effffff); + EXPECT_FALSE(lwpa_ip_is_loopback(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7f000000); + EXPECT_TRUE(lwpa_ip_is_loopback(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7fffffff); + EXPECT_TRUE(lwpa_ip_is_loopback(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x80000000); + EXPECT_FALSE(lwpa_ip_is_loopback(&test_addr)); + + // Test the IPv6 loopback address + std::array v6_data = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); + EXPECT_TRUE(lwpa_ip_is_loopback(&test_addr)); + + v6_data[15] = 0; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); + EXPECT_FALSE(lwpa_ip_is_loopback(&test_addr)); +} + +// Test the lwpa_ip_is_multicast() function TEST_F(InetTest, multicast) { LwpaIpAddr test_addr; From 7ba01a61d694a91776ff7a0aa8323c124ab8a8c4 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 6 Jun 2019 21:48:43 -0500 Subject: [PATCH 021/264] Fix gcc warnings --- include/lwpa/pdu.h | 45 ++++++++++++++++++++------------------- src/lwpa/root_layer_pdu.c | 22 +++++++++---------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/include/lwpa/pdu.h b/include/lwpa/pdu.h index f17d18272..dab6fc5c5 100644 --- a/include/lwpa/pdu.h +++ b/include/lwpa/pdu.h @@ -42,27 +42,28 @@ /*! Determine whether the L flag is set in a PDU flags field. * \param flags_byte The first byte of the PDU. * \return true (the L flag is set) or false (the L flags is not set). */ -#define lwpa_pdu_l_flag_set(flags_byte) ((bool)(flags_byte & 0x80)) +#define lwpa_pdu_l_flag_set(flags_byte) ((bool)(flags_byte & 0x80u)) /*! Determine whether the V flag is set in a PDU flags field. * \param flags_byte The first byte of the PDU. * \return true (the V flag is set) or false (the V flag is not set). */ -#define lwpa_pdu_v_flag_set(flags_byte) ((bool)(flags_byte & 0x40)) +#define lwpa_pdu_v_flag_set(flags_byte) ((bool)(flags_byte & 0x40u)) /*! Determine whether the H flag is set in a PDU flags field. * \param flags_byte The first byte of the PDU. * \return true (the H flag is set) or false (the H flag is not set). */ -#define lwpa_pdu_h_flag_set(flags_byte) ((bool)(flags_byte & 0x20)) +#define lwpa_pdu_h_flag_set(flags_byte) ((bool)(flags_byte & 0x20u)) /*! Determine whether the D flag is set in a PDU flags field. * \param flags_byte The first byte of the PDU. * \return true (the D flag is set) or false (the D flag is not set). */ -#define lwpa_pdu_d_flag_set(flags_byte) ((bool)(flags_byte & 0x10)) +#define lwpa_pdu_d_flag_set(flags_byte) ((bool)(flags_byte & 0x10u)) /*!@}*/ /*! Get the length from the Length field of a PDU. * \param pdu_buf Pointer to the start of the PDU buffer. * \return The length of the PDU. */ -#define lwpa_pdu_length(pdu_buf) \ - ((uint32_t)(lwpa_pdu_l_flag_set(pdu_buf[0]) ? (((pdu_buf[0] & 0x0f) << 16) | (pdu_buf[1] << 8) | pdu_buf[2]) \ - : (((pdu_buf[0] & 0x0f) << 8) | pdu_buf[1]))) +#define lwpa_pdu_length(pdu_buf) \ + ((uint32_t)(lwpa_pdu_l_flag_set(pdu_buf[0]) \ + ? ((uint32_t)((pdu_buf[0] & 0x0fu) << 16) | (uint32_t)(pdu_buf[1] << 8) | (uint32_t)pdu_buf[2]) \ + : ((uint32_t)((pdu_buf[0] & 0x0fu) << 8) | (uint32_t)pdu_buf[1]))) /*! \name Set the inheritance and length bits in a PDU Flags & Length segment. * The first byte of each PDU contains a flags field which indicates the inheritance properties of @@ -71,16 +72,16 @@ */ /*! Set the L flag in a PDU flags field. * \param flags_byte The first byte of the PDU. */ -#define lwpa_pdu_set_l_flag(flags_byte) (flags_byte |= 0x80) +#define lwpa_pdu_set_l_flag(flags_byte) (flags_byte |= 0x80u) /*! Set the V flag in a PDU flags field. * \param flags_byte The first byte of the PDU. */ -#define lwpa_pdu_set_v_flag(flags_byte) (flags_byte |= 0x40) +#define lwpa_pdu_set_v_flag(flags_byte) (flags_byte |= 0x40u) /*! Set the H flag in a PDU flags field. * \param flags_byte The first byte of the PDU. */ -#define lwpa_pdu_set_h_flag(flags_byte) (flags_byte |= 0x20) +#define lwpa_pdu_set_h_flag(flags_byte) (flags_byte |= 0x20u) /*! Set the D flag in a PDU flags field. * \param flags_byte The first byte of the PDU. */ -#define lwpa_pdu_set_d_flag(flags_byte) (flags_byte |= 0x10) +#define lwpa_pdu_set_d_flag(flags_byte) (flags_byte |= 0x10u) /*!@}*/ /*! Fill in the Length field of a PDU which has a length less than 4096. The L flag of this PDU must @@ -88,11 +89,11 @@ * \param pdu_buf Pointer to the start of the PDU buffer. * \param length Length of this PDU. */ -#define lwpa_pdu_pack_normal_len(pdu_buf, length) \ - do \ - { \ - (pdu_buf)[0] = (((pdu_buf)[0] & 0xf0) | (((length) >> 8) & 0x0f)); \ - (pdu_buf)[1] = (length)&0xff; \ +#define lwpa_pdu_pack_normal_len(pdu_buf, length) \ + do \ + { \ + (pdu_buf)[0] = (uint8_t)(((pdu_buf)[0] & 0xf0) | (((length) >> 8) & 0x0fu)); \ + (pdu_buf)[1] = (uint8_t)(length)&0xffu; \ } while (0) /*! Fill in the Length field of a PDU which has a length 4096 or greater. The L flag of this PDU @@ -100,12 +101,12 @@ * \param pdu_buf Pointer to the start of the PDU buffer. * \param length Length of this PDU. */ -#define lwpa_pdu_pack_ext_len(pdu_buf, length) \ - do \ - { \ - (pdu_buf)[0] = (((pdu_buf)[0] & 0xf0) | (((length) >> 16) & 0x0f)); \ - (pdu_buf)[1] = (((length) >> 8) & 0xff); \ - (pdu_buf)[2] = (length)&0xff; \ +#define lwpa_pdu_pack_ext_len(pdu_buf, length) \ + do \ + { \ + (pdu_buf)[0] = (uint8_t)(((pdu_buf)[0] & 0xf0) | (((length) >> 16) & 0x0fu)); \ + (pdu_buf)[1] = (uint8_t)(((length) >> 8) & 0xffu); \ + (pdu_buf)[2] = (uint8_t)(length)&0xffu; \ } while (0) /*! Holds state data used when parsing multiple PDUs in a PDU block. */ diff --git a/src/lwpa/root_layer_pdu.c b/src/lwpa/root_layer_pdu.c index c5389bcff..69ef5d802 100644 --- a/src/lwpa/root_layer_pdu.c +++ b/src/lwpa/root_layer_pdu.c @@ -22,8 +22,8 @@ #include -#define ACN_RLP_HEADER_SIZE 16 -#define RLP_VECTOR_SIZE 4 +#define ACN_RLP_HEADER_SIZE 16u +#define RLP_VECTOR_SIZE 4u #define rlp_extended_length(inheritvec, inherithead, datalen) \ ((datalen + (inheritvec ? 0 : RLP_VECTOR_SIZE) + (inherithead ? 0 : ACN_RLP_HEADER_SIZE)) > 4095) @@ -166,7 +166,7 @@ bool lwpa_parse_root_layer_header(const uint8_t* buf, size_t buflen, LwpaRootLay else { pdu->pdata = cur_ptr; - pdu->datalen = pdu_len - (cur_ptr - buf); + pdu->datalen = (size_t)(pdu_len - (cur_ptr - buf)); } return true; } @@ -247,7 +247,7 @@ size_t lwpa_pack_udp_preamble(uint8_t* buf, size_t buflen) cur_ptr += 2; memcpy(cur_ptr, ACN_PACKET_IDENT, ACN_PACKET_IDENT_SIZE); cur_ptr += ACN_PACKET_IDENT_SIZE; - return cur_ptr - buf; + return (size_t)(cur_ptr - buf); } /*! \brief Pack an ACN TCP Preamble into a buffer. @@ -273,7 +273,7 @@ size_t lwpa_pack_tcp_preamble(uint8_t* buf, size_t buflen, size_t rlp_block_len) cur_ptr += ACN_PACKET_IDENT_SIZE; lwpa_pack_32b(cur_ptr, rlp_block_len); cur_ptr += 4; - return cur_ptr - buf; + return (size_t)(cur_ptr - buf); } /*! \brief Get the buffer size to allocate for a Root Layer PDU block. @@ -334,7 +334,7 @@ size_t lwpa_pack_root_layer_header(uint8_t* buf, size_t buflen, const LwpaRootLa cur_ptr += 4; memcpy(cur_ptr, pdu->sender_cid.data, LWPA_UUID_BYTES); cur_ptr += LWPA_UUID_BYTES; - return cur_ptr - buf; + return (size_t)(cur_ptr - buf); } /*! \brief Pack a Root Layer PDU block into a buffer. @@ -412,16 +412,16 @@ size_t lwpa_pack_root_layer_block(uint8_t* buf, size_t buflen, const LwpaRootLay if (prot_mandates_l_flag(pdu->vector) || rlp_extended_length(inheritvec, inherithead, inheritdata ? 0 : pdu->datalen)) { - size_t len = 3 + (inheritvec ? 0 : RLP_VECTOR_SIZE) + (inherithead ? 0 : ACN_RLP_HEADER_SIZE) + - (inheritdata ? 0 : pdu->datalen); + size_t len = 3u + (inheritvec ? 0u : RLP_VECTOR_SIZE) + (inherithead ? 0u : ACN_RLP_HEADER_SIZE) + + (inheritdata ? 0u : pdu->datalen); lwpa_pdu_set_l_flag(*cur_ptr); lwpa_pdu_pack_ext_len(cur_ptr, len); cur_ptr += 3; } else { - size_t len = 2 + (inheritvec ? 0 : RLP_VECTOR_SIZE) + (inherithead ? 0 : ACN_RLP_HEADER_SIZE) + - (inheritdata ? 0 : pdu->datalen); + size_t len = 2 + (inheritvec ? 0u : RLP_VECTOR_SIZE) + (inherithead ? 0u : ACN_RLP_HEADER_SIZE) + + (inheritdata ? 0u : pdu->datalen); lwpa_pdu_pack_normal_len(cur_ptr, len); cur_ptr += 2; } @@ -442,5 +442,5 @@ size_t lwpa_pack_root_layer_block(uint8_t* buf, size_t buflen, const LwpaRootLay cur_ptr += pdu->datalen; } } - return cur_ptr - buf; + return (size_t)(cur_ptr - buf); } From f743a94e237282c482514e09272cf36346cd5c07 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 6 Jun 2019 22:23:11 -0500 Subject: [PATCH 022/264] Implement some of the basic socket functions --- src/os/linux/lwpa/os_socket.c | 204 +++++++++++++++++----------------- 1 file changed, 100 insertions(+), 104 deletions(-) diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 6ca99832d..2a69aee6b 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -18,11 +18,46 @@ ******************************************************************************/ #include "lwpa/socket.h" -#include -#include +#include + #include +#include +#include +#include + #include "os_error.h" +/**************************** Private variables ******************************/ + +/* clang-format off */ + +#define LWPA_NUM_SHUT 3 +static const int shutmap[LWPA_NUM_SHUT] = +{ + SHUT_RD, + SHUT_WR, + SHUT_RDWR +}; + +#define LWPA_NUM_AF 3 +static const int sfmap[LWPA_NUM_AF] = +{ + AF_UNSPEC, + AF_INET, + AF_INET6 +}; + +#define LWPA_NUM_TYPE 2 +static const int stmap[LWPA_NUM_TYPE] = +{ + SOCK_STREAM, + SOCK_DGRAM +}; + +/* clang-format on */ + +/*************************** Function definitions ****************************/ + bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) { if (pfsa->sa_family == AF_INET) @@ -64,89 +99,60 @@ size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) return ret; } -lwpa_error_t lwpa_socket_init(void* os_data) -{ - return kLwpaErrNotImpl; -} - -void lwpa_socket_deinit() -{ -} - lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { - /* - struct sockaddr_storage ss; - int sa_size = sizeof ss; - SOCKET res; - if (!conn_sock) return kLwpaErrInvalid; - res = accept(id, (struct sockaddr *)&ss, &sa_size); + struct sockaddr_storage ss; + socklen_t sa_size = sizeof ss; + int res = accept(id, (struct sockaddr*)&ss, &sa_size); - if (res != INVALID_SOCKET) + if (res != -1) { - if (address && !sockaddr_os_to_lwpa(address, (struct sockaddr *)&ss)) + if (address && !sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) { - closesocket(res); + close(res); return kLwpaErrSys; -} + } *conn_sock = res; return kLwpaErrOk; } - return err_os_to_lwpa(WSAGetLastError()); - */ - return kLwpaErrNotImpl; + return errno_os_to_lwpa(errno); } lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) { - /* - struct sockaddr_storage ss; - size_t sa_size; - int res; - if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_os((struct sockaddr *)&ss, address); + struct sockaddr_storage ss; + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); if (sa_size == 0) return kLwpaErrInvalid; - res = bind(id, (struct sockaddr *)&ss, (int)sa_size); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); - */ - return kLwpaErrNotImpl; + int res = bind(id, (struct sockaddr*)&ss, sa_size); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } lwpa_error_t lwpa_close(lwpa_socket_t id) { - /* - int res = closesocket(id); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); - */ - return kLwpaErrNotImpl; + int res = close(id); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) { - /* - struct sockaddr_storage ss; - size_t sa_size; - int res; - if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_os((struct sockaddr *)&ss, address); + struct sockaddr_storage ss; + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); if (sa_size == 0) return kLwpaErrInvalid; - res = connect(id, (struct sockaddr *)&ss, (int)sa_size); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); - */ - return kLwpaErrNotImpl; + int res = connect(id, (struct sockaddr*)&ss, sa_size); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) @@ -159,24 +165,19 @@ lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) { - /* - int res; - struct sockaddr_storage ss; - socklen_t size = sizeof ss; - if (!address) return kLwpaErrInvalid; - res = getsockname(id, (struct sockaddr *)&ss, &size); + struct sockaddr_storage ss; + socklen_t size = sizeof ss; + int res = getsockname(id, (struct sockaddr*)&ss, &size); if (res == 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr *)&ss)) + if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) return kLwpaErrSys; return kLwpaErrOk; } - return err_os_to_lwpa(WSAGetLastError()); - */ - return kLwpaErrNotImpl; + return errno_os_to_lwpa(errno); } lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) @@ -192,87 +193,68 @@ lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) { - /* int res = listen(id, backlog); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); - */ - return kLwpaErrNotImpl; + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) { - /* - int res; - int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; - if (!buffer) return kLwpaErrInvalid; - res = recv(id, buffer, (int)length, impl_flags); - return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); - */ - return kLwpaErrNotImpl; + int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; + int res = (int)recv(id, buffer, length, impl_flags); + return (res >= 0 ? res : (int)errno_os_to_lwpa(errno)); } int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address) { - /* - int res; - int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; - struct sockaddr_storage fromaddr; - socklen_t fromlen = sizeof fromaddr; - if (!buffer) return (int)kLwpaErrInvalid; - res = recvfrom(id, buffer, (int)length, impl_flags, (struct sockaddr *)&fromaddr, &fromlen); + struct sockaddr_storage fromaddr; + socklen_t fromlen = sizeof fromaddr; + int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; + int res = (int)recvfrom(id, buffer, length, impl_flags, (struct sockaddr*)&fromaddr, &fromlen); if (res >= 0) { if (address && fromlen > 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr *)&fromaddr)) + if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) return kLwpaErrSys; } return res; } - return (int)err_os_to_lwpa(WSAGetLastError()); - */ - return kLwpaErrNotImpl; + return (int)errno_os_to_lwpa(errno); } int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) { - /* - int res; (void)flags; if (!message) - return kLwpaErrInvalid; + return (int)kLwpaErrInvalid; - res = send(id, message, (int)length, 0); - return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); - */ - return kLwpaErrNotImpl; + int res = (int)send(id, message, length, 0); + return (res >= 0 ? res : (int)errno_os_to_lwpa(errno)); } int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) { - /* - int res = -1; - size_t ss_size; - struct sockaddr_storage ss; (void)flags; if (!dest_addr || !message) return (int)kLwpaErrInvalid; - if ((ss_size = sockaddr_lwpa_to_os((struct sockaddr *)&ss, dest_addr)) > 0) - res = sendto(id, message, (int)length, 0, (struct sockaddr *)&ss, (int)ss_size); + struct sockaddr_storage ss; + socklen_t ss_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr); + if (ss_size == 0) + return (int)kLwpaErrSys; + + int res = (int)sendto(id, message, length, 0, (struct sockaddr*)&ss, ss_size); - return (res >= 0 ? res : (int)err_os_to_lwpa(WSAGetLastError())); - */ - return kLwpaErrNotImpl; + return (res >= 0 ? res : (int)errno_os_to_lwpa(errno)); } lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) @@ -461,24 +443,38 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) { - /* if (how >= 0 && how < LWPA_NUM_SHUT) { int res = shutdown(id, shutmap[how]); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } return kLwpaErrInvalid; - */ - return kLwpaErrNotImpl; } lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* id) { if (id) { - *id = LWPA_SOCKET_INVALID; + if (family < LWPA_NUM_AF && type < LWPA_NUM_TYPE) + { + int sock = socket(sfmap[family], stmap[type], 0); + if (sock != -1) + { + *id = sock; + return kLwpaErrOk; + } + else + { + *id = LWPA_SOCKET_INVALID; + return errno_os_to_lwpa(errno); + } + } + else + { + *id = LWPA_SOCKET_INVALID; + } } - return kLwpaErrNotImpl; + return kLwpaErrInvalid; } lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) From 19e9f1c3f28f97d6aaff55e7020e07ba867f576d Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 7 Jun 2019 11:37:44 -0500 Subject: [PATCH 023/264] Finish up Linux netints --- examples/netint/netint_example.c | 39 +++---- include/lwpa/inet.h | 2 - include/lwpa/netint.h | 2 +- src/os/linux/lwpa/os_netint.c | 175 ++++++++++++++++++++++++------- 4 files changed, 162 insertions(+), 56 deletions(-) diff --git a/examples/netint/netint_example.c b/examples/netint/netint_example.c index 2c5918db4..10c785ea5 100644 --- a/examples/netint/netint_example.c +++ b/examples/netint/netint_example.c @@ -36,7 +36,6 @@ static char line_format[FORMAT_BUF_SIZE]; #define NAME_COL_HEADER "Name" #define ADDR_COL_HEADER "Address" #define NETMASK_COL_HEADER "Netmask" -#define GATEWAY_COL_HEADER "Gateway" #define MAC_COL_HEADER "MAC" #define INDEX_COL_HEADER "OS Index" @@ -46,22 +45,18 @@ void create_format_strings(const LwpaNetintInfo* netint_arr, size_t num_interfac size_t longest_name = 0; size_t longest_addr = 0; size_t longest_netmask = 0; - size_t longest_gateway = 0; for (const LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_interfaces; ++netint) { char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; char netmask_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; - char gw_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); lwpa_inet_ntop(&netint->mask, netmask_str, LWPA_INET6_ADDRSTRLEN); - lwpa_inet_ntop(&netint->gate, gw_str, LWPA_INET6_ADDRSTRLEN); size_t name_len = strlen(netint->name); size_t addr_len = strlen(addr_str); size_t netmask_len = strlen(netmask_str); - size_t gw_len = strlen(gw_str); if (name_len > longest_name) longest_name = name_len; @@ -69,8 +64,6 @@ void create_format_strings(const LwpaNetintInfo* netint_arr, size_t num_interfac longest_addr = addr_len; if (netmask_len > longest_netmask) longest_netmask = netmask_len; - if (gw_len > longest_gateway) - longest_gateway = gw_len; } if (longest_name < sizeof(NAME_COL_HEADER)) @@ -79,13 +72,11 @@ void create_format_strings(const LwpaNetintInfo* netint_arr, size_t num_interfac longest_addr = sizeof(ADDR_COL_HEADER); if (longest_netmask < sizeof(NETMASK_COL_HEADER)) longest_netmask = sizeof(NETMASK_COL_HEADER); - if (longest_gateway < sizeof(GATEWAY_COL_HEADER)) - longest_gateway = sizeof(GATEWAY_COL_HEADER); - snprintf(header_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-%zus %%-17s %%s\n", longest_name, longest_addr, - longest_netmask, longest_gateway); - snprintf(line_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-%zus %%-17s %%8d\n", longest_name, longest_addr, - longest_netmask, longest_gateway); + snprintf(header_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-17s %%s\n", longest_name, longest_addr, + longest_netmask); + snprintf(line_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-17s %%8d\n", longest_name, longest_addr, + longest_netmask); } int main() @@ -112,21 +103,33 @@ int main() create_format_strings(netint_arr, num_interfaces); printf("Network interfaces found:\n"); - printf(header_format, NAME_COL_HEADER, ADDR_COL_HEADER, NETMASK_COL_HEADER, GATEWAY_COL_HEADER, MAC_COL_HEADER, - INDEX_COL_HEADER); + printf(header_format, NAME_COL_HEADER, ADDR_COL_HEADER, NETMASK_COL_HEADER, MAC_COL_HEADER, INDEX_COL_HEADER); for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_interfaces; ++netint) { char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; char netmask_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; - char gw_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; char mac_str[18]; lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); lwpa_inet_ntop(&netint->mask, netmask_str, LWPA_INET6_ADDRSTRLEN); - lwpa_inet_ntop(&netint->gate, gw_str, LWPA_INET6_ADDRSTRLEN); snprintf(mac_str, 18, "%02x:%02x:%02x:%02x:%02x:%02x", netint->mac[0], netint->mac[1], netint->mac[2], netint->mac[3], netint->mac[4], netint->mac[5]); - printf(line_format, netint->name, addr_str, netmask_str, gw_str, mac_str, netint->ifindex); + printf(line_format, netint->name, addr_str, netmask_str, mac_str, netint->ifindex); + } + + LwpaNetintInfo default_v4; + if (lwpa_netint_get_default_interface(kLwpaIpTypeV4, &default_v4)) + { + char addr_str[LWPA_INET_ADDRSTRLEN] = {'\0'}; + lwpa_inet_ntop(&default_v4.addr, addr_str, LWPA_INET_ADDRSTRLEN); + printf("Default IPv4 interface: %s (%s)\n", addr_str, default_v4.name); + } + LwpaNetintInfo default_v6; + if (lwpa_netint_get_default_interface(kLwpaIpTypeV6, &default_v6)) + { + char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; + lwpa_inet_ntop(&default_v6.addr, addr_str, LWPA_INET6_ADDRSTRLEN); + printf("Default IPv6 interface: %s (%s)\n", addr_str, default_v6.name); } lwpa_deinit(LWPA_FEATURE_NETINTS); diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index ea4c36f81..5feef0257 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -150,8 +150,6 @@ typedef struct LwpaNetintInfo LwpaIpAddr addr; /*! The subnet mask for this interface. */ LwpaIpAddr mask; - /*! The address of the default gateway for this interface. */ - LwpaIpAddr gate; /*! The adapter MAC address. */ uint8_t mac[LWPA_NETINTINFO_MAC_LEN]; /*! The adapter name as a string. */ diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index 2f57ae246..67c65ea93 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -41,7 +41,7 @@ extern "C" { size_t lwpa_netint_get_num_interfaces(); size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size); -bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint); +bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint); lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint); #ifdef __cplusplus diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 6f45583de..8a49d5b53 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -70,6 +70,7 @@ typedef struct RoutingTableEntry typedef struct RoutingTable { RoutingTableEntry* entries; + RoutingTableEntry* default_route; size_t size; } RoutingTable; @@ -92,6 +93,12 @@ static struct LwpaNetintState struct ifaddrs* os_addrs; size_t num_netints; LwpaNetintInfo* lwpa_netints; + + bool have_default_netint_index_v4; + size_t default_netint_index_v4; + + bool have_default_netint_index_v6; + size_t default_netint_index_v6; } state; /*********************** Private function prototypes *************************/ @@ -113,7 +120,7 @@ static int compare_routing_table_entries(const void* a, const void* b); // Functions for enumerating the interfaces static lwpa_error_t enumerate_netints(); -static void get_default_gateway(LwpaNetintInfo* netint); +static int compare_netints(const void* a, const void* b); static void free_netints(); #if LWPA_NETINT_DEBUG_OUTPUT @@ -139,18 +146,22 @@ void lwpa_netint_deinit() if (state.initialized) { free_netints(); - state.initialized = false; + memset(&state, 0, sizeof(state)); } } +/****************************************************************************** + * API Functions + *****************************************************************************/ + size_t lwpa_netint_get_num_interfaces() { - return state.num_netints; + return (state.initialized ? state.num_netints : 0); } size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) { - if (!netint_arr || netint_arr_size == 0) + if (!state.initialized || !netint_arr || netint_arr_size == 0) return 0; size_t addrs_copied = (netint_arr_size < state.num_netints ? netint_arr_size : state.num_netints); @@ -158,6 +169,73 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ return addrs_copied; } +bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) +{ + if (state.initialized && netint) + { + if (type == kLwpaIpTypeV4 && state.have_default_netint_index_v4) + { + *netint = state.lwpa_netints[state.default_netint_index_v4]; + return true; + } + else if (type == kLwpaIpTypeV6 && state.have_default_netint_index_v6) + { + *netint = state.lwpa_netints[state.default_netint_index_v6]; + return true; + } + } + return false; +} + +lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) +{ + if (!dest || !netint) + return kLwpaErrInvalid; + if (!state.initialized) + return kLwpaErrNotInit; + if (state.num_netints == 0) + return kLwpaErrNoNetints; + + RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &state.routing_table_v6 : &state.routing_table_v4); + + int index_found = -1; + for (RoutingTableEntry* entry = table_to_use->entries; entry < table_to_use->entries + table_to_use->size; ++entry) + { + if (entry->interface_index < 0 || LWPA_IP_IS_INVALID(&entry->mask)) + continue; + + // Check each route to see if it matches the destination address explicitly + if (lwpa_ip_network_portions_equal(&entry->addr, dest, &entry->mask)) + { + index_found = entry->interface_index; + break; + } + } + + // Fall back to the default route + if (index_found < 0 && table_to_use->default_route) + index_found = table_to_use->default_route->interface_index; + + // Find the network interface with the correct index + if (index_found >= 0) + { + for (LwpaNetintInfo* netint_entry = state.lwpa_netints; netint_entry < state.lwpa_netints + state.num_netints; + ++netint_entry) + { + if (netint_entry->ifindex == index_found) + { + *netint = *netint_entry; + return kLwpaErrOk; + } + } + } + return kLwpaErrNotFound; +} + +/****************************************************************************** + * Internal Functions + *****************************************************************************/ + lwpa_error_t build_routing_tables() { lwpa_error_t res = build_routing_table(AF_INET, &state.routing_table_v4); @@ -300,6 +378,7 @@ lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl { table->size = 0; table->entries = NULL; + table->default_route = NULL; // Parse the result // outer loop: loops thru all the NETLINK headers that also include the route entry header @@ -374,6 +453,17 @@ lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl if (table->size > 0) { qsort(table->entries, table->size, sizeof(RoutingTableEntry), compare_routing_table_entries); + + // Mark the default route with the lowest metric (the first one we encounter after sorting the + // table) + for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) + { + if (LWPA_IP_IS_INVALID(&entry->addr) && LWPA_IP_IS_INVALID(&entry->mask)) + { + table->default_route = entry; + break; + } + } return kLwpaErrOk; } else @@ -398,22 +488,16 @@ int compare_routing_table_entries(const void* a, const void* b) unsigned int mask_length_1 = lwpa_ip_mask_length(&e1->mask); unsigned int mask_length_2 = lwpa_ip_mask_length(&e2->mask); - if (mask_length_1 > mask_length_2) - { - return -1; - } - else if (mask_length_1 < mask_length_2) + + // Sort by mask length in descending order - within the same mask length, sort by metric in + // ascending order. + if (mask_length_1 == mask_length_2) { - return 1; + return (e1->metric > e2->metric) - (e1->metric < e2->metric); } else { - if (e1->metric < e2->metric) - return -1; - else if (e1->metric > e2->metric) - return 1; - else - return 0; + return (mask_length_1 < mask_length_2) - (mask_length_1 > mask_length_2); } } @@ -473,7 +557,7 @@ lwpa_error_t enumerate_netints() if (should_skip_ifaddr(ifaddr)) continue; - LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index++]; + LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; // Interface name strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); @@ -488,9 +572,6 @@ lwpa_error_t enumerate_netints() sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); current_info->mask = temp_sockaddr.ip; - // Default gateway - get_default_gateway(current_info); - // Struct ifreq to use with ioctl() calls struct ifreq if_req; strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); @@ -508,26 +589,50 @@ lwpa_error_t enumerate_netints() current_info->ifindex = if_req.ifr_ifindex; else current_info->ifindex = -1; - } - return kLwpaErrOk; -} + // Is Default + if (LWPA_IP_IS_V4(¤t_info->addr) && state.routing_table_v4.default_route && + current_info->ifindex == state.routing_table_v4.default_route->interface_index) + { + current_info->is_default = true; + } + else if (LWPA_IP_IS_V6(¤t_info->addr) && state.routing_table_v6.default_route && + current_info->ifindex == state.routing_table_v6.default_route->interface_index) + { + current_info->is_default = true; + } -void get_default_gateway(LwpaNetintInfo* netint) -{ - RoutingTable* table_to_use = (LWPA_IP_IS_V6(&netint->addr) ? &state.routing_table_v6 : &state.routing_table_v4); + current_lwpa_index++; + } - for (RoutingTableEntry* entry = table_to_use->entries; entry < table_to_use->entries + table_to_use->size; ++entry) + // Sort the interfaces by OS index + qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); + + // Store the locations of the default netints for access by the API function + for (size_t i = 0; i < state.num_netints; ++i) { - if (!LWPA_IP_IS_INVALID(&entry->gateway) && - lwpa_ip_network_portions_equal(&entry->addr, &netint->addr, &netint->mask)) + LwpaNetintInfo* netint = &state.lwpa_netints[i]; + if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) + { + state.have_default_netint_index_v4 = true; + state.default_netint_index_v4 = i; + } + else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) { - netint->gate = entry->gateway; - return; + state.have_default_netint_index_v6 = true; + state.default_netint_index_v6 = i; } } - // Reached the end of the routing table - no default gateway - LWPA_IP_SET_INVALID(&netint->gate); + close(ioctl_sock); + return kLwpaErrOk; +} + +int compare_netints(const void* a, const void* b) +{ + LwpaNetintInfo* netint1 = (LwpaNetintInfo*)a; + LwpaNetintInfo* netint2 = (LwpaNetintInfo*)b; + + return (netint1->ifindex > netint2->ifindex) - (netint1->ifindex < netint2->ifindex); } void free_routing_tables() @@ -565,7 +670,7 @@ void free_netints() #if LWPA_NETINT_DEBUG_OUTPUT void debug_print_routing_table(RoutingTable* table) { - printf("%-40s %-40s %-40s %s %s\n", "Address", "Mask", "Gateway", "Metric", "Index"); + printf("%-40s %-40s %-40s %-10s %s\n", "Address", "Mask", "Gateway", "Metric", "Index"); for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) { char addr_str[LWPA_INET6_ADDRSTRLEN]; @@ -587,7 +692,7 @@ void debug_print_routing_table(RoutingTable* table) else strcpy(gw_str, "0.0.0.0"); - printf("%-40s %-40s %-40s %d %d\n", addr_str, mask_str, gw_str, entry->metric, entry->interface_index); + printf("%-40s %-40s %-40s %-10d %d\n", addr_str, mask_str, gw_str, entry->metric, entry->interface_index); } } #endif From 2b30323987cc6a796647a2e6bdee342d825f5d86 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 7 Jun 2019 13:10:09 -0500 Subject: [PATCH 024/264] Cleanup windows side --- src/os/windows/lwpa/os_netint.c | 158 ++++++++++++++++++++++---------- 1 file changed, 111 insertions(+), 47 deletions(-) diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index c0b63ae16..760337b44 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -37,16 +37,23 @@ static struct LwpaNetintState size_t num_netints; LwpaNetintInfo* lwpa_netints; - bool have_default_netint_index; - size_t default_netint_index; + + bool have_default_netint_index_v4; + size_t default_netint_index_v4; + + bool have_default_netint_index_v6; + size_t default_netint_index_v6; } state; /*********************** Private function prototypes *************************/ static IP_ADAPTER_ADDRESSES* get_windows_adapters(); -static void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, IP_ADAPTER_GATEWAY_ADDRESS* pgate, LwpaNetintInfo* info); +static void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info); +static void copy_ipv6_info(IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info); static void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters); + static lwpa_error_t enumerate_netints(); +static int compare_netints(const void* a, const void* b); static void free_netints(); /*************************** Function definitions ****************************/ @@ -74,12 +81,12 @@ void lwpa_netint_deinit() size_t lwpa_netint_get_num_interfaces() { - return state.num_netints; + return (state.initialized ? state.num_netints : 0); } size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) { - if (!netint_arr || netint_arr_size == 0) + if (!state.initialized || !netint_arr || netint_arr_size == 0) return 0; size_t addrs_copied = (netint_arr_size < state.num_netints ? netint_arr_size : state.num_netints); @@ -87,23 +94,35 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ return addrs_copied; } -bool lwpa_netint_get_default_interface(LwpaNetintInfo* netint) +bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) { - if (netint && state.have_default_netint_index) + if (state.initialized && netint) { - *netint = state.lwpa_netints[state.default_netint_index]; - return true; + if (type == kLwpaIpTypeV4 && state.have_default_netint_index_v4) + { + *netint = state.lwpa_netints[state.default_netint_index_v4]; + return true; + } + else if (type == kLwpaIpTypeV6 && state.have_default_netint_index_v6) + { + *netint = state.lwpa_netints[state.default_netint_index_v6]; + return true; + } } return false; } lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) { - const LwpaNetintInfo* res = NULL; - const LwpaNetintInfo* def = NULL; - if (!dest || !netint) return kLwpaErrInvalid; + if (!state.initialized) + return kLwpaErrNotInit; + if (state.num_netints == 0) + return kLwpaErrNoNetints; + + const LwpaNetintInfo* res = NULL; + const LwpaNetintInfo* def = NULL; for (const LwpaNetintInfo* netint_entry = state.lwpa_netints; netint_entry < state.lwpa_netints + state.num_netints; ++netint_entry) @@ -150,11 +169,10 @@ lwpa_error_t enumerate_netints() switch (pip->Address.lpSockaddr->sa_family) { case AF_INET: + case AF_INET6: ++state.num_netints; break; - case AF_INET6: default: - // TODO IPv6 break; } pip = pip->Next; @@ -177,9 +195,37 @@ lwpa_error_t enumerate_netints() copy_all_netint_info(padapters); free(padapters); + + // Sort the interfaces by OS index + qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); + + // Store the locations of the default netints for access by the API function + for (size_t i = 0; i < state.num_netints; ++i) + { + LwpaNetintInfo* netint = &state.lwpa_netints[i]; + if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) + { + state.have_default_netint_index_v4 = true; + state.default_netint_index_v4 = i; + } + else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) + { + state.have_default_netint_index_v6 = true; + state.default_netint_index_v6 = i; + } + } + return kLwpaErrOk; } +int compare_netints(const void* a, const void* b) +{ + LwpaNetintInfo* netint1 = (LwpaNetintInfo*)a; + LwpaNetintInfo* netint2 = (LwpaNetintInfo*)b; + + return (netint1->ifindex > netint2->ifindex) - (netint1->ifindex < netint2->ifindex); +} + void free_netints() { if (state.lwpa_netints) @@ -192,7 +238,7 @@ void free_netints() IP_ADAPTER_ADDRESSES* get_windows_adapters() { ULONG buflen = 0; - ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_GATEWAYS; + ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; // Preallocating a buffer specifically this size is expressly recommended by the Microsoft usage // page. @@ -213,64 +259,85 @@ IP_ADAPTER_ADDRESSES* get_windows_adapters() return NULL; } -void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, IP_ADAPTER_GATEWAY_ADDRESS* pgate, LwpaNetintInfo* info) +void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info) { struct sockaddr_in* sin = (struct sockaddr_in*)pip->Address.lpSockaddr; - struct sockaddr_in* gw_sin = pgate ? (struct sockaddr_in*)pgate->Address.lpSockaddr : NULL; - ULONG mask = 0; - ConvertLengthToIpv4Mask(pip->OnLinkPrefixLength, &mask); LWPA_IP_SET_V4_ADDRESS(&info->addr, ntohl(sin->sin_addr.s_addr)); - LWPA_IP_SET_V4_ADDRESS(&info->mask, ntohl((uint32_t)mask)); - if (pgate) - LWPA_IP_SET_V4_ADDRESS(&info->gate, ntohl(gw_sin->sin_addr.s_addr)); - else - LWPA_IP_SET_V4_ADDRESS(&info->gate, 0u); + info->mask = lwpa_ip_mask_from_length(kLwpaIpTypeV4, pip->OnLinkPrefixLength); +} + +void copy_ipv6_info(IP_ADAPTER_UNICAST_ADDRESS *pip, LwpaNetintInfo *info) +{ + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pip->Address.lpSockaddr; + + LWPA_IP_SET_V6_ADDRESS(&info->addr, sin6->sin6_addr.s6_addr); + info->mask = lwpa_ip_mask_from_length(kLwpaIpTypeV6, pip->OnLinkPrefixLength); } void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) { IP_ADAPTER_ADDRESSES* pcur = adapters; - DWORD def_ifindex; - bool have_def_index = false; - if (NO_ERROR == GetBestInterface(0, &def_ifindex)) - have_def_index = true; + + // Get the index of the default interface for IPv4 + DWORD def_ifindex_v4; + bool have_def_index_v4 = false; + struct sockaddr_in v4_dest; + memset(&v4_dest, 0, sizeof v4_dest); + v4_dest.sin_family = AF_INET; + if (NO_ERROR == GetBestInterfaceEx((struct sockaddr *)&v4_dest, &def_ifindex_v4)) + have_def_index_v4 = true; + + // And the same for IPv6 + DWORD def_ifindex_v6; + bool have_def_index_v6 = false; + struct sockaddr_in6 v6_dest; + memset(&v6_dest, 0, sizeof v6_dest); + v6_dest.sin6_family = AF_INET6; + if (NO_ERROR == GetBestInterfaceEx((struct sockaddr *)&v6_dest, &def_ifindex_v6)) + have_def_index_v6 = true; + size_t netint_index = 0; while (pcur) { // If this is multihomed, there may be multiple addresses under the same adapter IP_ADAPTER_UNICAST_ADDRESS* pip = pcur->FirstUnicastAddress; - IP_ADAPTER_GATEWAY_ADDRESS* pgate = pcur->FirstGatewayAddress; while (pip) { LwpaNetintInfo* info = &state.lwpa_netints[netint_index]; switch (pip->Address.lpSockaddr->sa_family) { case AF_INET: - copy_ipv4_info(pip, pgate, info); + copy_ipv4_info(pip, info); + if (have_def_index_v4 && pcur->IfIndex == def_ifindex_v4) + { + info->is_default = true; + have_def_index_v4 = false; + } + else + { + info->is_default = false; + } break; case AF_INET6: + copy_ipv6_info(pip, info); + if (have_def_index_v6 && pcur->IfIndex == def_ifindex_v6) + { + info->is_default = true; + have_def_index_v6 = false; + } + else + { + info->is_default = false; + } + break; default: - /* TODO IPv6 */ pip = pip->Next; - if (pgate && pgate->Next) - pgate = pgate->Next; continue; } info->ifindex = pcur->IfIndex; - if (have_def_index && pcur->IfIndex == def_ifindex) - { - info->is_default = true; - state.have_default_netint_index = true; - state.default_netint_index = netint_index; - have_def_index = false; - } - else - { - info->is_default = false; - } strncpy_s(info->name, LWPA_NETINTINFO_NAME_LEN, pcur->AdapterName, _TRUNCATE); if (pcur->PhysicalAddressLength == LWPA_NETINTINFO_MAC_LEN) memcpy(info->mac, pcur->PhysicalAddress, LWPA_NETINTINFO_MAC_LEN); @@ -280,9 +347,6 @@ void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) ++netint_index; pip = pip->Next; - // Just in case there's only ever one gateway but more addrs (probably not possible) - if (pgate && pgate->Next) - pgate = pgate->Next; } pcur = pcur->Next; } From e1ca9574293097f9a63c47606d19d18aaff0a92c Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 7 Jun 2019 17:27:59 -0500 Subject: [PATCH 025/264] Working through some socket code, WIP --- src/os/linux/lwpa/os_socket.c | 363 +++++++++++++++++----------------- 1 file changed, 178 insertions(+), 185 deletions(-) diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 2a69aee6b..fdc323f92 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -56,6 +57,10 @@ static const int stmap[LWPA_NUM_TYPE] = /* clang-format on */ +/*********************** Private function prototypes *************************/ + +static void ms_to_timeval(int ms, struct timeval* tv); + /*************************** Function definitions ****************************/ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) @@ -259,185 +264,173 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) { - // int res = -1; - // - // if (!option_value) - // return kLwpaErrInvalid; - // - // /* TODO this OS implementation could be simplified by use of socket option lookup arrays. */ - // switch (level) - // { - // case LWPA_SOL_SOCKET: - // switch (option_name) - // { - // case LWPA_SO_RCVBUF: - // res = setsockopt(id, SOL_SOCKET, SO_RCVBUF, option_value, (int)option_len); - // break; - // case LWPA_SO_SNDBUF: - // res = setsockopt(id, SOL_SOCKET, SO_SNDBUF, option_value, (int)option_len); - // break; - // case LWPA_SO_RCVTIMEO: - // if (option_len == sizeof(int)) - // { - // DWORD val = (DWORD) * (int *)option_value; - // res = setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, (char *)&val, sizeof val); - // } - // break; - // case LWPA_SO_SNDTIMEO: - // if (option_len == sizeof(int)) - // { - // DWORD val = (DWORD) * (int *)option_value; - // res = setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, (char *)&val, sizeof val); - // } - // break; - // case LWPA_SO_REUSEADDR: - // if (option_len == sizeof(int)) - // { - // BOOL val = (BOOL) * (int *)option_value; - // res = setsockopt(id, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof val); - // } - // break; - // case LWPA_SO_BROADCAST: - // if (option_len == sizeof(int)) - // { - // BOOL val = (BOOL) * (int *)option_value; - // res = setsockopt(id, SOL_SOCKET, SO_BROADCAST, (char *)&val, sizeof val); - // } - // break; - // case LWPA_SO_KEEPALIVE: - // if (option_len == sizeof(int)) - // { - // BOOL val = (BOOL) * (int *)option_value; - // res = setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof val); - // } - // break; - // case LWPA_SO_LINGER: - // if (option_len == sizeof(LwpaLinger)) - // { - // LwpaLinger *ll = (LwpaLinger *)option_value; - // struct linger val; - // val.l_onoff = (u_short)ll->onoff; - // val.l_linger = (u_short)ll->linger; - // res = setsockopt(id, SOL_SOCKET, SO_LINGER, (char *)&val, sizeof val); - // } - // break; - // case LWPA_SO_ERROR: /* Set not supported */ - // case LWPA_SO_TYPE: /* Not supported */ - // default: - // return kLwpaErrInvalid; - // } - // break; - // case LWPA_IPPROTO_IP: - // switch (option_name) - // { - // case LWPA_IP_TTL: - // if (option_len == sizeof(int)) - // { - // DWORD val = (DWORD) * (int *)option_value; - // res = setsockopt(id, IPPROTO_IP, IP_TTL, (char *)&val, sizeof val); - // } - // break; - // case LWPA_MCAST_JOIN_GROUP: - // if (option_len == sizeof(LwpaMreq)) - // { - // LwpaMreq *amreq = (LwpaMreq *)option_value; - // if (LWPA_IP_IS_V4(&amreq->group)) - // { - // struct ip_mreq val; - // val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); - // val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); - // res = setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&val, sizeof val); - // } - // } - // break; - // case LWPA_MCAST_LEAVE_GROUP: - // if (option_len == sizeof(LwpaMreq)) - // { - // LwpaMreq *amreq = (LwpaMreq *)option_value; - // if (LWPA_IP_IS_V4(&amreq->group)) - // { - // struct ip_mreq val; - // val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); - // val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); - // res = setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&val, sizeof val); - // } - // } - // break; - // case LWPA_IP_MULTICAST_IF: - // if (option_len == sizeof(LwpaIpAddr)) - // { - // LwpaIpAddr *netint = (LwpaIpAddr *)option_value; - // if (LWPA_IP_IS_V4(netint)) - // { - // DWORD val = htonl(LWPA_IP_V4_ADDRESS(netint)); - // res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char *)&val, sizeof val); - // } - // } - // break; - // case LWPA_IP_MULTICAST_TTL: - // if (option_len == sizeof(int)) - // { - // DWORD val = (DWORD) * (int *)option_value; - // res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&val, sizeof val); - // } - // break; - // case LWPA_IP_MULTICAST_LOOP: - // if (option_len == sizeof(int)) - // { - // DWORD val = (DWORD) * (int *)option_value; - // res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&val, sizeof val); - // } - // break; - // default: - // return kLwpaErrInvalid; - // } - // break; - // case LWPA_IPPROTO_IPV6: - // switch (option_name) - // { - // case LWPA_MCAST_JOIN_GROUP: - // /* TODO on windows. - // if (option_len == sizeof(struct lwpa_mreq)) - // { - // LwpaMreq *amreq = (LwpaMreq *)option_value; - // if (LWPA_IP_IS_V6(&amreq->group)) - // { - // struct ipv6_mreq val; - // val.ipv6imr_interface = 0; - // memcpy(&val.ipv6imr_multiaddr.s6_addr, - // LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); - // res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - // sizeof val); - // } - // } - // */ - // break; - // case LWPA_MCAST_LEAVE_GROUP: - // /* TODO on windows. - // if (option_len == sizeof(struct lwpa_mreq)) - // { - // LwpaMreq *amreq = (LwpaMreq *)option_value; - // if (LWPA_IP_IS_V6(&amreq->group)) - // { - // struct ipv6_mreq val; - // val.ipv6imr_interface = 0; - // memcpy(&val.ipv6imr_multiaddr.s6_addr, - // LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); - // res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - // sizeof val); - // } - // } - // */ - // break; - // default: /* Other IPv6 options TODO on windows. */ - // return kLwpaErrInvalid; - // } - // break; - // case LWPA_SO_REUSEPORT: /* Not supported on this OS. */ - // default: - // return kLwpaErrInvalid; - // } - // return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); + int res = -1; + + if (!option_value) + return kLwpaErrInvalid; + + // TODO this OS implementation could be simplified by use of socket option lookup arrays. + switch (level) + { + case LWPA_SOL_SOCKET: + switch (option_name) + { + case LWPA_SO_RCVBUF: + res = setsockopt(id, SOL_SOCKET, SO_RCVBUF, option_value, (socklen_t)option_len); + break; + case LWPA_SO_SNDBUF: + res = setsockopt(id, SOL_SOCKET, SO_SNDBUF, option_value, (socklen_t)option_len); + break; + case LWPA_SO_RCVTIMEO: + if (option_len == sizeof(int)) + { + int val = *(int*)option_value; + struct timeval sys_val; + ms_to_timeval(val, &sys_val); + res = setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, &sys_val, sizeof sys_val); + } + break; + case LWPA_SO_SNDTIMEO: + if (option_len == sizeof(int)) + { + int val = *(int*)option_value; + struct timeval sys_val; + ms_to_timeval(val, &sys_val); + res = setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, &sys_val, sizeof sys_val); + } + break; + case LWPA_SO_REUSEADDR: + res = setsockopt(id, SOL_SOCKET, SO_REUSEADDR, option_value, (socklen_t)option_len); + break; + case LWPA_SO_BROADCAST: + res = setsockopt(id, SOL_SOCKET, SO_BROADCAST, option_value, (socklen_t)option_len); + break; + case LWPA_SO_KEEPALIVE: + res = setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, option_value, (socklen_t)option_len); + break; + case LWPA_SO_LINGER: + if (option_len == sizeof(LwpaLinger)) + { + LwpaLinger* ll = (LwpaLinger*)option_value; + struct linger val; + val.l_onoff = (u_short)ll->onoff; + val.l_linger = (u_short)ll->linger; + res = setsockopt(id, SOL_SOCKET, SO_LINGER, &val, sizeof val); + } + break; + case LWPA_SO_ERROR: /* Set not supported */ + case LWPA_SO_TYPE: /* Set not supported */ + default: + return kLwpaErrInvalid; + } + break; + case LWPA_IPPROTO_IP: + switch (option_name) + { + case LWPA_IP_TTL: + res = setsockopt(id, IPPROTO_IP, IP_TTL, option_value, (socklen_t)option_len); + break; + case LWPA_MCAST_JOIN_GROUP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) + { + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + res = setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&val, sizeof val); + } + } + break; + case LWPA_MCAST_LEAVE_GROUP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) + { + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + res = setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_IF: + if (option_len == sizeof(LwpaIpAddr)) + { + LwpaIpAddr* netint = (LwpaIpAddr*)option_value; + if (LWPA_IP_IS_V4(netint)) + { + DWORD val = htonl(LWPA_IP_V4_ADDRESS(netint)); + res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_TTL: + if (option_len == sizeof(int)) + { + DWORD val = (DWORD) * (int*)option_value; + res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&val, sizeof val); + } + break; + case LWPA_IP_MULTICAST_LOOP: + if (option_len == sizeof(int)) + { + DWORD val = (DWORD) * (int*)option_value; + res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&val, sizeof val); + } + break; + default: + return kLwpaErrInvalid; + } + break; + case LWPA_IPPROTO_IPV6: + switch (option_name) + { + case LWPA_MCAST_JOIN_GROUP: + /* TODO on windows. + if (option_len == sizeof(struct lwpa_mreq)) + { + LwpaMreq *amreq = (LwpaMreq *)option_value; + if (LWPA_IP_IS_V6(&amreq->group)) + { + struct ipv6_mreq val; + val.ipv6imr_interface = 0; + memcpy(&val.ipv6imr_multiaddr.s6_addr, + LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); + res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, + sizeof val); + } + } + */ + break; + case LWPA_MCAST_LEAVE_GROUP: + /* TODO on windows. + if (option_len == sizeof(struct lwpa_mreq)) + { + LwpaMreq *amreq = (LwpaMreq *)option_value; + if (LWPA_IP_IS_V6(&amreq->group)) + { + struct ipv6_mreq val; + val.ipv6imr_interface = 0; + memcpy(&val.ipv6imr_multiaddr.s6_addr, + LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); + res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, + sizeof val); + } + } + */ + break; + default: /* Other IPv6 options TODO on windows. */ + return kLwpaErrInvalid; + } + break; + case LWPA_SO_REUSEPORT: /* Not supported on this OS. */ + default: + return kLwpaErrInvalid; + } + return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); return kLwpaErrNotImpl; } @@ -479,12 +472,12 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) { - /* - unsigned long val = (blocking ? 0 : 1); - int res = ioctlsocket(id, FIONBIO, &val); - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); - */ - return kLwpaErrNotImpl; + int val = fcntl(id, F_GETFL, 0); + if (val >= 0) + { + val = fcntl(id, F_SETFL, val | O_NONBLOCK); + } + return (val >= 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) From 6858efdc8d38cde53bb5f7ec3e146cb15e0340b7 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 9 Jun 2019 22:14:54 -0500 Subject: [PATCH 026/264] Finish up socket options --- include/lwpa/socket.h | 36 ++- src/os/linux/lwpa/os_netint.c | 4 +- src/os/linux/lwpa/os_socket.c | 441 ++++++++++++++++++++-------------- 3 files changed, 284 insertions(+), 197 deletions(-) diff --git a/include/lwpa/socket.h b/include/lwpa/socket.h index 73b42cdb7..3feff4481 100644 --- a/include/lwpa/socket.h +++ b/include/lwpa/socket.h @@ -87,13 +87,23 @@ typedef uint32_t lwpa_poll_events_t; * Used in the option parameter to lwpa_setsockopt() and lwpa_getsockopt(). * Refer to the similarly-named option on your favorite man page for more details. * @{ */ -#define LWPA_IP_TTL 11 /*!< Get/Set, value is int */ -#define LWPA_IP_MULTICAST_IF 12 /*!< Get/Set, value is LwpaIpAddr */ -#define LWPA_IP_MULTICAST_TTL 13 /*!< Get/Set, value is int */ -#define LWPA_IP_MULTICAST_LOOP 14 /*!< Get/Set, value is boolean int */ -#define LWPA_MCAST_JOIN_GROUP 15 /*!< Set only, value is LwpaMreq */ -#define LWPA_MCAST_LEAVE_GROUP 16 /*!< Set only, value is LwpaMreq */ -#define LWPA_IPV6_V6ONLY 17 /*!< Get/Set, value is boolean int */ +/*! Get/Set, value is int. Value indicates TTL for IPv4 or hop limit for IPv6. */ +#define LWPA_IP_TTL 11 +/*! Get/Set, value is LwpaIpAddr indicating interface IP address for IPv4, or int representing + * interface index for IPv6. */ +#define LWPA_IP_MULTICAST_IF 12 +/*! Get/Set, value is int. Value indicates TTL for IPv4 or hop limit for IPv6. */ +#define LWPA_IP_MULTICAST_TTL 13 +#define LWPA_IP_MULTICAST_LOOP 14 /*!< Get/Set, value is boolean int */ +/*! [Legacy IPv4-only option, use of #LWPA_MCAST_JOIN_GROUP is preferred] Set only, value is + * LwpaMreq. */ +#define LWPA_IP_ADD_MEMBERSHIP 15 +/*! [Legacy IPv4-only option, use of #LWPA_MCAST_LEAVE_GROUP is preferred] Set only, value is + * LwpaMreq. */ +#define LWPA_IP_DROP_MEMBERSHIP 16 +#define LWPA_MCAST_JOIN_GROUP 17 /*!< Set only, value is LwpaGroupReq */ +#define LWPA_MCAST_LEAVE_GROUP 18 /*!< Set only, value is LwpaGroupReq */ +#define LWPA_IPV6_V6ONLY 19 /*!< Get/Set, value is boolean int */ /*! @} */ /* clang-format on */ @@ -107,7 +117,7 @@ typedef struct LwpaLinger int linger; /*!< Linger time in seconds */ } LwpaLinger; -/*! Option value for #LWPA_MCAST_JOIN_GROUP and #LWPA_MCAST_LEAVE_GROUP. */ +/*! Option value for #LWPA_IP_ADD_MEMBERSHIP and #LWPA_IP_DROP_MEMBERSHIP. */ typedef struct LwpaMreq { /*! Address of network interface on which to join the multicast group. */ @@ -116,6 +126,16 @@ typedef struct LwpaMreq LwpaIpAddr group; } LwpaMreq; +/*! Option value for #LWPA_MCAST_JOIN_GROUP and #LWPA_MCAST_LEAVE_GROUP. */ +typedef struct LwpaGroupReq +{ + /*! Index of newtork interface on which to join the multicast group. This index is provided in + * LwpaNetintInfo structures. */ + int interface; + /*! Multicast group to join. */ + LwpaIpAddr group; +} LwpaGroupReq; + /*! \name 'how' values for lwpa_shutdown() * @{ */ #define LWPA_SHUT_RD 0 diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 8a49d5b53..5a4269576 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -400,7 +400,7 @@ lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl { // inner loop: loop thru all the attributes of one route entry. struct rtattr* rt_attributes = (struct rtattr*)RTM_RTA(rt_message); - int rt_attr_size = (int)RTM_PAYLOAD(nl_header); + unsigned int rt_attr_size = (unsigned int)RTM_PAYLOAD(nl_header); for (; RTA_OK(rt_attributes, rt_attr_size); rt_attributes = RTA_NEXT(rt_attributes, rt_attr_size)) { // We only care about the gateway and DST attribute @@ -458,7 +458,7 @@ lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl // table) for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) { - if (LWPA_IP_IS_INVALID(&entry->addr) && LWPA_IP_IS_INVALID(&entry->mask)) + if (LWPA_IP_IS_INVALID(&entry->addr) && LWPA_IP_IS_INVALID(&entry->mask) && !LWPA_IP_IS_INVALID(&entry->gateway)) { table->default_route = entry; break; diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index fdc323f92..a2e5ec3a5 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -22,8 +22,10 @@ #include #include +#include #include #include +#include #include #include "os_error.h" @@ -55,11 +57,45 @@ static const int stmap[LWPA_NUM_TYPE] = SOCK_DGRAM }; +#define LWPA_NUM_AIF 8 +static const int aiflagmap[LWPA_NUM_AIF] = +{ + 0, + AI_PASSIVE, + AI_CANONNAME, + AI_PASSIVE | AI_CANONNAME, + AI_NUMERICHOST, + AI_PASSIVE | AI_NUMERICHOST, + AI_CANONNAME | AI_NUMERICHOST, + AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST +}; + +static const int aifammap[LWPA_NUM_AF] = +{ + AF_UNSPEC, + AF_INET, + AF_INET6 +}; + +#define LWPA_NUM_IPPROTO 6 +static const int aiprotmap[LWPA_NUM_IPPROTO] = +{ + 0, + IPPROTO_IP, + IPPROTO_ICMPV6, + IPPROTO_IPV6, + IPPROTO_TCP, + IPPROTO_UDP +}; + /* clang-format on */ /*********************** Private function prototypes *************************/ static void ms_to_timeval(int ms, struct timeval* tv); +static int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); /*************************** Function definitions ****************************/ @@ -273,165 +309,200 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const switch (level) { case LWPA_SOL_SOCKET: - switch (option_name) + res = setsockopt_socket(id, option_name, option_value, option_len); + break; + case LWPA_IPPROTO_IP: + res = setsockopt_ip(id, option_name, option_value, option_len); + break; + case LWPA_IPPROTO_IPV6: + res = setsockopt_ip6(id, option_name, option_value, option_len); + break; + default: + return kLwpaErrInvalid; + } + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); +} + +int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_SO_RCVBUF: + return setsockopt(id, SOL_SOCKET, SO_RCVBUF, option_value, (socklen_t)option_len); + case LWPA_SO_SNDBUF: + return setsockopt(id, SOL_SOCKET, SO_SNDBUF, option_value, (socklen_t)option_len); + case LWPA_SO_RCVTIMEO: + if (option_len == sizeof(int)) { - case LWPA_SO_RCVBUF: - res = setsockopt(id, SOL_SOCKET, SO_RCVBUF, option_value, (socklen_t)option_len); - break; - case LWPA_SO_SNDBUF: - res = setsockopt(id, SOL_SOCKET, SO_SNDBUF, option_value, (socklen_t)option_len); - break; - case LWPA_SO_RCVTIMEO: - if (option_len == sizeof(int)) - { - int val = *(int*)option_value; - struct timeval sys_val; - ms_to_timeval(val, &sys_val); - res = setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, &sys_val, sizeof sys_val); - } - break; - case LWPA_SO_SNDTIMEO: - if (option_len == sizeof(int)) - { - int val = *(int*)option_value; - struct timeval sys_val; - ms_to_timeval(val, &sys_val); - res = setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, &sys_val, sizeof sys_val); - } - break; - case LWPA_SO_REUSEADDR: - res = setsockopt(id, SOL_SOCKET, SO_REUSEADDR, option_value, (socklen_t)option_len); - break; - case LWPA_SO_BROADCAST: - res = setsockopt(id, SOL_SOCKET, SO_BROADCAST, option_value, (socklen_t)option_len); - break; - case LWPA_SO_KEEPALIVE: - res = setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, option_value, (socklen_t)option_len); - break; - case LWPA_SO_LINGER: - if (option_len == sizeof(LwpaLinger)) - { - LwpaLinger* ll = (LwpaLinger*)option_value; - struct linger val; - val.l_onoff = (u_short)ll->onoff; - val.l_linger = (u_short)ll->linger; - res = setsockopt(id, SOL_SOCKET, SO_LINGER, &val, sizeof val); - } - break; - case LWPA_SO_ERROR: /* Set not supported */ - case LWPA_SO_TYPE: /* Set not supported */ - default: - return kLwpaErrInvalid; + int val = *(int*)option_value; + struct timeval sys_val; + ms_to_timeval(val, &sys_val); + return setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, &sys_val, sizeof sys_val); } break; - case LWPA_IPPROTO_IP: - switch (option_name) + case LWPA_SO_SNDTIMEO: + if (option_len == sizeof(int)) { - case LWPA_IP_TTL: - res = setsockopt(id, IPPROTO_IP, IP_TTL, option_value, (socklen_t)option_len); - break; - case LWPA_MCAST_JOIN_GROUP: - if (option_len == sizeof(LwpaMreq)) - { - LwpaMreq* amreq = (LwpaMreq*)option_value; - if (LWPA_IP_IS_V4(&amreq->group)) - { - struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); - val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); - res = setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&val, sizeof val); - } - } - break; - case LWPA_MCAST_LEAVE_GROUP: - if (option_len == sizeof(LwpaMreq)) - { - LwpaMreq* amreq = (LwpaMreq*)option_value; - if (LWPA_IP_IS_V4(&amreq->group)) - { - struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); - val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); - res = setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&val, sizeof val); - } - } - break; - case LWPA_IP_MULTICAST_IF: - if (option_len == sizeof(LwpaIpAddr)) - { - LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (LWPA_IP_IS_V4(netint)) - { - DWORD val = htonl(LWPA_IP_V4_ADDRESS(netint)); - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, sizeof val); - } - } - break; - case LWPA_IP_MULTICAST_TTL: - if (option_len == sizeof(int)) - { - DWORD val = (DWORD) * (int*)option_value; - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&val, sizeof val); - } - break; - case LWPA_IP_MULTICAST_LOOP: - if (option_len == sizeof(int)) - { - DWORD val = (DWORD) * (int*)option_value; - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&val, sizeof val); - } - break; - default: - return kLwpaErrInvalid; + int val = *(int*)option_value; + struct timeval sys_val; + ms_to_timeval(val, &sys_val); + return setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, &sys_val, sizeof sys_val); } break; - case LWPA_IPPROTO_IPV6: - switch (option_name) + case LWPA_SO_REUSEADDR: + return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, option_value, (socklen_t)option_len); + case LWPA_SO_REUSEPORT: + return setsockopt(id, SOL_SOCKET, SO_REUSEPORT, option_value, (socklen_t)option_len); + case LWPA_SO_BROADCAST: + return setsockopt(id, SOL_SOCKET, SO_BROADCAST, option_value, (socklen_t)option_len); + case LWPA_SO_KEEPALIVE: + return setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, option_value, (socklen_t)option_len); + case LWPA_SO_LINGER: + if (option_len == sizeof(LwpaLinger)) { - case LWPA_MCAST_JOIN_GROUP: - /* TODO on windows. - if (option_len == sizeof(struct lwpa_mreq)) - { - LwpaMreq *amreq = (LwpaMreq *)option_value; - if (LWPA_IP_IS_V6(&amreq->group)) - { - struct ipv6_mreq val; - val.ipv6imr_interface = 0; - memcpy(&val.ipv6imr_multiaddr.s6_addr, - LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); - res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - sizeof val); - } - } - */ - break; - case LWPA_MCAST_LEAVE_GROUP: - /* TODO on windows. - if (option_len == sizeof(struct lwpa_mreq)) - { - LwpaMreq *amreq = (LwpaMreq *)option_value; - if (LWPA_IP_IS_V6(&amreq->group)) - { - struct ipv6_mreq val; - val.ipv6imr_interface = 0; - memcpy(&val.ipv6imr_multiaddr.s6_addr, - LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); - res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - sizeof val); - } - } - */ - break; - default: /* Other IPv6 options TODO on windows. */ - return kLwpaErrInvalid; + LwpaLinger* ll = (LwpaLinger*)option_value; + struct linger val; + val.l_onoff = (u_short)ll->onoff; + val.l_linger = (u_short)ll->linger; + return setsockopt(id, SOL_SOCKET, SO_LINGER, &val, sizeof val); } break; - case LWPA_SO_REUSEPORT: /* Not supported on this OS. */ + case LWPA_SO_ERROR: // Set not supported + case LWPA_SO_TYPE: // Set not supported default: - return kLwpaErrInvalid; + break; } - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(WSAGetLastError())); - return kLwpaErrNotImpl; + // If we got here, something was invalid. Set errno accordingly + errno = EINVAL; + return -1; +} + +int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_IP_TTL: + return setsockopt(id, IPPROTO_IP, IP_TTL, option_value, (socklen_t)option_len); + case LWPA_IP_ADD_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) + { + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + return setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &val, sizeof val); + } + } + break; + case LWPA_IP_DROP_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) + { + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + return setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, &val, sizeof val); + } + } + break; + case LWPA_MCAST_JOIN_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V4(&greq->group) && greq->interface >= 0) + { + struct group_req val; + val.gr_interface = (uint32_t)greq->interface; + ((struct sockaddr_in*)&val.gr_group)->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + return setsockopt(id, IPPROTO_IP, MCAST_JOIN_GROUP, &val, sizeof val); + } + } + break; + case LWPA_MCAST_LEAVE_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group) && greq->interface >= 0) + { + struct group_req val; + val.gr_interface = (uint32_t)greq->interface; + ((struct sockaddr_in*)&val.gr_group)->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + return setsockopt(id, IPPROTO_IP, MCAST_LEAVE_GROUP, &val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_IF: + if (option_len == sizeof(LwpaIpAddr)) + { + LwpaIpAddr* netint = (LwpaIpAddr*)option_value; + if (LWPA_IP_IS_V4(netint)) + { + struct in_addr val; + val.s_addr = LWPA_IP_V4_ADDRESS(netint); + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_TTL: + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, option_value, (socklen_t)option_len); + case LWPA_IP_MULTICAST_LOOP: + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, option_value, (socklen_t)option_len); + default: + break; + } + // If we got here, something was invalid. Set errno accordingly + errno = EINVAL; + return -1; +} + +int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_MCAST_JOIN_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group) && greq->interface >= 0) + { + struct group_req val; + val.gr_interface = (uint32_t)greq->interface; + memcpy(&((struct sockaddr_in6*)&val.gr_group)->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), + LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, sizeof val); + } + } + break; + case LWPA_MCAST_LEAVE_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group) && greq->interface >= 0) + { + struct group_req val; + val.gr_interface = (uint32_t)greq->interface; + memcpy(&((struct sockaddr_in6*)&val.gr_group)->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), + LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, MCAST_LEAVE_GROUP, &val, sizeof val); + } + } + break; + default: /* Other IPv6 options TODO on linux. */ + break; + } + // If we got here, something was invalid. Set errno accordingly + errno = EINVAL; + return -1; +} + +void ms_to_timeval(int ms, struct timeval* tv) +{ + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; } lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) @@ -607,9 +678,8 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, LwpaAddrinfo* result) { - /* int res; - struct addrinfo *pf_res; + struct addrinfo* pf_res; struct addrinfo pf_hints; if ((!hostname && !service) || !result) @@ -632,53 +702,50 @@ lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const L if (!lwpa_nextaddr(result)) res = -1; } - return (res == 0 ? kLwpaErrOk : err_os_to_lwpa(res)); - */ - return kLwpaErrNotImpl; + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(res)); } bool lwpa_nextaddr(LwpaAddrinfo* ai) { - // if (ai && ai->pd[1]) - // { - // struct addrinfo *pf_ai = (struct addrinfo *)ai->pd[1]; - // ai->ai_flags = 0; - // if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) - // return false; - // /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS - // * constants. Ugh. */ - // if (pf_ai->ai_family == AF_INET) - // ai->ai_family = LWPA_AF_INET; - // else if (pf_ai->ai_family == AF_INET6) - // ai->ai_family = LWPA_AF_INET6; - // else - // ai->ai_family = LWPA_AF_UNSPEC; - // if (pf_ai->ai_socktype == SOCK_DGRAM) - // ai->ai_socktype = LWPA_DGRAM; - // else if (pf_ai->ai_socktype == SOCK_STREAM) - // ai->ai_socktype = LWPA_STREAM; - // else - // ai->ai_socktype = 0; - // if (pf_ai->ai_protocol == IPPROTO_UDP) - // ai->ai_protocol = LWPA_IPPROTO_UDP; - // else if (pf_ai->ai_protocol == IPPROTO_TCP) - // ai->ai_protocol = LWPA_IPPROTO_TCP; - // else - // ai->ai_protocol = 0; - // ai->ai_canonname = pf_ai->ai_canonname; - // ai->pd[1] = pf_ai->ai_next; - // - // return true; - // } + if (ai && ai->pd[1]) + { + struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; + ai->ai_flags = 0; + if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + return false; + + /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS + * constants. Ugh. */ + if (pf_ai->ai_family == AF_INET) + ai->ai_family = LWPA_AF_INET; + else if (pf_ai->ai_family == AF_INET6) + ai->ai_family = LWPA_AF_INET6; + else + ai->ai_family = LWPA_AF_UNSPEC; + if (pf_ai->ai_socktype == SOCK_DGRAM) + ai->ai_socktype = LWPA_DGRAM; + else if (pf_ai->ai_socktype == SOCK_STREAM) + ai->ai_socktype = LWPA_STREAM; + else + ai->ai_socktype = 0; + if (pf_ai->ai_protocol == IPPROTO_UDP) + ai->ai_protocol = LWPA_IPPROTO_UDP; + else if (pf_ai->ai_protocol == IPPROTO_TCP) + ai->ai_protocol = LWPA_IPPROTO_TCP; + else + ai->ai_protocol = 0; + ai->ai_canonname = pf_ai->ai_canonname; + ai->pd[1] = pf_ai->ai_next; + + return true; + } return false; } void lwpa_freeaddrinfo(LwpaAddrinfo* ai) { - /* if (ai) - freeaddrinfo((struct addrinfo *)ai->pd[0]); - */ + freeaddrinfo((struct addrinfo*)ai->pd[0]); } lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) From 1909ad89a77a78490e78dac9a41dd67e88574dfa Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 10 Jun 2019 16:41:02 -0500 Subject: [PATCH 027/264] Lots of progress, only 4 failing unit tests now. --- docs/mainpage.md | 1 + include/lwpa/error.h | 24 +- include/lwpa/lock.h | 2 +- include/os/linux/lwpa/os_lock.h | 44 ++-- include/os/linux/lwpa/os_socket.h | 3 + src/lwpa/error.c | 58 ++--- src/lwpa/log.c | 2 +- src/lwpa/mempool.c | 8 +- src/os/linux/lwpa/os_error.c | 110 +++++---- src/os/linux/lwpa/os_lock.c | 103 +++++++++ src/os/linux/lwpa/os_socket.c | 361 +++++++++++++++++++++--------- tests/unit/test_log.cpp | 13 +- tests/unit/test_mutex.cpp | 14 +- tests/unit/test_netint.cpp | 5 +- tests/unit/test_signal.cpp | 24 +- tests/unit/test_socket.cpp | 72 ++++-- tests/unit/test_socket_poll.cpp | 15 +- 17 files changed, 586 insertions(+), 273 deletions(-) diff --git a/docs/mainpage.md b/docs/mainpage.md index 9f3471b6e..b0e513e24 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -105,3 +105,4 @@ The platform ports of lwpa have the following dependencies: equivalent method for your distribution) - Optional Features: * lwpa_netint (Network Interfaces): Linux 2.2, glibc 2.3.3 + * lwpa_socket (Socket interface): Linux 2.6 diff --git a/include/lwpa/error.h b/include/lwpa/error.h index 721d8f792..4de8d9ff2 100644 --- a/include/lwpa/error.h +++ b/include/lwpa/error.h @@ -76,29 +76,33 @@ typedef enum kLwpaErrShutdown = -17, /*! A connection timed out. */ kLwpaErrTimedOut = -18, + /*! A connection has been aborted. */ + kLwpaErrConnAborted = -19, /*! A connection was refused. */ - kLwpaErrConnRefused = -19, + kLwpaErrConnRefused = -20, /*! The operation requested is already in progress. */ - kLwpaErrAlready = -20, + kLwpaErrAlready = -21, /*! The operation requested is now in progress and will complete later. */ - kLwpaErrInProgress = -21, + kLwpaErrInProgress = -22, /*! A buffer provided to a function was not big enough to hold the data that needed to be packed * into it. */ - kLwpaErrBufSize = -22, + kLwpaErrBufSize = -23, /*! An API function was called from a module that was not previously initialized. */ - kLwpaErrNotInit = -23, + kLwpaErrNotInit = -24, /*! No network interfaces were found on the system, or there are no network interfaces of a type * that can satisfy the call being made. */ - kLwpaErrNoNetints = -24, + kLwpaErrNoNetints = -25, /*! No sockets have been added to the context. */ - kLwpaErrNoSockets = -25, + kLwpaErrNoSockets = -26, /*! A function or specific use of a function is not implemented yet. */ - kLwpaErrNotImpl = -26, + kLwpaErrNotImpl = -27, + /*! The operation is not permitted. */ + kLwpaErrPerm = -28, /*! A system call or C library call failed in a way not covered by other errors. */ - kLwpaErrSys = -27, + kLwpaErrSys = -29, } lwpa_error_t; -#define LWPA_NUM_ERROR_CODES 28 +#define LWPA_NUM_ERROR_CODES 30 #ifdef __cplusplus extern "C" { diff --git a/include/lwpa/lock.h b/include/lwpa/lock.h index 19876148c..7a6502c84 100644 --- a/include/lwpa/lock.h +++ b/include/lwpa/lock.h @@ -55,7 +55,7 @@ class MutexGuard public: explicit MutexGuard(lwpa_mutex_t& mutex) : mutex_(mutex) { - if (!lwpa_mutex_take(&mutex_, LWPA_WAIT_FOREVER)) + if (!lwpa_mutex_take(&mutex_)) throw std::runtime_error("lwpa_mutex_take failed."); } ~MutexGuard() { lwpa_mutex_give(&mutex_); } diff --git a/include/os/linux/lwpa/os_lock.h b/include/os/linux/lwpa/os_lock.h index aca4a8f6b..8cb02e2a8 100644 --- a/include/os/linux/lwpa/os_lock.h +++ b/include/os/linux/lwpa/os_lock.h @@ -23,23 +23,37 @@ #include #include "lwpa/bool.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef pthread_mutex_t lwpa_mutex_t; -/* Temporary placeholders */ -#define lwpa_mutex_create(idptr) false -#define lwpa_mutex_take(idptr, wait_ms) false -#define lwpa_mutex_give(idptr) -#define lwpa_mutex_destroy(idptr) +#define lwpa_mutex_create(idptr) ((pthread_mutex_init((idptr), NULL) == 0) ? true : false) +#define lwpa_mutex_take(idptr) ((pthread_mutex_lock(idptr) == 0) ? true : false) +#define lwpa_mutex_try_take(idptr) ((pthread_mutex_trylock(idptr) == 0) ? true : false) +#define lwpa_mutex_give(idptr) ((void)pthread_mutex_unlock(idptr)) +#define lwpa_mutex_destroy(idptr) ((void)pthread_mutex_destroy(idptr)) -typedef pthread_cond_t lwpa_signal_t; +typedef struct +{ + bool valid; + bool signaled; + pthread_cond_t cond; + pthread_mutex_t mutex; +} lwpa_signal_t; -/* Temporary placeholders */ -#define lwpa_signal_create(idptr) false -#define lwpa_signal_wait(idptr, wait_ms) false -#define lwpa_signal_post(idptr) -#define lwpa_signal_destroy(idptr) +bool lwpa_signal_create(lwpa_signal_t* id); +bool lwpa_signal_wait(lwpa_signal_t* id); +bool lwpa_signal_poll(lwpa_signal_t* id); +void lwpa_signal_post(lwpa_signal_t* id); +void lwpa_signal_destroy(lwpa_signal_t* id); -typedef pthread_rwlock_t lwpa_rwlock_t; +typedef struct +{ + bool valid; + pthread_mutex_t mutex; +} lwpa_rwlock_t; /* Temporary placeholders */ #define lwpa_rwlock_create(idptr) false @@ -49,4 +63,8 @@ typedef pthread_rwlock_t lwpa_rwlock_t; #define lwpa_rwlock_writeunlock(idptr) #define lwpa_rwlock_destroy(idptr) -#endif /* _LWPA_OS_LOCK_H_ */ \ No newline at end of file +#ifdef __cplusplus +} +#endif + +#endif /* _LWPA_OS_LOCK_H_ */ diff --git a/include/os/linux/lwpa/os_socket.h b/include/os/linux/lwpa/os_socket.h index ccace63eb..b461aed2c 100644 --- a/include/os/linux/lwpa/os_socket.h +++ b/include/os/linux/lwpa/os_socket.h @@ -23,6 +23,7 @@ #include #include #include "lwpa/inet.h" +#include "lwpa/rbtree.h" #ifdef __cplusplus extern "C" { @@ -36,7 +37,9 @@ typedef int lwpa_socket_t; typedef struct LwpaPollContext { + bool valid; int epoll_fd; + LwpaRbTree sockets; } LwpaPollContext; #define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), ntohl((pfipptr)->s_addr)) diff --git a/src/lwpa/error.c b/src/lwpa/error.c index 4d31068a3..005f8c7a9 100644 --- a/src/lwpa/error.c +++ b/src/lwpa/error.c @@ -24,32 +24,34 @@ /* The lwpa_error string array, for use by lwpa_strerror(). */ const char *lwpa_error_strings[LWPA_NUM_ERROR_CODES] = { - "No error", /* kLwpaErrOk */ - "Handle not found", /* kLwpaErrNotFound */ - "Out of memory", /* kLwpaErrNoMem */ - "Resource unavailable", /* kLwpaErrBusy */ - "Already exists", /* kLwpaErrExists */ - "Invalid argument", /* kLwpaErrInvalid */ - "Operation would block", /* kLwpaErrWouldBlock */ - "No data available", /* kLwpaErrNoData */ - "Malformed packet", /* kLwpaErrProtocol */ - "Message too long", /* kLwpaErrMsgSize */ - "Address already in use", /* kLwpaErrAddrInUse */ - "Cannot assign requested address", /* kLwpaErrAddrNotAvail */ - "Network down or unreachable", /* kLwpaErrNetwork */ - "Connection reset by peer", /* kLwpaErrConnReset */ - "Connection closed by peer", /* kLwpaErrConnClosed */ - "Already connected", /* kLwpaErrIsConn */ - "Not connected", /* kLwpaErrNotConn */ - "Transport endpoint shut down", /* kLwpaErrShutdown */ - "Operation timed out", /* kLwpaErrTimedOut */ - "Connection refused", /* kLwpaErrConnRefused */ - "Operation already in progress", /* kLwpaErrAlready */ - "Operation now in progress", /* kLwpaErrInProgress */ - "Buffer not big enough", /* kLwpaErrBufSize */ - "Module not initialized", /* kLwpaErrNotInit */ - "No network interfaces", /* kLwpaErrNoNetints */ - "No sockets", /* kLwpaErrNoSockets */ - "Not implemented", /* kLwpaErrNotImpl */ - "System or library call failed", /* kLwpaErrSys */ + "No error", /* kLwpaErrOk */ + "Handle not found", /* kLwpaErrNotFound */ + "Out of memory", /* kLwpaErrNoMem */ + "Resource unavailable", /* kLwpaErrBusy */ + "Already exists", /* kLwpaErrExists */ + "Invalid argument", /* kLwpaErrInvalid */ + "Operation would block", /* kLwpaErrWouldBlock */ + "No data available", /* kLwpaErrNoData */ + "Malformed packet", /* kLwpaErrProtocol */ + "Message too long", /* kLwpaErrMsgSize */ + "Address already in use", /* kLwpaErrAddrInUse */ + "Cannot assign requested address", /* kLwpaErrAddrNotAvail */ + "Network down or unreachable", /* kLwpaErrNetwork */ + "Connection reset by peer", /* kLwpaErrConnReset */ + "Connection closed by peer", /* kLwpaErrConnClosed */ + "Already connected", /* kLwpaErrIsConn */ + "Not connected", /* kLwpaErrNotConn */ + "Transport endpoint shut down", /* kLwpaErrShutdown */ + "Operation timed out", /* kLwpaErrTimedOut */ + "Software caused connection abort", /* kLwpaErrConnAborted */ + "Connection refused", /* kLwpaErrConnRefused */ + "Operation already in progress", /* kLwpaErrAlready */ + "Operation now in progress", /* kLwpaErrInProgress */ + "Buffer not big enough", /* kLwpaErrBufSize */ + "Module not initialized", /* kLwpaErrNotInit */ + "No network interfaces", /* kLwpaErrNoNetints */ + "No sockets", /* kLwpaErrNoSockets */ + "Not implemented", /* kLwpaErrNotImpl */ + "Operation not permitted", /* kLwpaErrPerm */ + "System or library call failed", /* kLwpaErrSys */ }; diff --git a/src/lwpa/log.c b/src/lwpa/log.c index f29dac3a6..82c887913 100644 --- a/src/lwpa/log.c +++ b/src/lwpa/log.c @@ -353,7 +353,7 @@ void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list LwpaLogTimeParams time_params; bool have_time = get_time(params, &time_params); - if (lwpa_mutex_take(&buf_lock, LWPA_WAIT_FOREVER)) + if (lwpa_mutex_take(&buf_lock)) { static char syslogmsg[LWPA_SYSLOG_STR_MAX_LEN + 1]; static char humanlogmsg[LWPA_HUMAN_LOG_STR_MAX_LEN + 1]; diff --git a/src/lwpa/mempool.c b/src/lwpa/mempool.c index a4c9060b6..c281b3910 100644 --- a/src/lwpa/mempool.c +++ b/src/lwpa/mempool.c @@ -38,7 +38,7 @@ lwpa_error_t lwpa_mempool_init_priv(LwpaMempoolDesc* desc) return res; } - if (lwpa_mutex_take(&mempool_lock, LWPA_WAIT_FOREVER)) + if (lwpa_mutex_take(&mempool_lock)) { size_t i; for (i = 0; i < desc->pool_size - 1; ++i) @@ -56,7 +56,7 @@ void* lwpa_mempool_alloc_priv(LwpaMempoolDesc* desc) { void* elem = NULL; - if (lwpa_mutex_take(&mempool_lock, LWPA_WAIT_FOREVER)) + if (lwpa_mutex_take(&mempool_lock)) { char* c_pool = (char*)desc->pool; LwpaMempool* elem_desc = desc->freelist; @@ -83,7 +83,7 @@ void lwpa_mempool_free_priv(LwpaMempoolDesc* desc, void* elem) ptrdiff_t offset = (char*)elem - c_pool; if (offset >= 0) { - if (((size_t)offset % desc->elem_size == 0) && lwpa_mutex_take(&mempool_lock, LWPA_WAIT_FOREVER)) + if (((size_t)offset % desc->elem_size == 0) && lwpa_mutex_take(&mempool_lock)) { size_t index = (size_t)offset / desc->elem_size; LwpaMempool* elem_desc = &desc->list[index]; @@ -98,7 +98,7 @@ void lwpa_mempool_free_priv(LwpaMempoolDesc* desc, void* elem) size_t lwpa_mempool_used_priv(LwpaMempoolDesc* desc) { size_t res = 0; - if (lwpa_mutex_take(&mempool_lock, LWPA_WAIT_FOREVER)) + if (lwpa_mutex_take(&mempool_lock)) { res = desc->current_used; lwpa_mutex_give(&mempool_lock); diff --git a/src/os/linux/lwpa/os_error.c b/src/os/linux/lwpa/os_error.c index 2f4a6980e..45770f791 100644 --- a/src/os/linux/lwpa/os_error.c +++ b/src/os/linux/lwpa/os_error.c @@ -18,79 +18,75 @@ ******************************************************************************/ #include "os_error.h" +#include -lwpa_error_t errno_os_to_lwpa(int errno) +lwpa_error_t errno_os_to_lwpa(int os_errno) { - switch (errno) + switch (os_errno) { - /* - case WSAEBADF: - case WSAENOTSOCK: - case WSATYPE_NOT_FOUND: - case WSAHOST_NOT_FOUND: - case WSAESTALE: + case EPERM: + case EACCES: + return kLwpaErrPerm; + case ENOENT: + case EBADF: + case ENOTSOCK: return kLwpaErrNotFound; - case WSA_INVALID_HANDLE: - case WSA_INVALID_PARAMETER: - case WSAEFAULT: - case WSAEINVAL: - case WSAEDESTADDRREQ: - case WSAENOPROTOOPT: + case EFAULT: + case EINVAL: + case EDESTADDRREQ: + case EPROTOTYPE: + case EOPNOTSUPP: return kLwpaErrInvalid; - case WSA_NOT_ENOUGH_MEMORY: - case WSAEMFILE: - case WSAETOOMANYREFS: - case WSAEPROCLIM: - case WSAEUSERS: - return kLwpaErrNoMem; - case WSA_IO_PENDING: - case WSAEINPROGRESS: - return kLwpaErrInProgress; - case WSA_IO_INCOMPLETE: - case WSAEALREADY: - return kLwpaErrAlready; - case WSAEWOULDBLOCK: + // case EAGAIN: // EWOULDBLOCK defined to EAGAIN + case EWOULDBLOCK: return kLwpaErrWouldBlock; - case WSAEMSGSIZE: + case EBUSY: + return kLwpaErrBusy; + case ENOMEM: + case ENOBUFS: + return kLwpaErrNoMem; + case EEXIST: + return kLwpaErrExists; + case ENOSYS: + return kLwpaErrNotImpl; + case EPROTO: + return kLwpaErrProtocol; + case EMSGSIZE: return kLwpaErrMsgSize; - case WSAEADDRINUSE: + case EADDRINUSE: return kLwpaErrAddrInUse; - case WSAEADDRNOTAVAIL: + case EADDRNOTAVAIL: return kLwpaErrAddrNotAvail; - case WSAENETDOWN: - case WSAENETUNREACH: - case WSAENETRESET: - case WSAEHOSTDOWN: - case WSAEHOSTUNREACH: + case ENETDOWN: + case ENETUNREACH: + case ENETRESET: return kLwpaErrNetwork; - case WSAECONNRESET: - case WSAECONNABORTED: + case ECONNABORTED: + return kLwpaErrConnAborted; + case ECONNRESET: return kLwpaErrConnReset; - case WSAEISCONN: + case EISCONN: return kLwpaErrIsConn; - case WSAENOTCONN: + case ENOTCONN: return kLwpaErrNotConn; - case WSAESHUTDOWN: + case ESHUTDOWN: return kLwpaErrShutdown; - case WSAETIMEDOUT: + case ETIMEDOUT: return kLwpaErrTimedOut; - case WSAECONNREFUSED: + case ECONNREFUSED: return kLwpaErrConnRefused; - case WSAENOBUFS: - return kLwpaErrBufSize; - case WSANOTIMPLIALISED: - case WSASYSNOTREADY: - return kLwpaErrNotImpl; - case WSAEACCES: - case WSA_OPERATION_ABORTED: - case WSAEPROTOTYPE: - case WSAEPROTONOSUPPORT: - case WSAESOCKTNOSUPPORT: - case WSAEOPNOTSUPP: - case WSAEPFNOSUPPORT: - case WSAEAFNOSUPPORT: - case WSASYSCALLFAILURE: - */ + case EALREADY: + return kLwpaErrAlready; + case EINPROGRESS: + return kLwpaErrInProgress; + case EINTR: + case ENFILE: + case EMFILE: + case ENOSPC: + case EPFNOSUPPORT: + case EAFNOSUPPORT: + case EPROTONOSUPPORT: + case ESOCKTNOSUPPORT: default: return kLwpaErrSys; } diff --git a/src/os/linux/lwpa/os_lock.c b/src/os/linux/lwpa/os_lock.c index e69de29bb..3fa7fa748 100644 --- a/src/os/linux/lwpa/os_lock.c +++ b/src/os/linux/lwpa/os_lock.c @@ -0,0 +1,103 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/lock.h" + +bool lwpa_signal_create(lwpa_signal_t* id) +{ + if (id) + { + if (0 == pthread_mutex_init(&id->mutex, NULL)) + { + if (0 == pthread_cond_init(&id->cond, NULL)) + { + id->valid = true; + id->signaled = false; + return true; + } + else + { + pthread_mutex_destroy(&id->mutex); + } + } + } + return false; +} + +bool lwpa_signal_wait(lwpa_signal_t* id) +{ + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + while (!id->signaled) + { + if (0 != pthread_cond_wait(&id->cond, &id->mutex)) + { + // On error, the mutex is not locked + } + } + id->signaled = false; + pthread_mutex_unlock(&id->mutex); + return true; + } + } + return false; +} + +bool lwpa_signal_poll(lwpa_signal_t* id) +{ + bool res = false; + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + if (id->signaled) + { + res = true; + id->signaled = false; + } + pthread_mutex_unlock(&id->mutex); + } + } + return res; +} + +void lwpa_signal_post(lwpa_signal_t* id) +{ + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + id->signaled = true; + pthread_cond_signal(&id->cond); + pthread_mutex_unlock(&id->mutex); + } + } +} + +void lwpa_signal_destroy(lwpa_signal_t* id) +{ + if (id && id->valid) + { + pthread_cond_destroy(&id->cond); + pthread_mutex_destroy(&id->mutex); + id->valid = false; + } +} diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index a2e5ec3a5..5da6a6867 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -19,17 +19,37 @@ #include "lwpa/socket.h" #include +#include #include #include #include #include +#include #include #include #include #include "os_error.h" +/**************************** Private constants ******************************/ + +/* Per the docs, this constant is ignored in Linux 2.6.8 and later, but must be > 0. + * Here is a random number. */ +#define EPOLL_CREATE_SIZE 1024 + +/****************************** Private types ********************************/ + +/* A struct to track sockets being polled by the lwpa_poll() API */ +typedef struct LwpaPollSocket +{ + // 'sock' must always remain as the first member in the struct to facilitate an LwpaRbTree lookup + // shortcut + lwpa_socket_t sock; + lwpa_poll_events_t events; + void* user_data; +} LwpaPollSocket; + /**************************** Private variables ******************************/ /* clang-format off */ @@ -97,6 +117,14 @@ static int setsockopt_socket(lwpa_socket_t id, int option_name, const void* opti static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt); +static void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, + lwpa_poll_events_t* events); + +static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); +static LwpaRbNode* poll_socket_alloc(); +static void poll_socket_free(LwpaRbNode* node); + /*************************** Function definitions ****************************/ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) @@ -417,7 +445,11 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s { struct group_req val; val.gr_interface = (uint32_t)greq->interface; - ((struct sockaddr_in*)&val.gr_group)->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); return setsockopt(id, IPPROTO_IP, MCAST_JOIN_GROUP, &val, sizeof val); } } @@ -426,11 +458,15 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s if (option_len == sizeof(LwpaGroupReq)) { LwpaGroupReq* greq = (LwpaGroupReq*)option_value; - if (LWPA_IP_IS_V6(&greq->group) && greq->interface >= 0) + if (LWPA_IP_IS_V4(&greq->group) && greq->interface >= 0) { struct group_req val; val.gr_interface = (uint32_t)greq->interface; - ((struct sockaddr_in*)&val.gr_group)->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); return setsockopt(id, IPPROTO_IP, MCAST_LEAVE_GROUP, &val, sizeof val); } } @@ -471,8 +507,11 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, { struct group_req val; val.gr_interface = (uint32_t)greq->interface; - memcpy(&((struct sockaddr_in6*)&val.gr_group)->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), - LWPA_IPV6_BYTES); + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); return setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, sizeof val); } } @@ -485,8 +524,11 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, { struct group_req val; val.gr_interface = (uint32_t)greq->interface; - memcpy(&((struct sockaddr_in6*)&val.gr_group)->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), - LWPA_IPV6_BYTES); + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); return setsockopt(id, IPPROTO_IPV6, MCAST_LEAVE_GROUP, &val, sizeof val); } } @@ -553,126 +595,235 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { - return kLwpaErrNotImpl; + if (!context) + return kLwpaErrInvalid; + + context->epoll_fd = epoll_create(EPOLL_CREATE_SIZE); + if (context->epoll_fd >= 0) + { + lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); + context->valid = true; + return kLwpaErrOk; + } + else + { + return errno_os_to_lwpa(errno); + } } void lwpa_poll_context_deinit(LwpaPollContext* context) { + if (context && context->valid) + { + lwpa_rbtree_clear(&context->sockets); + close(context->epoll_fd); + context->valid = false; + } } lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, void* user_data) { - return kLwpaErrNotImpl; + if (context && context->valid && socket != LWPA_SOCKET_INVALID && (events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)malloc(sizeof(LwpaPollSocket)); + if (sock_desc) + { + sock_desc->sock = socket; + sock_desc->events = events; + sock_desc->user_data = user_data; + int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); + if (insert_res != 0) + { + struct epoll_event ep_evt; + events_lwpa_to_epoll(events, &ep_evt); + ep_evt.data.fd = socket; + + int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_ADD, socket, &ep_evt); + if (res == 0) + { + return kLwpaErrOk; + } + else + { + // Our node dealloc function also deallocates sock_desc, so no need to free it here. + lwpa_rbtree_remove(&context->sockets, sock_desc); + return errno_os_to_lwpa(errno); + } + } + else + { + free(sock_desc); + return kLwpaErrNoMem; + } + } + else + { + return kLwpaErrNoMem; + } + } + else + { + return kLwpaErrInvalid; + } } lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, void* new_user_data) { - return kLwpaErrNotImpl; + if (context && context->valid && socket != LWPA_SOCKET_INVALID && (new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); + if (sock_desc) + { + struct epoll_event ep_evt; + events_lwpa_to_epoll(new_events, &ep_evt); + ep_evt.data.fd = socket; + + int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_MOD, socket, &ep_evt); + if (res == 0) + { + sock_desc->events = new_events; + sock_desc->user_data = new_user_data; + return kLwpaErrOk; + } + else + { + return errno_os_to_lwpa(errno); + } + } + else + { + return kLwpaErrNotFound; + } + } + else + { + return kLwpaErrInvalid; + } } void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) { + if (context && context->valid) + { + // Need a dummy struct for portability - some versions require event to always be non-NULL + // even though it is ignored + struct epoll_event ep_evt; + epoll_ctl(context->epoll_fd, EPOLL_CTL_DEL, socket, &ep_evt); + lwpa_rbtree_remove(&context->sockets, &socket); + } } lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms) { - // fd_set readfds, writefds, exceptfds; - // LwpaPollfd *fd; - // int nosfds; - // int sel_res; - // int nreadfds = 0, nwritefds = 0, nexceptfds = 0; - // struct timeval os_timeout; - // - // if (fds && nfds > 0) - // { - // FD_ZERO(&readfds); - // FD_ZERO(&writefds); - // FD_ZERO(&exceptfds); - // - // for (fd = fds; fd < fds + nfds; ++fd) - // { - // if (fd->events & LWPA_POLLIN) - // { - // FD_SET(fd->fd, &readfds); - // nreadfds++; - // } - // if (fd->events & LWPA_POLLOUT) - // { - // FD_SET(fd->fd, &writefds); - // nwritefds++; - // } - // if (fd->events & LWPA_POLLPRI) - // { - // FD_SET(fd->fd, &exceptfds); - // nexceptfds++; - // } - // } - // } - // - // if (timeout_ms == 0) - // { - // os_timeout.tv_sec = 0; - // os_timeout.tv_usec = 0; - // } - // else if (timeout_ms != LWPA_WAIT_FOREVER) - // { - // os_timeout.tv_sec = timeout_ms / 1000; - // os_timeout.tv_usec = (timeout_ms % 1000) * 1000; - // } - // nosfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; - // nosfds = (nexceptfds > nosfds) ? nexceptfds : nosfds; - // sel_res = select(nosfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, nexceptfds ? &exceptfds : - // NULL, - // timeout_ms == LWPA_WAIT_FOREVER ? NULL : &os_timeout); - // - // if (sel_res < 0) - // { - // return err_os_to_lwpa(WSAGetLastError()); - // } - // else if (sel_res == 0) - // { - // return kLwpaErrTimedOut; - // } - // else if (fds && nfds > 0) - // { - // for (fd = fds; fd < fds + nfds; ++fd) - // { - // fd->revents = 0; - // - // if (FD_ISSET(fd->fd, &readfds) || FD_ISSET(fd->fd, &writefds) || FD_ISSET(fd->fd, &exceptfds)) - // { - // /* Check for errors */ - // int error; - // int error_size = sizeof(error); - // if (getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, (char *)&error, &error_size) == 0) - // { - // if (error != 0) - // { - // fd->revents |= LWPA_POLLERR; - // fd->err = err_os_to_lwpa(error); - // } - // } - // else - // return (int)err_os_to_lwpa(WSAGetLastError()); - // } - // if (nreadfds && (fd->events & LWPA_POLLIN) && FD_ISSET(fd->fd, &readfds)) - // { - // fd->revents |= LWPA_POLLIN; - // } - // if (nwritefds && (fd->events & LWPA_POLLOUT) && FD_ISSET(fd->fd, &writefds)) - // { - // fd->revents |= LWPA_POLLOUT; - // } - // if (nexceptfds && (fd->events & LWPA_POLLPRI) && FD_ISSET(fd->fd, &exceptfds)) - // { - // fd->revents |= LWPA_POLLPRI; - // } - // } - // } - // return sel_res; - return kLwpaErrNotImpl; + if (context && context->valid && event) + { + if (lwpa_rbtree_size(&context->sockets) > 0) + { + int sys_timeout = (timeout_ms == LWPA_WAIT_FOREVER ? -1 : timeout_ms); + + struct epoll_event epoll_evt; + int wait_res = epoll_wait(context->epoll_fd, &epoll_evt, 1, sys_timeout); + if (wait_res > 0) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &epoll_evt.data.fd); + if (sock_desc) + { + event->socket = sock_desc->sock; + events_epoll_to_lwpa(&epoll_evt, sock_desc, &event->events); + event->err = kLwpaErrOk; + event->user_data = sock_desc->user_data; + + // Check for errors + int error; + socklen_t error_size = sizeof error; + if (getsockopt(sock_desc->sock, SOL_SOCKET, SO_ERROR, &error, &error_size) == 0) + { + if (error != 0) + { + event->events |= LWPA_POLL_ERR; + event->err = errno_os_to_lwpa(error); + } + } + + return kLwpaErrOk; + } + else + { + return kLwpaErrSys; + } + } + else if (wait_res == 0) + { + return kLwpaErrTimedOut; + } + else + { + return errno_os_to_lwpa(errno); + } + } + else + { + return kLwpaErrNoSockets; + } + } + else + { + return kLwpaErrInvalid; + } +} + +void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt) +{ + epoll_evt->events = 0; + if (events & LWPA_POLL_IN) + epoll_evt->events |= EPOLLIN; + if ((events & LWPA_POLL_OUT) || (events & LWPA_POLL_CONNECT)) + epoll_evt->events |= EPOLLOUT; + if (events & LWPA_POLL_OOB) + epoll_evt->events |= EPOLLPRI; +} + +void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, + lwpa_poll_events_t* events_out) +{ + *events_out = 0; + if (epoll_evt->events & EPOLLIN) + *events_out |= LWPA_POLL_IN; + if (epoll_evt->events & EPOLLOUT) + { + if (sock_desc->events & LWPA_POLL_OUT) + *events_out |= LWPA_POLL_OUT; + if (sock_desc->events & LWPA_POLL_CONNECT) + *events_out |= LWPA_POLL_CONNECT; + } + if (epoll_evt->events & EPOLLPRI) + *events_out |= (LWPA_POLL_OOB); + if (epoll_evt->events & EPOLLERR) + *events_out |= (LWPA_POLL_ERR); +} + +int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b) +{ + LwpaPollSocket* a = (LwpaPollSocket*)node_a->value; + LwpaPollSocket* b = (LwpaPollSocket*)node_b->value; + + return (a->sock > b->sock) - (a->sock < b->sock); +} + +LwpaRbNode* poll_socket_alloc() +{ + return (LwpaRbNode*)malloc(sizeof(LwpaRbNode)); +} + +void poll_socket_free(LwpaRbNode* node) +{ + if (node) + { + free(node->value); + free(node); + } } lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, diff --git a/tests/unit/test_log.cpp b/tests/unit/test_log.cpp index dd5707825..b2992bee9 100644 --- a/tests/unit/test_log.cpp +++ b/tests/unit/test_log.cpp @@ -39,10 +39,7 @@ class LogTest : public ::testing::Test lwpa_init(LWPA_FEATURE_LOGGING); FillDefaultTime(cur_time); } - ~LogTest() - { - lwpa_deinit(LWPA_FEATURE_LOGGING); - } + ~LogTest() { lwpa_deinit(LWPA_FEATURE_LOGGING); } void TestLwpaVlogHelper(std::string expect_syslog_str, std::string expect_human_str, std::string expect_raw_str, LwpaLogParams* lparams, int pri, const char* format, ...); @@ -220,19 +217,23 @@ void LogTest::TestLwpaVlogHelper(std::string expect_syslog_str, std::string expe lwpa_vlog(lparams, pri, format, args); Mock::VerifyAndClearExpectations(this); + va_end(args); + va_start(args, format); + // Try logging both lparams->action = kLwpaLogCreateBoth; EXPECT_CALL(*this, VerifyLogCallback(expect_syslog_str, expect_human_str, expect_raw_str)); lwpa_vlog(lparams, pri, format, args); Mock::VerifyAndClearExpectations(this); + va_end(args); + va_start(args, format); + // Try logging only human-readable lparams->action = kLwpaLogCreateHumanReadableLog; EXPECT_CALL(*this, VerifyLogCallback(std::string(), expect_human_str, expect_raw_str)); lwpa_vlog(lparams, pri, format, args); Mock::VerifyAndClearExpectations(this); - - va_end(args); } // Test logging of: diff --git a/tests/unit/test_mutex.cpp b/tests/unit/test_mutex.cpp index df034934f..81192702b 100644 --- a/tests/unit/test_mutex.cpp +++ b/tests/unit/test_mutex.cpp @@ -34,17 +34,21 @@ class MutexTest : public ::testing::Test int shared_var{0}; // For general usage - lwpa_mutex_t mutex; + lwpa_mutex_t mutex{}; }; TEST_F(MutexTest, create_destroy) { // Basic creation and taking ownership. ASSERT_TRUE(lwpa_mutex_create(&mutex)); - ASSERT_TRUE(lwpa_mutex_take(&mutex, LWPA_WAIT_FOREVER)); + ASSERT_TRUE(lwpa_mutex_take(&mutex)); // On Windows, take succeeds when taking a mutex again from the same thread. - ASSERT_TRUE(lwpa_mutex_take(&mutex, LWPA_WAIT_FOREVER)); +#ifdef WIN32 + ASSERT_TRUE(lwpa_mutex_take(&mutex)); +#else + ASSERT_FALSE(lwpa_mutex_try_take(&mutex)); +#endif lwpa_mutex_give(&mutex); @@ -56,7 +60,7 @@ TEST_F(MutexTest, create_destroy) // Take should fail on a destroyed mutex. lwpa_mutex_destroy(&mutex); - ASSERT_FALSE(lwpa_mutex_take(&mutex, LWPA_WAIT_FOREVER)); + ASSERT_FALSE(lwpa_mutex_take(&mutex)); } static void mutex_test_thread(MutexTest* fixture) @@ -65,7 +69,7 @@ static void mutex_test_thread(MutexTest* fixture) { for (int i = 0; i < MutexTest::kNumIterations; ++i) { - lwpa_mutex_take(&fixture->mutex, LWPA_WAIT_FOREVER); + lwpa_mutex_take(&fixture->mutex); ++fixture->shared_var; lwpa_mutex_give(&fixture->mutex); // Had to insert an artificial delay to get it to fail reliably when the mutexes don't work. diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index d628e9831..bc2365622 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -63,7 +63,7 @@ TEST_F(NetintTest, default) memset(netint_arr, 0, sizeof(struct LwpaNetintInfo) * num_netints); num_netints = lwpa_netint_get_interfaces(netint_arr, num_netints); - ASSERT_TRUE(lwpa_netint_get_default_interface(&def)); + ASSERT_TRUE(lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def)); ASSERT_TRUE(def.is_default); for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) { @@ -87,6 +87,9 @@ TEST_F(NetintTest, ipv4_routing) for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) { + if (!LWPA_IP_IS_V4(&netint->addr) || lwpa_ip_is_loopback(&netint->addr)) + continue; + uint32_t net = LWPA_IP_V4_ADDRESS(&netint->addr) & LWPA_IP_V4_ADDRESS(&netint->mask); LwpaIpAddr test_addr; diff --git a/tests/unit/test_signal.cpp b/tests/unit/test_signal.cpp index 2716002b7..0a93ad9f6 100644 --- a/tests/unit/test_signal.cpp +++ b/tests/unit/test_signal.cpp @@ -31,7 +31,7 @@ class SignalTest : public ::testing::Test { public: // For general usage - lwpa_signal_t signal; + lwpa_signal_t signal{}; }; TEST_F(SignalTest, create_destroy) @@ -40,23 +40,23 @@ TEST_F(SignalTest, create_destroy) ASSERT_TRUE(lwpa_signal_create(&signal)); // Signals shouldn't be created in the signaled state. - ASSERT_FALSE(lwpa_signal_wait(&signal, 0)); + ASSERT_FALSE(lwpa_signal_poll(&signal)); lwpa_signal_post(&signal); - ASSERT_TRUE(lwpa_signal_wait(&signal, LWPA_WAIT_FOREVER)); + ASSERT_TRUE(lwpa_signal_wait(&signal)); - auto start_time = std::chrono::high_resolution_clock::now(); - // Signal wait should fail if not signaled - ASSERT_FALSE(lwpa_signal_wait(&signal, 100)); - // It should wait for at least the timeout specified, minus up to one ms - auto time_taken = - std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); - ASSERT_GE(time_taken.count(), 99); + // auto start_time = std::chrono::high_resolution_clock::now(); + // // Signal wait should fail if not signaled + // ASSERT_FALSE(lwpa_signal_timed_wait(&signal, 100)); + // // It should wait for at least the timeout specified, minus up to one ms + // auto time_taken = + // std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); + // ASSERT_GE(time_taken.count(), 99); // Take should fail on a destroyed signal. lwpa_signal_post(&signal); lwpa_signal_destroy(&signal); - ASSERT_FALSE(lwpa_signal_wait(&signal, LWPA_WAIT_FOREVER)); + ASSERT_FALSE(lwpa_signal_wait(&signal)); } static void signal_test_thread(SignalTest* fixture) @@ -64,7 +64,7 @@ static void signal_test_thread(SignalTest* fixture) if (fixture) { for (size_t i = 0; i < 3; ++i) - lwpa_signal_wait(&fixture->signal, LWPA_WAIT_FOREVER); + lwpa_signal_wait(&fixture->signal); } } diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 2ef39240a..5c5cf3197 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -27,7 +27,7 @@ class SocketTest : public ::testing::Test public: static const size_t NUM_TEST_PACKETS = 1000; static const char* SEND_MSG; - static const size_t SEND_MSG_LEN = 12; + static const size_t SEND_MSG_LEN; static const uint32_t TEST_MCAST_ADDR = 0xec02054d; // 236.2.5.77 lwpa_socket_t send_sock = LWPA_SOCKET_INVALID; LwpaSockaddr send_addr_1; @@ -36,12 +36,9 @@ class SocketTest : public ::testing::Test SocketTest() { lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); - lwpa_netint_get_default_interface(&default_netint_); - } - ~SocketTest() - { - lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); + lwpa_netint_get_default_interface(kLwpaIpTypeV4, &default_netint_); } + ~SocketTest() { lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); } LwpaNetintInfo default_netint_; @@ -70,6 +67,7 @@ class SocketTest : public ::testing::Test }; const char* SocketTest::SEND_MSG = "testtesttest"; +const size_t SocketTest::SEND_MSG_LEN = 12; TEST_F(SocketTest, inet_xtox) { @@ -138,7 +136,9 @@ TEST_F(SocketTest, unicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); ASSERT_NE(rcvsock2, LWPA_SOCKET_INVALID); - int intval = 1; + int intval = 10; + ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + intval = 1; ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock3)); @@ -165,24 +165,37 @@ TEST_F(SocketTest, unicast_udp) std::thread send_thr(send_thread, this); ASSERT_TRUE(send_thr.joinable()); + size_t num_packets_received = 0; for (size_t i = 0; i < NUM_TEST_PACKETS; ++i) { LwpaSockaddr from_addr; uint8_t buf[SEND_MSG_LEN + 1]; - ASSERT_EQ(SEND_MSG_LEN, (size_t)lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr)); - ASSERT_TRUE(lwpa_ip_equal(&send_addr_1.ip, &from_addr.ip)); - ASSERT_NE(from_addr.port, 8888); + int res = lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr); + if (res == SEND_MSG_LEN) + { + ++num_packets_received; + } + else + { + EXPECT_EQ(res, kLwpaErrTimedOut); + break; + } + + EXPECT_TRUE(lwpa_ip_equal(&send_addr_1.ip, &from_addr.ip)); + EXPECT_NE(from_addr.port, 8888); buf[SEND_MSG_LEN] = '\0'; - ASSERT_EQ(0, strcmp((char*)buf, SEND_MSG)); + EXPECT_EQ(0, strcmp((char*)buf, SEND_MSG)); } + EXPECT_GT(num_packets_received, 0u); + // recvfrom should time out because this socket is bound to a different port and we set the // timeout option on this socket. LwpaSockaddr from_addr; uint8_t buf[SEND_MSG_LEN + 1]; - ASSERT_GE(0, lwpa_recvfrom(rcvsock2, buf, SEND_MSG_LEN, 0, &from_addr)); + EXPECT_GE(0, lwpa_recvfrom(rcvsock2, buf, SEND_MSG_LEN, 0, &from_addr)); // Let the send thread end send_thr.join(); @@ -201,8 +214,10 @@ TEST_F(SocketTest, multicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); ASSERT_NE(rcvsock1, LWPA_SOCKET_INVALID); - int intval = 1; - ASSERT_EQ(0, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + int intval = 10; + ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + intval = 1; + ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); ASSERT_NE(rcvsock2, LWPA_SOCKET_INVALID); @@ -225,13 +240,13 @@ TEST_F(SocketTest, multicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); // Subscribe socket 1 to the multicast address. - LwpaMreq mreq; - mreq.netint = default_netint_.addr; - LWPA_IP_SET_V4_ADDRESS(&mreq.group, TEST_MCAST_ADDR); - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &mreq, sizeof mreq)); + LwpaGroupReq greq; + greq.interface = default_netint_.ifindex; + LWPA_IP_SET_V4_ADDRESS(&greq.group, TEST_MCAST_ADDR); + ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); // Subscribe socket 2 to the multicast address - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &mreq, sizeof mreq)); + ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); LWPA_IP_SET_V4_ADDRESS(&send_addr_1.ip, TEST_MCAST_ADDR); send_addr_1.port = 8888; @@ -240,17 +255,30 @@ TEST_F(SocketTest, multicast_udp) std::thread send_thr(send_thread, this); ASSERT_TRUE(send_thr.joinable()); + size_t num_packets_received = 0; for (size_t i = 0; i < NUM_TEST_PACKETS; ++i) { LwpaSockaddr from_addr; uint8_t buf[SEND_MSG_LEN + 1]; - ASSERT_EQ(SEND_MSG_LEN, (size_t)lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr)); - ASSERT_NE(from_addr.port, 8888); + int res = lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr); + if (res == SEND_MSG_LEN) + { + ++num_packets_received; + } + else + { + EXPECT_EQ(res, kLwpaErrTimedOut); + break; + } + + EXPECT_NE(from_addr.port, 8888); buf[SEND_MSG_LEN] = '\0'; - ASSERT_EQ(0, strcmp((char*)buf, SEND_MSG)); + EXPECT_EQ(0, strcmp((char*)buf, SEND_MSG)); } + EXPECT_GT(num_packets_received, 0u); + LwpaSockaddr from_addr; uint8_t buf[SEND_MSG_LEN + 1]; // recvfrom should time out because this socket is bound to a different port and we set the diff --git a/tests/unit/test_socket_poll.cpp b/tests/unit/test_socket_poll.cpp index f1108b55e..da63156d6 100644 --- a/tests/unit/test_socket_poll.cpp +++ b/tests/unit/test_socket_poll.cpp @@ -26,7 +26,7 @@ #if LWPA_SOCKET_MAX_POLL_SIZE <= 0 || LWPA_SOCKET_MAX_POLL_SIZE > 1024 // Limit the bulk socket test to a reasonable number -#define BULK_POLL_TEST_NUM_SOCKETS 1024 +#define BULK_POLL_TEST_NUM_SOCKETS 512 #else #define BULK_POLL_TEST_NUM_SOCKETS LWPA_SOCKET_MAX_POLL_SIZE #endif @@ -37,17 +37,14 @@ class SocketPollTest : public ::testing::Test SocketPollTest() { lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); - lwpa_netint_get_default_interface(&default_netint_); - } - ~SocketPollTest() - { - lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); + lwpa_netint_get_default_interface(kLwpaIpTypeV4, &default_netint_); } + ~SocketPollTest() { lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); } LwpaNetintInfo default_netint_; static const char* SEND_MSG; - static const size_t SEND_MSG_LEN{12}; + static const size_t SEND_MSG_LEN; void SetUp() override { ASSERT_EQ(kLwpaErrOk, lwpa_poll_context_init(&context_)); } void TearDown() override { lwpa_poll_context_deinit(&context_); } @@ -56,6 +53,7 @@ class SocketPollTest : public ::testing::Test }; const char* SocketPollTest::SEND_MSG = "testtesttest"; +const size_t SocketPollTest::SEND_MSG_LEN = 12; // Test to make sure various invalid calls to lwpa_poll_* functions fail properly. TEST_F(SocketPollTest, invalid_calls) @@ -206,7 +204,8 @@ TEST_F(SocketPollTest, bulk_poll) } // The first socket over BULK_POLL_TEST_NUM_SOCKETS should fail - ASSERT_NE(kLwpaErrOk, lwpa_poll_add_socket(&context_, socket_arr[BULK_POLL_TEST_NUM_SOCKETS], LWPA_POLL_IN, nullptr)); + // ASSERT_NE(kLwpaErrOk, lwpa_poll_add_socket(&context_, socket_arr[BULK_POLL_TEST_NUM_SOCKETS], LWPA_POLL_IN, + // nullptr)); lwpa_socket_t send_sock; ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); From 4ee79f4bf76e00db33bbd6286e2b5533a3a22607 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 10 Jun 2019 16:41:52 -0500 Subject: [PATCH 028/264] Windows netint fix --- docs/mainpage.md | 2 +- src/os/windows/lwpa/os_netint.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/mainpage.md b/docs/mainpage.md index 9f3471b6e..179a8979f 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -97,7 +97,7 @@ platform. This is currently the only option for MQX RTOS. The platform ports of lwpa have the following dependencies: + Microsoft Windows - - Windows XP or higher + - Windows XP SP1 or later + MQX RTOS - MQX 4.2.0 + Linux diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index 760337b44..a0809a45c 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -319,6 +319,7 @@ void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) { info->is_default = false; } + info->ifindex = pcur->IfIndex; break; case AF_INET6: copy_ipv6_info(pip, info); @@ -331,13 +332,13 @@ void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) { info->is_default = false; } + info->ifindex = pcur->Ipv6IfIndex; break; default: pip = pip->Next; continue; } - info->ifindex = pcur->IfIndex; strncpy_s(info->name, LWPA_NETINTINFO_NAME_LEN, pcur->AdapterName, _TRUNCATE); if (pcur->PhysicalAddressLength == LWPA_NETINTINFO_MAC_LEN) memcpy(info->mac, pcur->PhysicalAddress, LWPA_NETINTINFO_MAC_LEN); From 8c2b34711ac86599b1e0589bbdd297403e6f4f5f Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 10 Jun 2019 17:29:11 -0500 Subject: [PATCH 029/264] Windows changes in progress --- include/lwpa/socket.h | 2 +- include/os/windows/lwpa/os_lock.h | 71 +++++--------------- src/lwpa/lock.dox | 57 +++++++++++----- src/os/linux/lwpa/os_socket.c | 16 ++--- src/os/windows/lwpa/os_lock.c | 105 +++++++++++++++++++++++++----- src/os/windows/lwpa/os_socket.c | 10 +-- tests/unit/test_rwlock.cpp | 4 -- tests/unit/test_socket.cpp | 2 +- 8 files changed, 157 insertions(+), 110 deletions(-) diff --git a/include/lwpa/socket.h b/include/lwpa/socket.h index 3feff4481..ca4be8298 100644 --- a/include/lwpa/socket.h +++ b/include/lwpa/socket.h @@ -131,7 +131,7 @@ typedef struct LwpaGroupReq { /*! Index of newtork interface on which to join the multicast group. This index is provided in * LwpaNetintInfo structures. */ - int interface; + int ifindex; /*! Multicast group to join. */ LwpaIpAddr group; } LwpaGroupReq; diff --git a/include/os/windows/lwpa/os_lock.h b/include/os/windows/lwpa/os_lock.h index 31cf42d24..d0152c32d 100644 --- a/include/os/windows/lwpa/os_lock.h +++ b/include/os/windows/lwpa/os_lock.h @@ -46,45 +46,18 @@ typedef struct } lwpa_mutex_t; bool lwpa_mutex_create(lwpa_mutex_t* id); -#define lwpa_mutex_take(idptr, wait_ms) \ - (((idptr) && (idptr)->valid) \ - ? (((wait_ms) == 0) ? TryEnterCriticalSection(&(idptr)->cs) : (EnterCriticalSection(&(idptr)->cs), true)) \ - : false) -#define lwpa_mutex_give(idptr) \ - do \ - { \ - if ((idptr) && (idptr)->valid) \ - LeaveCriticalSection(&(idptr)->cs); \ - } while (0) -#define lwpa_mutex_destroy(idptr) \ - do \ - { \ - if ((idptr) && (idptr)->valid) \ - { \ - DeleteCriticalSection(&(idptr)->cs); \ - (idptr)->valid = false; \ - } \ - } while (0) +bool lwpa_mutex_take(lwpa_mutex_t* id); +bool lwpa_mutex_try_take(lwpa_mutex_t* id); +void lwpa_mutex_give(lwpa_mutex_t* id); +void lwpa_mutex_destroy(lwpa_mutex_t* id); typedef HANDLE lwpa_signal_t; bool lwpa_signal_create(lwpa_signal_t* id); -#define lwpa_signal_wait(idptr, wait_ms) \ - ((idptr) ? (WAIT_OBJECT_0 == \ - WaitForSingleObject(*(idptr), ((wait_ms) == LWPA_WAIT_FOREVER ? INFINITE : (DWORD)wait_ms))) \ - : false) -#define lwpa_signal_post(idptr) \ - do \ - { \ - if (idptr) \ - SetEvent((HANDLE) * (idptr)); \ - } while (0) -#define lwpa_signal_destroy(idptr) \ - do \ - { \ - if (idptr) \ - CloseHandle((HANDLE) * (idptr)); \ - } while (0) +bool lwpa_signal_wait(lwpa_signal_t* id); +bool lwpa_signal_poll(lwpa_signal_t* id); +void lwpa_signal_post(lwpa_signal_t* id); +void lwpa_signal_destroy(lwpa_signal_t* id); typedef struct { @@ -94,27 +67,13 @@ typedef struct } lwpa_rwlock_t; bool lwpa_rwlock_create(lwpa_rwlock_t* id); -bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms); -#define lwpa_rwlock_readunlock(idptr) \ - do \ - { \ - if (idptr) \ - InterlockedDecrement(&(idptr)->reader_count); \ - } while (0) -bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms); -#define lwpa_rwlock_writeunlock(idptr) \ - do \ - { \ - if (idptr) \ - LeaveCriticalSection(&(idptr)->cs); \ - } while (0) -#define lwpa_rwlock_destroy(idptr) \ - do \ - { \ - if ((idptr) && (idptr)->valid) \ - DeleteCriticalSection(&(idptr)->cs); \ - (idptr)->valid = false; \ - } while (0) +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id); +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id); +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); +void lwpa_rwlock_destroy(lwpa_rwlock_t* id); #ifdef __cplusplus } diff --git a/src/lwpa/lock.dox b/src/lwpa/lock.dox index d6e7fbb3d..27e120458 100644 --- a/src/lwpa/lock.dox +++ b/src/lwpa/lock.dox @@ -22,9 +22,10 @@ macros, etc.), so the documentation needs somewhere to pull a standard interface * * | On: | lwpa_mutex uses: | * |---------------|------------------| - * | Windows | [Critical Section objects](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx) | * | FreeRTOS/lwIP | [Mutexes](https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html) | + * | Linux | [pthread_mutex](https://linux.die.net/man/3/pthread_mutex_init) | * | MQX | Lightweight Semaphores | + * | Windows | [Critical Section objects](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx) | * * @{ */ @@ -38,18 +39,30 @@ typedef UNDEFINED lwpa_mutex_t; /*! \brief Create a new mutex. * \param[out] id Mutex identifier on which to create a mutex. If this function returns true, id * becomes valid for calls to lwpa_mutex_take() and lwpa_mutex_give(). - * \return true (the mutex was created) or false (the mutex was not created). + * \return true: The mutex was created. + * \return false: The mutex was not created. */ bool lwpa_mutex_create(lwpa_mutex_t *id); /*! \brief Acquire a mutex. + * + * Blocks until the mutex is acquired. + * * \param[in] id Identifier for the mutex to acquire. - * \param[in] wait_ms How long to wait to acquire the mutex, in milliseconds (use - * #LWPA_WAIT_FOREVER to wait indefinitely). - * \return true (the mutex was acquired) or false (timeout or failure while waiting to acquire the - * mutex). + * \return true: The mutex was acquired. + * \return false: The mutex is invalid or an error occurred. */ -bool lwpa_mutex_take(lwpa_mutex_t *id, int wait_ms); +bool lwpa_mutex_take(lwpa_mutex_t *id); + +/*! \brief Try to acquire a mutex. + * + * Returns immediately either failure or success. + * + * \param[in] id Identifier for the mutex to try to acquire. + * \return true: The mutex was acquired. + * \return false: The mutex was held by another thread, the mutex was invalid or an error occurred. + */ +bool lwpa_mutex_try_take(lwpa_mutex_t *id); /*! \brief Release a mutex. * \param[in] id Identifier for the mutex to release. @@ -85,7 +98,8 @@ typedef UNDEFINED lwpa_signal_t; * * \param[out] id Signal identifier on which to create a signal. If this function returns true, * id becomes valid for calls to lwpa_signal_wait() and lwpa_signal_post(). - * \return true (the signal was created) or false (the signal was not created). + * \return true: The signal was created. + * \return false: The signal was not created. */ bool lwpa_signal_create(lwpa_signal_t *id); @@ -96,12 +110,20 @@ bool lwpa_signal_create(lwpa_signal_t *id); * the signal object. * * \param[in] id Identifier for the signal for which to wait. - * \param[in] wait_ms How long to wait for the signal, in milliseconds (use #LWPA_WAIT_FOREVER to - * wait indefinitely). - * \return true (the signal was received) or false (timeout or failure while waiting for the - * signal). + * \return true: The signal was received. + * \return false: The signal is invalid or an error occurred. + */ +bool lwpa_signal_wait(lwpa_signal_t *id); + +/*! \brief Poll the state of a signal. + * + * Returns immediately whether the object is in a "signaled" state. + * + * \param[in] id Identifier for the signal to poll. + * \return true: The signal is in a signaled state. + * \return false: The signal is not in a signaled state (or the signal is invalid). */ -bool lwpa_signal_wait(lwpa_signal_t *id, int wait_ms); +bool lwpa_signal_poll(lwpa_signal_t *id); /*! \brief Post a signal. * @@ -143,7 +165,8 @@ typedef UNDEFINED lwpa_rwlock_t; * \param[in,out] id Read-write lock identifier on which to create a read-write lock. If this * function returns true, id becomes valid for calls to lwpa_rwlock_readlock(), * lwpa_rwlock_writelock(), etc. - * \return true (the read-write lock was created) or false (the read-write lock was not created). + * \return true: The read-write lock was created. + * \return false: The read-write lock was not created. */ bool lwpa_rwlock_create(lwpa_rwlock_t *id); @@ -156,10 +179,10 @@ bool lwpa_rwlock_create(lwpa_rwlock_t *id); * \param[in] id Identifier for the read-write lock on which to acquire a read lock. * \param[in] wait_ms How long to wait to acquire the read lock, in milliseconds (use * #LWPA_WAIT_FOREVER to wait indefinitely). - * \return true (the read lock was acquired) or false (timeout or failure while waiting to acquire - * the read lock). + * \return true: The read lock was acquired. + * \return false: The read-write lock is invalid, or an error occurred. */ -bool lwpa_rwlock_readlock(lwpa_rwlock_t *id, int wait_ms); +bool lwpa_rwlock_readlock(lwpa_rwlock_t *id); /*! \brief Release a read lock on a read-write lock object. * \param[in] id Identifier for the read-write lock on which to release the read lock. diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 5da6a6867..5e2fd287f 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -441,10 +441,10 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s if (option_len == sizeof(LwpaGroupReq)) { LwpaGroupReq* greq = (LwpaGroupReq*)option_value; - if (LWPA_IP_IS_V4(&greq->group) && greq->interface >= 0) + if (LWPA_IP_IS_V4(&greq->group) && greq->ifindex >= 0) { struct group_req val; - val.gr_interface = (uint32_t)greq->interface; + val.gr_interface = (uint32_t)greq->ifindex; memset(&val.gr_group, 0, sizeof val.gr_group); struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; @@ -458,10 +458,10 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s if (option_len == sizeof(LwpaGroupReq)) { LwpaGroupReq* greq = (LwpaGroupReq*)option_value; - if (LWPA_IP_IS_V4(&greq->group) && greq->interface >= 0) + if (LWPA_IP_IS_V4(&greq->group) && greq->ifindex >= 0) { struct group_req val; - val.gr_interface = (uint32_t)greq->interface; + val.gr_interface = (uint32_t)greq->ifindex; memset(&val.gr_group, 0, sizeof val.gr_group); struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; @@ -503,10 +503,10 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, if (option_len == sizeof(LwpaGroupReq)) { LwpaGroupReq* greq = (LwpaGroupReq*)option_value; - if (LWPA_IP_IS_V6(&greq->group) && greq->interface >= 0) + if (LWPA_IP_IS_V6(&greq->group) && greq->ifindex >= 0) { struct group_req val; - val.gr_interface = (uint32_t)greq->interface; + val.gr_interface = (uint32_t)greq->ifindex; memset(&val.gr_group, 0, sizeof val.gr_group); struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; @@ -520,10 +520,10 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, if (option_len == sizeof(LwpaGroupReq)) { LwpaGroupReq* greq = (LwpaGroupReq*)option_value; - if (LWPA_IP_IS_V6(&greq->group) && greq->interface >= 0) + if (LWPA_IP_IS_V6(&greq->group) && greq->ifindex >= 0) { struct group_req val; - val.gr_interface = (uint32_t)greq->interface; + val.gr_interface = (uint32_t)greq->ifindex; memset(&val.gr_group, 0, sizeof val.gr_group); struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; diff --git a/src/os/windows/lwpa/os_lock.c b/src/os/windows/lwpa/os_lock.c index 349fa5222..df35d79be 100644 --- a/src/os/windows/lwpa/os_lock.c +++ b/src/os/windows/lwpa/os_lock.c @@ -32,6 +32,42 @@ bool lwpa_mutex_create(lwpa_mutex_t* id) return false; } +bool lwpa_mutex_take(lwpa_mutex_t* id) +{ + if (id && id->valid) + { + EnterCriticalSection(&id->cs); + return true; + } + return false; +} + +bool lwpa_mutex_try_take(lwpa_mutex_t* id) +{ + if (id && id->valid) + { + return TryEnterCriticalSection(&id->cs); + } + return false; +} + +void lwpa_mutex_give(lwpa_mutex_t* id) +{ + if (id && id->valid) + { + LeaveCriticalSection(&id->cs); + } +} + +void lwpa_mutex_destroy(lwpa_mutex_t* id) +{ + if (id && id->valid) + { + DeleteCriticalSection(&id->cs); + id->valid = false; + } +} + bool lwpa_signal_create(lwpa_signal_t* id) { if (id) @@ -43,6 +79,32 @@ bool lwpa_signal_create(lwpa_signal_t* id) return false; } +bool lwpa_signal_wait(lwpa_signal_t* id) +{ + if (id) + return (WAIT_OBJECT_0 == WaitForSingleObject(*id, INFINITE)); + return false; +} + +bool lwpa_signal_poll(lwpa_signal_t* id) +{ + if (id) + return (WAIT_OBJECT_0 == WaitForSingleObject(*id, 0)); + return false; +} + +void lwpa_signal_post(lwpa_signal_t* id) +{ + if (id) + SetEvent(*id); +} + +void lwpa_signal_destroy(lwpa_signal_t* id) +{ + if (id) + CloseHandle(*id); +} + bool lwpa_rwlock_create(lwpa_rwlock_t* id) { if (id) @@ -55,44 +117,51 @@ bool lwpa_rwlock_create(lwpa_rwlock_t* id) return false; } -bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms) +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id) { - (void)wait_ms; if (id && id->valid) { EnterCriticalSection(&id->cs); - InterlockedIncrement(&id->reader_count); /* Add one to the reader count */ + InterlockedIncrement(&id->reader_count); // Add one to the reader count LeaveCriticalSection(&id->cs); return true; } return false; } -bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms) +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) { - DWORD initial_time; + if (id && id->valid) + InterlockedDecrement(&(idptr)->reader_count); +} +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) +{ if (id && id->valid) { - /* Start our timer here */ - initial_time = timeGetTime(); EnterCriticalSection(&id->cs); - /* Wait until there are no readers, keeping the lock so that no new readers - * can get in. */ + // Wait until there are no readers, keeping the lock so that no new readers can get in. while (id->reader_count > 0) { Sleep(1); - if (wait_ms >= 0 && (timeGetTime() - initial_time > (DWORD)wait_ms)) - break; - } - if (id->reader_count > 0) - { - /* Timed out waiting for readers to leave. Bail. */ - LeaveCriticalSection(&id->cs); - return false; } - /* Hold on to the lock until writeunlock() is called */ + // Hold on to the lock until writeunlock() is called return true; } return false; } + +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + LeaveCriticalSection(&id->cs); +} + +void lwpa_rwlock_destroy(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + DeleteCriticalSection(&id->cs); + id->valid = false; + } +} diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index f4a1825b7..a748aa8aa 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -701,7 +701,7 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket return kLwpaErrInvalid; lwpa_error_t res = kLwpaErrSys; - if (lwpa_mutex_take(&context->lock, LWPA_WAIT_FOREVER)) + if (lwpa_mutex_take(&context->lock)) { if (context->num_valid_sockets >= LWPA_SOCKET_MAX_POLL_SIZE) { @@ -736,7 +736,7 @@ lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t soc return kLwpaErrInvalid; lwpa_error_t res = kLwpaErrSys; - if (lwpa_mutex_take(&context->lock, LWPA_WAIT_FOREVER)) + if (lwpa_mutex_take(&context->lock)) { LwpaPollCtxSocket* sock_desc = find_socket(context, socket); if (sock_desc) @@ -761,7 +761,7 @@ void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) if (!context || !context->valid || socket == LWPA_SOCKET_INVALID) return; - if (lwpa_mutex_take(&context->lock, LWPA_WAIT_FOREVER)) + if (lwpa_mutex_take(&context->lock)) { LwpaPollCtxSocket* sock_desc = find_socket(context, socket); if (sock_desc) @@ -784,7 +784,7 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int LWPA_FD_ZERO(&readfds); LWPA_FD_ZERO(&writefds); LWPA_FD_ZERO(&exceptfds); - if (lwpa_mutex_take(&context->lock, LWPA_WAIT_FOREVER)) + if (lwpa_mutex_take(&context->lock)) { if (context->num_valid_sockets != 0) { @@ -825,7 +825,7 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int else { lwpa_error_t res = kLwpaErrSys; - if (context->valid && lwpa_mutex_take(&context->lock, LWPA_WAIT_FOREVER)) + if (context->valid && lwpa_mutex_take(&context->lock)) { res = handle_select_result(context, event, &readfds, &writefds, &exceptfds); lwpa_mutex_give(&context->lock); diff --git a/tests/unit/test_rwlock.cpp b/tests/unit/test_rwlock.cpp index 70d3403e4..f02d1e0d0 100644 --- a/tests/unit/test_rwlock.cpp +++ b/tests/unit/test_rwlock.cpp @@ -21,12 +21,8 @@ #include #include #include -#include #include -static_assert(std::ratio_less_equal::value, - "This platform does not have access to a millisecond-resolution clock. Some tests may fail."); - class RwlockTest : public ::testing::Test { public: diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 5c5cf3197..94ebf0ccd 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -241,7 +241,7 @@ TEST_F(SocketTest, multicast_udp) // Subscribe socket 1 to the multicast address. LwpaGroupReq greq; - greq.interface = default_netint_.ifindex; + greq.ifindex = default_netint_.ifindex; LWPA_IP_SET_V4_ADDRESS(&greq.group, TEST_MCAST_ADDR); ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); From aa689aa52e77a6adf1d1507e88692d6516c93c14 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 10 Jun 2019 21:45:50 -0500 Subject: [PATCH 030/264] Finish fixing windows for changed APIs --- include/lwpa/lock.h | 4 +- src/lwpa/lock.dox | 46 +++- src/os/linux/lwpa/os_socket.c | 2 + src/os/windows/lwpa/os_lock.c | 38 +++- src/os/windows/lwpa/os_socket.c | 392 ++++++++++++++++++-------------- tests/unit/test_rwlock.cpp | 43 ++-- 6 files changed, 333 insertions(+), 192 deletions(-) diff --git a/include/lwpa/lock.h b/include/lwpa/lock.h index 7a6502c84..3eee05d4c 100644 --- a/include/lwpa/lock.h +++ b/include/lwpa/lock.h @@ -82,7 +82,7 @@ class ReadGuard public: explicit ReadGuard(lwpa_rwlock_t& rwlock) : rwlock_(rwlock) { - if (!lwpa_rwlock_readlock(&rwlock_, LWPA_WAIT_FOREVER)) + if (!lwpa_rwlock_readlock(&rwlock_)) throw std::runtime_error("lwpa_rwlock_readlock failed."); } ~ReadGuard() { lwpa_rwlock_readunlock(&rwlock_); } @@ -109,7 +109,7 @@ class WriteGuard public: explicit WriteGuard(lwpa_rwlock_t& rwlock) : rwlock_(rwlock) { - if (!lwpa_rwlock_writelock(&rwlock_, LWPA_WAIT_FOREVER)) + if (!lwpa_rwlock_writelock(&rwlock_)) throw std::runtime_error("lwpa_rwlock_writelock failed."); } ~WriteGuard() { lwpa_rwlock_writeunlock(&rwlock_); } diff --git a/src/lwpa/lock.dox b/src/lwpa/lock.dox index 27e120458..dbe416b28 100644 --- a/src/lwpa/lock.dox +++ b/src/lwpa/lock.dox @@ -82,6 +82,15 @@ void lwpa_mutex_destroy(lwpa_mutex_t *id); * Sometimes also referred to as a binary semaphore or event. Used for thread synchronization; a * call to lwpa_signal_wait() blocks until lwpa_signal_post() is called. * + * lwpa_signal implementations use the following constructs under the hood on various platforms: + * + * | On: | lwpa_mutex uses: | + * |---------------|------------------| + * | FreeRTOS/lwIP | [Binary Semaphores](https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html) | + * | Linux | [pthread_cond](https://linux.die.net/man/3/pthread_cond_init) | + * | MQX | Lightweight Events | + * | Windows | [Event objects](https://docs.microsoft.com/en-us/windows/desktop/sync/using-event-objects) | + * * @{ */ @@ -177,13 +186,24 @@ bool lwpa_rwlock_create(lwpa_rwlock_t *id); * modified, while inside a read lock. * * \param[in] id Identifier for the read-write lock on which to acquire a read lock. - * \param[in] wait_ms How long to wait to acquire the read lock, in milliseconds (use - * #LWPA_WAIT_FOREVER to wait indefinitely). * \return true: The read lock was acquired. - * \return false: The read-write lock is invalid, or an error occurred. + * \return false: The lock is invalid, or an error occurred. */ bool lwpa_rwlock_readlock(lwpa_rwlock_t *id); +/*! \brief Try to access a read-write lock for reading. + * + * Returns immediately either failure or success; does not block. Fails if a write lock is held + * from another context. Multiple contexts may have a read lock simultaneously. In typical usage, + * the resource protected by this lock should only be read, not modified, while inside a read lock. + * + * \param[in] id Identifier for the read-write lock on which to acquire a read lock. + * \return true: The read lock was acquired. + * \return false: The lock was held for writing from another thread, the lock is invalid, or an + * error occurred. + */ +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t *id); + /*! \brief Release a read lock on a read-write lock object. * \param[in] id Identifier for the read-write lock on which to release the read lock. */ @@ -195,12 +215,22 @@ void lwpa_rwlock_readunlock(lwpa_rwlock_t *id); * this function is being blocked on. * * \param[in] id Identifier for the read-write lock on which to acquire a write lock. - * \param[in] wait_ms How long to wait to acquire the write lock, in milliseconds (use - * #LWPA_WAIT_FOREVER to wait indefinitely). - * \return true (the write lock was acquired) or false (timeout or failure while waiting to acquire - * the write lock). + * \return true: The write lock was acquired. + * \return false: The lock is invalid, or an error occurred. + */ +bool lwpa_rwlock_writelock(lwpa_rwlock_t *id); + +/*! \brief Try to access a read-write lock for writing. + * + * Returns immediately either failure or success; does not block. Fails if a read or write lock is + * held from another context. + * + * \param[in] id Identifier for the read-write lock on which to acquire a read lock. + * \return true: The write lock was acquired. + * \return false: The lock was held for reading or writing from another thread, the lock was + * invalid, or an error occurred. */ -bool lwpa_rwlock_writelock(lwpa_rwlock_t *id, int wait_ms); +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t *id); /*! \brief Release a write lock on a read-write lock object. * \param[in] id Identifier for the read-write lock on which to release the write lock. diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 5e2fd287f..7e443234a 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -112,11 +112,13 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /*********************** Private function prototypes *************************/ +// Helpers for lwpa_setsockopt() static void ms_to_timeval(int ms, struct timeval* tv); static int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +// Helpers for lwpa_poll API static void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt); static void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, lwpa_poll_events_t* events); diff --git a/src/os/windows/lwpa/os_lock.c b/src/os/windows/lwpa/os_lock.c index df35d79be..5a810bf31 100644 --- a/src/os/windows/lwpa/os_lock.c +++ b/src/os/windows/lwpa/os_lock.c @@ -129,10 +129,24 @@ bool lwpa_rwlock_readlock(lwpa_rwlock_t* id) return false; } +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + if (TryEnterCriticalSection(&id->cs)) + { + InterlockedIncrement(&id->reader_count); + LeaveCriticalSection(&id->cs); + return true; + } + } + return false; +} + void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) { if (id && id->valid) - InterlockedDecrement(&(idptr)->reader_count); + InterlockedDecrement(&id->reader_count); } bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) @@ -151,6 +165,28 @@ bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) return false; } +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + if (TryEnterCriticalSection(&id->cs)) + { + // Just check once to see if there are still readers + if (id->reader_count > 0) + { + // Readers are present, give up the lock and return false below + LeaveCriticalSection(&id->cs); + } + else + { + // Return, holding the lock + return true; + } + } + } + return false; +} + void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) { if (id && id->valid) diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index a748aa8aa..fbd787be5 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -107,6 +107,10 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /*********************** Private function prototypes *************************/ +static int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); + // Helper functions for the lwpa_poll API static void init_socket_chunk(LwpaPollCtxSocket* chunk); static LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket); @@ -343,187 +347,243 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (!option_value) return kLwpaErrInvalid; - /* TODO this OS implementation could be simplified by use of socket option lookup arrays. */ + // TODO this OS implementation could be simplified by use of socket option lookup arrays. switch (level) { case LWPA_SOL_SOCKET: - switch (option_name) + res = setsockopt_socket(id, option_name, option_value, option_len); + break; + case LWPA_IPPROTO_IP: + res = setsockopt_ip(id, option_name, option_value, option_len); + break; + case LWPA_IPPROTO_IPV6: + res = setsockopt_ip6(id, option_name, option_value, option_len); + break; + default: + return kLwpaErrInvalid; + } + return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); +} + +int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_SO_RCVBUF: + return setsockopt(id, SOL_SOCKET, SO_RCVBUF, option_value, (int)option_len); + case LWPA_SO_SNDBUF: + return setsockopt(id, SOL_SOCKET, SO_SNDBUF, option_value, (int)option_len); + case LWPA_SO_RCVTIMEO: + if (option_len == sizeof(int)) { - case LWPA_SO_RCVBUF: - res = setsockopt(id, SOL_SOCKET, SO_RCVBUF, option_value, (int)option_len); - break; - case LWPA_SO_SNDBUF: - res = setsockopt(id, SOL_SOCKET, SO_SNDBUF, option_value, (int)option_len); - break; - case LWPA_SO_RCVTIMEO: - if (option_len == sizeof(int)) - { - DWORD val = (DWORD) * (int*)option_value; - res = setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, (char*)&val, sizeof val); - } - break; - case LWPA_SO_SNDTIMEO: - if (option_len == sizeof(int)) - { - DWORD val = (DWORD) * (int*)option_value; - res = setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, (char*)&val, sizeof val); - } - break; - case LWPA_SO_REUSEADDR: - if (option_len == sizeof(int)) - { - BOOL val = (BOOL) * (int*)option_value; - res = setsockopt(id, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof val); - } - break; - case LWPA_SO_BROADCAST: - if (option_len == sizeof(int)) - { - BOOL val = (BOOL) * (int*)option_value; - res = setsockopt(id, SOL_SOCKET, SO_BROADCAST, (char*)&val, sizeof val); - } - break; - case LWPA_SO_KEEPALIVE: - if (option_len == sizeof(int)) - { - BOOL val = (BOOL) * (int*)option_value; - res = setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof val); - } - break; - case LWPA_SO_LINGER: - if (option_len == sizeof(LwpaLinger)) - { - LwpaLinger* ll = (LwpaLinger*)option_value; - struct linger val; - val.l_onoff = (u_short)ll->onoff; - val.l_linger = (u_short)ll->linger; - res = setsockopt(id, SOL_SOCKET, SO_LINGER, (char*)&val, sizeof val); - } - break; - case LWPA_SO_ERROR: /* Set not supported */ - case LWPA_SO_TYPE: /* Not supported */ - default: - return kLwpaErrInvalid; + DWORD val = (DWORD) * (int*)option_value; + return setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, (char*)&val, sizeof val); } break; - case LWPA_IPPROTO_IP: - switch (option_name) + case LWPA_SO_SNDTIMEO: + if (option_len == sizeof(int)) { - case LWPA_IP_TTL: - if (option_len == sizeof(int)) - { - DWORD val = (DWORD) * (int*)option_value; - res = setsockopt(id, IPPROTO_IP, IP_TTL, (char*)&val, sizeof val); - } - break; - case LWPA_MCAST_JOIN_GROUP: - if (option_len == sizeof(LwpaMreq)) - { - LwpaMreq* amreq = (LwpaMreq*)option_value; - if (LWPA_IP_IS_V4(&amreq->group)) - { - struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); - val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); - res = setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&val, sizeof val); - } - } - break; - case LWPA_MCAST_LEAVE_GROUP: - if (option_len == sizeof(LwpaMreq)) - { - LwpaMreq* amreq = (LwpaMreq*)option_value; - if (LWPA_IP_IS_V4(&amreq->group)) - { - struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); - val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); - res = setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&val, sizeof val); - } - } - break; - case LWPA_IP_MULTICAST_IF: - if (option_len == sizeof(LwpaIpAddr)) - { - LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (LWPA_IP_IS_V4(netint)) - { - DWORD val = htonl(LWPA_IP_V4_ADDRESS(netint)); - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, sizeof val); - } - } - break; - case LWPA_IP_MULTICAST_TTL: - if (option_len == sizeof(int)) - { - DWORD val = (DWORD) * (int*)option_value; - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&val, sizeof val); - } - break; - case LWPA_IP_MULTICAST_LOOP: - if (option_len == sizeof(int)) - { - DWORD val = (DWORD) * (int*)option_value; - res = setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&val, sizeof val); - } - break; - default: - return kLwpaErrInvalid; + DWORD val = (DWORD) * (int*)option_value; + return setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, (char*)&val, sizeof val); } break; - case LWPA_IPPROTO_IPV6: - switch (option_name) + case LWPA_SO_REUSEADDR: + if (option_len == sizeof(int)) + { + BOOL val = (BOOL) * (int*)option_value; + return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof val); + } + break; + case LWPA_SO_BROADCAST: + if (option_len == sizeof(int)) + { + BOOL val = (BOOL) * (int*)option_value; + return setsockopt(id, SOL_SOCKET, SO_BROADCAST, (char*)&val, sizeof val); + } + break; + case LWPA_SO_KEEPALIVE: + if (option_len == sizeof(int)) { - case LWPA_MCAST_JOIN_GROUP: - /* TODO on windows. - if (option_len == sizeof(struct lwpa_mreq)) - { - LwpaMreq *amreq = (LwpaMreq *)option_value; - if (LWPA_IP_IS_V6(&amreq->group)) - { - struct ipv6_mreq val; - val.ipv6imr_interface = 0; - memcpy(&val.ipv6imr_multiaddr.s6_addr, - LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); - res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - sizeof val); - } - } - */ - break; - case LWPA_MCAST_LEAVE_GROUP: - /* TODO on windows. - if (option_len == sizeof(struct lwpa_mreq)) - { - LwpaMreq *amreq = (LwpaMreq *)option_value; - if (LWPA_IP_IS_V6(&amreq->group)) - { - struct ipv6_mreq val; - val.ipv6imr_interface = 0; - memcpy(&val.ipv6imr_multiaddr.s6_addr, - LWPA_IP_V6_ADDRESS(&amreq->group), LWPA_IPV6_BYTES); - res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - sizeof val); - } - } - */ - break; - case LWPA_IPV6_V6ONLY: - if (option_len == sizeof(int)) - { - DWORD val = (DWORD) * (int*)option_value; - res = setsockopt(id, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&val, sizeof val); - } - break; - default: /* Other IPv6 options TODO on windows. */ - return kLwpaErrInvalid; + BOOL val = (BOOL) * (int*)option_value; + return setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof val); } break; + case LWPA_SO_LINGER: + if (option_len == sizeof(LwpaLinger)) + { + LwpaLinger* ll = (LwpaLinger*)option_value; + struct linger val; + val.l_onoff = (u_short)ll->onoff; + val.l_linger = (u_short)ll->linger; + return setsockopt(id, SOL_SOCKET, SO_LINGER, (char*)&val, sizeof val); + } + break; + case LWPA_SO_ERROR: /* Set not supported */ case LWPA_SO_REUSEPORT: /* Not supported on this OS. */ + case LWPA_SO_TYPE: /* Not supported */ default: - return kLwpaErrInvalid; + break; } - return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); + // If we got here, something was invalid. Set errno accordingly + WSASetLastError(WSAEINVAL); + return -1; +} + +int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_IP_TTL: + if (option_len == sizeof(int)) + { + DWORD val = (DWORD) * (int*)option_value; + return setsockopt(id, IPPROTO_IP, IP_TTL, (char*)&val, sizeof val); + } + break; + case LWPA_IP_ADD_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) + { + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + return setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&val, sizeof val); + } + } + break; + case LWPA_IP_DROP_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) + { + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + return setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&val, sizeof val); + } + } + break; + case LWPA_MCAST_JOIN_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V4(&greq->group) && greq->ifindex >= 0) + { + struct group_req val; + val.gr_interface = (ULONG)greq->ifindex; + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + return setsockopt(id, IPPROTO_IP, MCAST_JOIN_GROUP, (char*)&val, sizeof val); + } + } + break; + case LWPA_MCAST_LEAVE_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V4(&greq->group) && greq->ifindex >= 0) + { + struct group_req val; + val.gr_interface = (ULONG)greq->ifindex; + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + return setsockopt(id, IPPROTO_IP, MCAST_LEAVE_GROUP, (char*)&val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_IF: + if (option_len == sizeof(LwpaIpAddr)) + { + LwpaIpAddr* netint = (LwpaIpAddr*)option_value; + if (LWPA_IP_IS_V4(netint)) + { + DWORD val = htonl(LWPA_IP_V4_ADDRESS(netint)); + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_TTL: + if (option_len == sizeof(int)) + { + DWORD val = (DWORD) * (int*)option_value; + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&val, sizeof val); + } + break; + case LWPA_IP_MULTICAST_LOOP: + if (option_len == sizeof(int)) + { + DWORD val = (DWORD) * (int*)option_value; + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&val, sizeof val); + } + break; + default: + break; + } + // If we got here, something was invalid. Set errno accordingly + WSASetLastError(WSAEINVAL); + return -1; +} + +int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_MCAST_JOIN_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group) && greq->ifindex >= 0) + { + struct group_req val; + val.gr_interface = (ULONG)greq->ifindex; + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, (char*)&val, sizeof val); + } + } + break; + case LWPA_MCAST_LEAVE_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group) && greq->ifindex >= 0) + { + struct group_req val; + val.gr_interface = (ULONG)greq->ifindex; + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, MCAST_LEAVE_GROUP, (char*)&val, sizeof val); + } + } + break; + case LWPA_IPV6_V6ONLY: + if (option_len == sizeof(int)) + { + DWORD val = (DWORD) * (int*)option_value; + return setsockopt(id, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&val, sizeof val); + } + break; + default: /* Other IPv6 options TODO on windows. */ + break; + } + // If we got here, something was invalid. Set errno accordingly + WSASetLastError(WSAEINVAL); + return -1; } lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) diff --git a/tests/unit/test_rwlock.cpp b/tests/unit/test_rwlock.cpp index f02d1e0d0..85991318a 100644 --- a/tests/unit/test_rwlock.cpp +++ b/tests/unit/test_rwlock.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include class RwlockTest : public ::testing::Test @@ -43,39 +44,51 @@ TEST_F(RwlockTest, create_destroy) // Basic creation and taking ownership. ASSERT_TRUE(lwpa_rwlock_create(&rwlock)); for (size_t i = 0; i < 100; ++i) - ASSERT_TRUE(lwpa_rwlock_readlock(&rwlock, LWPA_WAIT_FOREVER)); + ASSERT_TRUE(lwpa_rwlock_readlock(&rwlock)); + + // Time-based functionality not implemented for now. + // auto start_time = std::chrono::high_resolution_clock::now(); - auto start_time = std::chrono::high_resolution_clock::now(); // Write lock should fail if there are readers - ASSERT_FALSE(lwpa_rwlock_writelock(&rwlock, 100)); + ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); + // It should wait for at least the timeout specified, minus up to one ms - auto time_taken = - std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); - ASSERT_GE(time_taken.count(), 99); + // auto time_taken = + // std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); + // ASSERT_GE(time_taken.count(), 99); // When there are no more readers, write lock should succeed for (size_t i = 0; i < 100; ++i) lwpa_rwlock_readunlock(&rwlock); - ASSERT_TRUE(lwpa_rwlock_writelock(&rwlock, LWPA_WAIT_FOREVER)); + ASSERT_TRUE(lwpa_rwlock_writelock(&rwlock)); // On Windows, take succeeds when taking a mutex again from the same thread. - ASSERT_TRUE(lwpa_rwlock_writelock(&rwlock, LWPA_WAIT_FOREVER)); +#ifdef WIN32 + ASSERT_TRUE(lwpa_rwlock_writelock(&rwlock)); +#else + ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); + ASSERT_FALSE(lwpa_rwlock_try_readlock(&rwlock)); +#endif lwpa_rwlock_writeunlock(&rwlock); // Test the guard classes { // Read lock scope lwpa::ReadGuard read(rwlock); - // Just make sure it doesn't throw + + ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); } { // Write lock scope lwpa::WriteGuard write(rwlock); - // Just make sure it doesn't throw + +#if !WIN32 + ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); +#endif } // Take should fail on a destroyed rwlock. lwpa_rwlock_destroy(&rwlock); - ASSERT_FALSE(lwpa_rwlock_writelock(&rwlock, LWPA_WAIT_FOREVER)); + ASSERT_FALSE(lwpa_rwlock_writelock(&rwlock)); } static void write_test_thread(RwlockTest* fixture) @@ -84,7 +97,7 @@ static void write_test_thread(RwlockTest* fixture) { for (size_t i = 0; i < RwlockTest::RWLOCK_TEST_NUM_ITERATIONS; ++i) { - lwpa_rwlock_writelock(&fixture->rwlock, LWPA_WAIT_FOREVER); + lwpa_rwlock_writelock(&fixture->rwlock); ++fixture->shared_var; lwpa_rwlock_writeunlock(&fixture->rwlock); // Had to insert an artificial delay to get it to fail reliably when the mutexes don't work. @@ -104,7 +117,7 @@ static void read_test_thread(RwlockTest* fixture) fixture->read_thread_pass = true; for (int i = 0; i < 10; ++i) { - lwpa_rwlock_readlock(&fixture->rwlock, LWPA_WAIT_FOREVER); + lwpa_rwlock_readlock(&fixture->rwlock); int val = fixture->shared_var; std::this_thread::sleep_for(5ms); @@ -150,8 +163,8 @@ TEST_F(RwlockTest, threads) for (auto& thread : threads) thread.join(); - ASSERT_TRUE(read_thread_pass); - ASSERT_EQ(shared_var, (RWLOCK_TEST_NUM_WRITE_THREADS * RWLOCK_TEST_NUM_ITERATIONS)); + EXPECT_TRUE(read_thread_pass); + EXPECT_EQ(shared_var, (RWLOCK_TEST_NUM_WRITE_THREADS * RWLOCK_TEST_NUM_ITERATIONS)); lwpa_rwlock_destroy(&rwlock); } From 22befe6cc2436f8abd3fa01cf0ee73d1f2d166b5 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 11 Jun 2019 12:37:04 -0500 Subject: [PATCH 031/264] Threads implemented. Linux - all unit tests passing --- include/lwpa/thread.h | 11 ++- include/os/linux/lwpa/os_lock.h | 17 ++-- include/os/linux/lwpa/os_thread.h | 33 +++++-- src/lwpa/thread.dox | 11 ++- src/os/linux/lwpa/os_lock.c | 150 ++++++++++++++++++++++++++++++ src/os/linux/lwpa/os_thread.c | 77 +++++++++++++++ src/os/windows/lwpa/os_lock.c | 27 ++++-- tests/unit/test_thread.cpp | 20 ++-- 8 files changed, 308 insertions(+), 38 deletions(-) diff --git a/include/lwpa/thread.h b/include/lwpa/thread.h index 255f3cef5..8f201d217 100644 --- a/include/lwpa/thread.h +++ b/include/lwpa/thread.h @@ -24,10 +24,19 @@ typedef struct LwpaThreadParams { unsigned int thread_priority; unsigned int stack_size; - char* thread_name; + const char* thread_name; void* platform_data; } LwpaThreadParams; +#define LWPA_THREAD_SET_DEFAULT_PARAMS(threadparamsptr) \ + do \ + { \ + (threadparamsptr)->thread_priority = LWPA_THREAD_DEFAULT_PRIORITY; \ + (threadparamsptr)->thread_stack = LWPA_THREAD_DEFAULT_STACK; \ + (threadparamsptr)->thread_name = LWPA_THREAD_DEFAULT_NAME; \ + (threadparamsptr)->platform_data = NULL; \ + } while (0) + #include "lwpa/os_thread.h" #endif /* _LWPA_THREAD_H_ */ diff --git a/include/os/linux/lwpa/os_lock.h b/include/os/linux/lwpa/os_lock.h index 8cb02e2a8..e46943045 100644 --- a/include/os/linux/lwpa/os_lock.h +++ b/include/os/linux/lwpa/os_lock.h @@ -52,16 +52,19 @@ void lwpa_signal_destroy(lwpa_signal_t* id); typedef struct { bool valid; + unsigned int reader_count; + pthread_mutex_t readcount_mutex; pthread_mutex_t mutex; } lwpa_rwlock_t; -/* Temporary placeholders */ -#define lwpa_rwlock_create(idptr) false -#define lwpa_rwlock_readlock(idptr, wait_ms) false -#define lwpa_rwlock_readunlock(idptr) -#define lwpa_rwlock_writelock(idptr, wait_ms) false -#define lwpa_rwlock_writeunlock(idptr) -#define lwpa_rwlock_destroy(idptr) +bool lwpa_rwlock_create(lwpa_rwlock_t* id); +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id); +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id); +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); +void lwpa_rwlock_destroy(lwpa_rwlock_t* id); #ifdef __cplusplus } diff --git a/include/os/linux/lwpa/os_thread.h b/include/os/linux/lwpa/os_thread.h index 628a13133..344a0317b 100644 --- a/include/os/linux/lwpa/os_thread.h +++ b/include/os/linux/lwpa/os_thread.h @@ -21,18 +21,31 @@ #define _LWPA_OS_THREAD_H_ #include +#include "lwpa/bool.h" -/* placeholders */ -#define LWPA_THREAD_DEFAULT_PRIORITY SCHED_OTHER -#define LWPA_THREAD_DEFAULT_STACK 0 -#define LWPA_THREAD_DEFAULT_NAME "lwpa_thread" +#ifdef __cplusplus +extern "C" { +#endif -#define LWPA_THREAD_NAME_MAX_LENGTH 32 +#define LWPA_THREAD_DEFAULT_PRIORITY 0 /* Priority ignored on Linux */ +#define LWPA_THREAD_DEFAULT_STACK 0 /* 0 means keep default */ +#define LWPA_THREAD_DEFAULT_NAME NULL /* Name ignored on Linux */ -typedef pthread_t lwpa_thread_t; +#define LWPA_THREAD_NAME_MAX_LENGTH 0 -#define lwpa_thread_create(idptr, paramsptr, thread_fn, thread_arg) false -#define lwpa_thread_stop(idptr, wait_ms) false -#define lwpa_thread_sleep(sleep_ms) +typedef struct +{ + void (*fn)(void*); + void* arg; + pthread_t handle; +} lwpa_thread_t; -#endif /* _LWPA_OS_THREAD_H_ */ \ No newline at end of file +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); +bool lwpa_thread_stop(lwpa_thread_t* id); +void lwpa_thread_sleep(int sleep_ms); + +#ifdef __cplusplus +} +#endif + +#endif /* _LWPA_OS_THREAD_H_ */ diff --git a/src/lwpa/thread.dox b/src/lwpa/thread.dox index 37075aa2c..7f8305804 100644 --- a/src/lwpa/thread.dox +++ b/src/lwpa/thread.dox @@ -61,18 +61,19 @@ typedef UNDEFINED lwpa_thread_t; * \param[in] thread_fn Pointer to function that should be called from the new thread. This * function takes one void* argument and returns void. * \param[in] thread_arg Argument to the function called from the new thread. - * \return true (the thread was created) or false (the thread was not created). + * \return true: The thread was created. + * \return false: The thread was not created. */ bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void (*thread_fn)(void *), void *thread_arg); /*! \brief Stop a thread. * - * On some platforms, wait_ms is ignored and you always wait forever for a thread to stop. + * This is sometimes referred to as 'joining' a thread in native platform APIs. Blocks until the + * thread has exited. * * \param[in] id Identifier for the thread to stop. - * \param[in] wait_ms How long to wait for the thread to stop, in milliseconds (use - * #LWPA_WAIT_FOREVER to wait indefinitely). - * \return true (the thread was stopped) or false (an error occurred). + * \return true: The thread was stopped. + * \return false: An error occurred. */ bool lwpa_thread_stop(lwpa_thread_t *id, int wait_ms); diff --git a/src/os/linux/lwpa/os_lock.c b/src/os/linux/lwpa/os_lock.c index 3fa7fa748..ec3c0cd47 100644 --- a/src/os/linux/lwpa/os_lock.c +++ b/src/os/linux/lwpa/os_lock.c @@ -18,6 +18,18 @@ ******************************************************************************/ #include "lwpa/lock.h" +#include + +/**************************** Private constants ******************************/ + +#define MAX_READERS 20000 + +/*********************** Private function prototypes *************************/ + +static void reader_atomic_increment(lwpa_rwlock_t* id); +static void reader_atomic_decrement(lwpa_rwlock_t* id); + +/*************************** Function definitions ****************************/ bool lwpa_signal_create(lwpa_signal_t* id) { @@ -101,3 +113,141 @@ void lwpa_signal_destroy(lwpa_signal_t* id) id->valid = false; } } + +bool lwpa_rwlock_create(lwpa_rwlock_t* id) +{ + if (id) + { + if (0 == pthread_mutex_init(&id->mutex, NULL)) + { + if (0 == pthread_mutex_init(&id->readcount_mutex, NULL)) + { + id->valid = true; + id->reader_count = 0; + return true; + } + else + { + pthread_mutex_destroy(&id->mutex); + } + } + } + return false; +} + +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id) +{ + bool res = false; + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + if (id->reader_count < MAX_READERS) + { + reader_atomic_increment(id); + res = true; + } + pthread_mutex_unlock(&id->mutex); + } + } + return res; +} + +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id) +{ + bool res = false; + if (id && id->valid) + { + if (0 == pthread_mutex_trylock(&id->mutex)) + { + if (id->reader_count < MAX_READERS) + { + reader_atomic_increment(id); + res = true; + } + pthread_mutex_unlock(&id->mutex); + } + } + return res; +} + +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + reader_atomic_decrement(id); +} + +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + // Wait until there are no readers, keeping the lock so that no new readers can get in. + while (id->reader_count > 0) + { + usleep(1000); + } + // Hold on to the lock until writeunlock() is called + return true; + } + } + return false; +} + +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + if (0 == pthread_mutex_trylock(&id->mutex)) + { + // Just check once to see if there are still readers + if (id->reader_count > 0) + { + // Readers are present, give up the lock and return false below + pthread_mutex_unlock(&id->mutex); + } + else + { + // Return, holding the lock + return true; + } + } + } + return false; +} + +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + pthread_mutex_unlock(&id->mutex); +} + +void lwpa_rwlock_destroy(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + pthread_mutex_destroy(&id->mutex); + pthread_mutex_destroy(&id->readcount_mutex); + id->valid = false; + } +} + +// TODO investigate C11 atomics for this +void reader_atomic_increment(lwpa_rwlock_t* id) +{ + if (0 == pthread_mutex_lock(&id->readcount_mutex)) + { + ++id->reader_count; + pthread_mutex_unlock(&id->readcount_mutex); + } +} + +void reader_atomic_decrement(lwpa_rwlock_t* id) +{ + if (0 == pthread_mutex_lock(&id->readcount_mutex)) + { + --id->reader_count; + pthread_mutex_unlock(&id->readcount_mutex); + } +} diff --git a/src/os/linux/lwpa/os_thread.c b/src/os/linux/lwpa/os_thread.c index e69de29bb..f52075112 100644 --- a/src/os/linux/lwpa/os_thread.c +++ b/src/os/linux/lwpa/os_thread.c @@ -0,0 +1,77 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/thread.h" + +#include + +/*********************** Private function prototypes *************************/ + +static void* thread_func_internal(void* arg); + +/*************************** Function definitions ****************************/ + +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg) +{ + if (!id || !params || !thread_fn) + return false; + + pthread_attr_t thread_attr; + pthread_attr_t* p_thread_attr = NULL; + + if (params && params->stack_size != LWPA_THREAD_DEFAULT_STACK) + { + pthread_attr_init(&thread_attr); + pthread_attr_setstacksize(&thread_attr, params->stack_size); + p_thread_attr = &thread_attr; + } + + id->fn = thread_fn; + id->arg = thread_arg; + bool res = (0 == pthread_create(&id->handle, p_thread_attr, thread_func_internal, id)); + + if (p_thread_attr) + pthread_attr_destroy(p_thread_attr); + + return res; +} + +bool lwpa_thread_stop(lwpa_thread_t* id) +{ + if (id) + { + return (0 == pthread_join(id->handle, NULL)); + } + return false; +} + +void lwpa_thread_sleep(int sleep_ms) +{ + usleep(((useconds_t)sleep_ms) * 1000); +} + +void* thread_func_internal(void* arg) +{ + lwpa_thread_t* thread_data = (lwpa_thread_t*)arg; + if (thread_data && thread_data->fn) + { + thread_data->fn(thread_data->arg); + } + return NULL; +} diff --git a/src/os/windows/lwpa/os_lock.c b/src/os/windows/lwpa/os_lock.c index 5a810bf31..fd780b55a 100644 --- a/src/os/windows/lwpa/os_lock.c +++ b/src/os/windows/lwpa/os_lock.c @@ -19,7 +19,12 @@ #include "lwpa/lock.h" #include "lwpa/int.h" -#include "mmsystem.h" + +/**************************** Private constants ******************************/ + +#define MAX_READERS 20000 + +/*************************** Function definitions ****************************/ bool lwpa_mutex_create(lwpa_mutex_t* id) { @@ -119,28 +124,36 @@ bool lwpa_rwlock_create(lwpa_rwlock_t* id) bool lwpa_rwlock_readlock(lwpa_rwlock_t* id) { + bool res = false; if (id && id->valid) { EnterCriticalSection(&id->cs); - InterlockedIncrement(&id->reader_count); // Add one to the reader count + if (id->reader_count < MAX_READERS) + { + InterlockedIncrement(&id->reader_count); // Add one to the reader count + res = true; + } LeaveCriticalSection(&id->cs); - return true; } - return false; + return res; } bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id) { + bool res = false; if (id && id->valid) { if (TryEnterCriticalSection(&id->cs)) { - InterlockedIncrement(&id->reader_count); + if (id->reader_count < MAX_READERS) + { + InterlockedIncrement(&id->reader_count); + res = true; + } LeaveCriticalSection(&id->cs); - return true; } } - return false; + return res; } void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) diff --git a/tests/unit/test_thread.cpp b/tests/unit/test_thread.cpp index 2a344ca5c..a84cdc2bf 100644 --- a/tests/unit/test_thread.cpp +++ b/tests/unit/test_thread.cpp @@ -61,19 +61,23 @@ TEST_F(ThreadTest, create_destroy) waitthread_run = true; ASSERT_TRUE(lwpa_thread_create(&wait_thread, ¶ms, wait_and_exit, this)); + ////////////////////////////////////////////////////////////////////////////// + // Time-based functionality not implemented for now. + ////////////////////////////////////////////////////////////////////////////// + // Stop should time out if the thread is still looping. - auto start_time = std::chrono::high_resolution_clock::now(); + // auto start_time = std::chrono::high_resolution_clock::now(); - ASSERT_FALSE(lwpa_thread_stop(&wait_thread, 100)); + // ASSERT_FALSE(lwpa_thread_stop(&wait_thread, 100)); // It should wait for at least the timeout specified, minus a fudge factor to account for // differing time resolutions on platforms. - auto time_taken = - std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); - ASSERT_GE(time_taken.count(), 80); + // auto time_taken = + // std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); + // ASSERT_GE(time_taken.count(), 80); // Stop should work if the thread has exited. waitthread_run = false; - ASSERT_TRUE(lwpa_thread_stop(&wait_thread, LWPA_WAIT_FOREVER)); + ASSERT_TRUE(lwpa_thread_stop(&wait_thread)); } void increment_and_spin(void* param) @@ -121,9 +125,9 @@ TEST_F(ThreadTest, time_slice) std::this_thread::sleep_for(100ms); // Stop the tasks oneshot_task_run = false; - ASSERT_TRUE(lwpa_thread_stop(&oneshot_task, LWPA_WAIT_FOREVER)); + ASSERT_TRUE(lwpa_thread_stop(&oneshot_task)); spin_task_run = false; - ASSERT_TRUE(lwpa_thread_stop(&spin_task, LWPA_WAIT_FOREVER)); + ASSERT_TRUE(lwpa_thread_stop(&spin_task)); ASSERT_TRUE(spin_task_ran); ASSERT_TRUE(oneshot_task_ran); } From f53e17cab741b67f565bde425ade837a59858f41 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 11 Jun 2019 13:49:07 -0500 Subject: [PATCH 032/264] Cleanup, fix some warnings, add pipeline step --- azure-pipelines.yml | 16 ++++++ external/fff/CMakeLists.txt | 4 +- include/lwpa/pack.h | 109 +++++++++++++++++++++++------------- tests/CMakeLists.txt | 3 + tests/unit/test_rbtree.cpp | 4 +- 5 files changed, 93 insertions(+), 43 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index bb4d7c265..713d79dc3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -30,6 +30,22 @@ jobs: displayName: 'lwpa Windows build' - script: build\tests\%LWPA_BUILD_CONFIG%\test_lwpa.exe displayName: 'lwpa Windows test' + +- job: linux_build + displayName: 'Linux Build and Test' + pool: + vmImage: 'ubuntu-16.04' + steps: + - script: | + mkdir build + cd build + cmake --version + cmake -G "Unix Makefiles" -DLWPA_BUILD_MOCK_LIB=ON .. + cmake --build . + displayName: 'lwpa Linux build' + - script: build/tests/test_lwpa + displayName: 'lwpa Linux test' + # Generate documentation with doxygen. Documentation is generated from the # develop branch and posted to the 'head' portion of the Github page # (etclabs.github.io/lwpa) diff --git a/external/fff/CMakeLists.txt b/external/fff/CMakeLists.txt index 42daa21d0..99ebfdf55 100644 --- a/external/fff/CMakeLists.txt +++ b/external/fff/CMakeLists.txt @@ -1,6 +1,8 @@ if(NOT TARGET meekrosoft::fff) add_library(meekrosoft::fff INTERFACE IMPORTED GLOBAL) - target_include_directories(meekrosoft::fff INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + # target_include_directories(meekrosoft::fff INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + # portable version for pre-3.11 CMake + set_property(TARGET meekrosoft::fff APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}) # FFF generates a lot of unreachable code warnings in Visual C++ if(MSVC) diff --git a/include/lwpa/pack.h b/include/lwpa/pack.h index 2c2734e04..bcf1550c4 100644 --- a/include/lwpa/pack.h +++ b/include/lwpa/pack.h @@ -43,10 +43,14 @@ * \param ptr Pointer to the buffer from which to unpack a uint16_t. * \return Unpacked uint16_t. */ -#define lwpa_upack_16b(ptr) \ - ((uint16_t)(0u | \ - (uint16_t)((((uint8_t *)(ptr))[0]) << 8) | \ - (uint16_t) (((uint8_t *)(ptr))[1])) \ +#define lwpa_upack_16b(ptr) \ + ( \ + (uint16_t)(0u | \ + (uint16_t)( \ + (((uint16_t)((uint8_t *)(ptr))[0]) << 8) | \ + ((uint16_t)((uint8_t *)(ptr))[1]) \ + ) \ + ) \ ) /*! \brief Pack a uint16_t to a known big-endian buffer. @@ -64,10 +68,15 @@ * \param ptr Pointer to the buffer from which to unpack a uint16_t. * \return Unpacked uint16_t. */ -#define lwpa_upack_16l(ptr) \ - (((uint16_t)0u) | \ - (((uint16_t)((uint8_t *)(ptr))[1]) << 8) | \ - ((uint16_t)((uint8_t *)(ptr))[0])) +#define lwpa_upack_16l(ptr) \ + ( \ + (uint16_t)(0u | \ + (uint16_t)( \ + (((uint16_t)((uint8_t *)(ptr))[1]) << 8) | \ + ((uint16_t)((uint8_t *)(ptr))[0]) \ + ) \ + ) \ + ) /*! \brief Pack a uint16_t to a known little-endian buffer. * \param ptr Pointer to the buffer into which to pack a uint16_t. @@ -84,12 +93,17 @@ * \param ptr Pointer to the buffer from which to unpack a uint32_t. * \return Unpacked uint32_t. */ -#define lwpa_upack_32b(ptr) \ - (((uint32_t)0u) | \ - (((uint32_t)((uint8_t *)(ptr))[0]) << 24) | \ - (((uint32_t)((uint8_t *)(ptr))[1]) << 16) | \ - (((uint32_t)((uint8_t *)(ptr))[2]) << 8) | \ - ((uint32_t)((uint8_t *)(ptr))[3])) +#define lwpa_upack_32b(ptr) \ + ( \ + (uint32_t)(0u | \ + (uint32_t)( \ + (((uint32_t)((uint8_t *)(ptr))[0]) << 24) | \ + (((uint32_t)((uint8_t *)(ptr))[1]) << 16) | \ + (((uint32_t)((uint8_t *)(ptr))[2]) << 8) | \ + ((uint32_t)((uint8_t *)(ptr))[3]) \ + ) \ + ) \ + ) /*! \brief Pack a uint32_t to a known big-endian buffer. * \param ptr Pointer to the buffer into which to pack a uint32_t. @@ -108,12 +122,17 @@ * \param ptr Pointer to the buffer from which to unpack a uint32_t. * \return Unpacked uint32_t. */ -#define lwpa_upack_32l(ptr) \ - (((uint32_t)0u) | \ - (((uint32_t)((uint8_t *)(ptr))[3]) << 24) | \ - (((uint32_t)((uint8_t *)(ptr))[2]) << 16) | \ - (((uint32_t)((uint8_t *)(ptr))[1]) << 8) | \ - ((uint32_t)((uint8_t *)(ptr))[0])) +#define lwpa_upack_32l(ptr) \ + ( \ + (uint32_t)(0u | \ + (uint32_t)( \ + (((uint32_t)((uint8_t *)(ptr))[3]) << 24) | \ + (((uint32_t)((uint8_t *)(ptr))[2]) << 16) | \ + (((uint32_t)((uint8_t *)(ptr))[1]) << 8) | \ + ((uint32_t)((uint8_t *)(ptr))[0]) \ + ) \ + ) \ + ) /*! \brief Pack a uint32_t to a known little-endian buffer. * \param ptr Pointer to the buffer into which to pack a uint32_t. @@ -134,16 +153,21 @@ * \param ptr Pointer to the buffer from which to unpack a uint64_t. * \return Unpacked uint64_t. */ -#define lwpa_upack_64b(ptr) \ - (((uint64_t)0u) | \ - (((uint64_t)((uint8_t *)(ptr))[0]) << 56) | \ - (((uint64_t)((uint8_t *)(ptr))[1]) << 48) | \ - (((uint64_t)((uint8_t *)(ptr))[2]) << 40) | \ - (((uint64_t)((uint8_t *)(ptr))[3]) << 32) | \ - (((uint64_t)((uint8_t *)(ptr))[4]) << 24) | \ - (((uint64_t)((uint8_t *)(ptr))[5]) << 16) | \ - (((uint64_t)((uint8_t *)(ptr))[6]) << 8) | \ - ((uint64_t)((uint8_t *)(ptr))[7])) +#define lwpa_upack_64b(ptr) \ + ( \ + (uint64_t)(0u | \ + (uint64_t)( \ + (((uint64_t)((uint8_t *)(ptr))[0]) << 56) | \ + (((uint64_t)((uint8_t *)(ptr))[1]) << 48) | \ + (((uint64_t)((uint8_t *)(ptr))[2]) << 40) | \ + (((uint64_t)((uint8_t *)(ptr))[3]) << 32) | \ + (((uint64_t)((uint8_t *)(ptr))[4]) << 24) | \ + (((uint64_t)((uint8_t *)(ptr))[5]) << 16) | \ + (((uint64_t)((uint8_t *)(ptr))[6]) << 8) | \ + ((uint64_t)((uint8_t *)(ptr))[7]) \ + ) \ + ) \ + ) /*! \brief Pack a uint64_t to a known big-endian buffer. * \param ptr Pointer to the buffer into which to pack a uint64_t. @@ -166,16 +190,21 @@ * \param ptr Pointer to the buffer from which to unpack a uint64_t. * \return Unpacked uint64_t. */ -#define lwpa_upack_64l(ptr) \ - (((uint64_t)0u) | \ - (((uint64_t)((uint8_t *)(ptr))[7]) << 56) | \ - (((uint64_t)((uint8_t *)(ptr))[6]) << 48) | \ - (((uint64_t)((uint8_t *)(ptr))[5]) << 40) | \ - (((uint64_t)((uint8_t *)(ptr))[4]) << 32) | \ - (((uint64_t)((uint8_t *)(ptr))[3]) << 24) | \ - (((uint64_t)((uint8_t *)(ptr))[2]) << 16) | \ - (((uint64_t)((uint8_t *)(ptr))[1]) << 8) | \ - ((uint64_t)((uint8_t *)(ptr))[0])) +#define lwpa_upack_64l(ptr) \ + ( \ + (uint64_t)(0u | \ + (uint64_t)( \ + (((uint64_t)((uint8_t *)(ptr))[7]) << 56) | \ + (((uint64_t)((uint8_t *)(ptr))[6]) << 48) | \ + (((uint64_t)((uint8_t *)(ptr))[5]) << 40) | \ + (((uint64_t)((uint8_t *)(ptr))[4]) << 32) | \ + (((uint64_t)((uint8_t *)(ptr))[3]) << 24) | \ + (((uint64_t)((uint8_t *)(ptr))[2]) << 16) | \ + (((uint64_t)((uint8_t *)(ptr))[1]) << 8) | \ + ((uint64_t)((uint8_t *)(ptr))[0]) \ + ) \ + ) \ + ) /*! \brief Pack a uint64_t to a known little-endian buffer. * \param ptr Pointer to the buffer into which to pack a uint64_t. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index beadd4013..707a56ea4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -26,4 +26,7 @@ if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL linux) ) set_target_properties(test_lwpa PROPERTIES CXX_STANDARD 14) target_link_libraries(test_lwpa lwpa gmock) + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_compile_options(test_lwpa PRIVATE -Wno-format-security) + endif() endif() diff --git a/tests/unit/test_rbtree.cpp b/tests/unit/test_rbtree.cpp index dec0424c6..4400fb7da 100644 --- a/tests/unit/test_rbtree.cpp +++ b/tests/unit/test_rbtree.cpp @@ -114,7 +114,7 @@ TEST_F(RbTreeTest, insert_static) ASSERT_NE(0, lwpa_rbtree_test(&tree, tree.root)); // Find a random number - int to_find = rand() / (RAND_MAX / kIntArraySize + 1); + int to_find = rand() / (int)(RAND_MAX / kIntArraySize + 1); int* found = (int*)lwpa_rbtree_find(&tree, &to_find); ASSERT_TRUE(found != NULL); ASSERT_EQ(*found, to_find); @@ -144,7 +144,7 @@ TEST_F(RbTreeTest, insert_dynamic) ASSERT_NE(0, lwpa_rbtree_test(&tree, tree.root)); // Find a random number - int to_find = rand() / (RAND_MAX / kIntArraySize + 1); + int to_find = rand() / (int)(RAND_MAX / kIntArraySize + 1); int* found = (int*)lwpa_rbtree_find(&tree, &to_find); ASSERT_TRUE(found != NULL); ASSERT_EQ(*found, to_find); From 3a32662506a289ef519467e38f30e8a6e46c7359 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 11 Jun 2019 13:51:44 -0500 Subject: [PATCH 033/264] Small optimization to linux threads --- include/os/linux/lwpa/os_thread.h | 3 ++- src/os/linux/lwpa/os_thread.c | 7 ------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/include/os/linux/lwpa/os_thread.h b/include/os/linux/lwpa/os_thread.h index 344a0317b..713e06264 100644 --- a/include/os/linux/lwpa/os_thread.h +++ b/include/os/linux/lwpa/os_thread.h @@ -21,6 +21,7 @@ #define _LWPA_OS_THREAD_H_ #include +#include #include "lwpa/bool.h" #ifdef __cplusplus @@ -42,7 +43,7 @@ typedef struct bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); bool lwpa_thread_stop(lwpa_thread_t* id); -void lwpa_thread_sleep(int sleep_ms); +#define lwpa_thread_sleep(sleep_ms) usleep(((useconds_t)sleep_ms) * 1000) #ifdef __cplusplus } diff --git a/src/os/linux/lwpa/os_thread.c b/src/os/linux/lwpa/os_thread.c index f52075112..d8aeb85e6 100644 --- a/src/os/linux/lwpa/os_thread.c +++ b/src/os/linux/lwpa/os_thread.c @@ -19,8 +19,6 @@ #include "lwpa/thread.h" -#include - /*********************** Private function prototypes *************************/ static void* thread_func_internal(void* arg); @@ -61,11 +59,6 @@ bool lwpa_thread_stop(lwpa_thread_t* id) return false; } -void lwpa_thread_sleep(int sleep_ms) -{ - usleep(((useconds_t)sleep_ms) * 1000); -} - void* thread_func_internal(void* arg) { lwpa_thread_t* thread_data = (lwpa_thread_t*)arg; From 7386f778d9012c977a03040b48575f7aa0d98e20 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 11 Jun 2019 13:53:17 -0500 Subject: [PATCH 034/264] And fix Windows a final time --- include/os/windows/lwpa/os_thread.h | 2 +- src/lwpa/lock.dox | 3 +++ src/os/windows/lwpa/os_thread.c | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/os/windows/lwpa/os_thread.h b/include/os/windows/lwpa/os_thread.h index 755d075a8..cf4082a83 100644 --- a/include/os/windows/lwpa/os_thread.h +++ b/include/os/windows/lwpa/os_thread.h @@ -54,7 +54,7 @@ typedef struct } lwpa_thread_t; bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); -bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); +bool lwpa_thread_stop(lwpa_thread_t* id); #define lwpa_thread_sleep(sleep_ms) Sleep(sleep_ms) #ifdef __cplusplus diff --git a/src/lwpa/lock.dox b/src/lwpa/lock.dox index dbe416b28..7018b354a 100644 --- a/src/lwpa/lock.dox +++ b/src/lwpa/lock.dox @@ -161,6 +161,9 @@ void lwpa_signal_destroy(lwpa_signal_t *id); * These are implemented as "write-preferring" reader-writer locks; this means that new readers are * blocked from acquiring a read lock if any context is currently waiting for a write lock. * + * lwpa read-write locks are typically implemented using multiple OS synchronization constructs + * under the hood. + * * @{ */ diff --git a/src/os/windows/lwpa/os_thread.c b/src/os/windows/lwpa/os_thread.c index 6b12cb7a5..3a12a0dc6 100644 --- a/src/os/windows/lwpa/os_thread.c +++ b/src/os/windows/lwpa/os_thread.c @@ -87,11 +87,11 @@ bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void return true; } -bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms) +bool lwpa_thread_stop(lwpa_thread_t* id) { if (id) { - if (WAIT_OBJECT_0 != WaitForSingleObject(id->tid, (wait_ms == LWPA_WAIT_FOREVER) ? INFINITE : (DWORD)wait_ms)) + if (WAIT_OBJECT_0 != WaitForSingleObject(id->tid, INFINITE)) { return false; } From ce020f7ccfe9c31e2ef5d743f3f675dd1b6dbce3 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 11 Jun 2019 13:57:04 -0500 Subject: [PATCH 035/264] Add UUID dependency to Linux pipeline script --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 713d79dc3..a56fe1215 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -37,6 +37,7 @@ jobs: vmImage: 'ubuntu-16.04' steps: - script: | + sudo apt-get install uuid-dev mkdir build cd build cmake --version From 24b5bb5a6a2f284a96204d3d9f7d15b3521f1e00 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 11 Jun 2019 13:58:45 -0500 Subject: [PATCH 036/264] Troubleshooting Linux pipeline --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a56fe1215..d70c53437 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -37,6 +37,7 @@ jobs: vmImage: 'ubuntu-16.04' steps: - script: | + sudo apt-get update sudo apt-get install uuid-dev mkdir build cd build From ceda930bbd343fd07b48aba9037e31a5ddd0813e Mon Sep 17 00:00:00 2001 From: Network Development Team Date: Tue, 11 Jun 2019 15:06:01 -0500 Subject: [PATCH 037/264] Initial start on macOS port - just copy the files from Linux --- include/os/macos/lwpa/os_lock.h | 73 +++ include/os/macos/lwpa/os_socket.h | 57 ++ include/os/macos/lwpa/os_thread.h | 52 ++ src/CMakeLists.txt | 7 +- src/os/macos/lwpa/os_common.c | 38 ++ src/os/macos/lwpa/os_error.c | 93 +++ src/os/macos/lwpa/os_error.h | 27 + src/os/macos/lwpa/os_lock.c | 253 ++++++++ src/os/macos/lwpa/os_netint.c | 698 ++++++++++++++++++++++ src/os/macos/lwpa/os_socket.c | 958 ++++++++++++++++++++++++++++++ src/os/macos/lwpa/os_thread.c | 70 +++ src/os/macos/lwpa/os_timer.c | 32 + src/os/macos/lwpa/os_uuid.c | 58 ++ 13 files changed, 2414 insertions(+), 2 deletions(-) create mode 100644 include/os/macos/lwpa/os_lock.h create mode 100644 include/os/macos/lwpa/os_socket.h create mode 100644 include/os/macos/lwpa/os_thread.h create mode 100644 src/os/macos/lwpa/os_common.c create mode 100644 src/os/macos/lwpa/os_error.c create mode 100644 src/os/macos/lwpa/os_error.h create mode 100644 src/os/macos/lwpa/os_lock.c create mode 100644 src/os/macos/lwpa/os_netint.c create mode 100644 src/os/macos/lwpa/os_socket.c create mode 100644 src/os/macos/lwpa/os_thread.c create mode 100644 src/os/macos/lwpa/os_timer.c create mode 100644 src/os/macos/lwpa/os_uuid.c diff --git a/include/os/macos/lwpa/os_lock.h b/include/os/macos/lwpa/os_lock.h new file mode 100644 index 000000000..e46943045 --- /dev/null +++ b/include/os/macos/lwpa/os_lock.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_LOCK_H_ +#define _LWPA_OS_LOCK_H_ + +#include +#include "lwpa/bool.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef pthread_mutex_t lwpa_mutex_t; + +#define lwpa_mutex_create(idptr) ((pthread_mutex_init((idptr), NULL) == 0) ? true : false) +#define lwpa_mutex_take(idptr) ((pthread_mutex_lock(idptr) == 0) ? true : false) +#define lwpa_mutex_try_take(idptr) ((pthread_mutex_trylock(idptr) == 0) ? true : false) +#define lwpa_mutex_give(idptr) ((void)pthread_mutex_unlock(idptr)) +#define lwpa_mutex_destroy(idptr) ((void)pthread_mutex_destroy(idptr)) + +typedef struct +{ + bool valid; + bool signaled; + pthread_cond_t cond; + pthread_mutex_t mutex; +} lwpa_signal_t; + +bool lwpa_signal_create(lwpa_signal_t* id); +bool lwpa_signal_wait(lwpa_signal_t* id); +bool lwpa_signal_poll(lwpa_signal_t* id); +void lwpa_signal_post(lwpa_signal_t* id); +void lwpa_signal_destroy(lwpa_signal_t* id); + +typedef struct +{ + bool valid; + unsigned int reader_count; + pthread_mutex_t readcount_mutex; + pthread_mutex_t mutex; +} lwpa_rwlock_t; + +bool lwpa_rwlock_create(lwpa_rwlock_t* id); +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id); +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id); +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); +void lwpa_rwlock_destroy(lwpa_rwlock_t* id); + +#ifdef __cplusplus +} +#endif + +#endif /* _LWPA_OS_LOCK_H_ */ diff --git a/include/os/macos/lwpa/os_socket.h b/include/os/macos/lwpa/os_socket.h new file mode 100644 index 000000000..b461aed2c --- /dev/null +++ b/include/os/macos/lwpa/os_socket.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_SOCKET_H_ +#define _LWPA_OS_SOCKET_H_ + +#include +#include +#include "lwpa/inet.h" +#include "lwpa/rbtree.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int lwpa_socket_t; + +#define LWPA_SOCKET_INVALID -1 + +#define LWPA_SOCKET_MAX_POLL_SIZE -1 + +typedef struct LwpaPollContext +{ + bool valid; + int epoll_fd; + LwpaRbTree sockets; +} LwpaPollContext; + +#define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), ntohl((pfipptr)->s_addr)) +#define IP_LWPA_TO_OS_V4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(LWPA_IP_V4_ADDRESS(lwpaipptr))) +#define IP_OS_TO_LWPA_V6(lwpaipptr, pfipptr) LWPA_IP_SET_V6_ADDRESS((lwpaipptr), (pfipptr)->s6_addr) +#define IP_LWPA_TO_OS_V6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, LWPA_IP_V6_ADDRESS(lwpaipptr), IPV6_BYTES) + +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); + +#ifdef __cplusplus +} +#endif + +#endif /* _LWPA_OS_SOCKET_H_ */ diff --git a/include/os/macos/lwpa/os_thread.h b/include/os/macos/lwpa/os_thread.h new file mode 100644 index 000000000..713e06264 --- /dev/null +++ b/include/os/macos/lwpa/os_thread.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_THREAD_H_ +#define _LWPA_OS_THREAD_H_ + +#include +#include +#include "lwpa/bool.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWPA_THREAD_DEFAULT_PRIORITY 0 /* Priority ignored on Linux */ +#define LWPA_THREAD_DEFAULT_STACK 0 /* 0 means keep default */ +#define LWPA_THREAD_DEFAULT_NAME NULL /* Name ignored on Linux */ + +#define LWPA_THREAD_NAME_MAX_LENGTH 0 + +typedef struct +{ + void (*fn)(void*); + void* arg; + pthread_t handle; +} lwpa_thread_t; + +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); +bool lwpa_thread_stop(lwpa_thread_t* id); +#define lwpa_thread_sleep(sleep_ms) usleep(((useconds_t)sleep_ms) * 1000) + +#ifdef __cplusplus +} +#endif + +#endif /* _LWPA_OS_THREAD_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1fb522fd8..7e3139811 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,16 +7,19 @@ endif() # The set of supported target OS set(VALID_LWPA_TARGETS - windows linux + macos mqx + windows ) if(NOT DEFINED LWPA_TARGET_OS) message(STATUS "LWPA_TARGET_OS not supplied, assuming native compile by default...") if(WIN32) set(LWPA_TARGET_OS windows) - elseif(UNIX AND NOT APPLE) + elseif(APPLE) + set(LWPA_TARGET_OS macos) + elseif(UNIX) set(LWPA_TARGET_OS linux) else() # The error check below will catch this and print the fatal error. diff --git a/src/os/macos/lwpa/os_common.c b/src/os/macos/lwpa/os_common.c new file mode 100644 index 000000000..7e1de52d0 --- /dev/null +++ b/src/os/macos/lwpa/os_common.c @@ -0,0 +1,38 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/common.h" +#include "lwpa/private/common.h" + +#include + +lwpa_error_t lwpa_os_init(lwpa_features_t features) +{ + if (features & LWPA_FEATURE_TIMERS) + { + if (sysconf(_SC_MONOTONIC_CLOCK) < 0) + return kLwpaErrSys; + } + return kLwpaErrOk; +} + +void lwpa_os_deinit(lwpa_features_t features) +{ + (void)features; +} diff --git a/src/os/macos/lwpa/os_error.c b/src/os/macos/lwpa/os_error.c new file mode 100644 index 000000000..45770f791 --- /dev/null +++ b/src/os/macos/lwpa/os_error.c @@ -0,0 +1,93 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "os_error.h" +#include + +lwpa_error_t errno_os_to_lwpa(int os_errno) +{ + switch (os_errno) + { + case EPERM: + case EACCES: + return kLwpaErrPerm; + case ENOENT: + case EBADF: + case ENOTSOCK: + return kLwpaErrNotFound; + case EFAULT: + case EINVAL: + case EDESTADDRREQ: + case EPROTOTYPE: + case EOPNOTSUPP: + return kLwpaErrInvalid; + // case EAGAIN: // EWOULDBLOCK defined to EAGAIN + case EWOULDBLOCK: + return kLwpaErrWouldBlock; + case EBUSY: + return kLwpaErrBusy; + case ENOMEM: + case ENOBUFS: + return kLwpaErrNoMem; + case EEXIST: + return kLwpaErrExists; + case ENOSYS: + return kLwpaErrNotImpl; + case EPROTO: + return kLwpaErrProtocol; + case EMSGSIZE: + return kLwpaErrMsgSize; + case EADDRINUSE: + return kLwpaErrAddrInUse; + case EADDRNOTAVAIL: + return kLwpaErrAddrNotAvail; + case ENETDOWN: + case ENETUNREACH: + case ENETRESET: + return kLwpaErrNetwork; + case ECONNABORTED: + return kLwpaErrConnAborted; + case ECONNRESET: + return kLwpaErrConnReset; + case EISCONN: + return kLwpaErrIsConn; + case ENOTCONN: + return kLwpaErrNotConn; + case ESHUTDOWN: + return kLwpaErrShutdown; + case ETIMEDOUT: + return kLwpaErrTimedOut; + case ECONNREFUSED: + return kLwpaErrConnRefused; + case EALREADY: + return kLwpaErrAlready; + case EINPROGRESS: + return kLwpaErrInProgress; + case EINTR: + case ENFILE: + case EMFILE: + case ENOSPC: + case EPFNOSUPPORT: + case EAFNOSUPPORT: + case EPROTONOSUPPORT: + case ESOCKTNOSUPPORT: + default: + return kLwpaErrSys; + } +} diff --git a/src/os/macos/lwpa/os_error.h b/src/os/macos/lwpa/os_error.h new file mode 100644 index 000000000..9978a07ef --- /dev/null +++ b/src/os/macos/lwpa/os_error.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_ERROR_H_ +#define _LWPA_OS_ERROR_H_ + +#include "lwpa/error.h" + +lwpa_error_t errno_os_to_lwpa(int os_errno); + +#endif /* _LWPA_OS_ERROR_H_ */ diff --git a/src/os/macos/lwpa/os_lock.c b/src/os/macos/lwpa/os_lock.c new file mode 100644 index 000000000..ec3c0cd47 --- /dev/null +++ b/src/os/macos/lwpa/os_lock.c @@ -0,0 +1,253 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/lock.h" +#include + +/**************************** Private constants ******************************/ + +#define MAX_READERS 20000 + +/*********************** Private function prototypes *************************/ + +static void reader_atomic_increment(lwpa_rwlock_t* id); +static void reader_atomic_decrement(lwpa_rwlock_t* id); + +/*************************** Function definitions ****************************/ + +bool lwpa_signal_create(lwpa_signal_t* id) +{ + if (id) + { + if (0 == pthread_mutex_init(&id->mutex, NULL)) + { + if (0 == pthread_cond_init(&id->cond, NULL)) + { + id->valid = true; + id->signaled = false; + return true; + } + else + { + pthread_mutex_destroy(&id->mutex); + } + } + } + return false; +} + +bool lwpa_signal_wait(lwpa_signal_t* id) +{ + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + while (!id->signaled) + { + if (0 != pthread_cond_wait(&id->cond, &id->mutex)) + { + // On error, the mutex is not locked + } + } + id->signaled = false; + pthread_mutex_unlock(&id->mutex); + return true; + } + } + return false; +} + +bool lwpa_signal_poll(lwpa_signal_t* id) +{ + bool res = false; + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + if (id->signaled) + { + res = true; + id->signaled = false; + } + pthread_mutex_unlock(&id->mutex); + } + } + return res; +} + +void lwpa_signal_post(lwpa_signal_t* id) +{ + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + id->signaled = true; + pthread_cond_signal(&id->cond); + pthread_mutex_unlock(&id->mutex); + } + } +} + +void lwpa_signal_destroy(lwpa_signal_t* id) +{ + if (id && id->valid) + { + pthread_cond_destroy(&id->cond); + pthread_mutex_destroy(&id->mutex); + id->valid = false; + } +} + +bool lwpa_rwlock_create(lwpa_rwlock_t* id) +{ + if (id) + { + if (0 == pthread_mutex_init(&id->mutex, NULL)) + { + if (0 == pthread_mutex_init(&id->readcount_mutex, NULL)) + { + id->valid = true; + id->reader_count = 0; + return true; + } + else + { + pthread_mutex_destroy(&id->mutex); + } + } + } + return false; +} + +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id) +{ + bool res = false; + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + if (id->reader_count < MAX_READERS) + { + reader_atomic_increment(id); + res = true; + } + pthread_mutex_unlock(&id->mutex); + } + } + return res; +} + +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id) +{ + bool res = false; + if (id && id->valid) + { + if (0 == pthread_mutex_trylock(&id->mutex)) + { + if (id->reader_count < MAX_READERS) + { + reader_atomic_increment(id); + res = true; + } + pthread_mutex_unlock(&id->mutex); + } + } + return res; +} + +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + reader_atomic_decrement(id); +} + +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + if (0 == pthread_mutex_lock(&id->mutex)) + { + // Wait until there are no readers, keeping the lock so that no new readers can get in. + while (id->reader_count > 0) + { + usleep(1000); + } + // Hold on to the lock until writeunlock() is called + return true; + } + } + return false; +} + +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + if (0 == pthread_mutex_trylock(&id->mutex)) + { + // Just check once to see if there are still readers + if (id->reader_count > 0) + { + // Readers are present, give up the lock and return false below + pthread_mutex_unlock(&id->mutex); + } + else + { + // Return, holding the lock + return true; + } + } + } + return false; +} + +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) +{ + if (id && id->valid) + pthread_mutex_unlock(&id->mutex); +} + +void lwpa_rwlock_destroy(lwpa_rwlock_t* id) +{ + if (id && id->valid) + { + pthread_mutex_destroy(&id->mutex); + pthread_mutex_destroy(&id->readcount_mutex); + id->valid = false; + } +} + +// TODO investigate C11 atomics for this +void reader_atomic_increment(lwpa_rwlock_t* id) +{ + if (0 == pthread_mutex_lock(&id->readcount_mutex)) + { + ++id->reader_count; + pthread_mutex_unlock(&id->readcount_mutex); + } +} + +void reader_atomic_decrement(lwpa_rwlock_t* id) +{ + if (0 == pthread_mutex_lock(&id->readcount_mutex)) + { + --id->reader_count; + pthread_mutex_unlock(&id->readcount_mutex); + } +} diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c new file mode 100644 index 000000000..5a4269576 --- /dev/null +++ b/src/os/macos/lwpa/os_netint.c @@ -0,0 +1,698 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +/* The os_netint implementation for Linux. + * + * Uses getifaddrs() to get an initial list of network interfaces. More info: + * http://man7.org/linux/man-pages/man3/getifaddrs.3.html + * + * Then uses netlink sockets (specifically RTNETLINK) to fill out missing information about each + * interface. More info: + * + * Netlink sockets: http://man7.org/linux/man-pages/man7/netlink.7.html + * Netlink macros, for decoding netlink messages: http://man7.org/linux/man-pages/man3/netlink.3.html + * RtNetlink sockets: http://man7.org/linux/man-pages/man7/rtnetlink.7.html + * Some sample RtNetlink code: https://www.linuxjournal.com/article/8498 + */ + +#include "lwpa/netint.h" + +#include +#include +#include + +#ifdef LWPA_NETINT_DEBUG_OUTPUT +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lwpa/socket.h" +#include "lwpa/private/netint.h" +#include "os_error.h" + +/***************************** Private types *********************************/ + +typedef struct RoutingTableEntry +{ + LwpaIpAddr addr; + LwpaIpAddr mask; + LwpaIpAddr gateway; + int interface_index; + int metric; +} RoutingTableEntry; + +typedef struct RoutingTable +{ + RoutingTableEntry* entries; + RoutingTableEntry* default_route; + size_t size; +} RoutingTable; + +/* A composite struct representing an RT_NETLINK request sent over a netlink socket. */ +typedef struct RtNetlinkRequest +{ + struct nlmsghdr nl_header; + struct rtmsg rt_msg; +} RtNetlinkRequest; + +/**************************** Private variables ******************************/ + +static struct LwpaNetintState +{ + bool initialized; + + RoutingTable routing_table_v4; + RoutingTable routing_table_v6; + + struct ifaddrs* os_addrs; + size_t num_netints; + LwpaNetintInfo* lwpa_netints; + + bool have_default_netint_index_v4; + size_t default_netint_index_v4; + + bool have_default_netint_index_v6; + size_t default_netint_index_v6; +} state; + +/*********************** Private function prototypes *************************/ + +// Functions for building the routing tables +static lwpa_error_t build_routing_tables(); +static lwpa_error_t build_routing_table(int family, RoutingTable* table); +static void free_routing_tables(); +static void free_routing_table(RoutingTable* table); + +// Interacting with RTNETLINK +static lwpa_error_t send_netlink_route_request(int socket, int family); +static lwpa_error_t receive_netlink_route_reply(int sock, int family, size_t buf_size, RoutingTable* table); +static lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl_msg_size, RoutingTable* table); + +// Manipulating routing table entries +static void init_routing_table_entry(RoutingTableEntry* entry); +static int compare_routing_table_entries(const void* a, const void* b); + +// Functions for enumerating the interfaces +static lwpa_error_t enumerate_netints(); +static int compare_netints(const void* a, const void* b); +static void free_netints(); + +#if LWPA_NETINT_DEBUG_OUTPUT +static void debug_print_routing_table(RoutingTable* table); +#endif + +/*************************** Function definitions ****************************/ + +lwpa_error_t lwpa_netint_init() +{ + lwpa_error_t res = kLwpaErrOk; + if (!state.initialized) + { + res = enumerate_netints(); + if (res == kLwpaErrOk) + state.initialized = true; + } + return res; +} + +void lwpa_netint_deinit() +{ + if (state.initialized) + { + free_netints(); + memset(&state, 0, sizeof(state)); + } +} + +/****************************************************************************** + * API Functions + *****************************************************************************/ + +size_t lwpa_netint_get_num_interfaces() +{ + return (state.initialized ? state.num_netints : 0); +} + +size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) +{ + if (!state.initialized || !netint_arr || netint_arr_size == 0) + return 0; + + size_t addrs_copied = (netint_arr_size < state.num_netints ? netint_arr_size : state.num_netints); + memcpy(netint_arr, state.lwpa_netints, addrs_copied * sizeof(LwpaNetintInfo)); + return addrs_copied; +} + +bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) +{ + if (state.initialized && netint) + { + if (type == kLwpaIpTypeV4 && state.have_default_netint_index_v4) + { + *netint = state.lwpa_netints[state.default_netint_index_v4]; + return true; + } + else if (type == kLwpaIpTypeV6 && state.have_default_netint_index_v6) + { + *netint = state.lwpa_netints[state.default_netint_index_v6]; + return true; + } + } + return false; +} + +lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) +{ + if (!dest || !netint) + return kLwpaErrInvalid; + if (!state.initialized) + return kLwpaErrNotInit; + if (state.num_netints == 0) + return kLwpaErrNoNetints; + + RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &state.routing_table_v6 : &state.routing_table_v4); + + int index_found = -1; + for (RoutingTableEntry* entry = table_to_use->entries; entry < table_to_use->entries + table_to_use->size; ++entry) + { + if (entry->interface_index < 0 || LWPA_IP_IS_INVALID(&entry->mask)) + continue; + + // Check each route to see if it matches the destination address explicitly + if (lwpa_ip_network_portions_equal(&entry->addr, dest, &entry->mask)) + { + index_found = entry->interface_index; + break; + } + } + + // Fall back to the default route + if (index_found < 0 && table_to_use->default_route) + index_found = table_to_use->default_route->interface_index; + + // Find the network interface with the correct index + if (index_found >= 0) + { + for (LwpaNetintInfo* netint_entry = state.lwpa_netints; netint_entry < state.lwpa_netints + state.num_netints; + ++netint_entry) + { + if (netint_entry->ifindex == index_found) + { + *netint = *netint_entry; + return kLwpaErrOk; + } + } + } + return kLwpaErrNotFound; +} + +/****************************************************************************** + * Internal Functions + *****************************************************************************/ + +lwpa_error_t build_routing_tables() +{ + lwpa_error_t res = build_routing_table(AF_INET, &state.routing_table_v4); + if (res == kLwpaErrOk) + { + res = build_routing_table(AF_INET6, &state.routing_table_v6); + } + + if (res != kLwpaErrOk) + free_routing_tables(); + +#if LWPA_NETINT_DEBUG_OUTPUT + debug_print_routing_table(&state.routing_table_v4); + debug_print_routing_table(&state.routing_table_v6); +#endif + + return res; +} + +lwpa_error_t build_routing_table(int family, RoutingTable* table) +{ + // Create a netlink socket, send a netlink request to get the routing table, and receive the + // reply. If the buffer was not big enough, repeat (cannot reuse the same socket because we've + // often received partial messages that must be discarded) + + lwpa_error_t result = kLwpaErrOk; + bool done = false; + size_t recv_buf_size = 2048; // Tests show this is usually enough for small routing tables + while (result == kLwpaErrOk && !done) + { + struct sockaddr_nl addr; + memset(&addr, 0, sizeof(struct sockaddr_nl)); + addr.nl_family = AF_NETLINK; + + int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (sock == -1) + result = errno_os_to_lwpa(errno); + + if (result == kLwpaErrOk) + { + if (0 != bind(sock, (struct sockaddr*)&addr, sizeof(addr))) + result = errno_os_to_lwpa(errno); + } + + if (result == kLwpaErrOk) + result = send_netlink_route_request(sock, family); + + if (result == kLwpaErrOk) + { + result = receive_netlink_route_reply(sock, family, recv_buf_size, table); + switch (result) + { + case kLwpaErrOk: + done = true; + break; + case kLwpaErrBufSize: + recv_buf_size *= 2; + result = kLwpaErrOk; + break; + default: + break; + } + } + + close(sock); + } + return result; +} + +lwpa_error_t send_netlink_route_request(int socket, int family) +{ + // Build the request + RtNetlinkRequest req; + memset(&req, 0, sizeof(req)); + req.nl_header.nlmsg_len = NLMSG_LENGTH(sizeof(RtNetlinkRequest)); + req.nl_header.nlmsg_type = RTM_GETROUTE; + req.nl_header.nlmsg_flags = (__u16)(NLM_F_REQUEST | NLM_F_DUMP); + req.nl_header.nlmsg_pid = (__u32)getpid(); + req.rt_msg.rtm_family = (unsigned char)family; + req.rt_msg.rtm_table = RT_TABLE_MAIN; + + // Send it to the kernel + struct sockaddr_nl naddr; + memset(&naddr, 0, sizeof(naddr)); + naddr.nl_family = AF_NETLINK; + + if (sendto(socket, &req.nl_header, req.nl_header.nlmsg_len, 0, (struct sockaddr*)&naddr, sizeof(naddr)) >= 0) + return kLwpaErrOk; + else + return errno_os_to_lwpa(errno); +} + +lwpa_error_t receive_netlink_route_reply(int sock, int family, size_t buf_size, RoutingTable* table) +{ + // Allocate slightly larger than buf_size, so we can detect when more room is needed + size_t real_size = buf_size + 20; + char* buffer = (char*)malloc(real_size); + if (!buffer) + return kLwpaErrNoMem; + memset(buffer, 0, real_size); + + char* cur_ptr = buffer; + size_t nl_msg_size = 0; + + // Read from the socket until the NLMSG_DONE is returned in the type of the RTNETLINK message + while (1) + { + // While we are receiving with real_size, checking against buf_size will detect when we've + // passed the limit given by the app + if (buf_size <= nl_msg_size) + { + free(buffer); + return kLwpaErrBufSize; + } + + ssize_t recv_res = recv(sock, cur_ptr, real_size - nl_msg_size, 0); + if (recv_res == -1) + { + free(buffer); + return errno_os_to_lwpa(errno); + } + + struct nlmsghdr* nl_header = (struct nlmsghdr*)cur_ptr; + + if (nl_header->nlmsg_type == NLMSG_DONE) + break; + + // Adjust our position in the buffer and size received + cur_ptr += recv_res; + nl_msg_size += (size_t)recv_res; + } + + lwpa_error_t parse_res = parse_netlink_route_reply(family, buffer, nl_msg_size, table); + + free(buffer); + return parse_res; +} + +lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl_msg_size, RoutingTable* table) +{ + table->size = 0; + table->entries = NULL; + table->default_route = NULL; + + // Parse the result + // outer loop: loops thru all the NETLINK headers that also include the route entry header + struct nlmsghdr* nl_header = (struct nlmsghdr*)buffer; + for (; NLMSG_OK(nl_header, nl_msg_size); nl_header = NLMSG_NEXT(nl_header, nl_msg_size)) + { + RoutingTableEntry new_entry; + init_routing_table_entry(&new_entry); + + bool new_entry_valid = true; + + // get route entry header + struct rtmsg* rt_message = (struct rtmsg*)NLMSG_DATA(nl_header); + + // Filter out entries from the local routing table. Netlink seems to give us those even though + // we only asked for the main one. + if (rt_message->rtm_type != RTN_LOCAL && rt_message->rtm_type != RTN_BROADCAST && + rt_message->rtm_type != RTN_ANYCAST) + { + // inner loop: loop thru all the attributes of one route entry. + struct rtattr* rt_attributes = (struct rtattr*)RTM_RTA(rt_message); + unsigned int rt_attr_size = (unsigned int)RTM_PAYLOAD(nl_header); + for (; RTA_OK(rt_attributes, rt_attr_size); rt_attributes = RTA_NEXT(rt_attributes, rt_attr_size)) + { + // We only care about the gateway and DST attribute + if (rt_attributes->rta_type == RTA_DST) + { + if (family == AF_INET6) + LWPA_IP_SET_V6_ADDRESS(&new_entry.addr, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); + else + LWPA_IP_SET_V4_ADDRESS(&new_entry.addr, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); + } + else if (rt_attributes->rta_type == RTA_GATEWAY) + { + if (family == AF_INET6) + LWPA_IP_SET_V6_ADDRESS(&new_entry.gateway, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); + else + LWPA_IP_SET_V4_ADDRESS(&new_entry.gateway, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); + } + else if (rt_attributes->rta_type == RTA_OIF) + { + new_entry.interface_index = *((int*)RTA_DATA(rt_attributes)); + } + else if (rt_attributes->rta_type == RTA_PRIORITY) + { + new_entry.metric = *((int*)RTA_DATA(rt_attributes)); + } + } + } + else + { + new_entry_valid = false; + } + + if (!LWPA_IP_IS_INVALID(&new_entry.addr)) + { + new_entry.mask = lwpa_ip_mask_from_length(new_entry.addr.type, rt_message->rtm_dst_len); + } + + // Insert the new entry into the list + if (new_entry_valid) + { + ++table->size; + if (table->entries) + table->entries = (RoutingTableEntry*)realloc(table->entries, table->size * sizeof(RoutingTableEntry)); + else + table->entries = (RoutingTableEntry*)malloc(sizeof(RoutingTableEntry)); + table->entries[table->size - 1] = new_entry; + } + } + + if (table->size > 0) + { + qsort(table->entries, table->size, sizeof(RoutingTableEntry), compare_routing_table_entries); + + // Mark the default route with the lowest metric (the first one we encounter after sorting the + // table) + for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) + { + if (LWPA_IP_IS_INVALID(&entry->addr) && LWPA_IP_IS_INVALID(&entry->mask) && !LWPA_IP_IS_INVALID(&entry->gateway)) + { + table->default_route = entry; + break; + } + } + return kLwpaErrOk; + } + else + { + return kLwpaErrSys; + } +} + +void init_routing_table_entry(RoutingTableEntry* entry) +{ + LWPA_IP_SET_INVALID(&entry->addr); + LWPA_IP_SET_INVALID(&entry->mask); + LWPA_IP_SET_INVALID(&entry->gateway); + entry->interface_index = -1; + entry->metric = INT_MAX; +} + +int compare_routing_table_entries(const void* a, const void* b) +{ + RoutingTableEntry* e1 = (RoutingTableEntry*)a; + RoutingTableEntry* e2 = (RoutingTableEntry*)b; + + unsigned int mask_length_1 = lwpa_ip_mask_length(&e1->mask); + unsigned int mask_length_2 = lwpa_ip_mask_length(&e2->mask); + + // Sort by mask length in descending order - within the same mask length, sort by metric in + // ascending order. + if (mask_length_1 == mask_length_2) + { + return (e1->metric > e2->metric) - (e1->metric < e2->metric); + } + else + { + return (mask_length_1 < mask_length_2) - (mask_length_1 > mask_length_2); + } +} + +/* Quick helper for enumerate_netints() to determine entries to skip in the linked list. */ +static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) +{ + // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. + return (!ifaddr->ifa_addr || (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6)); +} + +lwpa_error_t enumerate_netints() +{ + lwpa_error_t res = build_routing_tables(); + if (res != kLwpaErrOk) + return res; + + int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (ioctl_sock == -1) + return errno_os_to_lwpa(errno); + + if (getifaddrs(&state.os_addrs) < 0) + { + close(ioctl_sock); + return errno_os_to_lwpa(errno); + } + + // Pass 1: Total the number of addresses + state.num_netints = 0; + for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + { + if (should_skip_ifaddr(ifaddr)) + continue; + + ++state.num_netints; + } + + if (state.num_netints == 0) + { + freeifaddrs(state.os_addrs); + close(ioctl_sock); + return kLwpaErrNoNetints; + } + + // Allocate our interface array + state.lwpa_netints = (LwpaNetintInfo*)calloc(state.num_netints, sizeof(LwpaNetintInfo)); + if (!state.lwpa_netints) + { + freeifaddrs(state.os_addrs); + close(ioctl_sock); + return kLwpaErrNoMem; + } + + // Pass 2: Fill in all the info about each address + size_t current_lwpa_index = 0; + for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + { + if (should_skip_ifaddr(ifaddr)) + continue; + + LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; + + // Interface name + strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); + current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; + + // Interface address + LwpaSockaddr temp_sockaddr; + sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_addr); + current_info->addr = temp_sockaddr.ip; + + // Interface netmask + sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); + current_info->mask = temp_sockaddr.ip; + + // Struct ifreq to use with ioctl() calls + struct ifreq if_req; + strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); + + // Hardware address + int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); + if (ioctl_res == 0) + memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); + else + memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); + + // Interface index + ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); + if (ioctl_res == 0) + current_info->ifindex = if_req.ifr_ifindex; + else + current_info->ifindex = -1; + + // Is Default + if (LWPA_IP_IS_V4(¤t_info->addr) && state.routing_table_v4.default_route && + current_info->ifindex == state.routing_table_v4.default_route->interface_index) + { + current_info->is_default = true; + } + else if (LWPA_IP_IS_V6(¤t_info->addr) && state.routing_table_v6.default_route && + current_info->ifindex == state.routing_table_v6.default_route->interface_index) + { + current_info->is_default = true; + } + + current_lwpa_index++; + } + + // Sort the interfaces by OS index + qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); + + // Store the locations of the default netints for access by the API function + for (size_t i = 0; i < state.num_netints; ++i) + { + LwpaNetintInfo* netint = &state.lwpa_netints[i]; + if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) + { + state.have_default_netint_index_v4 = true; + state.default_netint_index_v4 = i; + } + else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) + { + state.have_default_netint_index_v6 = true; + state.default_netint_index_v6 = i; + } + } + close(ioctl_sock); + return kLwpaErrOk; +} + +int compare_netints(const void* a, const void* b) +{ + LwpaNetintInfo* netint1 = (LwpaNetintInfo*)a; + LwpaNetintInfo* netint2 = (LwpaNetintInfo*)b; + + return (netint1->ifindex > netint2->ifindex) - (netint1->ifindex < netint2->ifindex); +} + +void free_routing_tables() +{ + free_routing_table(&state.routing_table_v4); + free_routing_table(&state.routing_table_v6); +} + +void free_routing_table(RoutingTable* table) +{ + if (table->entries) + { + free(table->entries); + table->entries = NULL; + } + table->size = 0; +} + +void free_netints() +{ + if (state.os_addrs) + { + freeifaddrs(state.os_addrs); + state.os_addrs = NULL; + } + if (state.lwpa_netints) + { + free(state.lwpa_netints); + state.lwpa_netints = NULL; + } + + free_routing_tables(); +} + +#if LWPA_NETINT_DEBUG_OUTPUT +void debug_print_routing_table(RoutingTable* table) +{ + printf("%-40s %-40s %-40s %-10s %s\n", "Address", "Mask", "Gateway", "Metric", "Index"); + for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) + { + char addr_str[LWPA_INET6_ADDRSTRLEN]; + char mask_str[LWPA_INET6_ADDRSTRLEN]; + char gw_str[LWPA_INET6_ADDRSTRLEN]; + + if (!LWPA_IP_IS_INVALID(&entry->addr)) + lwpa_inet_ntop(&entry->addr, addr_str, LWPA_INET6_ADDRSTRLEN); + else + strcpy(addr_str, "0.0.0.0"); + + if (!LWPA_IP_IS_INVALID(&entry->mask)) + lwpa_inet_ntop(&entry->mask, mask_str, LWPA_INET6_ADDRSTRLEN); + else + strcpy(mask_str, "0.0.0.0"); + + if (!LWPA_IP_IS_INVALID(&entry->gateway)) + lwpa_inet_ntop(&entry->gateway, gw_str, LWPA_INET6_ADDRSTRLEN); + else + strcpy(gw_str, "0.0.0.0"); + + printf("%-40s %-40s %-40s %-10d %d\n", addr_str, mask_str, gw_str, entry->metric, entry->interface_index); + } +} +#endif diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c new file mode 100644 index 000000000..7e443234a --- /dev/null +++ b/src/os/macos/lwpa/os_socket.c @@ -0,0 +1,958 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/socket.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os_error.h" + +/**************************** Private constants ******************************/ + +/* Per the docs, this constant is ignored in Linux 2.6.8 and later, but must be > 0. + * Here is a random number. */ +#define EPOLL_CREATE_SIZE 1024 + +/****************************** Private types ********************************/ + +/* A struct to track sockets being polled by the lwpa_poll() API */ +typedef struct LwpaPollSocket +{ + // 'sock' must always remain as the first member in the struct to facilitate an LwpaRbTree lookup + // shortcut + lwpa_socket_t sock; + lwpa_poll_events_t events; + void* user_data; +} LwpaPollSocket; + +/**************************** Private variables ******************************/ + +/* clang-format off */ + +#define LWPA_NUM_SHUT 3 +static const int shutmap[LWPA_NUM_SHUT] = +{ + SHUT_RD, + SHUT_WR, + SHUT_RDWR +}; + +#define LWPA_NUM_AF 3 +static const int sfmap[LWPA_NUM_AF] = +{ + AF_UNSPEC, + AF_INET, + AF_INET6 +}; + +#define LWPA_NUM_TYPE 2 +static const int stmap[LWPA_NUM_TYPE] = +{ + SOCK_STREAM, + SOCK_DGRAM +}; + +#define LWPA_NUM_AIF 8 +static const int aiflagmap[LWPA_NUM_AIF] = +{ + 0, + AI_PASSIVE, + AI_CANONNAME, + AI_PASSIVE | AI_CANONNAME, + AI_NUMERICHOST, + AI_PASSIVE | AI_NUMERICHOST, + AI_CANONNAME | AI_NUMERICHOST, + AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST +}; + +static const int aifammap[LWPA_NUM_AF] = +{ + AF_UNSPEC, + AF_INET, + AF_INET6 +}; + +#define LWPA_NUM_IPPROTO 6 +static const int aiprotmap[LWPA_NUM_IPPROTO] = +{ + 0, + IPPROTO_IP, + IPPROTO_ICMPV6, + IPPROTO_IPV6, + IPPROTO_TCP, + IPPROTO_UDP +}; + +/* clang-format on */ + +/*********************** Private function prototypes *************************/ + +// Helpers for lwpa_setsockopt() +static void ms_to_timeval(int ms, struct timeval* tv); +static int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); + +// Helpers for lwpa_poll API +static void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt); +static void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, + lwpa_poll_events_t* events); + +static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); +static LwpaRbNode* poll_socket_alloc(); +static void poll_socket_free(LwpaRbNode* node); + +/*************************** Function definitions ****************************/ + +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) +{ + if (pfsa->sa_family == AF_INET) + { + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; + sa->port = ntohs(sin->sin_port); + LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); + return true; + } + else if (pfsa->sa_family == AF_INET6) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; + sa->port = ntohs(sin6->sin6_port); + LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); + return true; + } + return false; +} + +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) +{ + size_t ret = 0; + if (LWPA_IP_IS_V4(&sa->ip)) + { + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; + sin->sin_family = AF_INET; + sin->sin_port = htons(sa->port); + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); + ret = sizeof(struct sockaddr_in); + } + else if (LWPA_IP_IS_V6(&sa->ip)) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = htons(sa->port); + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); + ret = sizeof(struct sockaddr_in6); + } + return ret; +} + +lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) +{ + if (!conn_sock) + return kLwpaErrInvalid; + + struct sockaddr_storage ss; + socklen_t sa_size = sizeof ss; + int res = accept(id, (struct sockaddr*)&ss, &sa_size); + + if (res != -1) + { + if (address && !sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) + { + close(res); + return kLwpaErrSys; + } + *conn_sock = res; + return kLwpaErrOk; + } + return errno_os_to_lwpa(errno); +} + +lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) +{ + if (!address) + return kLwpaErrInvalid; + + struct sockaddr_storage ss; + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); + if (sa_size == 0) + return kLwpaErrInvalid; + + int res = bind(id, (struct sockaddr*)&ss, sa_size); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); +} + +lwpa_error_t lwpa_close(lwpa_socket_t id) +{ + int res = close(id); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); +} + +lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) +{ + if (!address) + return kLwpaErrInvalid; + + struct sockaddr_storage ss; + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); + if (sa_size == 0) + return kLwpaErrInvalid; + + int res = connect(id, (struct sockaddr*)&ss, sa_size); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); +} + +lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) +{ + /* TODO */ + (void)id; + (void)address; + return kLwpaErrNotImpl; +} + +lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) +{ + if (!address) + return kLwpaErrInvalid; + + struct sockaddr_storage ss; + socklen_t size = sizeof ss; + int res = getsockname(id, (struct sockaddr*)&ss, &size); + if (res == 0) + { + if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) + return kLwpaErrSys; + return kLwpaErrOk; + } + return errno_os_to_lwpa(errno); +} + +lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) +{ + /* TODO */ + (void)id; + (void)level; + (void)option_name; + (void)option_value; + (void)option_len; + return kLwpaErrNotImpl; +} + +lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) +{ + int res = listen(id, backlog); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); +} + +int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) +{ + if (!buffer) + return kLwpaErrInvalid; + + int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; + int res = (int)recv(id, buffer, length, impl_flags); + return (res >= 0 ? res : (int)errno_os_to_lwpa(errno)); +} + +int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address) +{ + if (!buffer) + return (int)kLwpaErrInvalid; + + struct sockaddr_storage fromaddr; + socklen_t fromlen = sizeof fromaddr; + int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; + int res = (int)recvfrom(id, buffer, length, impl_flags, (struct sockaddr*)&fromaddr, &fromlen); + + if (res >= 0) + { + if (address && fromlen > 0) + { + if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) + return kLwpaErrSys; + } + return res; + } + return (int)errno_os_to_lwpa(errno); +} + +int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) +{ + (void)flags; + + if (!message) + return (int)kLwpaErrInvalid; + + int res = (int)send(id, message, length, 0); + return (res >= 0 ? res : (int)errno_os_to_lwpa(errno)); +} + +int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) +{ + (void)flags; + + if (!dest_addr || !message) + return (int)kLwpaErrInvalid; + + struct sockaddr_storage ss; + socklen_t ss_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr); + if (ss_size == 0) + return (int)kLwpaErrSys; + + int res = (int)sendto(id, message, length, 0, (struct sockaddr*)&ss, ss_size); + + return (res >= 0 ? res : (int)errno_os_to_lwpa(errno)); +} + +lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) +{ + int res = -1; + + if (!option_value) + return kLwpaErrInvalid; + + // TODO this OS implementation could be simplified by use of socket option lookup arrays. + switch (level) + { + case LWPA_SOL_SOCKET: + res = setsockopt_socket(id, option_name, option_value, option_len); + break; + case LWPA_IPPROTO_IP: + res = setsockopt_ip(id, option_name, option_value, option_len); + break; + case LWPA_IPPROTO_IPV6: + res = setsockopt_ip6(id, option_name, option_value, option_len); + break; + default: + return kLwpaErrInvalid; + } + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); +} + +int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_SO_RCVBUF: + return setsockopt(id, SOL_SOCKET, SO_RCVBUF, option_value, (socklen_t)option_len); + case LWPA_SO_SNDBUF: + return setsockopt(id, SOL_SOCKET, SO_SNDBUF, option_value, (socklen_t)option_len); + case LWPA_SO_RCVTIMEO: + if (option_len == sizeof(int)) + { + int val = *(int*)option_value; + struct timeval sys_val; + ms_to_timeval(val, &sys_val); + return setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, &sys_val, sizeof sys_val); + } + break; + case LWPA_SO_SNDTIMEO: + if (option_len == sizeof(int)) + { + int val = *(int*)option_value; + struct timeval sys_val; + ms_to_timeval(val, &sys_val); + return setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, &sys_val, sizeof sys_val); + } + break; + case LWPA_SO_REUSEADDR: + return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, option_value, (socklen_t)option_len); + case LWPA_SO_REUSEPORT: + return setsockopt(id, SOL_SOCKET, SO_REUSEPORT, option_value, (socklen_t)option_len); + case LWPA_SO_BROADCAST: + return setsockopt(id, SOL_SOCKET, SO_BROADCAST, option_value, (socklen_t)option_len); + case LWPA_SO_KEEPALIVE: + return setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, option_value, (socklen_t)option_len); + case LWPA_SO_LINGER: + if (option_len == sizeof(LwpaLinger)) + { + LwpaLinger* ll = (LwpaLinger*)option_value; + struct linger val; + val.l_onoff = (u_short)ll->onoff; + val.l_linger = (u_short)ll->linger; + return setsockopt(id, SOL_SOCKET, SO_LINGER, &val, sizeof val); + } + break; + case LWPA_SO_ERROR: // Set not supported + case LWPA_SO_TYPE: // Set not supported + default: + break; + } + // If we got here, something was invalid. Set errno accordingly + errno = EINVAL; + return -1; +} + +int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_IP_TTL: + return setsockopt(id, IPPROTO_IP, IP_TTL, option_value, (socklen_t)option_len); + case LWPA_IP_ADD_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) + { + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + return setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &val, sizeof val); + } + } + break; + case LWPA_IP_DROP_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) + { + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + return setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, &val, sizeof val); + } + } + break; + case LWPA_MCAST_JOIN_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V4(&greq->group) && greq->ifindex >= 0) + { + struct group_req val; + val.gr_interface = (uint32_t)greq->ifindex; + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + return setsockopt(id, IPPROTO_IP, MCAST_JOIN_GROUP, &val, sizeof val); + } + } + break; + case LWPA_MCAST_LEAVE_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V4(&greq->group) && greq->ifindex >= 0) + { + struct group_req val; + val.gr_interface = (uint32_t)greq->ifindex; + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + return setsockopt(id, IPPROTO_IP, MCAST_LEAVE_GROUP, &val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_IF: + if (option_len == sizeof(LwpaIpAddr)) + { + LwpaIpAddr* netint = (LwpaIpAddr*)option_value; + if (LWPA_IP_IS_V4(netint)) + { + struct in_addr val; + val.s_addr = LWPA_IP_V4_ADDRESS(netint); + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_TTL: + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, option_value, (socklen_t)option_len); + case LWPA_IP_MULTICAST_LOOP: + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, option_value, (socklen_t)option_len); + default: + break; + } + // If we got here, something was invalid. Set errno accordingly + errno = EINVAL; + return -1; +} + +int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_MCAST_JOIN_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group) && greq->ifindex >= 0) + { + struct group_req val; + val.gr_interface = (uint32_t)greq->ifindex; + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, sizeof val); + } + } + break; + case LWPA_MCAST_LEAVE_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group) && greq->ifindex >= 0) + { + struct group_req val; + val.gr_interface = (uint32_t)greq->ifindex; + + memset(&val.gr_group, 0, sizeof val.gr_group); + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, MCAST_LEAVE_GROUP, &val, sizeof val); + } + } + break; + default: /* Other IPv6 options TODO on linux. */ + break; + } + // If we got here, something was invalid. Set errno accordingly + errno = EINVAL; + return -1; +} + +void ms_to_timeval(int ms, struct timeval* tv) +{ + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; +} + +lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) +{ + if (how >= 0 && how < LWPA_NUM_SHUT) + { + int res = shutdown(id, shutmap[how]); + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); + } + return kLwpaErrInvalid; +} + +lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* id) +{ + if (id) + { + if (family < LWPA_NUM_AF && type < LWPA_NUM_TYPE) + { + int sock = socket(sfmap[family], stmap[type], 0); + if (sock != -1) + { + *id = sock; + return kLwpaErrOk; + } + else + { + *id = LWPA_SOCKET_INVALID; + return errno_os_to_lwpa(errno); + } + } + else + { + *id = LWPA_SOCKET_INVALID; + } + } + return kLwpaErrInvalid; +} + +lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) +{ + int val = fcntl(id, F_GETFL, 0); + if (val >= 0) + { + val = fcntl(id, F_SETFL, val | O_NONBLOCK); + } + return (val >= 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); +} + +lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) +{ + if (!context) + return kLwpaErrInvalid; + + context->epoll_fd = epoll_create(EPOLL_CREATE_SIZE); + if (context->epoll_fd >= 0) + { + lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); + context->valid = true; + return kLwpaErrOk; + } + else + { + return errno_os_to_lwpa(errno); + } +} + +void lwpa_poll_context_deinit(LwpaPollContext* context) +{ + if (context && context->valid) + { + lwpa_rbtree_clear(&context->sockets); + close(context->epoll_fd); + context->valid = false; + } +} + +lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, + void* user_data) +{ + if (context && context->valid && socket != LWPA_SOCKET_INVALID && (events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)malloc(sizeof(LwpaPollSocket)); + if (sock_desc) + { + sock_desc->sock = socket; + sock_desc->events = events; + sock_desc->user_data = user_data; + int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); + if (insert_res != 0) + { + struct epoll_event ep_evt; + events_lwpa_to_epoll(events, &ep_evt); + ep_evt.data.fd = socket; + + int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_ADD, socket, &ep_evt); + if (res == 0) + { + return kLwpaErrOk; + } + else + { + // Our node dealloc function also deallocates sock_desc, so no need to free it here. + lwpa_rbtree_remove(&context->sockets, sock_desc); + return errno_os_to_lwpa(errno); + } + } + else + { + free(sock_desc); + return kLwpaErrNoMem; + } + } + else + { + return kLwpaErrNoMem; + } + } + else + { + return kLwpaErrInvalid; + } +} + +lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, + void* new_user_data) +{ + if (context && context->valid && socket != LWPA_SOCKET_INVALID && (new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); + if (sock_desc) + { + struct epoll_event ep_evt; + events_lwpa_to_epoll(new_events, &ep_evt); + ep_evt.data.fd = socket; + + int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_MOD, socket, &ep_evt); + if (res == 0) + { + sock_desc->events = new_events; + sock_desc->user_data = new_user_data; + return kLwpaErrOk; + } + else + { + return errno_os_to_lwpa(errno); + } + } + else + { + return kLwpaErrNotFound; + } + } + else + { + return kLwpaErrInvalid; + } +} + +void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) +{ + if (context && context->valid) + { + // Need a dummy struct for portability - some versions require event to always be non-NULL + // even though it is ignored + struct epoll_event ep_evt; + epoll_ctl(context->epoll_fd, EPOLL_CTL_DEL, socket, &ep_evt); + lwpa_rbtree_remove(&context->sockets, &socket); + } +} + +lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms) +{ + if (context && context->valid && event) + { + if (lwpa_rbtree_size(&context->sockets) > 0) + { + int sys_timeout = (timeout_ms == LWPA_WAIT_FOREVER ? -1 : timeout_ms); + + struct epoll_event epoll_evt; + int wait_res = epoll_wait(context->epoll_fd, &epoll_evt, 1, sys_timeout); + if (wait_res > 0) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &epoll_evt.data.fd); + if (sock_desc) + { + event->socket = sock_desc->sock; + events_epoll_to_lwpa(&epoll_evt, sock_desc, &event->events); + event->err = kLwpaErrOk; + event->user_data = sock_desc->user_data; + + // Check for errors + int error; + socklen_t error_size = sizeof error; + if (getsockopt(sock_desc->sock, SOL_SOCKET, SO_ERROR, &error, &error_size) == 0) + { + if (error != 0) + { + event->events |= LWPA_POLL_ERR; + event->err = errno_os_to_lwpa(error); + } + } + + return kLwpaErrOk; + } + else + { + return kLwpaErrSys; + } + } + else if (wait_res == 0) + { + return kLwpaErrTimedOut; + } + else + { + return errno_os_to_lwpa(errno); + } + } + else + { + return kLwpaErrNoSockets; + } + } + else + { + return kLwpaErrInvalid; + } +} + +void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt) +{ + epoll_evt->events = 0; + if (events & LWPA_POLL_IN) + epoll_evt->events |= EPOLLIN; + if ((events & LWPA_POLL_OUT) || (events & LWPA_POLL_CONNECT)) + epoll_evt->events |= EPOLLOUT; + if (events & LWPA_POLL_OOB) + epoll_evt->events |= EPOLLPRI; +} + +void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, + lwpa_poll_events_t* events_out) +{ + *events_out = 0; + if (epoll_evt->events & EPOLLIN) + *events_out |= LWPA_POLL_IN; + if (epoll_evt->events & EPOLLOUT) + { + if (sock_desc->events & LWPA_POLL_OUT) + *events_out |= LWPA_POLL_OUT; + if (sock_desc->events & LWPA_POLL_CONNECT) + *events_out |= LWPA_POLL_CONNECT; + } + if (epoll_evt->events & EPOLLPRI) + *events_out |= (LWPA_POLL_OOB); + if (epoll_evt->events & EPOLLERR) + *events_out |= (LWPA_POLL_ERR); +} + +int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b) +{ + LwpaPollSocket* a = (LwpaPollSocket*)node_a->value; + LwpaPollSocket* b = (LwpaPollSocket*)node_b->value; + + return (a->sock > b->sock) - (a->sock < b->sock); +} + +LwpaRbNode* poll_socket_alloc() +{ + return (LwpaRbNode*)malloc(sizeof(LwpaRbNode)); +} + +void poll_socket_free(LwpaRbNode* node) +{ + if (node) + { + free(node->value); + free(node); + } +} + +lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, + LwpaAddrinfo* result) +{ + int res; + struct addrinfo* pf_res; + struct addrinfo pf_hints; + + if ((!hostname && !service) || !result) + return kLwpaErrInvalid; + + memset(&pf_hints, 0, sizeof pf_hints); + if (hints) + { + pf_hints.ai_flags = (hints->ai_flags < LWPA_NUM_AIF) ? aiflagmap[hints->ai_flags] : 0; + pf_hints.ai_family = (hints->ai_family < LWPA_NUM_AF) ? aifammap[hints->ai_family] : AF_UNSPEC; + pf_hints.ai_socktype = (hints->ai_socktype < LWPA_NUM_TYPE) ? stmap[hints->ai_socktype] : 0; + pf_hints.ai_protocol = (hints->ai_protocol < LWPA_NUM_IPPROTO) ? aiprotmap[hints->ai_protocol] : 0; + } + + res = getaddrinfo(hostname, service, hints ? &pf_hints : NULL, &pf_res); + if (res == 0) + { + result->pd[0] = pf_res; + result->pd[1] = pf_res; + if (!lwpa_nextaddr(result)) + res = -1; + } + return (res == 0 ? kLwpaErrOk : errno_os_to_lwpa(res)); +} + +bool lwpa_nextaddr(LwpaAddrinfo* ai) +{ + if (ai && ai->pd[1]) + { + struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; + ai->ai_flags = 0; + if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + return false; + + /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS + * constants. Ugh. */ + if (pf_ai->ai_family == AF_INET) + ai->ai_family = LWPA_AF_INET; + else if (pf_ai->ai_family == AF_INET6) + ai->ai_family = LWPA_AF_INET6; + else + ai->ai_family = LWPA_AF_UNSPEC; + if (pf_ai->ai_socktype == SOCK_DGRAM) + ai->ai_socktype = LWPA_DGRAM; + else if (pf_ai->ai_socktype == SOCK_STREAM) + ai->ai_socktype = LWPA_STREAM; + else + ai->ai_socktype = 0; + if (pf_ai->ai_protocol == IPPROTO_UDP) + ai->ai_protocol = LWPA_IPPROTO_UDP; + else if (pf_ai->ai_protocol == IPPROTO_TCP) + ai->ai_protocol = LWPA_IPPROTO_TCP; + else + ai->ai_protocol = 0; + ai->ai_canonname = pf_ai->ai_canonname; + ai->pd[1] = pf_ai->ai_next; + + return true; + } + return false; +} + +void lwpa_freeaddrinfo(LwpaAddrinfo* ai) +{ + if (ai) + freeaddrinfo((struct addrinfo*)ai->pd[0]); +} + +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (src->type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); + if (NULL != inet_ntop(AF_INET, &addr, dest, (socklen_t)size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); + if (NULL != inet_ntop(AF_INET6, &addr, dest, (socklen_t)size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + default: + return kLwpaErrInvalid; + } +} + +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + if (1 != inet_pton(AF_INET, src, &addr)) + return kLwpaErrSys; + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); + return kLwpaErrOk; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + if (1 != inet_pton(AF_INET6, src, &addr)) + return kLwpaErrSys; + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); + return kLwpaErrOk; + } + default: + return kLwpaErrInvalid; + } +} diff --git a/src/os/macos/lwpa/os_thread.c b/src/os/macos/lwpa/os_thread.c new file mode 100644 index 000000000..d8aeb85e6 --- /dev/null +++ b/src/os/macos/lwpa/os_thread.c @@ -0,0 +1,70 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/thread.h" + +/*********************** Private function prototypes *************************/ + +static void* thread_func_internal(void* arg); + +/*************************** Function definitions ****************************/ + +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg) +{ + if (!id || !params || !thread_fn) + return false; + + pthread_attr_t thread_attr; + pthread_attr_t* p_thread_attr = NULL; + + if (params && params->stack_size != LWPA_THREAD_DEFAULT_STACK) + { + pthread_attr_init(&thread_attr); + pthread_attr_setstacksize(&thread_attr, params->stack_size); + p_thread_attr = &thread_attr; + } + + id->fn = thread_fn; + id->arg = thread_arg; + bool res = (0 == pthread_create(&id->handle, p_thread_attr, thread_func_internal, id)); + + if (p_thread_attr) + pthread_attr_destroy(p_thread_attr); + + return res; +} + +bool lwpa_thread_stop(lwpa_thread_t* id) +{ + if (id) + { + return (0 == pthread_join(id->handle, NULL)); + } + return false; +} + +void* thread_func_internal(void* arg) +{ + lwpa_thread_t* thread_data = (lwpa_thread_t*)arg; + if (thread_data && thread_data->fn) + { + thread_data->fn(thread_data->arg); + } + return NULL; +} diff --git a/src/os/macos/lwpa/os_timer.c b/src/os/macos/lwpa/os_timer.c new file mode 100644 index 000000000..813c97007 --- /dev/null +++ b/src/os/macos/lwpa/os_timer.c @@ -0,0 +1,32 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/timer.h" + +#include + +uint32_t lwpa_getms() +{ + struct timespec os_time; + if (0 == clock_gettime(CLOCK_MONOTONIC, &os_time)) + { + return (uint32_t)(os_time.tv_sec * 1000 + (os_time.tv_nsec / 1000000)); + } + return 0; +} diff --git a/src/os/macos/lwpa/os_uuid.c b/src/os/macos/lwpa/os_uuid.c new file mode 100644 index 000000000..dbd03ce8d --- /dev/null +++ b/src/os/macos/lwpa/os_uuid.c @@ -0,0 +1,58 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/uuid.h" + +#include + +// Use libuuid on Linux to generate UUIDs. +// https://linux.die.net/man/3/uuid_generate + +lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) +{ + if (!uuid) + return kLwpaErrInvalid; + + uuid_t os_uuid; + uuid_generate_time(os_uuid); + memcpy(uuid->data, os_uuid, LWPA_UUID_BYTES); + return kLwpaErrOk; +} + +lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid) +{ + if (!uuid) + return kLwpaErrInvalid; + + uuid_t os_uuid; + uuid_generate_random(os_uuid); + memcpy(uuid->data, os_uuid, LWPA_UUID_BYTES); + return kLwpaErrOk; +} + +lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid* uuid) +{ + if (!uuid) + return kLwpaErrInvalid; + + uuid_t os_uuid; + uuid_generate(os_uuid); + memcpy(uuid->data, os_uuid, LWPA_UUID_BYTES); + return kLwpaErrOk; +} From c005278dfc07b5b7347b715b922ebf2c66ddacce Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 11 Jun 2019 18:07:49 -0500 Subject: [PATCH 038/264] macOS WIP. Trying to figure out the BSD route messages. --- src/CMakeLists.txt | 5 + src/os/macos/lwpa/os_netint.c | 485 +++++++++++++++------------------- src/os/macos/lwpa/os_socket.c | 436 +++++++++++++++--------------- 3 files changed, 437 insertions(+), 489 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7e3139811..691321b8f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -109,6 +109,11 @@ if(LWPA_TARGET_OS STREQUAL windows) ${LWPA_ROOT}/src/os/windows/lwpa/winsock_error.c ) target_link_libraries(lwpa PUBLIC winmm ws2_32 Iphlpapi Rpcrt4) +elseif(LWPA_TARGET_OS STREQUAL macos) + target_sources(lwpa PRIVATE + ${LWPA_ROOT}/src/os/macos/lwpa/os_error.h + ${LWPA_ROOT}/src/os/macos/lwpa/os_error.c + ) elseif(LWPA_TARGET_OS STREQUAL linux) target_link_libraries(lwpa PUBLIC uuid) target_sources(lwpa PRIVATE diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c index 5a4269576..f701efb71 100644 --- a/src/os/macos/lwpa/os_netint.c +++ b/src/os/macos/lwpa/os_netint.c @@ -36,21 +36,18 @@ #include #include #include +#include #ifdef LWPA_NETINT_DEBUG_OUTPUT #include #endif #include -#include -#include -#include -#include #include -#include -#include +#include #include -#include +#include +#include #include "lwpa/socket.h" #include "lwpa/private/netint.h" @@ -74,13 +71,6 @@ typedef struct RoutingTable size_t size; } RoutingTable; -/* A composite struct representing an RT_NETLINK request sent over a netlink socket. */ -typedef struct RtNetlinkRequest -{ - struct nlmsghdr nl_header; - struct rtmsg rt_msg; -} RtNetlinkRequest; - /**************************** Private variables ******************************/ static struct LwpaNetintState @@ -109,10 +99,9 @@ static lwpa_error_t build_routing_table(int family, RoutingTable* table); static void free_routing_tables(); static void free_routing_table(RoutingTable* table); -// Interacting with RTNETLINK -static lwpa_error_t send_netlink_route_request(int socket, int family); -static lwpa_error_t receive_netlink_route_reply(int sock, int family, size_t buf_size, RoutingTable* table); -static lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl_msg_size, RoutingTable* table); +// Interacting with the BSD routing stack +static lwpa_error_t get_routing_table_dump(int family, uint8_t** buf, size_t* buf_len); +static lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, RoutingTable* table); // Manipulating routing table entries static void init_routing_table_entry(RoutingTableEntry* entry); @@ -257,133 +246,90 @@ lwpa_error_t build_routing_tables() lwpa_error_t build_routing_table(int family, RoutingTable* table) { - // Create a netlink socket, send a netlink request to get the routing table, and receive the - // reply. If the buffer was not big enough, repeat (cannot reuse the same socket because we've - // often received partial messages that must be discarded) - - lwpa_error_t result = kLwpaErrOk; - bool done = false; - size_t recv_buf_size = 2048; // Tests show this is usually enough for small routing tables - while (result == kLwpaErrOk && !done) - { - struct sockaddr_nl addr; - memset(&addr, 0, sizeof(struct sockaddr_nl)); - addr.nl_family = AF_NETLINK; + uint8_t* buf = NULL; + size_t buf_len = 0; - int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (sock == -1) - result = errno_os_to_lwpa(errno); + lwpa_error_t res = get_routing_table_dump(family, &buf, &buf_len); + if (res == kLwpaErrOk) + { + res = parse_routing_table_dump(family, buf, buf_len, table); + } - if (result == kLwpaErrOk) - { - if (0 != bind(sock, (struct sockaddr*)&addr, sizeof(addr))) - result = errno_os_to_lwpa(errno); - } + if (buf) + free(buf); + return res; +} - if (result == kLwpaErrOk) - result = send_netlink_route_request(sock, family); +// Get the routing table information from the system. +lwpa_error_t get_routing_table_dump(int family, uint8_t** buf, size_t* buf_len) +{ + // The MIB is a heirarchical series of codes determining the systcl operation to perform. + int mib[6]; + mib[0] = CTL_NET; // Networking messages + mib[1] = PF_ROUTE; // Routing messages + mib[2] = 0; // Reserved for this command, always 0 + mib[3] = family; // Address family + mib[4] = NET_RT_DUMP; // Dump routing table entries + mib[5] = 0; // Reserved for this command, always 0 + + // First pass just determines the size of buffer that is needed. + int sysctl_res = sysctl(mib, 6, NULL, buf_len, NULL, 0); + if ((sysctl_res != 0 && errno != ENOMEM) || *buf_len == 0) + return errno_os_to_lwpa(errno); - if (result == kLwpaErrOk) - { - result = receive_netlink_route_reply(sock, family, recv_buf_size, table); - switch (result) - { - case kLwpaErrOk: - done = true; - break; - case kLwpaErrBufSize: - recv_buf_size *= 2; - result = kLwpaErrOk; - break; - default: - break; - } - } + // Allocate the buffer + *buf = (uint8_t*)malloc(*buf_len); + if (!(*buf)) + return kLwpaErrNoMem; - close(sock); + // Second pass to actually get the info + sysctl_res = sysctl(mib, 6, *buf, buf_len, NULL, 0); + if (sysctl_res != 0 || *buf_len == 0) + { + free(*buf); + return errno_os_to_lwpa(errno); } - return result; -} -lwpa_error_t send_netlink_route_request(int socket, int family) -{ - // Build the request - RtNetlinkRequest req; - memset(&req, 0, sizeof(req)); - req.nl_header.nlmsg_len = NLMSG_LENGTH(sizeof(RtNetlinkRequest)); - req.nl_header.nlmsg_type = RTM_GETROUTE; - req.nl_header.nlmsg_flags = (__u16)(NLM_F_REQUEST | NLM_F_DUMP); - req.nl_header.nlmsg_pid = (__u32)getpid(); - req.rt_msg.rtm_family = (unsigned char)family; - req.rt_msg.rtm_table = RT_TABLE_MAIN; - - // Send it to the kernel - struct sockaddr_nl naddr; - memset(&naddr, 0, sizeof(naddr)); - naddr.nl_family = AF_NETLINK; - - if (sendto(socket, &req.nl_header, req.nl_header.nlmsg_len, 0, (struct sockaddr*)&naddr, sizeof(naddr)) >= 0) - return kLwpaErrOk; - else - return errno_os_to_lwpa(errno); + return kLwpaErrOk; } -lwpa_error_t receive_netlink_route_reply(int sock, int family, size_t buf_size, RoutingTable* table) -{ - // Allocate slightly larger than buf_size, so we can detect when more room is needed - size_t real_size = buf_size + 20; - char* buffer = (char*)malloc(real_size); - if (!buffer) - return kLwpaErrNoMem; - memset(buffer, 0, real_size); +// A function and some macros stolen from "Unix Network Programming: The Sockets Networking API" v3 +// by Stevens, Fenner, Rudoff, for parsing through the routing table dump. - char* cur_ptr = buffer; - size_t nl_msg_size = 0; +// This macro rounds up 'a' to the next multiple of 'size', which must be a power of 2. +#define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) - // Read from the socket until the NLMSG_DONE is returned in the type of the RTNETLINK message - while (1) +// This macro steps to the next socket address structure. If sa_len is 0, assume sizeof(u_long). +#define NEXT_SA(ap) \ + ap = (struct sockaddr*)((caddr_t)ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof(u_long)) : sizeof(u_long))) + +void get_rtaddrs(int addrs, struct sockaddr* sa, struct sockaddr** rti_info) +{ + for (int i = 0; i < RTAX_MAX; ++i) { - // While we are receiving with real_size, checking against buf_size will detect when we've - // passed the limit given by the app - if (buf_size <= nl_msg_size) + if (addrs & (1 << i)) { - free(buffer); - return kLwpaErrBufSize; + rti_info[i] = sa; + NEXT_SA(sa); } - - ssize_t recv_res = recv(sock, cur_ptr, real_size - nl_msg_size, 0); - if (recv_res == -1) + else { - free(buffer); - return errno_os_to_lwpa(errno); + rti_info[i] = NULL; } - - struct nlmsghdr* nl_header = (struct nlmsghdr*)cur_ptr; - - if (nl_header->nlmsg_type == NLMSG_DONE) - break; - - // Adjust our position in the buffer and size received - cur_ptr += recv_res; - nl_msg_size += (size_t)recv_res; } - - lwpa_error_t parse_res = parse_netlink_route_reply(family, buffer, nl_msg_size, table); - - free(buffer); - return parse_res; } -lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl_msg_size, RoutingTable* table) +lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, RoutingTable* table) { table->size = 0; table->entries = NULL; table->default_route = NULL; + size_t buf_pos = 0; + // Parse the result - // outer loop: loops thru all the NETLINK headers that also include the route entry header - struct nlmsghdr* nl_header = (struct nlmsghdr*)buffer; - for (; NLMSG_OK(nl_header, nl_msg_size); nl_header = NLMSG_NEXT(nl_header, nl_msg_size)) + // Loop through all routing table entries returned in the buffer + while (buf_pos < buf_len) { RoutingTableEntry new_entry; init_routing_table_entry(&new_entry); @@ -391,52 +337,48 @@ lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl bool new_entry_valid = true; // get route entry header - struct rtmsg* rt_message = (struct rtmsg*)NLMSG_DATA(nl_header); + struct rt_msghdr* rmsg = (struct rt_msghdr*)(&buf[buf_pos]); - // Filter out entries from the local routing table. Netlink seems to give us those even though - // we only asked for the main one. - if (rt_message->rtm_type != RTN_LOCAL && rt_message->rtm_type != RTN_BROADCAST && - rt_message->rtm_type != RTN_ANYCAST) + // Filter out entries from the local routing table, broadcast and ARP routes. + if (!(rmsg->rtm_flags & (RTF_LLDATA | RTF_LOCAL | RTF_BROADCAST))) { - // inner loop: loop thru all the attributes of one route entry. - struct rtattr* rt_attributes = (struct rtattr*)RTM_RTA(rt_message); - unsigned int rt_attr_size = (unsigned int)RTM_PAYLOAD(nl_header); - for (; RTA_OK(rt_attributes, rt_attr_size); rt_attributes = RTA_NEXT(rt_attributes, rt_attr_size)) + struct sockaddr* addr_start = (struct sockaddr*)(rmsg + 1); + struct sockaddr* rti_info[RTAX_MAX]; + get_rtaddrs(rmsg->rtm_addrs, addr_start, rti_info); + + // We only care about the gateway and DST attribute + if (rti_info[RTAX_DST] != NULL) { - // We only care about the gateway and DST attribute - if (rt_attributes->rta_type == RTA_DST) - { - if (family == AF_INET6) - LWPA_IP_SET_V6_ADDRESS(&new_entry.addr, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); - else - LWPA_IP_SET_V4_ADDRESS(&new_entry.addr, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); - } - else if (rt_attributes->rta_type == RTA_GATEWAY) - { - if (family == AF_INET6) - LWPA_IP_SET_V6_ADDRESS(&new_entry.gateway, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); - else - LWPA_IP_SET_V4_ADDRESS(&new_entry.gateway, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); - } - else if (rt_attributes->rta_type == RTA_OIF) - { - new_entry.interface_index = *((int*)RTA_DATA(rt_attributes)); - } - else if (rt_attributes->rta_type == RTA_PRIORITY) - { - new_entry.metric = *((int*)RTA_DATA(rt_attributes)); - } + if (family == AF_INET6) + LWPA_IP_SET_V6_ADDRESS(&new_entry.addr, ((struct sockaddr_in6*)rti_info[RTAX_DST])->sin6_addr.s6_addr); + else + LWPA_IP_SET_V4_ADDRESS(&new_entry.addr, ntohl(((struct sockaddr_in*)rti_info[RTAX_DST])->sin_addr.s_addr)); } + // else if (rti_info[RTAX_GATEWAY] != NULL) + // { + // if (family == AF_INET6) + // LWPA_IP_SET_V6_ADDRESS(&new_entry.gateway, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); + // else + // LWPA_IP_SET_V4_ADDRESS(&new_entry.gateway, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); + // } + // else if (rt_attributes->rta_type == RTA_OIF) + // { + // new_entry.interface_index = *((int*)RTA_DATA(rt_attributes)); + // } + // else if (rt_attributes->rta_type == RTA_PRIORITY) + // { + // new_entry.metric = *((int*)RTA_DATA(rt_attributes)); + // } } else { new_entry_valid = false; } - if (!LWPA_IP_IS_INVALID(&new_entry.addr)) - { - new_entry.mask = lwpa_ip_mask_from_length(new_entry.addr.type, rt_message->rtm_dst_len); - } + // if (!LWPA_IP_IS_INVALID(&new_entry.addr)) + // { + // new_entry.mask = lwpa_ip_mask_from_length(new_entry.addr.type, rt_message->rtm_dst_len); + // } // Insert the new entry into the list if (new_entry_valid) @@ -448,6 +390,8 @@ lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, size_t nl table->entries = (RoutingTableEntry*)malloc(sizeof(RoutingTableEntry)); table->entries[table->size - 1] = new_entry; } + + buf_pos += rmsg->rtm_msglen; } if (table->size > 0) @@ -511,120 +455,121 @@ static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) lwpa_error_t enumerate_netints() { lwpa_error_t res = build_routing_tables(); - if (res != kLwpaErrOk) - return res; - - int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (ioctl_sock == -1) - return errno_os_to_lwpa(errno); - - if (getifaddrs(&state.os_addrs) < 0) - { - close(ioctl_sock); - return errno_os_to_lwpa(errno); - } - - // Pass 1: Total the number of addresses - state.num_netints = 0; - for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) - { - if (should_skip_ifaddr(ifaddr)) - continue; - - ++state.num_netints; - } - - if (state.num_netints == 0) - { - freeifaddrs(state.os_addrs); - close(ioctl_sock); - return kLwpaErrNoNetints; - } - - // Allocate our interface array - state.lwpa_netints = (LwpaNetintInfo*)calloc(state.num_netints, sizeof(LwpaNetintInfo)); - if (!state.lwpa_netints) - { - freeifaddrs(state.os_addrs); - close(ioctl_sock); - return kLwpaErrNoMem; - } - - // Pass 2: Fill in all the info about each address - size_t current_lwpa_index = 0; - for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) - { - if (should_skip_ifaddr(ifaddr)) - continue; - - LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; - - // Interface name - strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); - current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; - - // Interface address - LwpaSockaddr temp_sockaddr; - sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_addr); - current_info->addr = temp_sockaddr.ip; - - // Interface netmask - sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); - current_info->mask = temp_sockaddr.ip; - - // Struct ifreq to use with ioctl() calls - struct ifreq if_req; - strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); - - // Hardware address - int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); - if (ioctl_res == 0) - memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); - else - memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); - - // Interface index - ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); - if (ioctl_res == 0) - current_info->ifindex = if_req.ifr_ifindex; - else - current_info->ifindex = -1; - - // Is Default - if (LWPA_IP_IS_V4(¤t_info->addr) && state.routing_table_v4.default_route && - current_info->ifindex == state.routing_table_v4.default_route->interface_index) - { - current_info->is_default = true; - } - else if (LWPA_IP_IS_V6(¤t_info->addr) && state.routing_table_v6.default_route && - current_info->ifindex == state.routing_table_v6.default_route->interface_index) - { - current_info->is_default = true; - } - - current_lwpa_index++; - } - - // Sort the interfaces by OS index - qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); - - // Store the locations of the default netints for access by the API function - for (size_t i = 0; i < state.num_netints; ++i) - { - LwpaNetintInfo* netint = &state.lwpa_netints[i]; - if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) - { - state.have_default_netint_index_v4 = true; - state.default_netint_index_v4 = i; - } - else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) - { - state.have_default_netint_index_v6 = true; - state.default_netint_index_v6 = i; - } - } - close(ioctl_sock); - return kLwpaErrOk; + return res; + // if (res != kLwpaErrOk) + // return res; + // + // int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + // if (ioctl_sock == -1) + // return errno_os_to_lwpa(errno); + // + // if (getifaddrs(&state.os_addrs) < 0) + // { + // close(ioctl_sock); + // return errno_os_to_lwpa(errno); + // } + // + // // Pass 1: Total the number of addresses + // state.num_netints = 0; + // for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + // { + // if (should_skip_ifaddr(ifaddr)) + // continue; + // + // ++state.num_netints; + // } + // + // if (state.num_netints == 0) + // { + // freeifaddrs(state.os_addrs); + // close(ioctl_sock); + // return kLwpaErrNoNetints; + // } + // + // // Allocate our interface array + // state.lwpa_netints = (LwpaNetintInfo*)calloc(state.num_netints, sizeof(LwpaNetintInfo)); + // if (!state.lwpa_netints) + // { + // freeifaddrs(state.os_addrs); + // close(ioctl_sock); + // return kLwpaErrNoMem; + // } + // + // // Pass 2: Fill in all the info about each address + // size_t current_lwpa_index = 0; + // for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + // { + // if (should_skip_ifaddr(ifaddr)) + // continue; + // + // LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; + // + // // Interface name + // strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); + // current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; + // + // // Interface address + // LwpaSockaddr temp_sockaddr; + // sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_addr); + // current_info->addr = temp_sockaddr.ip; + // + // // Interface netmask + // sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); + // current_info->mask = temp_sockaddr.ip; + // + // // Struct ifreq to use with ioctl() calls + // struct ifreq if_req; + // strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); + // + // // Hardware address + // int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); + // if (ioctl_res == 0) + // memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); + // else + // memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); + // + // // Interface index + // ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); + // if (ioctl_res == 0) + // current_info->ifindex = if_req.ifr_ifindex; + // else + // current_info->ifindex = -1; + // + // // Is Default + // if (LWPA_IP_IS_V4(¤t_info->addr) && state.routing_table_v4.default_route && + // current_info->ifindex == state.routing_table_v4.default_route->interface_index) + // { + // current_info->is_default = true; + // } + // else if (LWPA_IP_IS_V6(¤t_info->addr) && state.routing_table_v6.default_route && + // current_info->ifindex == state.routing_table_v6.default_route->interface_index) + // { + // current_info->is_default = true; + // } + // + // current_lwpa_index++; + // } + // + // // Sort the interfaces by OS index + // qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); + // + // // Store the locations of the default netints for access by the API function + // for (size_t i = 0; i < state.num_netints; ++i) + // { + // LwpaNetintInfo* netint = &state.lwpa_netints[i]; + // if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) + // { + // state.have_default_netint_index_v4 = true; + // state.default_netint_index_v4 = i; + // } + // else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) + // { + // state.have_default_netint_index_v6 = true; + // state.default_netint_index_v6 = i; + // } + // } + // close(ioctl_sock); + // return kLwpaErrOk; } int compare_netints(const void* a, const void* b) diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index 7e443234a..cfb745e7b 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -25,19 +25,13 @@ #include #include #include -#include +// #include #include #include #include #include "os_error.h" -/**************************** Private constants ******************************/ - -/* Per the docs, this constant is ignored in Linux 2.6.8 and later, but must be > 0. - * Here is a random number. */ -#define EPOLL_CREATE_SIZE 1024 - /****************************** Private types ********************************/ /* A struct to track sockets being polled by the lwpa_poll() API */ @@ -119,13 +113,13 @@ static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_v static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); // Helpers for lwpa_poll API -static void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt); -static void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, - lwpa_poll_events_t* events); +// static void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt); +// static void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, +// lwpa_poll_events_t* events); -static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); -static LwpaRbNode* poll_socket_alloc(); -static void poll_socket_free(LwpaRbNode* node); +// static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); +// static LwpaRbNode* poll_socket_alloc(); +// static void poll_socket_free(LwpaRbNode* node); /*************************** Function definitions ****************************/ @@ -597,236 +591,240 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { - if (!context) - return kLwpaErrInvalid; - - context->epoll_fd = epoll_create(EPOLL_CREATE_SIZE); - if (context->epoll_fd >= 0) - { - lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); - context->valid = true; - return kLwpaErrOk; - } - else - { - return errno_os_to_lwpa(errno); - } + // if (!context) + // return kLwpaErrInvalid; + // + // context->epoll_fd = epoll_create(EPOLL_CREATE_SIZE); + // if (context->epoll_fd >= 0) + // { + // lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); + // context->valid = true; + // return kLwpaErrOk; + // } + // else + // { + // return errno_os_to_lwpa(errno); + // } + return kLwpaErrNotImpl; } void lwpa_poll_context_deinit(LwpaPollContext* context) { - if (context && context->valid) - { - lwpa_rbtree_clear(&context->sockets); - close(context->epoll_fd); - context->valid = false; - } + // if (context && context->valid) + // { + // lwpa_rbtree_clear(&context->sockets); + // close(context->epoll_fd); + // context->valid = false; + // } } lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, void* user_data) { - if (context && context->valid && socket != LWPA_SOCKET_INVALID && (events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) - { - LwpaPollSocket* sock_desc = (LwpaPollSocket*)malloc(sizeof(LwpaPollSocket)); - if (sock_desc) - { - sock_desc->sock = socket; - sock_desc->events = events; - sock_desc->user_data = user_data; - int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); - if (insert_res != 0) - { - struct epoll_event ep_evt; - events_lwpa_to_epoll(events, &ep_evt); - ep_evt.data.fd = socket; - - int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_ADD, socket, &ep_evt); - if (res == 0) - { - return kLwpaErrOk; - } - else - { - // Our node dealloc function also deallocates sock_desc, so no need to free it here. - lwpa_rbtree_remove(&context->sockets, sock_desc); - return errno_os_to_lwpa(errno); - } - } - else - { - free(sock_desc); - return kLwpaErrNoMem; - } - } - else - { - return kLwpaErrNoMem; - } - } - else - { - return kLwpaErrInvalid; - } + // if (context && context->valid && socket != LWPA_SOCKET_INVALID && (events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + // { + // LwpaPollSocket* sock_desc = (LwpaPollSocket*)malloc(sizeof(LwpaPollSocket)); + // if (sock_desc) + // { + // sock_desc->sock = socket; + // sock_desc->events = events; + // sock_desc->user_data = user_data; + // int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); + // if (insert_res != 0) + // { + // struct epoll_event ep_evt; + // events_lwpa_to_epoll(events, &ep_evt); + // ep_evt.data.fd = socket; + // + // int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_ADD, socket, &ep_evt); + // if (res == 0) + // { + // return kLwpaErrOk; + // } + // else + // { + // // Our node dealloc function also deallocates sock_desc, so no need to free it here. + // lwpa_rbtree_remove(&context->sockets, sock_desc); + // return errno_os_to_lwpa(errno); + // } + // } + // else + // { + // free(sock_desc); + // return kLwpaErrNoMem; + // } + // } + // else + // { + // return kLwpaErrNoMem; + // } + // } + // else + // { + // return kLwpaErrInvalid; + // } + return kLwpaErrNotImpl; } lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, void* new_user_data) { - if (context && context->valid && socket != LWPA_SOCKET_INVALID && (new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) - { - LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); - if (sock_desc) - { - struct epoll_event ep_evt; - events_lwpa_to_epoll(new_events, &ep_evt); - ep_evt.data.fd = socket; - - int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_MOD, socket, &ep_evt); - if (res == 0) - { - sock_desc->events = new_events; - sock_desc->user_data = new_user_data; - return kLwpaErrOk; - } - else - { - return errno_os_to_lwpa(errno); - } - } - else - { - return kLwpaErrNotFound; - } - } - else - { - return kLwpaErrInvalid; - } + // if (context && context->valid && socket != LWPA_SOCKET_INVALID && (new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + // { + // LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); + // if (sock_desc) + // { + // struct epoll_event ep_evt; + // events_lwpa_to_epoll(new_events, &ep_evt); + // ep_evt.data.fd = socket; + // + // int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_MOD, socket, &ep_evt); + // if (res == 0) + // { + // sock_desc->events = new_events; + // sock_desc->user_data = new_user_data; + // return kLwpaErrOk; + // } + // else + // { + // return errno_os_to_lwpa(errno); + // } + // } + // else + // { + // return kLwpaErrNotFound; + // } + // } + // else + // { + // return kLwpaErrInvalid; + // } + return kLwpaErrNotImpl; } void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) { - if (context && context->valid) - { - // Need a dummy struct for portability - some versions require event to always be non-NULL - // even though it is ignored - struct epoll_event ep_evt; - epoll_ctl(context->epoll_fd, EPOLL_CTL_DEL, socket, &ep_evt); - lwpa_rbtree_remove(&context->sockets, &socket); - } + // if (context && context->valid) + // { + // // Need a dummy struct for portability - some versions require event to always be non-NULL + // // even though it is ignored + // struct epoll_event ep_evt; + // epoll_ctl(context->epoll_fd, EPOLL_CTL_DEL, socket, &ep_evt); + // lwpa_rbtree_remove(&context->sockets, &socket); + // } } lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms) { - if (context && context->valid && event) - { - if (lwpa_rbtree_size(&context->sockets) > 0) - { - int sys_timeout = (timeout_ms == LWPA_WAIT_FOREVER ? -1 : timeout_ms); - - struct epoll_event epoll_evt; - int wait_res = epoll_wait(context->epoll_fd, &epoll_evt, 1, sys_timeout); - if (wait_res > 0) - { - LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &epoll_evt.data.fd); - if (sock_desc) - { - event->socket = sock_desc->sock; - events_epoll_to_lwpa(&epoll_evt, sock_desc, &event->events); - event->err = kLwpaErrOk; - event->user_data = sock_desc->user_data; - - // Check for errors - int error; - socklen_t error_size = sizeof error; - if (getsockopt(sock_desc->sock, SOL_SOCKET, SO_ERROR, &error, &error_size) == 0) - { - if (error != 0) - { - event->events |= LWPA_POLL_ERR; - event->err = errno_os_to_lwpa(error); - } - } - - return kLwpaErrOk; - } - else - { - return kLwpaErrSys; - } - } - else if (wait_res == 0) - { - return kLwpaErrTimedOut; - } - else - { - return errno_os_to_lwpa(errno); - } - } - else - { - return kLwpaErrNoSockets; - } - } - else - { - return kLwpaErrInvalid; - } -} - -void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt) -{ - epoll_evt->events = 0; - if (events & LWPA_POLL_IN) - epoll_evt->events |= EPOLLIN; - if ((events & LWPA_POLL_OUT) || (events & LWPA_POLL_CONNECT)) - epoll_evt->events |= EPOLLOUT; - if (events & LWPA_POLL_OOB) - epoll_evt->events |= EPOLLPRI; -} - -void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, - lwpa_poll_events_t* events_out) -{ - *events_out = 0; - if (epoll_evt->events & EPOLLIN) - *events_out |= LWPA_POLL_IN; - if (epoll_evt->events & EPOLLOUT) - { - if (sock_desc->events & LWPA_POLL_OUT) - *events_out |= LWPA_POLL_OUT; - if (sock_desc->events & LWPA_POLL_CONNECT) - *events_out |= LWPA_POLL_CONNECT; - } - if (epoll_evt->events & EPOLLPRI) - *events_out |= (LWPA_POLL_OOB); - if (epoll_evt->events & EPOLLERR) - *events_out |= (LWPA_POLL_ERR); -} - -int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b) -{ - LwpaPollSocket* a = (LwpaPollSocket*)node_a->value; - LwpaPollSocket* b = (LwpaPollSocket*)node_b->value; - - return (a->sock > b->sock) - (a->sock < b->sock); -} - -LwpaRbNode* poll_socket_alloc() -{ - return (LwpaRbNode*)malloc(sizeof(LwpaRbNode)); + // if (context && context->valid && event) + // { + // if (lwpa_rbtree_size(&context->sockets) > 0) + // { + // int sys_timeout = (timeout_ms == LWPA_WAIT_FOREVER ? -1 : timeout_ms); + // + // struct epoll_event epoll_evt; + // int wait_res = epoll_wait(context->epoll_fd, &epoll_evt, 1, sys_timeout); + // if (wait_res > 0) + // { + // LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &epoll_evt.data.fd); + // if (sock_desc) + // { + // event->socket = sock_desc->sock; + // events_epoll_to_lwpa(&epoll_evt, sock_desc, &event->events); + // event->err = kLwpaErrOk; + // event->user_data = sock_desc->user_data; + // + // // Check for errors + // int error; + // socklen_t error_size = sizeof error; + // if (getsockopt(sock_desc->sock, SOL_SOCKET, SO_ERROR, &error, &error_size) == 0) + // { + // if (error != 0) + // { + // event->events |= LWPA_POLL_ERR; + // event->err = errno_os_to_lwpa(error); + // } + // } + // + // return kLwpaErrOk; + // } + // else + // { + // return kLwpaErrSys; + // } + // } + // else if (wait_res == 0) + // { + // return kLwpaErrTimedOut; + // } + // else + // { + // return errno_os_to_lwpa(errno); + // } + // } + // else + // { + // return kLwpaErrNoSockets; + // } + // } + // else + // { + // return kLwpaErrInvalid; + // } + return kLwpaErrNotImpl; } -void poll_socket_free(LwpaRbNode* node) -{ - if (node) - { - free(node->value); - free(node); - } -} +// void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt) +//{ +// epoll_evt->events = 0; +// if (events & LWPA_POLL_IN) +// epoll_evt->events |= EPOLLIN; +// if ((events & LWPA_POLL_OUT) || (events & LWPA_POLL_CONNECT)) +// epoll_evt->events |= EPOLLOUT; +// if (events & LWPA_POLL_OOB) +// epoll_evt->events |= EPOLLPRI; +//} +// +// void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, +// lwpa_poll_events_t* events_out) +//{ +// *events_out = 0; +// if (epoll_evt->events & EPOLLIN) +// *events_out |= LWPA_POLL_IN; +// if (epoll_evt->events & EPOLLOUT) +// { +// if (sock_desc->events & LWPA_POLL_OUT) +// *events_out |= LWPA_POLL_OUT; +// if (sock_desc->events & LWPA_POLL_CONNECT) +// *events_out |= LWPA_POLL_CONNECT; +// } +// if (epoll_evt->events & EPOLLPRI) +// *events_out |= (LWPA_POLL_OOB); +// if (epoll_evt->events & EPOLLERR) +// *events_out |= (LWPA_POLL_ERR); +//} +// +// int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b) +//{ +// LwpaPollSocket* a = (LwpaPollSocket*)node_a->value; +// LwpaPollSocket* b = (LwpaPollSocket*)node_b->value; +// +// return (a->sock > b->sock) - (a->sock < b->sock); +//} +// +// LwpaRbNode* poll_socket_alloc() +//{ +// return (LwpaRbNode*)malloc(sizeof(LwpaRbNode)); +//} +// +// void poll_socket_free(LwpaRbNode* node) +//{ +// if (node) +// { +// free(node->value); +// free(node); +// } +//} lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, LwpaAddrinfo* result) From 609b46f471a35f2e995f97c73f86089a0d7f2d91 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 13 Jun 2019 09:40:18 -0500 Subject: [PATCH 039/264] Checking in to continue LwpaIpAddr changes on Windows --- include/lwpa/inet.h | 47 +++++++--- src/os/macos/lwpa/os_netint.c | 172 ++++++++++++++++++++++++---------- 2 files changed, 157 insertions(+), 62 deletions(-) diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index 5feef0257..20421c257 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -52,17 +52,26 @@ typedef enum /*! The number of bytes in an IPv6 address. */ #define LWPA_IPV6_BYTES 16 -/*! An IP address. Can hold either an IPv4 or IPv6 address. IPv4 addresses are in host byte - * order. */ +/*! \brief An IP address. + * + * Can hold either an IPv4 or IPv6 address. IPv4 addresses are in host byte order. IPv6 addresses + * also contain a scope ID, which is also sometimes referred to as a zone index (RFC 4007), to + * help disambiguate link-local addresses, among other uses. In most cases, this field can be left + * at its default value, which is set by the LWPA_IP_SET_V6_ADDRESS() macro. + */ typedef struct LwpaIpAddr { /*! The IP address type (IPv4 or IPv6) */ lwpa_iptype_t type; - /*! The address, use either v4 or v6 depending on the value of type */ + /*! The address (use the macros to access), either v4 or v6 depending on the value of type. */ union AddrUnion { uint32_t v4; - uint8_t v6[LWPA_IPV6_BYTES]; + struct LwpaIpv6Addr + { + uint8_t addr_buf[LWPA_IPV6_BYTES]; + unsigned long scope_id; + } v6; } addr; } LwpaIpAddr; @@ -98,7 +107,7 @@ typedef struct LwpaIpAddr * sure this LwpaIpAddr contains a valid IPv6 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \return The IPv6 address (uint8_t[]). */ -#define LWPA_IP_V6_ADDRESS(lwpa_ip_ptr) ((lwpa_ip_ptr)->addr.v6) +#define LWPA_IP_V6_ADDRESS(lwpa_ip_ptr) ((lwpa_ip_ptr)->addr.v6.addr_buf) /*! Set the IPv4 address in a LwpaIpAddr. Also sets the type field to indicate that this LwpaIpAddr * contains an IPv4 address. @@ -115,12 +124,23 @@ typedef struct LwpaIpAddr * contains an IPv6 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \param val IPv6 address to set (uint8_t[]). Must be at least of length LWPA_IPV6_BYTES. Gets - * copied into the struct. */ -#define LWPA_IP_SET_V6_ADDRESS(lwpa_ip_ptr, val) \ - do \ - { \ - (lwpa_ip_ptr)->type = kLwpaIpTypeV6; \ - memcpy((lwpa_ip_ptr)->addr.v6, val, LWPA_IPV6_BYTES); \ + * copied into the struct. + */ +#define LWPA_IP_SET_V6_ADDRESS(lwpa_ip_ptr, val) LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(lwpa_ip_ptr, val, 0) + +/*! Set an IPv6 address with an explicit scope ID in a LwpaIpAddr. Also sets the type field to + * indicate that this LwpaIpAddr contains an IPv6 address. + * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. + * \param addr_val IPv6 address to set (uint8_t[]). Must be at least of length LWPA_IPV6_BYTES. + * Gets copied into the struct. + * \param scope_id IPv6 scope ID to set. + */ +#define LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(lwpa_ip_ptr, addr_val, scope_id) \ + do \ + { \ + (lwpa_ip_ptr)->type = kLwpaIpTypeV6; \ + memcpy((lwpa_ip_ptr)->addr.v6.addr_buf, (addr_val), LWPA_IPV6_BYTES); \ + (lwpa_ip_ptr)->addr.v6.scope_id = (scope_id); \ } while (0) /*! Set the type field in a LwpaIpAddr to indicate that it does not contain a valid address. @@ -132,9 +152,8 @@ typedef struct LwpaIpAddr /*! An IP address with associated interface and port. Ports are in host byte order. */ typedef struct LwpaSockaddr { - uint16_t port; /*!< TCP or UDP port. */ - LwpaIpAddr ip; /*!< IP address. */ - uint32_t scope_id; /*!< IPv6 scope ID. */ + uint16_t port; /*!< TCP or UDP port. */ + LwpaIpAddr ip; /*!< IP address. */ } LwpaSockaddr; #define LWPA_NETINTINFO_MAC_LEN 6 diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c index f701efb71..adc7d8345 100644 --- a/src/os/macos/lwpa/os_netint.c +++ b/src/os/macos/lwpa/os_netint.c @@ -17,26 +17,27 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -/* The os_netint implementation for Linux. +/* The os_netint implementation for macOS. * - * Uses getifaddrs() to get an initial list of network interfaces. More info: - * http://man7.org/linux/man-pages/man3/getifaddrs.3.html + * Uses getifaddrs() to get an initial list of network interfaces. More info: man 3 getifaddrs * - * Then uses netlink sockets (specifically RTNETLINK) to fill out missing information about each - * interface. More info: + * Then uses sysctl() and parses kernel-formatted routing table information to add supplementary + * information and determine default routes. * - * Netlink sockets: http://man7.org/linux/man-pages/man7/netlink.7.html - * Netlink macros, for decoding netlink messages: http://man7.org/linux/man-pages/man3/netlink.3.html - * RtNetlink sockets: http://man7.org/linux/man-pages/man7/rtnetlink.7.html - * Some sample RtNetlink code: https://www.linuxjournal.com/article/8498 + * The method by which the routing information is obtained in BSD-derived kernels is an + * underdocumented mess. I have tried to comment the documentation sources for how to parse the + * system information as best I can; sometimes this info was obtained from (with no better source + * being apparently available) a StackOverflow answer, or a Wikipedia page, or a print book, or + * simply by empirical testing. */ #include "lwpa/netint.h" -#include +#include #include +#include +#include #include -#include #ifdef LWPA_NETINT_DEBUG_OUTPUT #include @@ -44,22 +45,39 @@ #include #include +#include #include #include #include #include -#include "lwpa/socket.h" #include "lwpa/private/netint.h" #include "os_error.h" /***************************** Private types *********************************/ +typedef enum +{ + kGwAddress, + kGwIndex, + kGwInvalid +} routing_gateway_t; + +typedef struct RoutingGateway +{ + routing_gateway_t type; + union + { + LwpaIpAddr addr; + int ifindex; + } u; +} RoutingGateway; + typedef struct RoutingTableEntry { LwpaIpAddr addr; LwpaIpAddr mask; - LwpaIpAddr gateway; + RoutingGateway gateway; int interface_index; int metric; } RoutingTableEntry; @@ -293,24 +311,17 @@ lwpa_error_t get_routing_table_dump(int family, uint8_t** buf, size_t* buf_len) return kLwpaErrOk; } -// A function and some macros stolen from "Unix Network Programming: The Sockets Networking API" v3 -// by Stevens, Fenner, Rudoff, for parsing through the routing table dump. - -// This macro rounds up 'a' to the next multiple of 'size', which must be a power of 2. -#define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) - -// This macro steps to the next socket address structure. If sa_len is 0, assume sizeof(u_long). -#define NEXT_SA(ap) \ - ap = (struct sockaddr*)((caddr_t)ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof(u_long)) : sizeof(u_long))) +#define SOCKADDR_ALIGN 4 // not sizeof(long) +#define SA_SIZE(sa) ((!(sa) || (sa)->sa_len == 0) ? SOCKADDR_ALIGN : (1 + (((sa)->sa_len - 1) | (SOCKADDR_ALIGN - 1)))) -void get_rtaddrs(int addrs, struct sockaddr* sa, struct sockaddr** rti_info) +void get_addrs_from_route_entry(int addrs, struct sockaddr* sa, struct sockaddr** rti_info) { for (int i = 0; i < RTAX_MAX; ++i) { if (addrs & (1 << i)) { rti_info[i] = sa; - NEXT_SA(sa); + sa = (struct sockaddr*)((char*)sa + SA_SIZE(sa)); } else { @@ -319,6 +330,71 @@ void get_rtaddrs(int addrs, struct sockaddr* sa, struct sockaddr** rti_info) } } +static void dest_from_route_entry(int family, const struct sockaddr* os_dst, LwpaIpAddr* lwpa_dst) +{ + if (family == AF_INET6) + LWPA_IP_SET_V6_ADDRESS(lwpa_dst, ((struct sockaddr_in6*)os_dst)->sin6_addr.s6_addr); + else + LWPA_IP_SET_V4_ADDRESS(lwpa_dst, ntohl(((struct sockaddr_in*)os_dst)->sin_addr.s_addr)); +} + +static void netmask_from_route_entry(int family, const struct sockaddr* os_netmask, LwpaIpAddr* lwpa_netmask) +{ + if (family == AF_INET) + { + size_t mask_offset = offsetof(struct sockaddr_in, sin_addr); + const char* mask_ptr = &((char*)os_netmask)[mask_offset]; + + if (os_netmask->sa_len > mask_offset) + { + uint32_t mask_val = 0; + mask_val |= ((uint32_t)mask_ptr[0]) << 24; + if (os_netmask->sa_len > (mask_offset + 1)) + mask_val |= ((uint32_t)mask_ptr[1]) << 16; + if (os_netmask->sa_len > (mask_offset + 2)) + mask_val |= ((uint32_t)mask_ptr[2]) << 8; + if (os_netmask->sa_len > (mask_offset + 3)) + mask_val |= ((uint32_t)mask_ptr[3]); + LWPA_IP_SET_V4_ADDRESS(lwpa_netmask, mask_val); + } + } + else if (family == AF_INET6) + { + size_t mask_offset = offsetof(struct sockaddr_in6, sin6_addr); + const char* mask_ptr = &((char*)os_netmask)[mask_offset]; + + if (os_netmask->sa_len > mask_offset) + { + uint8_t ip_buf[LWPA_IPV6_BYTES]; + memset(ip_buf, 0, LWPA_IPV6_BYTES); + for (size_t mask_pos = 0; mask_pos < os_netmask->sa_len - mask_offset; ++mask_pos) + { + ip_buf[mask_pos] = mask_ptr[mask_pos]; + } + LWPA_IP_SET_V6_ADDRESS(lwpa_netmask, ip_buf); + } + } +} + +static void gateway_from_route_entry(const struct sockaddr* os_gw, RoutingGateway* lwpa_gw) +{ + if (os_gw->sa_family == AF_INET6) + { + lwpa_gw->type = kGwAddress; + LWPA_IP_SET_V6_ADDRESS(&lwpa_gw->u.addr, ((struct sockaddr_in6*)os_gw)->sin6_addr.s6_addr); + } + else if (os_gw->sa_family == AF_INET) + { + lwpa_gw->type = kGwAddress; + LWPA_IP_SET_V4_ADDRESS(&lwpa_gw->u.addr, ntohl(((struct sockaddr_in*)os_gw)->sin_addr.s_addr)); + } + else if (os_gw->sa_family == AF_LINK) + { + lwpa_gw->type = kGwIndex; + lwpa_gw->u.ifindex = ((struct sockaddr_dl*)os_gw)->sdl_index; + } +} + lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, RoutingTable* table) { table->size = 0; @@ -344,31 +420,29 @@ lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, { struct sockaddr* addr_start = (struct sockaddr*)(rmsg + 1); struct sockaddr* rti_info[RTAX_MAX]; - get_rtaddrs(rmsg->rtm_addrs, addr_start, rti_info); + get_addrs_from_route_entry(rmsg->rtm_addrs, addr_start, rti_info); // We only care about the gateway and DST attribute if (rti_info[RTAX_DST] != NULL) { - if (family == AF_INET6) - LWPA_IP_SET_V6_ADDRESS(&new_entry.addr, ((struct sockaddr_in6*)rti_info[RTAX_DST])->sin6_addr.s6_addr); - else - LWPA_IP_SET_V4_ADDRESS(&new_entry.addr, ntohl(((struct sockaddr_in*)rti_info[RTAX_DST])->sin_addr.s_addr)); + dest_from_route_entry(family, rti_info[RTAX_DST], &new_entry.addr); + } + if (rti_info[RTAX_GATEWAY] != NULL) + { + gateway_from_route_entry(rti_info[RTAX_GATEWAY], &new_entry.gateway); + } + if (rti_info[RTAX_NETMASK] != NULL) + { + netmask_from_route_entry(family, rti_info[RTAX_NETMASK], &new_entry.mask); } - // else if (rti_info[RTAX_GATEWAY] != NULL) - // { - // if (family == AF_INET6) - // LWPA_IP_SET_V6_ADDRESS(&new_entry.gateway, ((struct in6_addr*)RTA_DATA(rt_attributes))->s6_addr); - // else - // LWPA_IP_SET_V4_ADDRESS(&new_entry.gateway, ntohl(((struct in_addr*)RTA_DATA(rt_attributes))->s_addr)); - // } - // else if (rt_attributes->rta_type == RTA_OIF) - // { - // new_entry.interface_index = *((int*)RTA_DATA(rt_attributes)); - // } - // else if (rt_attributes->rta_type == RTA_PRIORITY) - // { - // new_entry.metric = *((int*)RTA_DATA(rt_attributes)); - // } + // else if (rt_attributes->rta_type == RTA_OIF) + //{ + // new_entry.interface_index = *((int*)RTA_DATA(rt_attributes)); + //} + // else if (rt_attributes->rta_type == RTA_PRIORITY) + //{ + // new_entry.metric = *((int*)RTA_DATA(rt_attributes)); + //} } else { @@ -420,7 +494,7 @@ void init_routing_table_entry(RoutingTableEntry* entry) { LWPA_IP_SET_INVALID(&entry->addr); LWPA_IP_SET_INVALID(&entry->mask); - LWPA_IP_SET_INVALID(&entry->gateway); + entry->gateway.type = kGwInvalid; entry->interface_index = -1; entry->metric = INT_MAX; } @@ -632,10 +706,12 @@ void debug_print_routing_table(RoutingTable* table) else strcpy(mask_str, "0.0.0.0"); - if (!LWPA_IP_IS_INVALID(&entry->gateway)) - lwpa_inet_ntop(&entry->gateway, gw_str, LWPA_INET6_ADDRSTRLEN); + if (entry->gateway.type == kGwAddress && !LWPA_IP_IS_INVALID(&entry->gateway.u.addr)) + lwpa_inet_ntop(&entry->gateway.u.addr, gw_str, LWPA_INET6_ADDRSTRLEN); + else if (entry->gateway.type == kGwIndex) + snprintf(gw_str, LWPA_INET6_ADDRSTRLEN, "link %d", entry->gateway.u.ifindex); else - strcpy(gw_str, "0.0.0.0"); + strcpy(gw_str, ""); printf("%-40s %-40s %-40s %-10d %d\n", addr_str, mask_str, gw_str, entry->metric, entry->interface_index); } From de2469d8b8fc5e327ed01846011740754d57d281 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 13 Jun 2019 09:57:22 -0500 Subject: [PATCH 040/264] Fix a static analysis error, fix lwpa_ip_cmp() and add test --- src/lwpa/inet.c | 4 ++-- tests/unit/test_inet.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/lwpa/inet.c b/src/lwpa/inet.c index 64ec8221d..9ba16414d 100644 --- a/src/lwpa/inet.c +++ b/src/lwpa/inet.c @@ -179,7 +179,7 @@ int lwpa_ip_cmp(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2) } else if (ip1->type == kLwpaIpTypeV4) { - return ((int)LWPA_IP_V4_ADDRESS(ip1) - (int)LWPA_IP_V4_ADDRESS(ip2)); + return (LWPA_IP_V4_ADDRESS(ip1) > LWPA_IP_V4_ADDRESS(ip2)) - (LWPA_IP_V4_ADDRESS(ip1) < LWPA_IP_V4_ADDRESS(ip2)); } else if (ip1->type == kLwpaIpTypeV6) { @@ -235,7 +235,7 @@ unsigned int lwpa_ip_mask_length(const LwpaIpAddr* netmask) { const uint8_t* addr_buf = LWPA_IP_V6_ADDRESS(netmask); size_t addr_index = 0; - while (addr_buf[addr_index] == 0xff && addr_index < LWPA_IPV6_BYTES) + while (addr_index < LWPA_IPV6_BYTES && addr_buf[addr_index] == 0xffu) { length += 8; addr_index++; diff --git a/tests/unit/test_inet.cpp b/tests/unit/test_inet.cpp index 8bcab8855..92866b294 100644 --- a/tests/unit/test_inet.cpp +++ b/tests/unit/test_inet.cpp @@ -165,6 +165,12 @@ TEST_F(InetTest, compare) EXPECT_LT(lwpa_ip_cmp(&v4_less, &v4), 0); EXPECT_LT(lwpa_ip_cmp(&v6_less, &v6), 0); + + // Make sure there are no gotchas with 2's complement by setting high bits of addresses + LWPA_IP_SET_V4_ADDRESS(&v4, 0xffffffff); + LWPA_IP_SET_V4_ADDRESS(&v4_less, 0x0); + + EXPECT_LT(lwpa_ip_cmp(&v4_less, &v4), 0); } // Test the lwpa_ip_mask_length() function From 36a1cbc68a91cdab75c7361cebd8841f111e2be4 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 13 Jun 2019 10:03:15 -0500 Subject: [PATCH 041/264] Improve thread API --- include/os/linux/lwpa/os_thread.h | 2 +- include/os/windows/lwpa/os_thread.h | 2 +- src/lwpa/thread.dox | 7 +++---- src/os/linux/lwpa/os_thread.c | 2 +- src/os/windows/lwpa/os_thread.c | 2 +- tests/unit/test_thread.cpp | 11 ++++------- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/include/os/linux/lwpa/os_thread.h b/include/os/linux/lwpa/os_thread.h index 713e06264..6a5e9e0c0 100644 --- a/include/os/linux/lwpa/os_thread.h +++ b/include/os/linux/lwpa/os_thread.h @@ -42,7 +42,7 @@ typedef struct } lwpa_thread_t; bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); -bool lwpa_thread_stop(lwpa_thread_t* id); +bool lwpa_thread_join(lwpa_thread_t* id); #define lwpa_thread_sleep(sleep_ms) usleep(((useconds_t)sleep_ms) * 1000) #ifdef __cplusplus diff --git a/include/os/windows/lwpa/os_thread.h b/include/os/windows/lwpa/os_thread.h index cf4082a83..7e1609890 100644 --- a/include/os/windows/lwpa/os_thread.h +++ b/include/os/windows/lwpa/os_thread.h @@ -54,7 +54,7 @@ typedef struct } lwpa_thread_t; bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); -bool lwpa_thread_stop(lwpa_thread_t* id); +bool lwpa_thread_join(lwpa_thread_t* id); #define lwpa_thread_sleep(sleep_ms) Sleep(sleep_ms) #ifdef __cplusplus diff --git a/src/lwpa/thread.dox b/src/lwpa/thread.dox index 7f8305804..2964d31f3 100644 --- a/src/lwpa/thread.dox +++ b/src/lwpa/thread.dox @@ -66,16 +66,15 @@ typedef UNDEFINED lwpa_thread_t; */ bool lwpa_thread_create(lwpa_thread_t *id, const LwpaThreadParams *params, void (*thread_fn)(void *), void *thread_arg); -/*! \brief Stop a thread. +/*! \brief Wait for a thread to finish execution. * - * This is sometimes referred to as 'joining' a thread in native platform APIs. Blocks until the - * thread has exited. + * Blocks until the thread has exited. * * \param[in] id Identifier for the thread to stop. * \return true: The thread was stopped. * \return false: An error occurred. */ -bool lwpa_thread_stop(lwpa_thread_t *id, int wait_ms); +bool lwpa_thread_join(lwpa_thread_t *id); /*! \brief Provides a platform-neutral sleep. * \param[in] sleep_ms How long to sleep, in milliseconds. diff --git a/src/os/linux/lwpa/os_thread.c b/src/os/linux/lwpa/os_thread.c index d8aeb85e6..73c6e53ff 100644 --- a/src/os/linux/lwpa/os_thread.c +++ b/src/os/linux/lwpa/os_thread.c @@ -50,7 +50,7 @@ bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void return res; } -bool lwpa_thread_stop(lwpa_thread_t* id) +bool lwpa_thread_join(lwpa_thread_t* id) { if (id) { diff --git a/src/os/windows/lwpa/os_thread.c b/src/os/windows/lwpa/os_thread.c index 3a12a0dc6..2197b36e8 100644 --- a/src/os/windows/lwpa/os_thread.c +++ b/src/os/windows/lwpa/os_thread.c @@ -87,7 +87,7 @@ bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void return true; } -bool lwpa_thread_stop(lwpa_thread_t* id) +bool lwpa_thread_join(lwpa_thread_t* id) { if (id) { diff --git a/tests/unit/test_thread.cpp b/tests/unit/test_thread.cpp index a84cdc2bf..5332ae06b 100644 --- a/tests/unit/test_thread.cpp +++ b/tests/unit/test_thread.cpp @@ -21,9 +21,6 @@ #include #include -static_assert(std::ratio_less_equal::value, - "This platform does not have access to a millisecond-resolution clock. This test cannot be run."); - class ThreadTest : public ::testing::Test { public: @@ -68,7 +65,7 @@ TEST_F(ThreadTest, create_destroy) // Stop should time out if the thread is still looping. // auto start_time = std::chrono::high_resolution_clock::now(); - // ASSERT_FALSE(lwpa_thread_stop(&wait_thread, 100)); + // ASSERT_FALSE(lwpa_thread_join(&wait_thread, 100)); // It should wait for at least the timeout specified, minus a fudge factor to account for // differing time resolutions on platforms. // auto time_taken = @@ -77,7 +74,7 @@ TEST_F(ThreadTest, create_destroy) // Stop should work if the thread has exited. waitthread_run = false; - ASSERT_TRUE(lwpa_thread_stop(&wait_thread)); + ASSERT_TRUE(lwpa_thread_join(&wait_thread)); } void increment_and_spin(void* param) @@ -125,9 +122,9 @@ TEST_F(ThreadTest, time_slice) std::this_thread::sleep_for(100ms); // Stop the tasks oneshot_task_run = false; - ASSERT_TRUE(lwpa_thread_stop(&oneshot_task)); + ASSERT_TRUE(lwpa_thread_join(&oneshot_task)); spin_task_run = false; - ASSERT_TRUE(lwpa_thread_stop(&spin_task)); + ASSERT_TRUE(lwpa_thread_join(&spin_task)); ASSERT_TRUE(spin_task_ran); ASSERT_TRUE(oneshot_task_ran); } From 38fae2bad69eb419aa3b5b1c08591a7db6683329 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 13 Jun 2019 16:24:26 -0500 Subject: [PATCH 042/264] Some updates from code review (not done yet): - Create a common module for netint and share API function code - Use GetBestInterfaceEx on Windows for lwpa_netint_get_interface_for_destination() - Move sockaddr conversion and lwpa_inet_xtox() functions to lwpa_inet - Touch up some documentation - Update changelog --- CHANGELOG.md | 5 + include/lwpa/inet.h | 22 +++- include/lwpa/socket.h | 10 -- include/os/linux/lwpa/os_inet.h | 37 ++++++ include/os/linux/lwpa/os_socket.h | 10 -- include/os/windows/lwpa/os_inet.h | 29 +++++ include/os/windows/lwpa/os_socket.h | 8 -- src/CMakeLists.txt | 3 + src/lwpa/inet.c | 35 +++++- src/lwpa/netint.c | 179 ++++++++++++++++++++++++++ src/lwpa/netint.dox | 69 ----------- src/lwpa/private/netint.h | 20 +++ src/lwpa/uuid.c | 24 ++-- src/os/linux/lwpa/os_inet.c | 30 +++++ src/os/windows/lwpa/os_inet.c | 147 ++++++++++++++++++++++ src/os/windows/lwpa/os_netint.c | 186 ++++++---------------------- src/os/windows/lwpa/os_socket.c | 114 ++--------------- tests/unit/test_netint.cpp | 12 +- 18 files changed, 570 insertions(+), 370 deletions(-) create mode 100644 include/os/linux/lwpa/os_inet.h create mode 100644 include/os/windows/lwpa/os_inet.h create mode 100644 src/lwpa/netint.c delete mode 100644 src/lwpa/netint.dox create mode 100644 src/os/linux/lwpa/os_inet.c create mode 100644 src/os/windows/lwpa/os_inet.c diff --git a/CHANGELOG.md b/CHANGELOG.md index 3023133cd..b63ac94f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Naming: 'operating system' and 'platform' are used somewhat interchangably by this library, but operating system more correctly refers to what lwpa targets. Plus, 'os' makes for nicer names than 'plat'. A pass is made for consistency. +- Moved the sockaddr and inet_xtox conversion functions into the lwpa_inet + module +- lwpa_thread_stop() changed to lwpa_thread_join() to better describe behavior +- LwpaNetintInfo: Removed 'gate' member, which has no consistent meaning across + platforms. ### Removed diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index 5feef0257..b50409632 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -22,8 +22,10 @@ #define _LWPA_INET_H_ #include -#include "lwpa/int.h" #include "lwpa/bool.h" +#include "lwpa/error.h" +#include "lwpa/int.h" +#include "lwpa/os_inet.h" /*! \defgroup lwpa_inet lwpa_inet * \ingroup lwpa @@ -154,10 +156,17 @@ typedef struct LwpaNetintInfo uint8_t mac[LWPA_NETINTINFO_MAC_LEN]; /*! The adapter name as a string. */ char name[LWPA_NETINTINFO_NAME_LEN]; - /*! Whether this is the default network interface. */ + /*! Whether this is the default network interface. The default network interface is defined as + * the network interface chosen for the default IP route on a system. */ bool is_default; } LwpaNetintInfo; +/*! Maximum length of the string representation of an IPv4 address. */ +#define LWPA_INET_ADDRSTRLEN 16 +/*! Maximum length of the string representation of an IPv6 address. */ +#define LWPA_INET6_ADDRSTRLEN 46 + +bool lwpa_ip_is_link_local(const LwpaIpAddr* ip); bool lwpa_ip_is_loopback(const LwpaIpAddr* ip); bool lwpa_ip_is_multicast(const LwpaIpAddr* ip); bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip); @@ -171,6 +180,15 @@ unsigned int lwpa_ip_mask_length(const LwpaIpAddr* netmask); LwpaIpAddr lwpa_ip_mask_from_length(lwpa_iptype_t type, unsigned int mask_length); bool lwpa_ip_network_portions_equal(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* netmask); +bool ip_os_to_lwpa(const lwpa_os_ipaddr_t* os_ip, LwpaIpAddr* ip); +size_t ip_lwpa_to_os(const LwpaIpAddr* ip, lwpa_os_ipaddr_t* os_ip); + +bool sockaddr_os_to_lwpa(const lwpa_os_sockaddr_t* os_sa, LwpaSockaddr* sa); +size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, lwpa_os_sockaddr_t* os_sa); + +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size); +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest); + #ifdef __cplusplus } #endif diff --git a/include/lwpa/socket.h b/include/lwpa/socket.h index ca4be8298..1897b0ca9 100644 --- a/include/lwpa/socket.h +++ b/include/lwpa/socket.h @@ -251,16 +251,6 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai); /* Call with any of the LwpaAddrinfos in the list to free the whole list */ void lwpa_freeaddrinfo(LwpaAddrinfo* ai); -/************************* Mimic inet_xtox() API *****************************/ - -/*! Maximum length of the string representation of an IPv4 address. */ -#define LWPA_INET_ADDRSTRLEN 16 -/*! Maximum length of the string representation of an IPv6 address. */ -#define LWPA_INET6_ADDRSTRLEN 46 - -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size); -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest); - #ifdef __cplusplus } #endif diff --git a/include/os/linux/lwpa/os_inet.h b/include/os/linux/lwpa/os_inet.h new file mode 100644 index 000000000..0cc14e407 --- /dev/null +++ b/include/os/linux/lwpa/os_inet.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_INET_H_ +#define _LWPA_OS_INET_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +bool ip_os_to_lwpa(const struct sockaddr* os_ip, LwpaIpAddr* ip); +size_t ip_lwpa_to_os(const LwpaIpAddr* ip, struct sockaddr* os_ip); + +bool sockaddr_os_to_lwpa(const struct sockaddr* os_sa, LwpaSockaddr* sa); +size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, struct sockaddr* os_sa); + +#ifdef __cplusplus +} +#endif + +#endif /* _LWPA_OS_INET_H_ */ diff --git a/include/os/linux/lwpa/os_socket.h b/include/os/linux/lwpa/os_socket.h index b461aed2c..bcc288b04 100644 --- a/include/os/linux/lwpa/os_socket.h +++ b/include/os/linux/lwpa/os_socket.h @@ -20,8 +20,6 @@ #ifndef _LWPA_OS_SOCKET_H_ #define _LWPA_OS_SOCKET_H_ -#include -#include #include "lwpa/inet.h" #include "lwpa/rbtree.h" @@ -42,14 +40,6 @@ typedef struct LwpaPollContext LwpaRbTree sockets; } LwpaPollContext; -#define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), ntohl((pfipptr)->s_addr)) -#define IP_LWPA_TO_OS_V4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(LWPA_IP_V4_ADDRESS(lwpaipptr))) -#define IP_OS_TO_LWPA_V6(lwpaipptr, pfipptr) LWPA_IP_SET_V6_ADDRESS((lwpaipptr), (pfipptr)->s6_addr) -#define IP_LWPA_TO_OS_V6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, LWPA_IP_V6_ADDRESS(lwpaipptr), IPV6_BYTES) - -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); - #ifdef __cplusplus } #endif diff --git a/include/os/windows/lwpa/os_inet.h b/include/os/windows/lwpa/os_inet.h new file mode 100644 index 000000000..5a58cfc32 --- /dev/null +++ b/include/os/windows/lwpa/os_inet.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_INET_H_ +#define _LWPA_OS_INET_H_ + +#include +#include + +typedef struct sockaddr lwpa_os_sockaddr_t; +typedef struct sockaddr lwpa_os_ipaddr_t; + +#endif /* _LWPA_OS_INET_H_ */ diff --git a/include/os/windows/lwpa/os_socket.h b/include/os/windows/lwpa/os_socket.h index 70eb842c5..54781da6a 100644 --- a/include/os/windows/lwpa/os_socket.h +++ b/include/os/windows/lwpa/os_socket.h @@ -73,14 +73,6 @@ typedef struct LwpaPollContext } LwpaPollContext; -#define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), ntohl((pfipptr)->s_addr)) -#define IP_LWPA_TO_OS_V4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(LWPA_IP_V4_ADDRESS(lwpaipptr))) -#define IP_OS_TO_LWPA_V6(lwpaipptr, pfipptr) LWPA_IP_SET_V6_ADDRESS((lwpaipptr), (pfipptr)->s6_addr) -#define IP_LWPA_TO_OS_V6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, LWPA_IP_V6_ADDRESS(lwpaipptr), IPV6_BYTES) - -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); - #ifdef __cplusplus } #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1fb522fd8..773982f93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,6 +63,7 @@ add_library(lwpa ${LWPA_ROOT}/include/lwpa/root_layer_pdu.h ${LWPA_ROOT}/include/lwpa/socket.h ${LWPA_ROOT}/include/lwpa/timer.h + ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_inet.h ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_lock.h ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_thread.h ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_socket.h @@ -74,11 +75,13 @@ add_library(lwpa ${LWPA_ROOT}/src/lwpa/md5.h ${LWPA_ROOT}/src/lwpa/md5.c ${LWPA_ROOT}/src/lwpa/mempool.c + ${LWPA_ROOT}/src/lwpa/netint.c ${LWPA_ROOT}/src/lwpa/pdu.c ${LWPA_ROOT}/src/lwpa/rbtree.c ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/uuid.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_common.c + ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_inet.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_uuid.c diff --git a/src/lwpa/inet.c b/src/lwpa/inet.c index 9ba16414d..9da42557c 100644 --- a/src/lwpa/inet.c +++ b/src/lwpa/inet.c @@ -26,6 +26,33 @@ static const uint8_t v6_loopback[LWPA_IPV6_BYTES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, /*************************** Function definitions ****************************/ +/*! \brief Determine whether a LwpaIpAddr contains a link-local address. + * + * Works for both IPv4 and IPv6 addresses. + * + * \param[in] ip Address to check. + * \return true: ip contains a link-local address. + * \return false: ip does not contain a link-local address. + */ +bool lwpa_ip_is_link_local(const LwpaIpAddr* ip) +{ + if (ip) + { + if (LWPA_IP_IS_V4(ip)) + { + // An IPv4 address is link-local if the first two octets are 0xa9fe (169.254.0.0/16) + return ((LWPA_IP_V4_ADDRESS(ip) & 0xffff0000u) == 0xa9fe0000u); + } + else if (LWPA_IP_IS_V6(ip)) + { + // An IPv6 address is link-local if the first 10 bits are 1111111010 (fe80::/10) + const uint8_t* addr_buf = LWPA_IP_V6_ADDRESS(ip); + return (addr_buf[0] == 0xfeu && ((addr_buf[1] & 0xc0u) == 0x80u)); + } + } + return false; +} + /*! \brief Determine whether a LwpaIpAddr contains a loopback address. * * Works for both IPv4 and IPv6 addresses. @@ -40,10 +67,12 @@ bool lwpa_ip_is_loopback(const LwpaIpAddr* ip) { if (LWPA_IP_IS_V4(ip)) { + // An IPv4 address is loopback if the first octet is 0x7f (127.0.0.0/8) return ((LWPA_IP_V4_ADDRESS(ip) & 0xff000000u) == 0x7f000000u); } else if (LWPA_IP_IS_V6(ip)) { + // An IPv6 address is loopback if it is equal to the address ::1 return (0 == memcmp(LWPA_IP_V6_ADDRESS(ip), v6_loopback, LWPA_IPV6_BYTES)); } } @@ -64,10 +93,13 @@ bool lwpa_ip_is_multicast(const LwpaIpAddr* ip) { if (LWPA_IP_IS_V4(ip)) { - return (LWPA_IP_V4_ADDRESS(ip) >= 0xe0000000 && LWPA_IP_V4_ADDRESS(ip) <= 0xefffffff); + // An IPv4 address is multicast if it is in the range 224.0.0.0 to 239.255.255.255, inclusive + // (224.0.0.0/4) + return (LWPA_IP_V4_ADDRESS(ip) >= 0xe0000000u && LWPA_IP_V4_ADDRESS(ip) <= 0xefffffffu); } else if (LWPA_IP_IS_V6(ip)) { + // An IPv6 address is multicast if the first octet is 0xff (ff00::/8) return (LWPA_IP_V6_ADDRESS(ip)[0] == 0xff); } } @@ -89,6 +121,7 @@ bool lwpa_ip_is_wildcard(const LwpaIpAddr* ip) { if (ip) { + // Wildcard addresses are all-zeroes if (LWPA_IP_IS_V4(ip)) { return (LWPA_IP_V4_ADDRESS(ip) == 0); diff --git a/src/lwpa/netint.c b/src/lwpa/netint.c new file mode 100644 index 000000000..bd8cd58b1 --- /dev/null +++ b/src/lwpa/netint.c @@ -0,0 +1,179 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/netint.h" +#include "lwpa/private/netint.h" + +#include + +/**************************** Private variables ******************************/ + +bool module_initialized; +CachedNetintInfo netint_cache; +DefaultNetint default_netint; + +/*********************** Private function prototypes *************************/ + +static int compare_netints(const void* a, const void* b); + +/*************************** Function definitions ****************************/ + +lwpa_error_t lwpa_netint_init() +{ + lwpa_error_t res = kLwpaErrOk; + if (!module_initialized) + { + res = os_enumerate_interfaces(&netint_cache); + if (res == kLwpaErrOk) + { + // Sort the interfaces by OS index + qsort(netint_cache.netints, netint_cache.num_netints, sizeof(LwpaNetintInfo), compare_netints); + + // Store the locations of the default netints for access by the API function + for (size_t i = 0; i < netint_cache.num_netints; ++i) + { + LwpaNetintInfo* netint = &netint_cache.netints[i]; + if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) + { + default_netint.v4_valid = true; + default_netint.v4_index = i; + } + else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) + { + default_netint.v6_valid = true; + default_netint.v6_index = i; + } + } + + module_initialized = true; + } + } + return res; +} + +void lwpa_netint_deinit() +{ + if (module_initialized) + { + os_free_interfaces(&netint_cache); + memset(&netint_cache, 0, sizeof(netint_cache)); + module_initialized = false; + } +} + +/*! \brief Get the number of network interfaces present on the system. + * \return Number of interfaces present. + */ +size_t lwpa_netint_get_num_interfaces() +{ + return (module_initialized ? netint_cache.num_netints : 0); +} + +/*! \brief Enumerate the network interfaces on the system. + * \param[out] netint_arr Array of network interface description structs to fill in with interface + * info. + * \param[in] netint_arr_size Size of the netint array. + * \return Number of network interfaces that were enumerated, up to a maximum of netint_arr_size, + * or 0 if there are no interfaces present or an error occurred. + */ +size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) +{ + if (!module_initialized || !netint_arr || netint_arr_size == 0) + return 0; + + size_t addrs_copied = (netint_arr_size < netint_cache.num_netints ? netint_arr_size : netint_cache.num_netints); + memcpy(netint_arr, netint_cache.netints, addrs_copied * sizeof(LwpaNetintInfo)); + return addrs_copied; +} + +/*! \brief Get information about the default network interface. + * + * For our purposes, the 'default' network interface is defined as the interface that is chosen + * for the default IP route. Note: If the network interfaces have already been enumerated with + * lwpa_netint_get_interfaces(), it is more efficient to inspect the is_default flag of each + * interface in that existing array. + * + * \param[out] netint Pointer to network interface description struct to fill with the information + * about the default interface. + * \return true (netint was filled in) or false (error occurred). + */ +bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) +{ + if (module_initialized && netint) + { + if (type == kLwpaIpTypeV4 && default_netint.v4_valid) + { + *netint = netint_cache.netints[default_netint.v4_index]; + return true; + } + else if (type == kLwpaIpTypeV6 && default_netint.v6_valid) + { + *netint = netint_cache.netints[default_netint.v6_index]; + return true; + } + } + return false; +} + +/*! \brief Get the network interface that the system will choose when routing an IP packet to the + * specified destination. + * + * \param[in] dest IP address of the destination. + * \param[out] netint Pointer to network interface description struct to fill in with information + * about the chosen interface. + * \return #kLwpaErrOk: Netint filled in successfully. + * \return #kLwpaErrInvalid: Invalid argument provided. + * \return #kLwpaErrNotInit: Module not initialized. + * \return #kLwpaErrNoNetints: No network interfaces found on system. + * \return #kLwpaErrNotFound: No route was able to be resolved to the destination. + */ +lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) +{ + if (!dest || !netint) + return kLwpaErrInvalid; + if (!module_initialized) + return kLwpaErrNotInit; + if (netint_cache.num_netints == 0) + return kLwpaErrNoNetints; + + int index; + lwpa_error_t res = os_resolve_route(dest, &index); + if (res == kLwpaErrOk) + { + for (LwpaNetintInfo* netint_entry = netint_cache.netints; + netint_entry < netint_cache.netints + netint_cache.num_netints; ++netint_entry) + { + if (netint_entry->ifindex == index) + { + *netint = *netint_entry; + return kLwpaErrOk; + } + } + return kLwpaErrNotFound; + } + return res; +} + +int compare_netints(const void* a, const void* b) +{ + LwpaNetintInfo* netint1 = (LwpaNetintInfo*)a; + LwpaNetintInfo* netint2 = (LwpaNetintInfo*)b; + + return (netint1->ifindex > netint2->ifindex) - (netint1->ifindex < netint2->ifindex); +} diff --git a/src/lwpa/netint.dox b/src/lwpa/netint.dox deleted file mode 100644 index e720227f5..000000000 --- a/src/lwpa/netint.dox +++ /dev/null @@ -1,69 +0,0 @@ -Whoa, this isn't a real source file! What's going on here? Well, the sources for this module are -platform-specific, so the functions are documented here to avoid repeating documentation in each -source file. - -/*! \addtogroup lwpa_netint - * @{ - */ - -/*! \brief Get the number of network interfaces present on the system. - * \return Number of interfaces present. */ -size_t lwpa_netint_get_num_interfaces(); - -/*! \brief Enumerate the network interfaces on the system. - * \param[out] netint_arr Array of network interface description structs to fill in with interface - * info. - * \param[in] netint_arr_size Size of the netint array. - * \return Number of network interfaces that were enumerated, up to a maximum of netint_arr_size, - * or 0 if there are no interfaces present or an error occurred. - */ -size_t lwpa_netint_get_interfaces(LwpaNetintInfo *netint_arr, size_t netint_arr_size); - -/*! \brief Get information about the default network interface. - * - * Note: If the network interfaces have already been enumerated with lwpa_netint_get_interfaces(), - * it is more efficient to inspect the is_default flag of each interface in that existing array. - * - * \param[out] netint Pointer to network interface description struct to fill with the information - * about the default interface. - * \return true (netint was filled in) or false (error occurred). - */ -bool lwpa_netint_get_default_interface(LwpaNetintInfo *netint); - -/*! \brief Get the network interface that the system will choose when routing an IP packet to the - * specified destination. - * - * \param[in] dest IP address of the destination. - * \param[in] netint_arr Array of network interface description structs previously populated using - * lwpa_netint_get_interfaces(). - * \param[in] netint_arr_size Size of the netint array. - * \return Pointer to info struct for interface that will be chosen for this destination. This will - * be a pointer to an element in the netint_arr, or NULL if the route could not be resolved - * (this will only occur if there is no default interface marked in the array). - */ -const LwpaNetintInfo * lwpa_netint_get_iface_for_dest(const LwpaIpAddr *dest, const LwpaNetintInfo *netint_arr, - size_t netint_arr_size); - -/*! \brief Register a callback function to be called when a network interface on the system has - * changed. - * - * On some systems, this will spawn a thread to check for network changes. Additional calls will - * add to the list of functions called on a network change, up to a platform-specific maximum. - * - * \param[in] fn Function to call when a network interface changes. - * \param[in] context Application data to pass to the callback function. - * \return A handle that can be used to unregister the function later on success, or -1 if an error - * occurred or too many functions were registered already. - */ -int lwpa_netint_register_change_cb(netint_change_notification fn, void *context); - -/*! \brief Unregister a network change callback. - * - * Pass the value returned from netint_register_change_cb() to this function to unregister the - * callback. That callback will no longer be called on network change. - * - * \param[in] handle Handle for callback to unregister. - */ -void lwpa_netint_unregister_change_cb(int handle); - -/*! @} */ diff --git a/src/lwpa/private/netint.h b/src/lwpa/private/netint.h index 11ffbad61..a1b4775a5 100644 --- a/src/lwpa/private/netint.h +++ b/src/lwpa/private/netint.h @@ -20,9 +20,29 @@ #ifndef _LWPA_PRIVATE_NETINT_H_ #define _LWPA_PRIVATE_NETINT_H_ +#include "lwpa/netint.h" #include "lwpa/error.h" +typedef struct DefaultNetint +{ + bool v4_valid; + size_t v4_index; + + bool v6_valid; + size_t v6_index; +} DefaultNetint; + +typedef struct CachedNetintInfo +{ + size_t num_netints; + LwpaNetintInfo* netints; +} CachedNetintInfo; + lwpa_error_t lwpa_netint_init(); void lwpa_netint_deinit(); +lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache); +void os_free_interfaces(CachedNetintInfo* cache); +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index); + #endif /* _LWPA_PRIVATE_NETINT_H_ */ diff --git a/src/lwpa/uuid.c b/src/lwpa/uuid.c index 00b88d0ed..01d7bc6f2 100644 --- a/src/lwpa/uuid.c +++ b/src/lwpa/uuid.c @@ -107,7 +107,7 @@ bool lwpa_string_to_uuid(LwpaUuid* uuid, const char* buf, size_t buflen) return false; } -/* This documentation appears here; the actual functions are in [platform]/lwpa_uuid_plat.c */ +/* This documentation appears here; the actual functions are in os/[os name]/lwpa/os_uuid.c */ /*! \fn lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid *uuid) * \brief Generate a Version 1 UUID. * @@ -122,10 +122,10 @@ bool lwpa_string_to_uuid(LwpaUuid* uuid, const char* buf, size_t buflen) * available (this is mostly a concern for RTOS-level embedded platforms). * * \param[out] uuid UUID to fill in with the generation result. - * \return #kLwpaErrOk: UUID generated successfully.\n - * #kLwpaErrInvalid: Invalid argument provided.\n - * #kLwpaErrNotImpl: This UUID generation method is not available on this platform.\n - * #kLwpaErrSys: An internal library of system call error occurred. + * \return #kLwpaErrOk: UUID generated successfully. + * \return #kLwpaErrInvalid: Invalid argument provided. + * \return #kLwpaErrNotImpl: This UUID generation method is not available on this platform. + * \return #kLwpaErrSys: An internal library of system call error occurred. */ /* Quick utility for generating a uuid out of a md5 hash buffer */ @@ -159,8 +159,8 @@ static void generate_from_hash(LwpaUuid* uuid_out, MD5_CTX* pmd5) * \param[in] macaddr The device's MAC address as an array of 6 bytes. * \param[in] uuidnum Component number. By changing this number, multiple unique UUIDs can be * generated for the same device string-MAC address combination. - * \return #kLwpaErrOk: UUID generated successfully.\n - * #kLwpaErrInvalid: Invalid argument provided. + * \return #kLwpaErrOk: UUID generated successfully. + * \return #kLwpaErrInvalid: Invalid argument provided. */ lwpa_error_t lwpa_generate_v3_uuid(LwpaUuid* uuid, const char* devstr, const uint8_t* macaddr, uint32_t uuidnum) { @@ -192,7 +192,7 @@ lwpa_error_t lwpa_generate_v3_uuid(LwpaUuid* uuid, const char* devstr, const uin return kLwpaErrOk; } -/* This documentation appears here; the actual functions are in [platform]/lwpa_uuid_plat.c */ +/* This documentation appears here; the actual functions are in os/[os name]/lwpa/os_uuid.c */ /*! \fn lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid *uuid) * \brief Generate a Version 4 UUID. * @@ -204,8 +204,8 @@ lwpa_error_t lwpa_generate_v3_uuid(LwpaUuid* uuid, const char* devstr, const uin * available (this is mostly a concern for RTOS-level embedded platforms). * * \param[out] uuid UUID to fill in with the generation result. - * \return #kLwpaErrOk: UUID generated successfully.\n - * #kLwpaErrInvalid: Invalid argument provided.\n - * #kLwpaErrNotImpl: This UUID generation method is not available on this platform.\n - * #kLwpaErrSys: An internal library of system call error occurred. + * \return #kLwpaErrOk: UUID generated successfully. + * \return #kLwpaErrInvalid: Invalid argument provided. + * \return #kLwpaErrNotImpl: This UUID generation method is not available on this platform. + * \return #kLwpaErrSys: An internal library of system call error occurred. */ diff --git a/src/os/linux/lwpa/os_inet.c b/src/os/linux/lwpa/os_inet.c new file mode 100644 index 000000000..0dfcf1437 --- /dev/null +++ b/src/os/linux/lwpa/os_inet.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/inet.h" + +bool ip_os_to_lwpa(const struct sockaddr *os_ip, LwpaIpAddr *ip) +{ + return false; +} + +bool ip_lwpa_to_os(const LwpaIpAddr *ip, struct sockaddr *os_ip) +{ + return false; +} diff --git a/src/os/windows/lwpa/os_inet.c b/src/os/windows/lwpa/os_inet.c new file mode 100644 index 000000000..11cb92ef8 --- /dev/null +++ b/src/os/windows/lwpa/os_inet.c @@ -0,0 +1,147 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/inet.h" +#include + +bool ip_os_to_lwpa(const lwpa_os_ipaddr_t* os_ip, LwpaIpAddr* ip) +{ + if (os_ip->sa_family == AF_INET) + { + const struct sockaddr_in* sin = (const struct sockaddr_in*)os_ip; + LWPA_IP_SET_V4_ADDRESS(ip, ntohl(sin->sin_addr.s_addr)); + return true; + } + else if (os_ip->sa_family == AF_INET6) + { + const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)os_ip; + LWPA_IP_SET_V6_ADDRESS(ip, sin6->sin6_addr.s6_addr); + return true; + } + return false; +} + +size_t ip_lwpa_to_os(const LwpaIpAddr* ip, lwpa_os_ipaddr_t* os_ip) +{ + size_t ret = 0; + if (LWPA_IP_IS_V4(ip)) + { + struct sockaddr_in* sin = (struct sockaddr_in*)os_ip; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(ip)); + ret = sizeof(struct sockaddr_in); + } + else if (LWPA_IP_IS_V6(ip)) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_ip; + memset(sin6, 0, sizeof(struct sockaddr_in6)); + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(ip), LWPA_IPV6_BYTES); + ret = sizeof(struct sockaddr_in6); + } + return ret; +} + +bool sockaddr_os_to_lwpa(const lwpa_os_sockaddr_t* os_sa, LwpaSockaddr* sa) +{ + if (ip_os_to_lwpa(os_sa, &sa->ip)) + { + if (os_sa->sa_family == AF_INET) + { + sa->port = ntohs(((const struct sockaddr_in*)os_sa)->sin_port); + return true; + } + else if (os_sa->sa_family == AF_INET6) + { + sa->port = ntohs(((const struct sockaddr_in6*)os_sa)->sin6_port); + return true; + } + } + return false; +} + +size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, lwpa_os_sockaddr_t* os_sa) +{ + size_t ret = ip_lwpa_to_os(&sa->ip, os_sa); + if (ret != 0) + { + if (LWPA_IP_IS_V4(&sa->ip)) + ((struct sockaddr_in*)os_sa)->sin_port = htons(sa->port); + else if (LWPA_IP_IS_V6(&sa->ip)) + ((struct sockaddr_in6*)os_sa)->sin6_port = htons(sa->port); + } + return ret; +} + +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (src->type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); + if (NULL != inet_ntop(AF_INET, &addr, dest, size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); + if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + default: + return kLwpaErrInvalid; + } +} + +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + if (1 != inet_pton(AF_INET, src, &addr)) + return kLwpaErrSys; + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); + return kLwpaErrOk; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + if (1 != inet_pton(AF_INET6, src, &addr)) + return kLwpaErrSys; + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); + return kLwpaErrOk; + } + default: + return kLwpaErrInvalid; + } +} diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index a0809a45c..b2abb8823 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -27,130 +27,46 @@ #include #include "lwpa/int.h" +#include "lwpa/socket.h" #include "lwpa/private/netint.h" -/**************************** Private variables ******************************/ - -static struct LwpaNetintState -{ - bool initialized; - - size_t num_netints; - LwpaNetintInfo* lwpa_netints; - - bool have_default_netint_index_v4; - size_t default_netint_index_v4; - - bool have_default_netint_index_v6; - size_t default_netint_index_v6; -} state; - /*********************** Private function prototypes *************************/ static IP_ADAPTER_ADDRESSES* get_windows_adapters(); -static void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info); -static void copy_ipv6_info(IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info); -static void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters); - -static lwpa_error_t enumerate_netints(); -static int compare_netints(const void* a, const void* b); -static void free_netints(); +static void copy_ipv4_info(const IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info); +static void copy_ipv6_info(const IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info); +static void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNetintInfo* cache); /*************************** Function definitions ****************************/ -lwpa_error_t lwpa_netint_init() +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) { - lwpa_error_t res = kLwpaErrOk; - if (!state.initialized) + struct sockaddr_storage os_addr; + if (ip_lwpa_to_os(dest, (lwpa_os_ipaddr_t*)&os_addr)) { - res = enumerate_netints(); - if (res == kLwpaErrOk) - state.initialized = true; - } - return res; -} - -void lwpa_netint_deinit() -{ - if (state.initialized) - { - free_netints(); - memset(&state, 0, sizeof(state)); - } -} - -size_t lwpa_netint_get_num_interfaces() -{ - return (state.initialized ? state.num_netints : 0); -} - -size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) -{ - if (!state.initialized || !netint_arr || netint_arr_size == 0) - return 0; - - size_t addrs_copied = (netint_arr_size < state.num_netints ? netint_arr_size : state.num_netints); - memcpy(netint_arr, state.lwpa_netints, addrs_copied * sizeof(LwpaNetintInfo)); - return addrs_copied; -} - -bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) -{ - if (state.initialized && netint) - { - if (type == kLwpaIpTypeV4 && state.have_default_netint_index_v4) + DWORD resolved_index; + DWORD res = GetBestInterfaceEx((struct sockaddr*)&os_addr, &resolved_index); + if (res == NO_ERROR) { - *netint = state.lwpa_netints[state.default_netint_index_v4]; - return true; + *index = resolved_index; + return kLwpaErrOk; } - else if (type == kLwpaIpTypeV6 && state.have_default_netint_index_v6) + else if (res == ERROR_INVALID_PARAMETER) { - *netint = state.lwpa_netints[state.default_netint_index_v6]; - return true; + return kLwpaErrInvalid; } - } - return false; -} - -lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) -{ - if (!dest || !netint) - return kLwpaErrInvalid; - if (!state.initialized) - return kLwpaErrNotInit; - if (state.num_netints == 0) - return kLwpaErrNoNetints; - - const LwpaNetintInfo* res = NULL; - const LwpaNetintInfo* def = NULL; - - for (const LwpaNetintInfo* netint_entry = state.lwpa_netints; netint_entry < state.lwpa_netints + state.num_netints; - ++netint_entry) - { - if (netint_entry->is_default) - def = netint_entry; - if (!lwpa_ip_is_wildcard(&netint_entry->mask) && - lwpa_ip_network_portions_equal(&netint_entry->addr, dest, &netint_entry->mask)) + else { - res = netint_entry; - break; + return kLwpaErrNotFound; } } - if (!res) - res = def; - - if (res) - { - *netint = *res; - return kLwpaErrOk; - } else { - return kLwpaErrNotFound; + return kLwpaErrInvalid; } } -lwpa_error_t enumerate_netints() +lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) { IP_ADAPTER_ADDRESSES *padapters, *pcur; @@ -159,7 +75,7 @@ lwpa_error_t enumerate_netints() return kLwpaErrSys; pcur = padapters; - state.num_netints = 0; + cache->num_netints = 0; while (pcur) { // If this is multihomed, there may be multiple addresses under the same adapter @@ -170,7 +86,7 @@ lwpa_error_t enumerate_netints() { case AF_INET: case AF_INET6: - ++state.num_netints; + ++cache->num_netints; break; default: break; @@ -180,58 +96,30 @@ lwpa_error_t enumerate_netints() pcur = pcur->Next; } - if (state.num_netints == 0) + if (cache->num_netints == 0) { free(padapters); return kLwpaErrNoNetints; } - state.lwpa_netints = calloc(state.num_netints, sizeof(LwpaNetintInfo)); - if (!state.lwpa_netints) + cache->netints = calloc(cache->num_netints, sizeof(LwpaNetintInfo)); + if (!cache->netints) { free(padapters); return kLwpaErrNoMem; } - copy_all_netint_info(padapters); + copy_all_netint_info(padapters, cache); free(padapters); - - // Sort the interfaces by OS index - qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); - - // Store the locations of the default netints for access by the API function - for (size_t i = 0; i < state.num_netints; ++i) - { - LwpaNetintInfo* netint = &state.lwpa_netints[i]; - if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) - { - state.have_default_netint_index_v4 = true; - state.default_netint_index_v4 = i; - } - else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) - { - state.have_default_netint_index_v6 = true; - state.default_netint_index_v6 = i; - } - } - return kLwpaErrOk; } -int compare_netints(const void* a, const void* b) -{ - LwpaNetintInfo* netint1 = (LwpaNetintInfo*)a; - LwpaNetintInfo* netint2 = (LwpaNetintInfo*)b; - - return (netint1->ifindex > netint2->ifindex) - (netint1->ifindex < netint2->ifindex); -} - -void free_netints() +void os_free_interfaces(CachedNetintInfo* cache) { - if (state.lwpa_netints) + if (cache->netints) { - free(state.lwpa_netints); - state.lwpa_netints = NULL; + free(cache->netints); + cache->netints = NULL; } } @@ -259,25 +147,25 @@ IP_ADAPTER_ADDRESSES* get_windows_adapters() return NULL; } -void copy_ipv4_info(IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info) +void copy_ipv4_info(const IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info) { - struct sockaddr_in* sin = (struct sockaddr_in*)pip->Address.lpSockaddr; + const struct sockaddr_in* sin = (const struct sockaddr_in*)pip->Address.lpSockaddr; LWPA_IP_SET_V4_ADDRESS(&info->addr, ntohl(sin->sin_addr.s_addr)); info->mask = lwpa_ip_mask_from_length(kLwpaIpTypeV4, pip->OnLinkPrefixLength); } -void copy_ipv6_info(IP_ADAPTER_UNICAST_ADDRESS *pip, LwpaNetintInfo *info) +void copy_ipv6_info(const IP_ADAPTER_UNICAST_ADDRESS* pip, LwpaNetintInfo* info) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pip->Address.lpSockaddr; + const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)pip->Address.lpSockaddr; LWPA_IP_SET_V6_ADDRESS(&info->addr, sin6->sin6_addr.s6_addr); info->mask = lwpa_ip_mask_from_length(kLwpaIpTypeV6, pip->OnLinkPrefixLength); } -void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) +void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNetintInfo* cache) { - IP_ADAPTER_ADDRESSES* pcur = adapters; + const IP_ADAPTER_ADDRESSES* pcur = adapters; // Get the index of the default interface for IPv4 DWORD def_ifindex_v4; @@ -285,7 +173,7 @@ void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) struct sockaddr_in v4_dest; memset(&v4_dest, 0, sizeof v4_dest); v4_dest.sin_family = AF_INET; - if (NO_ERROR == GetBestInterfaceEx((struct sockaddr *)&v4_dest, &def_ifindex_v4)) + if (NO_ERROR == GetBestInterfaceEx((struct sockaddr*)&v4_dest, &def_ifindex_v4)) have_def_index_v4 = true; // And the same for IPv6 @@ -294,7 +182,7 @@ void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) struct sockaddr_in6 v6_dest; memset(&v6_dest, 0, sizeof v6_dest); v6_dest.sin6_family = AF_INET6; - if (NO_ERROR == GetBestInterfaceEx((struct sockaddr *)&v6_dest, &def_ifindex_v6)) + if (NO_ERROR == GetBestInterfaceEx((struct sockaddr*)&v6_dest, &def_ifindex_v6)) have_def_index_v6 = true; size_t netint_index = 0; @@ -305,7 +193,7 @@ void copy_all_netint_info(IP_ADAPTER_ADDRESSES* adapters) IP_ADAPTER_UNICAST_ADDRESS* pip = pcur->FirstUnicastAddress; while (pip) { - LwpaNetintInfo* info = &state.lwpa_netints[netint_index]; + LwpaNetintInfo* info = &cache->netints[netint_index]; switch (pip->Address.lpSockaddr->sa_family) { case AF_INET: diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index fbd787be5..01908ae6f 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -122,50 +122,6 @@ static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent /*************************** Function definitions ****************************/ -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) -{ - if (pfsa->sa_family == AF_INET) - { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sa->port = ntohs(sin->sin_port); - LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); - return true; - } - else if (pfsa->sa_family == AF_INET6) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sa->port = ntohs(sin6->sin6_port); - LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); - return true; - } - return false; -} - -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) -{ - size_t ret = 0; - if (LWPA_IP_IS_V4(&sa->ip)) - { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - memset(sin, 0, sizeof(struct sockaddr_in)); - sin->sin_family = AF_INET; - sin->sin_port = htons(sa->port); - sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); - ret = sizeof(struct sockaddr_in); - } - else if (LWPA_IP_IS_V6(&sa->ip)) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - memset(sin6, 0, sizeof(struct sockaddr_in6)); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(sa->port); - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); - ret = sizeof(struct sockaddr_in6); - in6addr_any; - } - return ret; -} - #if !defined(LWPA_BUILDING_MOCK_LIB) lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) @@ -181,7 +137,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* if (res != INVALID_SOCKET) { - if (address && !sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) + if (address && !sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&ss, address)) { closesocket(res); return kLwpaErrSys; @@ -201,7 +157,7 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); + sa_size = sockaddr_lwpa_to_os(address, (lwpa_os_sockaddr_t*)&ss); if (sa_size == 0) return kLwpaErrInvalid; @@ -224,7 +180,7 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); + sa_size = sockaddr_lwpa_to_os(address, (lwpa_os_sockaddr_t*)&ss); if (sa_size == 0) return kLwpaErrInvalid; @@ -252,7 +208,7 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) res = getsockname(id, (struct sockaddr*)&ss, &size); if (res == 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) + if (!sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&ss, address)) return kLwpaErrSys; return kLwpaErrOk; } @@ -304,7 +260,7 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa { if (address && fromlen > 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) + if (!sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&fromaddr, address)) return kLwpaErrSys; } return res; @@ -334,7 +290,7 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, if (!dest_addr || !message) return (int)kLwpaErrInvalid; - if ((ss_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr)) > 0) + if ((ss_size = sockaddr_lwpa_to_os(dest_addr, (lwpa_os_sockaddr_t*)&ss)) > 0) res = sendto(id, message, (int)length, 0, (struct sockaddr*)&ss, (int)ss_size); return (res >= 0 ? res : (int)err_winsock_to_lwpa(WSAGetLastError())); @@ -996,7 +952,7 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) { struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; - if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + if (!sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)pf_ai->ai_addr, &ai->ai_addr)) return false; /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS @@ -1037,59 +993,3 @@ void lwpa_freeaddrinfo(LwpaAddrinfo* ai) } #endif /* !defined(LWPA_BUILDING_MOCK_LIB) */ - -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (src->type) - { - case kLwpaIpTypeV4: - { - struct in_addr addr; - addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); - if (NULL != inet_ntop(AF_INET, &addr, dest, size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - case kLwpaIpTypeV6: - { - struct in6_addr addr; - memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); - if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - default: - return kLwpaErrInvalid; - } -} - -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (type) - { - case kLwpaIpTypeV4: - { - struct in_addr addr; - if (1 != inet_pton(AF_INET, src, &addr)) - return kLwpaErrSys; - LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); - return kLwpaErrOk; - } - case kLwpaIpTypeV6: - { - struct in6_addr addr; - if (1 != inet_pton(AF_INET6, src, &addr)) - return kLwpaErrSys; - LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); - return kLwpaErrOk; - } - default: - return kLwpaErrInvalid; - } -} diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index bc2365622..1f36daf3f 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -87,7 +87,7 @@ TEST_F(NetintTest, ipv4_routing) for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) { - if (!LWPA_IP_IS_V4(&netint->addr) || lwpa_ip_is_loopback(&netint->addr)) + if (!LWPA_IP_IS_V4(&netint->addr) || lwpa_ip_is_loopback(&netint->addr) || lwpa_ip_is_link_local(&netint->addr)) continue; uint32_t net = LWPA_IP_V4_ADDRESS(&netint->addr) & LWPA_IP_V4_ADDRESS(&netint->mask); @@ -100,7 +100,15 @@ TEST_F(NetintTest, ipv4_routing) LwpaNetintInfo netint_res; ASSERT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&test_addr, &netint_res)); - EXPECT_TRUE(lwpa_ip_equal(&netint_res.addr, &netint->addr)); + + // Put addresses in print form to test meaningful information in case of test failure + char test_addr_str[LWPA_INET6_ADDRSTRLEN]; + char result_str[LWPA_INET6_ADDRSTRLEN]; + lwpa_inet_ntop(&test_addr, test_addr_str, LWPA_INET6_ADDRSTRLEN); + lwpa_inet_ntop(&netint_res.addr, result_str, LWPA_INET6_ADDRSTRLEN); + + EXPECT_TRUE(lwpa_ip_equal(&netint_res.addr, &netint->addr)) + << "Address tried: " << test_addr_str << ", interface returned: " << result_str; } LwpaIpAddr ext_addr; From 317c37d194a4e86071df64f050661fe995eb35bb Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 13 Jun 2019 16:48:55 -0500 Subject: [PATCH 043/264] And fix the Linux side. --- include/os/linux/lwpa/os_inet.h | 15 +- src/os/linux/lwpa/os_inet.c | 121 ++++++++++- src/os/linux/lwpa/os_netint.c | 354 ++++++++++---------------------- src/os/linux/lwpa/os_socket.c | 111 +--------- tests/unit/test_socket.cpp | 2 +- 5 files changed, 244 insertions(+), 359 deletions(-) diff --git a/include/os/linux/lwpa/os_inet.h b/include/os/linux/lwpa/os_inet.h index 0cc14e407..4d066e72e 100644 --- a/include/os/linux/lwpa/os_inet.h +++ b/include/os/linux/lwpa/os_inet.h @@ -20,18 +20,9 @@ #ifndef _LWPA_OS_INET_H_ #define _LWPA_OS_INET_H_ -#ifdef __cplusplus -extern "C" { -#endif +#include -bool ip_os_to_lwpa(const struct sockaddr* os_ip, LwpaIpAddr* ip); -size_t ip_lwpa_to_os(const LwpaIpAddr* ip, struct sockaddr* os_ip); - -bool sockaddr_os_to_lwpa(const struct sockaddr* os_sa, LwpaSockaddr* sa); -size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, struct sockaddr* os_sa); - -#ifdef __cplusplus -} -#endif +typedef struct sockaddr lwpa_os_sockaddr_t; +typedef struct sockaddr lwpa_os_ipaddr_t; #endif /* _LWPA_OS_INET_H_ */ diff --git a/src/os/linux/lwpa/os_inet.c b/src/os/linux/lwpa/os_inet.c index 0dfcf1437..f17ca5e27 100644 --- a/src/os/linux/lwpa/os_inet.c +++ b/src/os/linux/lwpa/os_inet.c @@ -18,13 +18,130 @@ ******************************************************************************/ #include "lwpa/inet.h" +#include -bool ip_os_to_lwpa(const struct sockaddr *os_ip, LwpaIpAddr *ip) +bool ip_os_to_lwpa(const lwpa_os_ipaddr_t* os_ip, LwpaIpAddr* ip) { + if (os_ip->sa_family == AF_INET) + { + const struct sockaddr_in* sin = (const struct sockaddr_in*)os_ip; + LWPA_IP_SET_V4_ADDRESS(ip, ntohl(sin->sin_addr.s_addr)); + return true; + } + else if (os_ip->sa_family == AF_INET6) + { + const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)os_ip; + LWPA_IP_SET_V6_ADDRESS(ip, sin6->sin6_addr.s6_addr); + return true; + } return false; } -bool ip_lwpa_to_os(const LwpaIpAddr *ip, struct sockaddr *os_ip) +size_t ip_lwpa_to_os(const LwpaIpAddr* ip, lwpa_os_ipaddr_t* os_ip) { + size_t ret = 0; + if (LWPA_IP_IS_V4(ip)) + { + struct sockaddr_in* sin = (struct sockaddr_in*)os_ip; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(ip)); + ret = sizeof(struct sockaddr_in); + } + else if (LWPA_IP_IS_V6(ip)) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_ip; + memset(sin6, 0, sizeof(struct sockaddr_in6)); + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(ip), LWPA_IPV6_BYTES); + ret = sizeof(struct sockaddr_in6); + } + return ret; +} + +bool sockaddr_os_to_lwpa(const lwpa_os_sockaddr_t* os_sa, LwpaSockaddr* sa) +{ + if (ip_os_to_lwpa(os_sa, &sa->ip)) + { + if (os_sa->sa_family == AF_INET) + { + sa->port = ntohs(((const struct sockaddr_in*)os_sa)->sin_port); + return true; + } + else if (os_sa->sa_family == AF_INET6) + { + sa->port = ntohs(((const struct sockaddr_in6*)os_sa)->sin6_port); + return true; + } + } return false; } + +size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, lwpa_os_sockaddr_t* os_sa) +{ + size_t ret = ip_lwpa_to_os(&sa->ip, os_sa); + if (ret != 0) + { + if (LWPA_IP_IS_V4(&sa->ip)) + ((struct sockaddr_in*)os_sa)->sin_port = htons(sa->port); + else if (LWPA_IP_IS_V6(&sa->ip)) + ((struct sockaddr_in6*)os_sa)->sin6_port = htons(sa->port); + } + return ret; +} + +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (src->type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); + if (NULL != inet_ntop(AF_INET, &addr, dest, (socklen_t)size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); + if (NULL != inet_ntop(AF_INET6, &addr, dest, (socklen_t)size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + default: + return kLwpaErrInvalid; + } +} + +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + if (1 != inet_pton(AF_INET, src, &addr)) + return kLwpaErrSys; + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); + return kLwpaErrOk; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + if (1 != inet_pton(AF_INET6, src, &addr)) + return kLwpaErrSys; + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); + return kLwpaErrOk; + } + default: + return kLwpaErrInvalid; + } +} diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 5a4269576..2db13a185 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -83,23 +83,8 @@ typedef struct RtNetlinkRequest /**************************** Private variables ******************************/ -static struct LwpaNetintState -{ - bool initialized; - - RoutingTable routing_table_v4; - RoutingTable routing_table_v6; - - struct ifaddrs* os_addrs; - size_t num_netints; - LwpaNetintInfo* lwpa_netints; - - bool have_default_netint_index_v4; - size_t default_netint_index_v4; - - bool have_default_netint_index_v6; - size_t default_netint_index_v6; -} state; +RoutingTable routing_table_v4; +RoutingTable routing_table_v6; /*********************** Private function prototypes *************************/ @@ -118,85 +103,133 @@ static lwpa_error_t parse_netlink_route_reply(int family, const char* buffer, si static void init_routing_table_entry(RoutingTableEntry* entry); static int compare_routing_table_entries(const void* a, const void* b); -// Functions for enumerating the interfaces -static lwpa_error_t enumerate_netints(); -static int compare_netints(const void* a, const void* b); -static void free_netints(); - #if LWPA_NETINT_DEBUG_OUTPUT static void debug_print_routing_table(RoutingTable* table); #endif /*************************** Function definitions ****************************/ -lwpa_error_t lwpa_netint_init() +/* Quick helper for enumerate_netints() to determine entries to skip in the linked list. */ +static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) { - lwpa_error_t res = kLwpaErrOk; - if (!state.initialized) - { - res = enumerate_netints(); - if (res == kLwpaErrOk) - state.initialized = true; - } - return res; + // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. + return (!ifaddr->ifa_addr || (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6)); } -void lwpa_netint_deinit() +lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) { - if (state.initialized) + lwpa_error_t res = build_routing_tables(); + if (res != kLwpaErrOk) + return res; + + int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (ioctl_sock == -1) + return errno_os_to_lwpa(errno); + + struct ifaddrs* os_addrs; + if (getifaddrs(&os_addrs) < 0) { - free_netints(); - memset(&state, 0, sizeof(state)); + close(ioctl_sock); + return errno_os_to_lwpa(errno); } -} -/****************************************************************************** - * API Functions - *****************************************************************************/ + // Pass 1: Total the number of addresses + cache->num_netints = 0; + for (struct ifaddrs* ifaddr = os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + { + if (should_skip_ifaddr(ifaddr)) + continue; -size_t lwpa_netint_get_num_interfaces() -{ - return (state.initialized ? state.num_netints : 0); -} + ++cache->num_netints; + } -size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) -{ - if (!state.initialized || !netint_arr || netint_arr_size == 0) - return 0; + if (cache->num_netints == 0) + { + freeifaddrs(os_addrs); + close(ioctl_sock); + return kLwpaErrNoNetints; + } - size_t addrs_copied = (netint_arr_size < state.num_netints ? netint_arr_size : state.num_netints); - memcpy(netint_arr, state.lwpa_netints, addrs_copied * sizeof(LwpaNetintInfo)); - return addrs_copied; -} + // Allocate our interface array + cache->netints = (LwpaNetintInfo*)calloc(cache->num_netints, sizeof(LwpaNetintInfo)); + if (!cache->netints) + { + freeifaddrs(os_addrs); + close(ioctl_sock); + return kLwpaErrNoMem; + } -bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) -{ - if (state.initialized && netint) + // Pass 2: Fill in all the info about each address + size_t current_lwpa_index = 0; + for (struct ifaddrs* ifaddr = os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) { - if (type == kLwpaIpTypeV4 && state.have_default_netint_index_v4) + if (should_skip_ifaddr(ifaddr)) + continue; + + LwpaNetintInfo* current_info = &cache->netints[current_lwpa_index]; + + // Interface name + strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); + current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; + + // Interface address + ip_os_to_lwpa(ifaddr->ifa_addr, ¤t_info->addr); + + // Interface netmask + ip_os_to_lwpa(ifaddr->ifa_netmask, ¤t_info->mask); + + // Struct ifreq to use with ioctl() calls + struct ifreq if_req; + strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); + + // Hardware address + int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); + if (ioctl_res == 0) + memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); + else + memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); + + // Interface index + ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); + if (ioctl_res == 0) + current_info->ifindex = if_req.ifr_ifindex; + else + current_info->ifindex = -1; + + // Is Default + if (LWPA_IP_IS_V4(¤t_info->addr) && routing_table_v4.default_route && + current_info->ifindex == routing_table_v4.default_route->interface_index) { - *netint = state.lwpa_netints[state.default_netint_index_v4]; - return true; + current_info->is_default = true; } - else if (type == kLwpaIpTypeV6 && state.have_default_netint_index_v6) + else if (LWPA_IP_IS_V6(¤t_info->addr) && routing_table_v6.default_route && + current_info->ifindex == routing_table_v6.default_route->interface_index) { - *netint = state.lwpa_netints[state.default_netint_index_v6]; - return true; + current_info->is_default = true; } + + current_lwpa_index++; } - return false; + + freeifaddrs(os_addrs); + close(ioctl_sock); + return kLwpaErrOk; } -lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) +void os_free_interfaces(CachedNetintInfo* cache) { - if (!dest || !netint) - return kLwpaErrInvalid; - if (!state.initialized) - return kLwpaErrNotInit; - if (state.num_netints == 0) - return kLwpaErrNoNetints; + if (cache->netints) + { + free(cache->netints); + cache->netints = NULL; + } + + free_routing_tables(); +} - RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &state.routing_table_v6 : &state.routing_table_v4); +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) +{ + RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &routing_table_v6 : &routing_table_v4); int index_found = -1; for (RoutingTableEntry* entry = table_to_use->entries; entry < table_to_use->entries + table_to_use->size; ++entry) @@ -216,40 +249,31 @@ lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNeti if (index_found < 0 && table_to_use->default_route) index_found = table_to_use->default_route->interface_index; - // Find the network interface with the correct index if (index_found >= 0) { - for (LwpaNetintInfo* netint_entry = state.lwpa_netints; netint_entry < state.lwpa_netints + state.num_netints; - ++netint_entry) - { - if (netint_entry->ifindex == index_found) - { - *netint = *netint_entry; - return kLwpaErrOk; - } - } + *index = index_found; + return kLwpaErrOk; + } + else + { + return kLwpaErrNotFound; } - return kLwpaErrNotFound; } -/****************************************************************************** - * Internal Functions - *****************************************************************************/ - lwpa_error_t build_routing_tables() { - lwpa_error_t res = build_routing_table(AF_INET, &state.routing_table_v4); + lwpa_error_t res = build_routing_table(AF_INET, &routing_table_v4); if (res == kLwpaErrOk) { - res = build_routing_table(AF_INET6, &state.routing_table_v6); + res = build_routing_table(AF_INET6, &routing_table_v6); } if (res != kLwpaErrOk) free_routing_tables(); #if LWPA_NETINT_DEBUG_OUTPUT - debug_print_routing_table(&state.routing_table_v4); - debug_print_routing_table(&state.routing_table_v6); + debug_print_routing_table(&routing_table_v4); + debug_print_routing_table(&routing_table_v6); #endif return res; @@ -501,144 +525,10 @@ int compare_routing_table_entries(const void* a, const void* b) } } -/* Quick helper for enumerate_netints() to determine entries to skip in the linked list. */ -static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) -{ - // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. - return (!ifaddr->ifa_addr || (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6)); -} - -lwpa_error_t enumerate_netints() -{ - lwpa_error_t res = build_routing_tables(); - if (res != kLwpaErrOk) - return res; - - int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (ioctl_sock == -1) - return errno_os_to_lwpa(errno); - - if (getifaddrs(&state.os_addrs) < 0) - { - close(ioctl_sock); - return errno_os_to_lwpa(errno); - } - - // Pass 1: Total the number of addresses - state.num_netints = 0; - for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) - { - if (should_skip_ifaddr(ifaddr)) - continue; - - ++state.num_netints; - } - - if (state.num_netints == 0) - { - freeifaddrs(state.os_addrs); - close(ioctl_sock); - return kLwpaErrNoNetints; - } - - // Allocate our interface array - state.lwpa_netints = (LwpaNetintInfo*)calloc(state.num_netints, sizeof(LwpaNetintInfo)); - if (!state.lwpa_netints) - { - freeifaddrs(state.os_addrs); - close(ioctl_sock); - return kLwpaErrNoMem; - } - - // Pass 2: Fill in all the info about each address - size_t current_lwpa_index = 0; - for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) - { - if (should_skip_ifaddr(ifaddr)) - continue; - - LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; - - // Interface name - strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); - current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; - - // Interface address - LwpaSockaddr temp_sockaddr; - sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_addr); - current_info->addr = temp_sockaddr.ip; - - // Interface netmask - sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); - current_info->mask = temp_sockaddr.ip; - - // Struct ifreq to use with ioctl() calls - struct ifreq if_req; - strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); - - // Hardware address - int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); - if (ioctl_res == 0) - memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); - else - memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); - - // Interface index - ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); - if (ioctl_res == 0) - current_info->ifindex = if_req.ifr_ifindex; - else - current_info->ifindex = -1; - - // Is Default - if (LWPA_IP_IS_V4(¤t_info->addr) && state.routing_table_v4.default_route && - current_info->ifindex == state.routing_table_v4.default_route->interface_index) - { - current_info->is_default = true; - } - else if (LWPA_IP_IS_V6(¤t_info->addr) && state.routing_table_v6.default_route && - current_info->ifindex == state.routing_table_v6.default_route->interface_index) - { - current_info->is_default = true; - } - - current_lwpa_index++; - } - - // Sort the interfaces by OS index - qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); - - // Store the locations of the default netints for access by the API function - for (size_t i = 0; i < state.num_netints; ++i) - { - LwpaNetintInfo* netint = &state.lwpa_netints[i]; - if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) - { - state.have_default_netint_index_v4 = true; - state.default_netint_index_v4 = i; - } - else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) - { - state.have_default_netint_index_v6 = true; - state.default_netint_index_v6 = i; - } - } - close(ioctl_sock); - return kLwpaErrOk; -} - -int compare_netints(const void* a, const void* b) -{ - LwpaNetintInfo* netint1 = (LwpaNetintInfo*)a; - LwpaNetintInfo* netint2 = (LwpaNetintInfo*)b; - - return (netint1->ifindex > netint2->ifindex) - (netint1->ifindex < netint2->ifindex); -} - void free_routing_tables() { - free_routing_table(&state.routing_table_v4); - free_routing_table(&state.routing_table_v6); + free_routing_table(&routing_table_v4); + free_routing_table(&routing_table_v6); } void free_routing_table(RoutingTable* table) @@ -651,22 +541,6 @@ void free_routing_table(RoutingTable* table) table->size = 0; } -void free_netints() -{ - if (state.os_addrs) - { - freeifaddrs(state.os_addrs); - state.os_addrs = NULL; - } - if (state.lwpa_netints) - { - free(state.lwpa_netints); - state.lwpa_netints = NULL; - } - - free_routing_tables(); -} - #if LWPA_NETINT_DEBUG_OUTPUT void debug_print_routing_table(RoutingTable* table) { diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 7e443234a..2c1f786b5 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -129,47 +129,6 @@ static void poll_socket_free(LwpaRbNode* node); /*************************** Function definitions ****************************/ -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) -{ - if (pfsa->sa_family == AF_INET) - { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sa->port = ntohs(sin->sin_port); - LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); - return true; - } - else if (pfsa->sa_family == AF_INET6) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sa->port = ntohs(sin6->sin6_port); - LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); - return true; - } - return false; -} - -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) -{ - size_t ret = 0; - if (LWPA_IP_IS_V4(&sa->ip)) - { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sin->sin_family = AF_INET; - sin->sin_port = htons(sa->port); - sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); - ret = sizeof(struct sockaddr_in); - } - else if (LWPA_IP_IS_V6(&sa->ip)) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(sa->port); - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); - ret = sizeof(struct sockaddr_in6); - } - return ret; -} - lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { if (!conn_sock) @@ -181,7 +140,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* if (res != -1) { - if (address && !sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) + if (address && !sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&ss, address)) { close(res); return kLwpaErrSys; @@ -198,7 +157,7 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) return kLwpaErrInvalid; struct sockaddr_storage ss; - socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os(address, (lwpa_os_sockaddr_t*)&ss); if (sa_size == 0) return kLwpaErrInvalid; @@ -218,7 +177,7 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) return kLwpaErrInvalid; struct sockaddr_storage ss; - socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os(address, (lwpa_os_sockaddr_t*)&ss); if (sa_size == 0) return kLwpaErrInvalid; @@ -244,7 +203,7 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) int res = getsockname(id, (struct sockaddr*)&ss, &size); if (res == 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) + if (!sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&ss, address)) return kLwpaErrSys; return kLwpaErrOk; } @@ -292,7 +251,7 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa { if (address && fromlen > 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) + if (!sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&fromaddr, address)) return kLwpaErrSys; } return res; @@ -319,7 +278,7 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, return (int)kLwpaErrInvalid; struct sockaddr_storage ss; - socklen_t ss_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr); + socklen_t ss_size = (socklen_t)sockaddr_lwpa_to_os(dest_addr, (lwpa_os_sockaddr_t*)&ss); if (ss_size == 0) return (int)kLwpaErrSys; @@ -864,7 +823,7 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) { struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; - if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + if (!sockaddr_os_to_lwpa(pf_ai->ai_addr, &ai->ai_addr)) return false; /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS @@ -900,59 +859,3 @@ void lwpa_freeaddrinfo(LwpaAddrinfo* ai) if (ai) freeaddrinfo((struct addrinfo*)ai->pd[0]); } - -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (src->type) - { - case kLwpaIpTypeV4: - { - struct in_addr addr; - addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); - if (NULL != inet_ntop(AF_INET, &addr, dest, (socklen_t)size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - case kLwpaIpTypeV6: - { - struct in6_addr addr; - memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); - if (NULL != inet_ntop(AF_INET6, &addr, dest, (socklen_t)size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - default: - return kLwpaErrInvalid; - } -} - -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (type) - { - case kLwpaIpTypeV4: - { - struct in_addr addr; - if (1 != inet_pton(AF_INET, src, &addr)) - return kLwpaErrSys; - LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); - return kLwpaErrOk; - } - case kLwpaIpTypeV6: - { - struct in6_addr addr; - if (1 != inet_pton(AF_INET6, src, &addr)) - return kLwpaErrSys; - LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); - return kLwpaErrOk; - } - default: - return kLwpaErrInvalid; - } -} diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 94ebf0ccd..803b8eb47 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -268,7 +268,7 @@ TEST_F(SocketTest, multicast_udp) } else { - EXPECT_EQ(res, kLwpaErrTimedOut); + EXPECT_EQ(res, kLwpaErrWouldBlock); break; } From ec8ab161035817b3a44f13e54ce59e4b17812519 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 13 Jun 2019 17:06:57 -0500 Subject: [PATCH 044/264] Update main README with Linux line --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 392f95b99..2159d3d43 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ The lwpa library serves two main purposes: ## Platform Ports lwpa is currently ported for the following platforms: ++ Linux + Microsoft Windows + MQX RTOS From 87125b98be185e84dae314428b5bfdaa8d080145 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 14 Jun 2019 17:51:17 -0500 Subject: [PATCH 045/264] Bring macos up-to-date with Linux API changes, make more progress on netint routing code --- include/lwpa/inet.h | 22 +- include/os/macos/lwpa/os_inet.h | 28 ++ include/os/macos/lwpa/os_socket.h | 8 - src/os/macos/lwpa/os_inet.c | 147 +++++++++ src/os/macos/lwpa/os_netint.c | 523 +++++++++++++++--------------- src/os/macos/lwpa/os_socket.c | 111 +------ 6 files changed, 462 insertions(+), 377 deletions(-) create mode 100644 include/os/macos/lwpa/os_inet.h create mode 100644 src/os/macos/lwpa/os_inet.c diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index a321b04a7..e818776b8 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -125,24 +125,22 @@ typedef struct LwpaIpAddr /*! Set the IPv6 address in a LwpaIpAddr. Also sets the type field to indicate that this LwpaIpAddr * contains an IPv6 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. - * \param val IPv6 address to set (uint8_t[]). Must be at least of length LWPA_IPV6_BYTES. Gets - * copied into the struct. - */ -#define LWPA_IP_SET_V6_ADDRESS(lwpa_ip_ptr, val) LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(lwpa_ip_ptr, val, 0) + * \param addr_val IPv6 address to set (uint8_t[]). Must be at least of length #LWPA_IPV6_BYTES. + * Gets copied into the struct. */ +#define LWPA_IP_SET_V6_ADDRESS(lwpa_ip_ptr, addr_val) LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(lwpa_ip_ptr, addr_val, 0u) /*! Set an IPv6 address with an explicit scope ID in a LwpaIpAddr. Also sets the type field to * indicate that this LwpaIpAddr contains an IPv6 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. * \param addr_val IPv6 address to set (uint8_t[]). Must be at least of length LWPA_IPV6_BYTES. * Gets copied into the struct. - * \param scope_id IPv6 scope ID to set. - */ -#define LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(lwpa_ip_ptr, addr_val, scope_id) \ - do \ - { \ - (lwpa_ip_ptr)->type = kLwpaIpTypeV6; \ - memcpy((lwpa_ip_ptr)->addr.v6.addr_buf, (addr_val), LWPA_IPV6_BYTES); \ - (lwpa_ip_ptr)->addr.v6.scope_id = (scope_id); \ + * \param scope_id_val IPv6 scope ID to set. */ +#define LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(lwpa_ip_ptr, addr_val, scope_id_val) \ + do \ + { \ + (lwpa_ip_ptr)->type = kLwpaIpTypeV6; \ + memcpy((lwpa_ip_ptr)->addr.v6.addr_buf, (addr_val), LWPA_IPV6_BYTES); \ + (lwpa_ip_ptr)->addr.v6.scope_id = (scope_id_val); \ } while (0) /*! Set the type field in a LwpaIpAddr to indicate that it does not contain a valid address. diff --git a/include/os/macos/lwpa/os_inet.h b/include/os/macos/lwpa/os_inet.h new file mode 100644 index 000000000..4d066e72e --- /dev/null +++ b/include/os/macos/lwpa/os_inet.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_INET_H_ +#define _LWPA_OS_INET_H_ + +#include + +typedef struct sockaddr lwpa_os_sockaddr_t; +typedef struct sockaddr lwpa_os_ipaddr_t; + +#endif /* _LWPA_OS_INET_H_ */ diff --git a/include/os/macos/lwpa/os_socket.h b/include/os/macos/lwpa/os_socket.h index b461aed2c..accda16a3 100644 --- a/include/os/macos/lwpa/os_socket.h +++ b/include/os/macos/lwpa/os_socket.h @@ -42,14 +42,6 @@ typedef struct LwpaPollContext LwpaRbTree sockets; } LwpaPollContext; -#define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), ntohl((pfipptr)->s_addr)) -#define IP_LWPA_TO_OS_V4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = htonl(LWPA_IP_V4_ADDRESS(lwpaipptr))) -#define IP_OS_TO_LWPA_V6(lwpaipptr, pfipptr) LWPA_IP_SET_V6_ADDRESS((lwpaipptr), (pfipptr)->s6_addr) -#define IP_LWPA_TO_OS_V6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, LWPA_IP_V6_ADDRESS(lwpaipptr), IPV6_BYTES) - -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); - #ifdef __cplusplus } #endif diff --git a/src/os/macos/lwpa/os_inet.c b/src/os/macos/lwpa/os_inet.c new file mode 100644 index 000000000..f17ca5e27 --- /dev/null +++ b/src/os/macos/lwpa/os_inet.c @@ -0,0 +1,147 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/inet.h" +#include + +bool ip_os_to_lwpa(const lwpa_os_ipaddr_t* os_ip, LwpaIpAddr* ip) +{ + if (os_ip->sa_family == AF_INET) + { + const struct sockaddr_in* sin = (const struct sockaddr_in*)os_ip; + LWPA_IP_SET_V4_ADDRESS(ip, ntohl(sin->sin_addr.s_addr)); + return true; + } + else if (os_ip->sa_family == AF_INET6) + { + const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)os_ip; + LWPA_IP_SET_V6_ADDRESS(ip, sin6->sin6_addr.s6_addr); + return true; + } + return false; +} + +size_t ip_lwpa_to_os(const LwpaIpAddr* ip, lwpa_os_ipaddr_t* os_ip) +{ + size_t ret = 0; + if (LWPA_IP_IS_V4(ip)) + { + struct sockaddr_in* sin = (struct sockaddr_in*)os_ip; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(ip)); + ret = sizeof(struct sockaddr_in); + } + else if (LWPA_IP_IS_V6(ip)) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_ip; + memset(sin6, 0, sizeof(struct sockaddr_in6)); + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(ip), LWPA_IPV6_BYTES); + ret = sizeof(struct sockaddr_in6); + } + return ret; +} + +bool sockaddr_os_to_lwpa(const lwpa_os_sockaddr_t* os_sa, LwpaSockaddr* sa) +{ + if (ip_os_to_lwpa(os_sa, &sa->ip)) + { + if (os_sa->sa_family == AF_INET) + { + sa->port = ntohs(((const struct sockaddr_in*)os_sa)->sin_port); + return true; + } + else if (os_sa->sa_family == AF_INET6) + { + sa->port = ntohs(((const struct sockaddr_in6*)os_sa)->sin6_port); + return true; + } + } + return false; +} + +size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, lwpa_os_sockaddr_t* os_sa) +{ + size_t ret = ip_lwpa_to_os(&sa->ip, os_sa); + if (ret != 0) + { + if (LWPA_IP_IS_V4(&sa->ip)) + ((struct sockaddr_in*)os_sa)->sin_port = htons(sa->port); + else if (LWPA_IP_IS_V6(&sa->ip)) + ((struct sockaddr_in6*)os_sa)->sin6_port = htons(sa->port); + } + return ret; +} + +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (src->type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); + if (NULL != inet_ntop(AF_INET, &addr, dest, (socklen_t)size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); + if (NULL != inet_ntop(AF_INET6, &addr, dest, (socklen_t)size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + default: + return kLwpaErrInvalid; + } +} + +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + if (1 != inet_pton(AF_INET, src, &addr)) + return kLwpaErrSys; + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); + return kLwpaErrOk; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + if (1 != inet_pton(AF_INET6, src, &addr)) + return kLwpaErrSys; + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); + return kLwpaErrOk; + } + default: + return kLwpaErrInvalid; + } +} diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c index adc7d8345..eff03b69a 100644 --- a/src/os/macos/lwpa/os_netint.c +++ b/src/os/macos/lwpa/os_netint.c @@ -29,6 +29,10 @@ * system information as best I can; sometimes this info was obtained from (with no better source * being apparently available) a StackOverflow answer, or a Wikipedia page, or a print book, or * simply by empirical testing. + * + * Some info comes from the following books, which are referenced below: + * - Unix Network Programming: The Sockets Networking API (Stevens, Fenner, Rudoff) + * - TCP/IP Illustrated, Volume 2: The Implementation (Fall, Stevens) */ #include "lwpa/netint.h" @@ -91,23 +95,8 @@ typedef struct RoutingTable /**************************** Private variables ******************************/ -static struct LwpaNetintState -{ - bool initialized; - - RoutingTable routing_table_v4; - RoutingTable routing_table_v6; - - struct ifaddrs* os_addrs; - size_t num_netints; - LwpaNetintInfo* lwpa_netints; - - bool have_default_netint_index_v4; - size_t default_netint_index_v4; - - bool have_default_netint_index_v6; - size_t default_netint_index_v6; -} state; +RoutingTable routing_table_v4; +RoutingTable routing_table_v6; /*********************** Private function prototypes *************************/ @@ -125,85 +114,154 @@ static lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t bu static void init_routing_table_entry(RoutingTableEntry* entry); static int compare_routing_table_entries(const void* a, const void* b); -// Functions for enumerating the interfaces -static lwpa_error_t enumerate_netints(); -static int compare_netints(const void* a, const void* b); -static void free_netints(); - #if LWPA_NETINT_DEBUG_OUTPUT static void debug_print_routing_table(RoutingTable* table); #endif /*************************** Function definitions ****************************/ -lwpa_error_t lwpa_netint_init() -{ - lwpa_error_t res = kLwpaErrOk; - if (!state.initialized) - { - res = enumerate_netints(); - if (res == kLwpaErrOk) - state.initialized = true; - } - return res; -} - -void lwpa_netint_deinit() -{ - if (state.initialized) - { - free_netints(); - memset(&state, 0, sizeof(state)); - } -} - -/****************************************************************************** - * API Functions - *****************************************************************************/ - -size_t lwpa_netint_get_num_interfaces() +/* Quick helper for enumerate_netints() to determine entries to skip in the linked list. */ +static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) { - return (state.initialized ? state.num_netints : 0); + // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. + return (!ifaddr->ifa_addr || (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6)); } -size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) +lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) { - if (!state.initialized || !netint_arr || netint_arr_size == 0) - return 0; - - size_t addrs_copied = (netint_arr_size < state.num_netints ? netint_arr_size : state.num_netints); - memcpy(netint_arr, state.lwpa_netints, addrs_copied * sizeof(LwpaNetintInfo)); - return addrs_copied; + lwpa_error_t res = build_routing_tables(); + return res; + // if (res != kLwpaErrOk) + // return res; + // + // int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + // if (ioctl_sock == -1) + // return errno_os_to_lwpa(errno); + // + // if (getifaddrs(&state.os_addrs) < 0) + // { + // close(ioctl_sock); + // return errno_os_to_lwpa(errno); + // } + // + // // Pass 1: Total the number of addresses + // state.num_netints = 0; + // for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + // { + // if (should_skip_ifaddr(ifaddr)) + // continue; + // + // ++state.num_netints; + // } + // + // if (state.num_netints == 0) + // { + // freeifaddrs(state.os_addrs); + // close(ioctl_sock); + // return kLwpaErrNoNetints; + // } + // + // // Allocate our interface array + // state.lwpa_netints = (LwpaNetintInfo*)calloc(state.num_netints, sizeof(LwpaNetintInfo)); + // if (!state.lwpa_netints) + // { + // freeifaddrs(state.os_addrs); + // close(ioctl_sock); + // return kLwpaErrNoMem; + // } + // + // // Pass 2: Fill in all the info about each address + // size_t current_lwpa_index = 0; + // for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + // { + // if (should_skip_ifaddr(ifaddr)) + // continue; + // + // LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; + // + // // Interface name + // strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); + // current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; + // + // // Interface address + // LwpaSockaddr temp_sockaddr; + // sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_addr); + // current_info->addr = temp_sockaddr.ip; + // + // // Interface netmask + // sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); + // current_info->mask = temp_sockaddr.ip; + // + // // Struct ifreq to use with ioctl() calls + // struct ifreq if_req; + // strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); + // + // // Hardware address + // int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); + // if (ioctl_res == 0) + // memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); + // else + // memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); + // + // // Interface index + // ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); + // if (ioctl_res == 0) + // current_info->ifindex = if_req.ifr_ifindex; + // else + // current_info->ifindex = -1; + // + // // Is Default + // if (LWPA_IP_IS_V4(¤t_info->addr) && state.routing_table_v4.default_route && + // current_info->ifindex == state.routing_table_v4.default_route->interface_index) + // { + // current_info->is_default = true; + // } + // else if (LWPA_IP_IS_V6(¤t_info->addr) && state.routing_table_v6.default_route && + // current_info->ifindex == state.routing_table_v6.default_route->interface_index) + // { + // current_info->is_default = true; + // } + // + // current_lwpa_index++; + // } + // + // // Sort the interfaces by OS index + // qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); + // + // // Store the locations of the default netints for access by the API function + // for (size_t i = 0; i < state.num_netints; ++i) + // { + // LwpaNetintInfo* netint = &state.lwpa_netints[i]; + // if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) + // { + // state.have_default_netint_index_v4 = true; + // state.default_netint_index_v4 = i; + // } + // else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) + // { + // state.have_default_netint_index_v6 = true; + // state.default_netint_index_v6 = i; + // } + // } + // close(ioctl_sock); + // freeifaddrs(os_addrs); + // return kLwpaErrOk; } -bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) +void os_free_interfaces(CachedNetintInfo* cache) { - if (state.initialized && netint) + if (cache->netints) { - if (type == kLwpaIpTypeV4 && state.have_default_netint_index_v4) - { - *netint = state.lwpa_netints[state.default_netint_index_v4]; - return true; - } - else if (type == kLwpaIpTypeV6 && state.have_default_netint_index_v6) - { - *netint = state.lwpa_netints[state.default_netint_index_v6]; - return true; - } + free(cache->netints); + cache->netints = NULL; } - return false; + + free_routing_tables(); } -lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) { - if (!dest || !netint) - return kLwpaErrInvalid; - if (!state.initialized) - return kLwpaErrNotInit; - if (state.num_netints == 0) - return kLwpaErrNoNetints; - - RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &state.routing_table_v6 : &state.routing_table_v4); + RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &routing_table_v6 : &routing_table_v4); int index_found = -1; for (RoutingTableEntry* entry = table_to_use->entries; entry < table_to_use->entries + table_to_use->size; ++entry) @@ -223,20 +281,15 @@ lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNeti if (index_found < 0 && table_to_use->default_route) index_found = table_to_use->default_route->interface_index; - // Find the network interface with the correct index if (index_found >= 0) { - for (LwpaNetintInfo* netint_entry = state.lwpa_netints; netint_entry < state.lwpa_netints + state.num_netints; - ++netint_entry) - { - if (netint_entry->ifindex == index_found) - { - *netint = *netint_entry; - return kLwpaErrOk; - } - } + *index = index_found; + return kLwpaErrOk; + } + else + { + return kLwpaErrNotFound; } - return kLwpaErrNotFound; } /****************************************************************************** @@ -245,18 +298,18 @@ lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNeti lwpa_error_t build_routing_tables() { - lwpa_error_t res = build_routing_table(AF_INET, &state.routing_table_v4); + lwpa_error_t res = build_routing_table(AF_INET, &routing_table_v4); if (res == kLwpaErrOk) { - res = build_routing_table(AF_INET6, &state.routing_table_v6); + res = build_routing_table(AF_INET6, &routing_table_v6); } if (res != kLwpaErrOk) free_routing_tables(); #if LWPA_NETINT_DEBUG_OUTPUT - debug_print_routing_table(&state.routing_table_v4); - debug_print_routing_table(&state.routing_table_v6); + debug_print_routing_table(&routing_table_v4); + debug_print_routing_table(&routing_table_v6); #endif return res; @@ -311,10 +364,16 @@ lwpa_error_t get_routing_table_dump(int family, uint8_t** buf, size_t* buf_len) return kLwpaErrOk; } -#define SOCKADDR_ALIGN 4 // not sizeof(long) +/* These two macros and the following function were taken from the Unix Network Programming book + * (sect. 18.3) but they required some modification, because they mistakenly assert that the + * sockaddr structures following a route message header are aligned to sizeof(unsigned long), when + * in fact on 64-bit macOS platforms they still seem to be aligned on 4-byte boundaries. + * (sizeof(unsigned long) is 8 on 64-bit platforms) + */ +#define SOCKADDR_ALIGN 4 // not sizeof(unsigned long) #define SA_SIZE(sa) ((!(sa) || (sa)->sa_len == 0) ? SOCKADDR_ALIGN : (1 + (((sa)->sa_len - 1) | (SOCKADDR_ALIGN - 1)))) -void get_addrs_from_route_entry(int addrs, struct sockaddr* sa, struct sockaddr** rti_info) +static void get_addrs_from_route_entry(int addrs, struct sockaddr* sa, struct sockaddr** rti_info) { for (int i = 0; i < RTAX_MAX; ++i) { @@ -330,6 +389,9 @@ void get_addrs_from_route_entry(int addrs, struct sockaddr* sa, struct sockaddr* } } +/* Get the route destination from a normal socket address structure packed as part of a route + * entry. + */ static void dest_from_route_entry(int family, const struct sockaddr* os_dst, LwpaIpAddr* lwpa_dst) { if (family == AF_INET6) @@ -338,6 +400,61 @@ static void dest_from_route_entry(int family, const struct sockaddr* os_dst, Lwp LWPA_IP_SET_V4_ADDRESS(lwpa_dst, ntohl(((struct sockaddr_in*)os_dst)->sin_addr.s_addr)); } +/* Get the netmask from a socket address structure packed as part of a route entry. + * + * The netmask sockaddrs take the form of a struct sockaddr, but they are incomplete (they are + * variable-length and not always the full length of the struct). The length field of the sockaddr + * correctly indicates where the structure is truncated, EXCEPT for the special case of a zero + * length, which indicates that the structure contains no other information (an implied zero + * netmask) but nevertheless occupies four bytes. + * + * If you have made it this far without throwing a full wine bottle at your computer screen, I + * congratulate you. + * + * This method for determining an IPv4 netmask comes from the Unix Network Programming book, sect. + * 18.3. It also references TCP/IP Illustrated Volume 2, fig. 18.21, which presents the way this + * data is held in the kernel. The method for obtaining an IPv6 netmask is undocumented anywhere, + * but inferred from the IPv4 method and empirical debugging. + * + * Here are some examples: + * + * IPv4 netmask in struct sockaddr_in + * +------------------------------------+ + * | sin_len, indicates length | + * +------------------------------------+ + * | sin_family, contains no valid data | + * +------------------------------------+ + * | sin_port, contains no valid data | + * | | + * +------------------------------------+ + * | sin_addr, contains one to four | + * | bytes of netmask, indicated by | + * | (sin_len - (this field's offset)). | + * | The remaining netmask bytes are | + * | inferred to be zero. | + * +------------------------------------+ + * + * IPv6 netmask in struct sockaddr_in6 + * +------------------------------------+ + * | sin6_len, indicates length | + * +------------------------------------+ + * | sin6_family, contains no valid data| + * +------------------------------------+ + * | sin6_port, contains no valid data | + * | | + * +------------------------------------+ + * | sin6_flowinfo, contains no valid | + * | data | + * | | + * | | + * +------------------------------------+ + * | sin6_addr, contains one to sixteen | + * | bytes of netmask, indicated by | + * | (sin6_len - (this field's offset)).| + * | The remaining netmask bytes are | + * | inferred to be zero. | + * +------------------------------------+ + */ static void netmask_from_route_entry(int family, const struct sockaddr* os_netmask, LwpaIpAddr* lwpa_netmask) { if (family == AF_INET) @@ -376,6 +493,10 @@ static void netmask_from_route_entry(int family, const struct sockaddr* os_netma } } +/* Get the gateway from a socket address structure packed as part of a route entry. The gateway + * can either be a network socket address (indicating an actual gateway route) or a datalink + * sockaddr, indicating that this route is "on-link" (on a local subnet only). + */ static void gateway_from_route_entry(const struct sockaddr* os_gw, RoutingGateway* lwpa_gw) { if (os_gw->sa_family == AF_INET6) @@ -395,6 +516,33 @@ static void gateway_from_route_entry(const struct sockaddr* os_gw, RoutingGatewa } } +/* Anyone debugging this code might benefit from this: a mapping of netstat -r flags to + * rmsg->rtm_flags values. + * + * 1 RTF_PROTO1 Protocol specific routing flag #1 + * 2 RTF_PROTO2 Protocol specific routing flag #2 + * 3 RTF_PROTO3 Protocol specific routing flag #3 + * B RTF_BLACKHOLE Just discard packets (during updates) + * b RTF_BROADCAST The route represents a broadcast address + * C RTF_CLONING Generate new routes on use + * c RTF_PRCLONING Protocol-specified generate new routes on use + * D RTF_DYNAMIC Created dynamically (by redirect) + * G RTF_GATEWAY Destination requires forwarding by intermediary + * H RTF_HOST Host entry (net otherwise) + * I RTF_IFSCOPE Route is associated with an interface scope + * i RTF_IFREF Route is holding a reference to the interface + * L RTF_LLINFO Valid protocol to link address translation + * M RTF_MODIFIED Modified dynamically (by redirect) + * m RTF_MULTICAST The route represents a multicast address + * R RTF_REJECT Host or net unreachable + * r RTF_ROUTER Host is a default router + * S RTF_STATIC Manually added + * U RTF_UP Route usable + * W RTF_WASCLONED Route was generated as a result of cloning + * X RTF_XRESOLVE External daemon translates proto to link address + * Y RTF_PROXY Proxying; cloned routes will not be scoped + */ + lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, RoutingTable* table) { table->size = 0; @@ -415,8 +563,12 @@ lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, // get route entry header struct rt_msghdr* rmsg = (struct rt_msghdr*)(&buf[buf_pos]); - // Filter out entries from the local routing table, broadcast and ARP routes. - if (!(rmsg->rtm_flags & (RTF_LLDATA | RTF_LOCAL | RTF_BROADCAST))) + // Filter out entries: + // - from the local routing table (RTF_LOCAL) + // - Representing broadcast routes (RTF_BROADCAST) + // - Representing ARP routes (RTF_LLDATA) + // - Cloned routes (RTF_WASCLONED) + if (!(rmsg->rtm_flags & (RTF_LLDATA | RTF_LOCAL | RTF_BROADCAST | RTF_WASCLONED))) { struct sockaddr* addr_start = (struct sockaddr*)(rmsg + 1); struct sockaddr* rti_info[RTAX_MAX]; @@ -431,10 +583,22 @@ lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, { gateway_from_route_entry(rti_info[RTAX_GATEWAY], &new_entry.gateway); } - if (rti_info[RTAX_NETMASK] != NULL) + + // If this is a host route, it indicates that it has an address with a full netmask (and the + // netmask field is not included) + if (rmsg->rtm_flags & RTF_HOST) + { + if (family == AF_INET6) + new_entry.mask = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 128); + else + new_entry.mask = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 32); + } + else if (rti_info[RTAX_NETMASK] != NULL) { netmask_from_route_entry(family, rti_info[RTAX_NETMASK], &new_entry.mask); } + + new_entry.interface_index = rmsg->rtm_index; // else if (rt_attributes->rta_type == RTA_OIF) //{ // new_entry.interface_index = *((int*)RTA_DATA(rt_attributes)); @@ -519,145 +683,10 @@ int compare_routing_table_entries(const void* a, const void* b) } } -/* Quick helper for enumerate_netints() to determine entries to skip in the linked list. */ -static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) -{ - // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. - return (!ifaddr->ifa_addr || (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6)); -} - -lwpa_error_t enumerate_netints() -{ - lwpa_error_t res = build_routing_tables(); - return res; - // if (res != kLwpaErrOk) - // return res; - // - // int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - // if (ioctl_sock == -1) - // return errno_os_to_lwpa(errno); - // - // if (getifaddrs(&state.os_addrs) < 0) - // { - // close(ioctl_sock); - // return errno_os_to_lwpa(errno); - // } - // - // // Pass 1: Total the number of addresses - // state.num_netints = 0; - // for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) - // { - // if (should_skip_ifaddr(ifaddr)) - // continue; - // - // ++state.num_netints; - // } - // - // if (state.num_netints == 0) - // { - // freeifaddrs(state.os_addrs); - // close(ioctl_sock); - // return kLwpaErrNoNetints; - // } - // - // // Allocate our interface array - // state.lwpa_netints = (LwpaNetintInfo*)calloc(state.num_netints, sizeof(LwpaNetintInfo)); - // if (!state.lwpa_netints) - // { - // freeifaddrs(state.os_addrs); - // close(ioctl_sock); - // return kLwpaErrNoMem; - // } - // - // // Pass 2: Fill in all the info about each address - // size_t current_lwpa_index = 0; - // for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) - // { - // if (should_skip_ifaddr(ifaddr)) - // continue; - // - // LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; - // - // // Interface name - // strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); - // current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; - // - // // Interface address - // LwpaSockaddr temp_sockaddr; - // sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_addr); - // current_info->addr = temp_sockaddr.ip; - // - // // Interface netmask - // sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); - // current_info->mask = temp_sockaddr.ip; - // - // // Struct ifreq to use with ioctl() calls - // struct ifreq if_req; - // strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); - // - // // Hardware address - // int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); - // if (ioctl_res == 0) - // memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); - // else - // memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); - // - // // Interface index - // ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); - // if (ioctl_res == 0) - // current_info->ifindex = if_req.ifr_ifindex; - // else - // current_info->ifindex = -1; - // - // // Is Default - // if (LWPA_IP_IS_V4(¤t_info->addr) && state.routing_table_v4.default_route && - // current_info->ifindex == state.routing_table_v4.default_route->interface_index) - // { - // current_info->is_default = true; - // } - // else if (LWPA_IP_IS_V6(¤t_info->addr) && state.routing_table_v6.default_route && - // current_info->ifindex == state.routing_table_v6.default_route->interface_index) - // { - // current_info->is_default = true; - // } - // - // current_lwpa_index++; - // } - // - // // Sort the interfaces by OS index - // qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); - // - // // Store the locations of the default netints for access by the API function - // for (size_t i = 0; i < state.num_netints; ++i) - // { - // LwpaNetintInfo* netint = &state.lwpa_netints[i]; - // if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) - // { - // state.have_default_netint_index_v4 = true; - // state.default_netint_index_v4 = i; - // } - // else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) - // { - // state.have_default_netint_index_v6 = true; - // state.default_netint_index_v6 = i; - // } - // } - // close(ioctl_sock); - // return kLwpaErrOk; -} - -int compare_netints(const void* a, const void* b) -{ - LwpaNetintInfo* netint1 = (LwpaNetintInfo*)a; - LwpaNetintInfo* netint2 = (LwpaNetintInfo*)b; - - return (netint1->ifindex > netint2->ifindex) - (netint1->ifindex < netint2->ifindex); -} - void free_routing_tables() { - free_routing_table(&state.routing_table_v4); - free_routing_table(&state.routing_table_v6); + free_routing_table(&routing_table_v4); + free_routing_table(&routing_table_v6); } void free_routing_table(RoutingTable* table) @@ -670,31 +699,16 @@ void free_routing_table(RoutingTable* table) table->size = 0; } -void free_netints() -{ - if (state.os_addrs) - { - freeifaddrs(state.os_addrs); - state.os_addrs = NULL; - } - if (state.lwpa_netints) - { - free(state.lwpa_netints); - state.lwpa_netints = NULL; - } - - free_routing_tables(); -} - #if LWPA_NETINT_DEBUG_OUTPUT void debug_print_routing_table(RoutingTable* table) { - printf("%-40s %-40s %-40s %-10s %s\n", "Address", "Mask", "Gateway", "Metric", "Index"); + printf("%-40s %-40s %-40s %-10s %s %s\n", "Address", "Mask", "Gateway", "Metric", "Index", "Name"); for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) { char addr_str[LWPA_INET6_ADDRSTRLEN]; char mask_str[LWPA_INET6_ADDRSTRLEN]; char gw_str[LWPA_INET6_ADDRSTRLEN]; + char ifname_str[IF_NAMESIZE]; if (!LWPA_IP_IS_INVALID(&entry->addr)) lwpa_inet_ntop(&entry->addr, addr_str, LWPA_INET6_ADDRSTRLEN); @@ -713,7 +727,10 @@ void debug_print_routing_table(RoutingTable* table) else strcpy(gw_str, ""); - printf("%-40s %-40s %-40s %-10d %d\n", addr_str, mask_str, gw_str, entry->metric, entry->interface_index); + if_indextoname(entry->interface_index, ifname_str); + + printf("%-40s %-40s %-40s %-10d %-5d %s\n", addr_str, mask_str, gw_str, entry->metric, entry->interface_index, + ifname_str); } } #endif diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index cfb745e7b..306ca1d66 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -123,47 +123,6 @@ static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_ /*************************** Function definitions ****************************/ -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) -{ - if (pfsa->sa_family == AF_INET) - { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sa->port = ntohs(sin->sin_port); - LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); - return true; - } - else if (pfsa->sa_family == AF_INET6) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sa->port = ntohs(sin6->sin6_port); - LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); - return true; - } - return false; -} - -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) -{ - size_t ret = 0; - if (LWPA_IP_IS_V4(&sa->ip)) - { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sin->sin_family = AF_INET; - sin->sin_port = htons(sa->port); - sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); - ret = sizeof(struct sockaddr_in); - } - else if (LWPA_IP_IS_V6(&sa->ip)) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(sa->port); - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); - ret = sizeof(struct sockaddr_in6); - } - return ret; -} - lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { if (!conn_sock) @@ -175,7 +134,7 @@ lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* if (res != -1) { - if (address && !sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) + if (address && !sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&ss, address)) { close(res); return kLwpaErrSys; @@ -192,7 +151,7 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) return kLwpaErrInvalid; struct sockaddr_storage ss; - socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os(address, (lwpa_os_sockaddr_t*)&ss); if (sa_size == 0) return kLwpaErrInvalid; @@ -212,7 +171,7 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) return kLwpaErrInvalid; struct sockaddr_storage ss; - socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os(address, (lwpa_os_sockaddr_t*)&ss); if (sa_size == 0) return kLwpaErrInvalid; @@ -238,7 +197,7 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) int res = getsockname(id, (struct sockaddr*)&ss, &size); if (res == 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) + if (!sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&ss, address)) return kLwpaErrSys; return kLwpaErrOk; } @@ -286,7 +245,7 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa { if (address && fromlen > 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) + if (!sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&fromaddr, address)) return kLwpaErrSys; } return res; @@ -313,7 +272,7 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, return (int)kLwpaErrInvalid; struct sockaddr_storage ss; - socklen_t ss_size = (socklen_t)sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr); + socklen_t ss_size = (socklen_t)sockaddr_lwpa_to_os(dest_addr, (lwpa_os_sockaddr_t*)&ss); if (ss_size == 0) return (int)kLwpaErrSys; @@ -862,7 +821,7 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) { struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; - if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + if (!sockaddr_os_to_lwpa(pf_ai->ai_addr, &ai->ai_addr)) return false; /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS @@ -898,59 +857,3 @@ void lwpa_freeaddrinfo(LwpaAddrinfo* ai) if (ai) freeaddrinfo((struct addrinfo*)ai->pd[0]); } - -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (src->type) - { - case kLwpaIpTypeV4: - { - struct in_addr addr; - addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); - if (NULL != inet_ntop(AF_INET, &addr, dest, (socklen_t)size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - case kLwpaIpTypeV6: - { - struct in6_addr addr; - memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); - if (NULL != inet_ntop(AF_INET6, &addr, dest, (socklen_t)size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - default: - return kLwpaErrInvalid; - } -} - -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (type) - { - case kLwpaIpTypeV4: - { - struct in_addr addr; - if (1 != inet_pton(AF_INET, src, &addr)) - return kLwpaErrSys; - LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); - return kLwpaErrOk; - } - case kLwpaIpTypeV6: - { - struct in6_addr addr; - if (1 != inet_pton(AF_INET6, src, &addr)) - return kLwpaErrSys; - LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); - return kLwpaErrOk; - } - default: - return kLwpaErrInvalid; - } -} From 5ed9b3d43ff1f639cd3d7bb970d4a0934e9548ca Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 11:36:30 -0500 Subject: [PATCH 046/264] Finish netint implementation, get tests compiling --- include/lwpa/thread.h | 17 +- include/os/linux/lwpa/os_thread.h | 2 - include/os/macos/lwpa/os_thread.h | 2 - include/os/windows/lwpa/os_thread.h | 5 +- src/os/macos/lwpa/os_netint.c | 327 +++++++++++++--------------- src/os/macos/lwpa/os_thread.c | 2 +- tests/CMakeLists.txt | 2 +- 7 files changed, 170 insertions(+), 187 deletions(-) diff --git a/include/lwpa/thread.h b/include/lwpa/thread.h index 8f201d217..fc3aa14ad 100644 --- a/include/lwpa/thread.h +++ b/include/lwpa/thread.h @@ -20,6 +20,12 @@ #ifndef _LWPA_THREAD_H_ #define _LWPA_THREAD_H_ +#include "lwpa/os_thread.h" + +#ifdef __cplusplus +extern "C" { +#endif + typedef struct LwpaThreadParams { unsigned int thread_priority; @@ -37,6 +43,15 @@ typedef struct LwpaThreadParams (threadparamsptr)->platform_data = NULL; \ } while (0) -#include "lwpa/os_thread.h" +bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); +bool lwpa_thread_join(lwpa_thread_t* id); + +#ifndef lwpa_thread_sleep +void lwpa_thread_sleep(int sleep_ms); +#endif + +#ifdef __cplusplus +} +#endif #endif /* _LWPA_THREAD_H_ */ diff --git a/include/os/linux/lwpa/os_thread.h b/include/os/linux/lwpa/os_thread.h index 6a5e9e0c0..fa41f39ff 100644 --- a/include/os/linux/lwpa/os_thread.h +++ b/include/os/linux/lwpa/os_thread.h @@ -41,8 +41,6 @@ typedef struct pthread_t handle; } lwpa_thread_t; -bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); -bool lwpa_thread_join(lwpa_thread_t* id); #define lwpa_thread_sleep(sleep_ms) usleep(((useconds_t)sleep_ms) * 1000) #ifdef __cplusplus diff --git a/include/os/macos/lwpa/os_thread.h b/include/os/macos/lwpa/os_thread.h index 713e06264..fa41f39ff 100644 --- a/include/os/macos/lwpa/os_thread.h +++ b/include/os/macos/lwpa/os_thread.h @@ -41,8 +41,6 @@ typedef struct pthread_t handle; } lwpa_thread_t; -bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); -bool lwpa_thread_stop(lwpa_thread_t* id); #define lwpa_thread_sleep(sleep_ms) usleep(((useconds_t)sleep_ms) * 1000) #ifdef __cplusplus diff --git a/include/os/windows/lwpa/os_thread.h b/include/os/windows/lwpa/os_thread.h index 7e1609890..930a5d1b6 100644 --- a/include/os/windows/lwpa/os_thread.h +++ b/include/os/windows/lwpa/os_thread.h @@ -37,7 +37,8 @@ extern "C" { #endif -/* Windows has no additional platform data and thus platform_data in the struct above is ignored. */ +/* Windows has no additional platform data and thus platform_data in the LwpaThreadParams struct + * is ignored. */ #define LWPA_THREAD_DEFAULT_PRIORITY THREAD_PRIORITY_NORMAL #define LWPA_THREAD_DEFAULT_STACK 0 @@ -53,8 +54,6 @@ typedef struct char name[LWPA_THREAD_NAME_MAX_LENGTH]; } lwpa_thread_t; -bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); -bool lwpa_thread_join(lwpa_thread_t* id); #define lwpa_thread_sleep(sleep_ms) Sleep(sleep_ms) #ifdef __cplusplus diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c index eff03b69a..3c71784cf 100644 --- a/src/os/macos/lwpa/os_netint.c +++ b/src/os/macos/lwpa/os_netint.c @@ -60,30 +60,16 @@ /***************************** Private types *********************************/ -typedef enum -{ - kGwAddress, - kGwIndex, - kGwInvalid -} routing_gateway_t; - -typedef struct RoutingGateway -{ - routing_gateway_t type; - union - { - LwpaIpAddr addr; - int ifindex; - } u; -} RoutingGateway; - typedef struct RoutingTableEntry { LwpaIpAddr addr; LwpaIpAddr mask; - RoutingGateway gateway; + LwpaIpAddr gateway; int interface_index; - int metric; + /* Darwin seems to set this flag on default entries that are not chosen as *the* system-wide + * default. I have not seen this behavior documented anywhere, but it's the only way I can tell + * to determine which route is truly the default route. */ + bool interface_scope; } RoutingTableEntry; typedef struct RoutingTable @@ -121,131 +107,120 @@ static void debug_print_routing_table(RoutingTable* table); /*************************** Function definitions ****************************/ /* Quick helper for enumerate_netints() to determine entries to skip in the linked list. */ -static bool should_skip_ifaddr(const struct ifaddrs* ifaddr) +static size_t count_ifaddrs(const struct ifaddrs* ifaddrs) { - // Skip an entry if it doesn't have an address, or if the address is not IPv4 or IPv6. - return (!ifaddr->ifa_addr || (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6)); + size_t total = 0; + for (const struct ifaddrs* ifaddr = ifaddrs; ifaddr; ifaddr = ifaddr->ifa_next) + { + // Skip an entry if it is down, doesn't have an address, or if the address is not IPv4 or IPv6. + if ((ifaddr->ifa_flags & IFF_UP) && ifaddr->ifa_addr && + (ifaddr->ifa_addr->sa_family == AF_INET || ifaddr->ifa_addr->sa_family == AF_INET6)) + { + ++total; + } + } + return total; } lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) { lwpa_error_t res = build_routing_tables(); - return res; - // if (res != kLwpaErrOk) - // return res; - // - // int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - // if (ioctl_sock == -1) - // return errno_os_to_lwpa(errno); - // - // if (getifaddrs(&state.os_addrs) < 0) - // { - // close(ioctl_sock); - // return errno_os_to_lwpa(errno); - // } - // - // // Pass 1: Total the number of addresses - // state.num_netints = 0; - // for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) - // { - // if (should_skip_ifaddr(ifaddr)) - // continue; - // - // ++state.num_netints; - // } - // - // if (state.num_netints == 0) - // { - // freeifaddrs(state.os_addrs); - // close(ioctl_sock); - // return kLwpaErrNoNetints; - // } - // - // // Allocate our interface array - // state.lwpa_netints = (LwpaNetintInfo*)calloc(state.num_netints, sizeof(LwpaNetintInfo)); - // if (!state.lwpa_netints) - // { - // freeifaddrs(state.os_addrs); - // close(ioctl_sock); - // return kLwpaErrNoMem; - // } - // - // // Pass 2: Fill in all the info about each address - // size_t current_lwpa_index = 0; - // for (struct ifaddrs* ifaddr = state.os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) - // { - // if (should_skip_ifaddr(ifaddr)) - // continue; - // - // LwpaNetintInfo* current_info = &state.lwpa_netints[current_lwpa_index]; - // - // // Interface name - // strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); - // current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; - // - // // Interface address - // LwpaSockaddr temp_sockaddr; - // sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_addr); - // current_info->addr = temp_sockaddr.ip; - // - // // Interface netmask - // sockaddr_os_to_lwpa(&temp_sockaddr, ifaddr->ifa_netmask); - // current_info->mask = temp_sockaddr.ip; - // - // // Struct ifreq to use with ioctl() calls - // struct ifreq if_req; - // strncpy(if_req.ifr_name, ifaddr->ifa_name, IFNAMSIZ); - // - // // Hardware address - // int ioctl_res = ioctl(ioctl_sock, SIOCGIFHWADDR, &if_req); - // if (ioctl_res == 0) - // memcpy(current_info->mac, if_req.ifr_hwaddr.sa_data, LWPA_NETINTINFO_MAC_LEN); - // else - // memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); - // - // // Interface index - // ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); - // if (ioctl_res == 0) - // current_info->ifindex = if_req.ifr_ifindex; - // else - // current_info->ifindex = -1; - // - // // Is Default - // if (LWPA_IP_IS_V4(¤t_info->addr) && state.routing_table_v4.default_route && - // current_info->ifindex == state.routing_table_v4.default_route->interface_index) - // { - // current_info->is_default = true; - // } - // else if (LWPA_IP_IS_V6(¤t_info->addr) && state.routing_table_v6.default_route && - // current_info->ifindex == state.routing_table_v6.default_route->interface_index) - // { - // current_info->is_default = true; - // } - // - // current_lwpa_index++; - // } - // - // // Sort the interfaces by OS index - // qsort(state.lwpa_netints, state.num_netints, sizeof(LwpaNetintInfo), compare_netints); - // - // // Store the locations of the default netints for access by the API function - // for (size_t i = 0; i < state.num_netints; ++i) - // { - // LwpaNetintInfo* netint = &state.lwpa_netints[i]; - // if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) - // { - // state.have_default_netint_index_v4 = true; - // state.default_netint_index_v4 = i; - // } - // else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) - // { - // state.have_default_netint_index_v6 = true; - // state.default_netint_index_v6 = i; - // } - // } - // close(ioctl_sock); - // freeifaddrs(os_addrs); - // return kLwpaErrOk; + if (res != kLwpaErrOk) + return res; + + struct ifaddrs* os_addrs; + if (getifaddrs(&os_addrs) < 0) + { + return errno_os_to_lwpa(errno); + } + + // Pass 1: Total the number of addresses + cache->num_netints = count_ifaddrs(os_addrs); + + if (cache->num_netints == 0) + { + freeifaddrs(os_addrs); + return kLwpaErrNoNetints; + } + + // Allocate our interface array + cache->netints = (LwpaNetintInfo*)calloc(cache->num_netints, sizeof(LwpaNetintInfo)); + if (!cache->netints) + { + freeifaddrs(os_addrs); + return kLwpaErrNoMem; + } + + // Pass 2: Fill in all the info about each address + size_t current_lwpa_index = 0; + char* link_name = NULL; + struct sockaddr_dl* link_addr = NULL; + + for (struct ifaddrs* ifaddr = os_addrs; ifaddr; ifaddr = ifaddr->ifa_next) + { + // An AF_LINK entry appears before one or more internet address entries for each interface. + // Save the current AF_LINK entry for later use. If the entry is an IPv4 or IPv6 address, we + // can proceed. + if (ifaddr->ifa_addr) + { + if (ifaddr->ifa_addr->sa_family == AF_LINK) + { + link_name = ifaddr->ifa_name; + link_addr = (struct sockaddr_dl*)(ifaddr->ifa_addr); + continue; + } + else if (ifaddr->ifa_addr->sa_family != AF_INET && ifaddr->ifa_addr->sa_family != AF_INET6) + { + continue; + } + } + else + { + continue; + } + + LwpaNetintInfo* current_info = &cache->netints[current_lwpa_index]; + + // Interface name + strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); + current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; + + // Interface address + ip_os_to_lwpa(ifaddr->ifa_addr, ¤t_info->addr); + + // Interface netmask + ip_os_to_lwpa(ifaddr->ifa_netmask, ¤t_info->mask); + + // Make sure we match the corresponding link information + if (link_name && link_addr && 0 == strcmp(ifaddr->ifa_name, link_name)) + { + current_info->ifindex = link_addr->sdl_index; + memcpy(current_info->mac, link_addr->sdl_data + link_addr->sdl_nlen, LWPA_NETINTINFO_MAC_LEN); + } + else + { + // Backup - get the interface index using if_nametoindex + current_info->ifindex = if_nametoindex(ifaddr->ifa_name); + memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); + } + + // Is Default + if (LWPA_IP_IS_V4(¤t_info->addr) && routing_table_v4.default_route && + current_info->ifindex == routing_table_v4.default_route->interface_index) + { + current_info->is_default = true; + } + else if (LWPA_IP_IS_V6(¤t_info->addr) && routing_table_v6.default_route && + current_info->ifindex == routing_table_v6.default_route->interface_index) + { + current_info->is_default = true; + } + + current_lwpa_index++; + } + + freeifaddrs(os_addrs); + return kLwpaErrOk; } void os_free_interfaces(CachedNetintInfo* cache) @@ -497,22 +472,15 @@ static void netmask_from_route_entry(int family, const struct sockaddr* os_netma * can either be a network socket address (indicating an actual gateway route) or a datalink * sockaddr, indicating that this route is "on-link" (on a local subnet only). */ -static void gateway_from_route_entry(const struct sockaddr* os_gw, RoutingGateway* lwpa_gw) +static void gateway_from_route_entry(const struct sockaddr* os_gw, LwpaIpAddr* lwpa_gw) { if (os_gw->sa_family == AF_INET6) { - lwpa_gw->type = kGwAddress; - LWPA_IP_SET_V6_ADDRESS(&lwpa_gw->u.addr, ((struct sockaddr_in6*)os_gw)->sin6_addr.s6_addr); + LWPA_IP_SET_V6_ADDRESS(lwpa_gw, ((struct sockaddr_in6*)os_gw)->sin6_addr.s6_addr); } else if (os_gw->sa_family == AF_INET) { - lwpa_gw->type = kGwAddress; - LWPA_IP_SET_V4_ADDRESS(&lwpa_gw->u.addr, ntohl(((struct sockaddr_in*)os_gw)->sin_addr.s_addr)); - } - else if (os_gw->sa_family == AF_LINK) - { - lwpa_gw->type = kGwIndex; - lwpa_gw->u.ifindex = ((struct sockaddr_dl*)os_gw)->sdl_index; + LWPA_IP_SET_V4_ADDRESS(lwpa_gw, ntohl(((struct sockaddr_in*)os_gw)->sin_addr.s_addr)); } } @@ -543,6 +511,10 @@ static void gateway_from_route_entry(const struct sockaddr* os_gw, RoutingGatewa * Y RTF_PROXY Proxying; cloned routes will not be scoped */ +/* Build our internal representation of the system routing tables from the data buffer that + * sysctl() gives us. Relies on helper functions above. Much trial and error was involved in making + * this function work correctly. + */ lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, RoutingTable* table) { table->size = 0; @@ -574,7 +546,6 @@ lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, struct sockaddr* rti_info[RTAX_MAX]; get_addrs_from_route_entry(rmsg->rtm_addrs, addr_start, rti_info); - // We only care about the gateway and DST attribute if (rti_info[RTAX_DST] != NULL) { dest_from_route_entry(family, rti_info[RTAX_DST], &new_entry.addr); @@ -598,26 +569,18 @@ lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, netmask_from_route_entry(family, rti_info[RTAX_NETMASK], &new_entry.mask); } + if (rmsg->rtm_flags & RTF_IFSCOPE) + { + new_entry.interface_scope = true; + } + new_entry.interface_index = rmsg->rtm_index; - // else if (rt_attributes->rta_type == RTA_OIF) - //{ - // new_entry.interface_index = *((int*)RTA_DATA(rt_attributes)); - //} - // else if (rt_attributes->rta_type == RTA_PRIORITY) - //{ - // new_entry.metric = *((int*)RTA_DATA(rt_attributes)); - //} } else { new_entry_valid = false; } - // if (!LWPA_IP_IS_INVALID(&new_entry.addr)) - // { - // new_entry.mask = lwpa_ip_mask_from_length(new_entry.addr.type, rt_message->rtm_dst_len); - // } - // Insert the new entry into the list if (new_entry_valid) { @@ -636,11 +599,12 @@ lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, { qsort(table->entries, table->size, sizeof(RoutingTableEntry), compare_routing_table_entries); - // Mark the default route with the lowest metric (the first one we encounter after sorting the - // table) + // Mark the system-wide default route: the first default route we encounter after sorting the table. for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) { - if (LWPA_IP_IS_INVALID(&entry->addr) && LWPA_IP_IS_INVALID(&entry->mask) && !LWPA_IP_IS_INVALID(&entry->gateway)) + if ((LWPA_IP_IS_INVALID(&entry->addr) || lwpa_ip_is_wildcard(&entry->addr)) && + (LWPA_IP_IS_INVALID(&entry->mask) || lwpa_ip_is_wildcard(&entry->mask)) && + !LWPA_IP_IS_INVALID(&entry->gateway)) { table->default_route = entry; break; @@ -658,9 +622,9 @@ void init_routing_table_entry(RoutingTableEntry* entry) { LWPA_IP_SET_INVALID(&entry->addr); LWPA_IP_SET_INVALID(&entry->mask); - entry->gateway.type = kGwInvalid; + LWPA_IP_SET_INVALID(&entry->gateway); entry->interface_index = -1; - entry->metric = INT_MAX; + entry->interface_scope = false; } int compare_routing_table_entries(const void* a, const void* b) @@ -671,11 +635,11 @@ int compare_routing_table_entries(const void* a, const void* b) unsigned int mask_length_1 = lwpa_ip_mask_length(&e1->mask); unsigned int mask_length_2 = lwpa_ip_mask_length(&e2->mask); - // Sort by mask length in descending order - within the same mask length, sort by metric in - // ascending order. + // Sort by mask length in descending order - within the same mask length, sort by whether one + // entry has the "interface scope" flag set (unset gets priority, e.g. listed first). if (mask_length_1 == mask_length_2) { - return (e1->metric > e2->metric) - (e1->metric < e2->metric); + return (e1->interface_scope && !e2->interface_scope) - (!e1->interface_scope && e2->interface_scope); } else { @@ -702,7 +666,8 @@ void free_routing_table(RoutingTable* table) #if LWPA_NETINT_DEBUG_OUTPUT void debug_print_routing_table(RoutingTable* table) { - printf("%-40s %-40s %-40s %-10s %s %s\n", "Address", "Mask", "Gateway", "Metric", "Index", "Name"); + printf("%-40s %-40s %-40s %s %s\n", "Address", "Mask", "Gateway", "Index", "Name"); + for (RoutingTableEntry* entry = table->entries; entry < table->entries + table->size; ++entry) { char addr_str[LWPA_INET6_ADDRSTRLEN]; @@ -720,17 +685,25 @@ void debug_print_routing_table(RoutingTable* table) else strcpy(mask_str, "0.0.0.0"); - if (entry->gateway.type == kGwAddress && !LWPA_IP_IS_INVALID(&entry->gateway.u.addr)) - lwpa_inet_ntop(&entry->gateway.u.addr, gw_str, LWPA_INET6_ADDRSTRLEN); - else if (entry->gateway.type == kGwIndex) - snprintf(gw_str, LWPA_INET6_ADDRSTRLEN, "link %d", entry->gateway.u.ifindex); + if (!LWPA_IP_IS_INVALID(&entry->gateway)) + lwpa_inet_ntop(&entry->gateway, gw_str, LWPA_INET6_ADDRSTRLEN); else strcpy(gw_str, ""); if_indextoname(entry->interface_index, ifname_str); - printf("%-40s %-40s %-40s %-10d %-5d %s\n", addr_str, mask_str, gw_str, entry->metric, entry->interface_index, - ifname_str); + printf("%-40s %-40s %-40s %-5d %s\n", addr_str, mask_str, gw_str, entry->interface_index, ifname_str); + } + + if (table->default_route) + { + char gw_str[LWPA_INET6_ADDRSTRLEN]; + lwpa_inet_ntop(&table->default_route->gateway, gw_str, LWPA_INET6_ADDRSTRLEN); + printf("Default route: %s (%d)\n", gw_str, table->default_route->interface_index); + } + else + { + printf("Default route not found.\n"); } } #endif diff --git a/src/os/macos/lwpa/os_thread.c b/src/os/macos/lwpa/os_thread.c index d8aeb85e6..73c6e53ff 100644 --- a/src/os/macos/lwpa/os_thread.c +++ b/src/os/macos/lwpa/os_thread.c @@ -50,7 +50,7 @@ bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void return res; } -bool lwpa_thread_stop(lwpa_thread_t* id) +bool lwpa_thread_join(lwpa_thread_t* id) { if (id) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 707a56ea4..bfab975ea 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,6 @@ ################################### testing ################################### -if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL linux) +if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL macos OR LWPA_TARGET_OS STREQUAL linux) message(STATUS "Adding GoogleTest dependency...") include(AddGoogleTest) From 0e00b31f22c20ec3096f8e4d67b9b987d416ae79 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 13:52:11 -0500 Subject: [PATCH 047/264] Fix timer and netint modules so tests now pass. Only socket tests currently failing --- include/lwpa/common.h | 29 +++++-- src/CMakeLists.txt | 1 - src/lwpa/common.c | 78 +++++++++++-------- src/lwpa/netint.c | 2 +- src/lwpa/private/{common.h => socket.h} | 12 +-- .../lwpa/os_common.c => lwpa/private/timer.h} | 22 ++---- src/os/macos/lwpa/os_socket.c | 12 +++ src/os/macos/lwpa/os_timer.c | 27 +++++-- tests/unit/test_netint.cpp | 26 +++---- 9 files changed, 128 insertions(+), 81 deletions(-) rename src/lwpa/private/{common.h => socket.h} (80%) rename src/{os/macos/lwpa/os_common.c => lwpa/private/timer.h} (73%) diff --git a/include/lwpa/common.h b/include/lwpa/common.h index f5900191c..08c612249 100644 --- a/include/lwpa/common.h +++ b/include/lwpa/common.h @@ -41,15 +41,32 @@ /*! For lwpa_ functions that take a millisecond timeout, this means to wait indefinitely. */ #define LWPA_WAIT_FOREVER -1 -#define LWPA_FEATURE_SOCKETS 0x00000001u -#define LWPA_FEATURE_NETINTS 0x00000002u -#define LWPA_FEATURE_TIMERS 0x00000004u -#define LWPA_FEATURE_LOGGING 0x00000008u -#define LWPA_FEATURES_ALL 0xffffffffu +typedef uint32_t lwpa_features_t; + +#define LWPA_FEATURE_SOCKETS_OFFSET 0 +#define LWPA_FEATURE_NETINTS_OFFSET 1 +#define LWPA_FEATURE_TIMERS_OFFSET 2 +#define LWPA_FEATURE_LOGGING_OFFSET 3 +#define LWPA_NUM_FEATURES 4 + +/*! \name lwpa feature masks + * Pass one or more of these to lwpa_init() to initialize the relevant lwpa feature. + * lwpa modules not represented here require no initialization and are enabled by default. + * @{ + */ +#define LWPA_FEATURE_SOCKETS ((lwpa_features_t)(1u << LWPA_FEATURE_SOCKETS_OFFSET)) /*!< Use the lwpa_socket module. */ +#define LWPA_FEATURE_NETINTS ((lwpa_features_t)(1u << LWPA_FEATURE_NETINTS_OFFSET)) /*!< Use the lwpa_netint module. */ +#define LWPA_FEATURE_TIMERS ((lwpa_features_t)(1u << LWPA_FEATURE_TIMERS_OFFSET)) /*!< Use the lwpa_timer module. */ +#define LWPA_FEATURE_LOGGING ((lwpa_features_t)(1u << LWPA_FEATURE_LOGGING_OFFSET)) /*!< Use the lwpa_log module. */ +#define LWPA_FEATURES_ALL 0xffffffffu /*! Use every available module. */ +/*! \brief Use every available module except the ones passed in mask. + * \param mask Mask of LWPA_FEATURE_* macros to not include in the feature mask. + * \return Resulting lwpa feature mask to pass to lwpa_init(). + */ #define LWPA_FEATURES_ALL_BUT(mask) (((uint32_t)LWPA_FEATURES_ALL) & ((uint32_t)(~((uint32_t)(mask))))) +/*! @} */ -typedef uint32_t lwpa_features_t; #ifdef __cplusplus extern "C" { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dde806716..479c49377 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,7 +83,6 @@ add_library(lwpa ${LWPA_ROOT}/src/lwpa/rbtree.c ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/uuid.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_common.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_inet.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c diff --git a/src/lwpa/common.c b/src/lwpa/common.c index 1e8f55b09..74c321f25 100644 --- a/src/lwpa/common.c +++ b/src/lwpa/common.c @@ -20,55 +20,71 @@ #include "lwpa/common.h" #include "lwpa/bool.h" -#include "lwpa/private/common.h" + #include "lwpa/private/log.h" #include "lwpa/private/netint.h" +#include "lwpa/private/socket.h" +#include "lwpa/private/timer.h" -lwpa_error_t lwpa_init(lwpa_features_t features) +typedef struct LwpaModuleInit { - bool os_initted = false; - bool logging_initted = false; + bool initted; + lwpa_error_t (*init_fn)(); + void (*deinit_fn)(); +} LwpaModuleInit; - // Step 1: OS-specific init - lwpa_error_t res = lwpa_os_init(features); - os_initted = (res == kLwpaErrOk); +#define LWPA_MODULE_INIT(module_name) { false, module_name##_init, module_name##_deinit } - // Step 2: OS-neutral init - if (res == kLwpaErrOk) +#define LWPA_MODULE_INIT_ARRAY \ + { \ + LWPA_MODULE_INIT(lwpa_socket), \ + LWPA_MODULE_INIT(lwpa_netint), \ + LWPA_MODULE_INIT(lwpa_timer), \ + LWPA_MODULE_INIT(lwpa_log) \ + } + +lwpa_error_t lwpa_init(lwpa_features_t features) +{ + LwpaModuleInit init_array[LWPA_NUM_FEATURES] = LWPA_MODULE_INIT_ARRAY; + + lwpa_error_t init_res = kLwpaErrOk; + lwpa_features_t feature_mask = 1u; + for (LwpaModuleInit *init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) { - if (features & LWPA_FEATURE_LOGGING) + if (features & feature_mask) { - logging_initted = ((res = lwpa_log_init()) == kLwpaErrOk); + init_res = init_struct->init_fn(); + if (init_res == kLwpaErrOk) + init_struct->initted = true; + else + break; } + feature_mask <<= 1; } - if (features & LWPA_FEATURE_NETINTS) + if (init_res != kLwpaErrOk) { - res = lwpa_netint_init(); + for (LwpaModuleInit *init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) + { + if (init_struct->initted) + init_struct->deinit_fn(); + } } - if (res != kLwpaErrOk) - { - // Clean up on failure - if (logging_initted) - lwpa_log_deinit(); - if (os_initted) - lwpa_os_deinit(features); - } - return res; + return init_res; } void lwpa_deinit(lwpa_features_t features) { - // Step 1: OS-neutral deinit - if (features & LWPA_FEATURE_NETINTS) - { - lwpa_netint_deinit(); - } - if (features & LWPA_FEATURE_LOGGING) + LwpaModuleInit init_array[LWPA_NUM_FEATURES] = LWPA_MODULE_INIT_ARRAY; + + lwpa_features_t feature_mask = 1u; + for (LwpaModuleInit *init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) { - lwpa_log_deinit(); + if (features & feature_mask) + { + init_struct->deinit_fn(); + } + feature_mask <<= 1; } - - lwpa_os_deinit(features); } diff --git a/src/lwpa/netint.c b/src/lwpa/netint.c index bd8cd58b1..0aabcb4e4 100644 --- a/src/lwpa/netint.c +++ b/src/lwpa/netint.c @@ -159,7 +159,7 @@ lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNeti for (LwpaNetintInfo* netint_entry = netint_cache.netints; netint_entry < netint_cache.netints + netint_cache.num_netints; ++netint_entry) { - if (netint_entry->ifindex == index) + if (netint_entry->addr.type == dest->type && netint_entry->ifindex == index) { *netint = *netint_entry; return kLwpaErrOk; diff --git a/src/lwpa/private/common.h b/src/lwpa/private/socket.h similarity index 80% rename from src/lwpa/private/common.h rename to src/lwpa/private/socket.h index 1c0fe8f07..1536deb2c 100644 --- a/src/lwpa/private/common.h +++ b/src/lwpa/private/socket.h @@ -17,12 +17,12 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_PRIVATE_COMMON_H_ -#define _LWPA_PRIVATE_COMMON_H_ +#ifndef _LWPA_PRIVATE_SOCKET_H_ +#define _LWPA_PRIVATE_SOCKET_H_ -#include "lwpa/common.h" +#include "lwpa/error.h" -lwpa_error_t lwpa_os_init(lwpa_features_t features); -void lwpa_os_deinit(lwpa_features_t features); +lwpa_error_t lwpa_socket_init(); +void lwpa_socket_deinit(); -#endif /* _LWPA_PRIVATE_COMMON_H_ */ +#endif /* _LWPA_PRIVATE_SOCKET_H_ */ \ No newline at end of file diff --git a/src/os/macos/lwpa/os_common.c b/src/lwpa/private/timer.h similarity index 73% rename from src/os/macos/lwpa/os_common.c rename to src/lwpa/private/timer.h index 7e1de52d0..d1481f359 100644 --- a/src/os/macos/lwpa/os_common.c +++ b/src/lwpa/private/timer.h @@ -17,22 +17,12 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa/common.h" -#include "lwpa/private/common.h" +#ifndef _LWPA_PRIVATE_TIMER_H_ +#define _LWPA_PRIVATE_TIMER_H_ -#include +#include "lwpa/error.h" -lwpa_error_t lwpa_os_init(lwpa_features_t features) -{ - if (features & LWPA_FEATURE_TIMERS) - { - if (sysconf(_SC_MONOTONIC_CLOCK) < 0) - return kLwpaErrSys; - } - return kLwpaErrOk; -} +lwpa_error_t lwpa_timer_init(); +void lwpa_timer_deinit(); -void lwpa_os_deinit(lwpa_features_t features) -{ - (void)features; -} +#endif /* _LWPA_PRIVATE_TIMER_H_ */ \ No newline at end of file diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index 306ca1d66..e18fd5815 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -17,6 +17,7 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/socket.h" +#include "lwpa/private/socket.h" #include #include @@ -123,6 +124,17 @@ static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_ /*************************** Function definitions ****************************/ +lwpa_error_t lwpa_socket_init() +{ + // No initialization necessary on this platform + return kLwpaErrOk; +} + +void lwpa_socket_deinit() +{ + // No deinitialization necessary on this platform +} + lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { if (!conn_sock) diff --git a/src/os/macos/lwpa/os_timer.c b/src/os/macos/lwpa/os_timer.c index 813c97007..857d22679 100644 --- a/src/os/macos/lwpa/os_timer.c +++ b/src/os/macos/lwpa/os_timer.c @@ -18,15 +18,28 @@ ******************************************************************************/ #include "lwpa/timer.h" +#include "lwpa/private/timer.h" -#include +#include + +double ticks_to_ms = 0; + +lwpa_error_t lwpa_timer_init() +{ + mach_timebase_info_data_t timebase; + mach_timebase_info(&timebase); + + ticks_to_ms = (((double)timebase.numer) / (((double)timebase.denom) * ((double)1000000))); + return kLwpaErrOk; +} + +void lwpa_timer_deinit() +{ + // No deinitialization necessary on this platform. +} uint32_t lwpa_getms() { - struct timespec os_time; - if (0 == clock_gettime(CLOCK_MONOTONIC, &os_time)) - { - return (uint32_t)(os_time.tv_sec * 1000 + (os_time.tv_nsec / 1000000)); - } - return 0; + uint64_t ticks = mach_absolute_time(); + return ((uint32_t)(ticks * ticks_to_ms)); } diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index 1f36daf3f..e50defb3a 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -20,6 +20,7 @@ #include "gtest/gtest.h" #include #include +#include #include class NetintTest : public ::testing::Test @@ -38,19 +39,19 @@ class NetintTest : public ::testing::Test TEST_F(NetintTest, enumerate) { ASSERT_GT(num_netints, 0u); - LwpaNetintInfo* netint_arr = new LwpaNetintInfo[num_netints]; - size_t num_netints_returned = lwpa_netint_get_interfaces(netint_arr, num_netints); + auto netint_arr = std::make_unique(num_netints); + size_t num_netints_returned = lwpa_netint_get_interfaces(netint_arr.get(), num_netints); ASSERT_EQ(num_netints_returned, num_netints); size_t num_defaults = 0; - for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints_returned; ++netint) + for (LwpaNetintInfo* netint = netint_arr.get(); netint < netint_arr.get() + num_netints_returned; ++netint) { if (netint->is_default) ++num_defaults; ASSERT_GT(strlen(netint->name), 0u); } - ASSERT_EQ(num_defaults, 1u); - delete[] netint_arr; + // There can be a maximum of two default interfaces: one each for IPv4 and IPv6. + ASSERT_TRUE(num_defaults <= 2); } TEST_F(NetintTest, default) @@ -58,14 +59,14 @@ TEST_F(NetintTest, default) ASSERT_GT(num_netints, 0u); LwpaNetintInfo def; - LwpaNetintInfo* netint_arr = new LwpaNetintInfo[num_netints]; + auto netint_arr = std::make_unique(num_netints); memset(&def, 0, sizeof def); - memset(netint_arr, 0, sizeof(struct LwpaNetintInfo) * num_netints); + memset(netint_arr.get(), 0, sizeof(struct LwpaNetintInfo) * num_netints); - num_netints = lwpa_netint_get_interfaces(netint_arr, num_netints); + num_netints = lwpa_netint_get_interfaces(netint_arr.get(), num_netints); ASSERT_TRUE(lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def)); ASSERT_TRUE(def.is_default); - for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) + for (LwpaNetintInfo* netint = netint_arr.get(); netint < netint_arr.get() + num_netints; ++netint) { if (netint->is_default) { @@ -73,19 +74,18 @@ TEST_F(NetintTest, default) break; } } - delete[] netint_arr; } TEST_F(NetintTest, ipv4_routing) { ASSERT_GT(num_netints, 0u); - LwpaNetintInfo* netint_arr = new LwpaNetintInfo[num_netints]; - num_netints = lwpa_netint_get_interfaces(netint_arr, num_netints); + auto netint_arr = std::make_unique(num_netints); + num_netints = lwpa_netint_get_interfaces(netint_arr.get(), num_netints); std::set nets_already_tried; - for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) + for (LwpaNetintInfo* netint = netint_arr.get(); netint < netint_arr.get() + num_netints; ++netint) { if (!LWPA_IP_IS_V4(&netint->addr) || lwpa_ip_is_loopback(&netint->addr) || lwpa_ip_is_link_local(&netint->addr)) continue; From d277d40a6074b34843bad83823d99d18110562cd Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 16:05:31 -0500 Subject: [PATCH 048/264] Bring Windows along to new init methods --- src/os/windows/lwpa/os_common.c | 64 --------------------------------- src/os/windows/lwpa/os_socket.c | 18 ++++++++++ src/os/windows/lwpa/os_timer.c | 16 +++++++++ 3 files changed, 34 insertions(+), 64 deletions(-) delete mode 100644 src/os/windows/lwpa/os_common.c diff --git a/src/os/windows/lwpa/os_common.c b/src/os/windows/lwpa/os_common.c deleted file mode 100644 index 1959a7b1d..000000000 --- a/src/os/windows/lwpa/os_common.c +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ - -#include "lwpa/common.h" - -#include -#include "lwpa/bool.h" -#include "winsock_error.h" - -#define LWPA_WINDOWS_TIMER_RESOLUTION 1 // ms - -lwpa_error_t lwpa_os_init(lwpa_features_t features) -{ - bool timer_initted = false; - - if (features & LWPA_FEATURE_TIMERS) - { - if (TIMERR_NOERROR == timeBeginPeriod(LWPA_WINDOWS_TIMER_RESOLUTION)) - timer_initted = true; - else - return kLwpaErrSys; - } - if (features & LWPA_FEATURE_SOCKETS) - { - WSADATA wsdata; - WORD wsver = MAKEWORD(2, 2); - int startup_res = WSAStartup(wsver, &wsdata); - if (startup_res != 0) - { - if (timer_initted) - timeEndPeriod(LWPA_WINDOWS_TIMER_RESOLUTION); - return err_winsock_to_lwpa(startup_res); - } - } - return kLwpaErrOk; -} - -void lwpa_os_deinit(lwpa_features_t features) -{ - if (features & LWPA_FEATURE_TIMERS) - { - timeEndPeriod(LWPA_WINDOWS_TIMER_RESOLUTION); - } - if (features & LWPA_FEATURE_SOCKETS) - { - WSACleanup(); - } -} diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index 01908ae6f..dfdb66158 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -18,6 +18,7 @@ ******************************************************************************/ #include "lwpa/socket.h" +#include "lwpa/private/socket.h" #include #include @@ -124,6 +125,23 @@ static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent #if !defined(LWPA_BUILDING_MOCK_LIB) +lwpa_error_t lwpa_socket_init() +{ + WSADATA wsdata; + WORD wsver = MAKEWORD(2, 2); + int startup_res = WSAStartup(wsver, &wsdata); + if (startup_res != 0) + { + return err_winsock_to_lwpa(startup_res); + } + return kLwpaErrOk; +} + +void lwpa_socket_deinit() +{ + WSACleanup(); +} + lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { struct sockaddr_storage ss; diff --git a/src/os/windows/lwpa/os_timer.c b/src/os/windows/lwpa/os_timer.c index f3e241bb6..e5caaa583 100644 --- a/src/os/windows/lwpa/os_timer.c +++ b/src/os/windows/lwpa/os_timer.c @@ -18,9 +18,25 @@ ******************************************************************************/ #include "lwpa/timer.h" +#include "lwpa/private/timer.h" #include +#define LWPA_WINDOWS_TIMER_RESOLUTION 1 // ms + +lwpa_error_t lwpa_timer_init() +{ + if (TIMERR_NOERROR == timeBeginPeriod(LWPA_WINDOWS_TIMER_RESOLUTION)) + return kLwpaErrOk; + else + return kLwpaErrSys; +} + +void lwpa_timer_deinit() +{ + timeEndPeriod(LWPA_WINDOWS_TIMER_RESOLUTION); +} + uint32_t lwpa_getms() { return timeGetTime(); From dba8843bc7467c4684ef3568b94e656179a011f4 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 16:12:12 -0500 Subject: [PATCH 049/264] And Linux as well --- src/os/linux/lwpa/os_common.c | 38 ----------------------------------- src/os/linux/lwpa/os_socket.c | 11 ++++++++++ src/os/linux/lwpa/os_timer.c | 14 +++++++++++++ 3 files changed, 25 insertions(+), 38 deletions(-) delete mode 100644 src/os/linux/lwpa/os_common.c diff --git a/src/os/linux/lwpa/os_common.c b/src/os/linux/lwpa/os_common.c deleted file mode 100644 index 7e1de52d0..000000000 --- a/src/os/linux/lwpa/os_common.c +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ - -#include "lwpa/common.h" -#include "lwpa/private/common.h" - -#include - -lwpa_error_t lwpa_os_init(lwpa_features_t features) -{ - if (features & LWPA_FEATURE_TIMERS) - { - if (sysconf(_SC_MONOTONIC_CLOCK) < 0) - return kLwpaErrSys; - } - return kLwpaErrOk; -} - -void lwpa_os_deinit(lwpa_features_t features) -{ - (void)features; -} diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 2c1f786b5..bdbd4150b 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -129,6 +129,17 @@ static void poll_socket_free(LwpaRbNode* node); /*************************** Function definitions ****************************/ +lwpa_error_t lwpa_socket_init() +{ + // No initialization necessary on this platform + return kLwpaErrOk; +} + +void lwpa_socket_deinit() +{ + // No deinitialization necessary on this platform +} + lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { if (!conn_sock) diff --git a/src/os/linux/lwpa/os_timer.c b/src/os/linux/lwpa/os_timer.c index 813c97007..dc4de267b 100644 --- a/src/os/linux/lwpa/os_timer.c +++ b/src/os/linux/lwpa/os_timer.c @@ -18,8 +18,22 @@ ******************************************************************************/ #include "lwpa/timer.h" +#include "lwpa/private/timer.h" #include +#include + +lwpa_error_t lwpa_timer_init() +{ + if (sysconf(_SC_MONOTONIC_CLOCK) < 0) + return kLwpaErrSys; + return kLwpaErrOk; +} + +void lwpa_timer_deinit() +{ + // No deinitialization necessary on this platform. +} uint32_t lwpa_getms() { From 549328a059ac83bc11a6d4bf50afe3a8c3a0ea97 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 16:17:16 -0500 Subject: [PATCH 050/264] Make netint.ipv4_routing unit test more deterministic --- tests/unit/test_netint.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index 1f36daf3f..74e95cec1 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -83,21 +83,15 @@ TEST_F(NetintTest, ipv4_routing) LwpaNetintInfo* netint_arr = new LwpaNetintInfo[num_netints]; num_netints = lwpa_netint_get_interfaces(netint_arr, num_netints); - std::set nets_already_tried; - + // For each normally routable (non-loopback, non-link-local) network interface, check to make sure + // that lwpa_netint_get_interface_for_dest() resolves to that interface when asked for a route to + // the interface address itself. for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_netints; ++netint) { if (!LWPA_IP_IS_V4(&netint->addr) || lwpa_ip_is_loopback(&netint->addr) || lwpa_ip_is_link_local(&netint->addr)) continue; - uint32_t net = LWPA_IP_V4_ADDRESS(&netint->addr) & LWPA_IP_V4_ADDRESS(&netint->mask); - LwpaIpAddr test_addr; - - if (nets_already_tried.find(net) != nets_already_tried.end()) - continue; - nets_already_tried.insert(net); - LWPA_IP_SET_V4_ADDRESS(&test_addr, net + 1); - + LwpaIpAddr test_addr = netint->addr; LwpaNetintInfo netint_res; ASSERT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&test_addr, &netint_res)); From 9ff0b6bec75a49080f20869f805fc523998469e7 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 16:29:43 -0500 Subject: [PATCH 051/264] LWPA_15 lwpa_canlog() check for NULL --- include/lwpa/log.h | 5 +++-- tests/unit/test_log.cpp | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/include/lwpa/log.h b/include/lwpa/log.h index 13f9367a6..5c188d492 100644 --- a/include/lwpa/log.h +++ b/include/lwpa/log.h @@ -218,9 +218,10 @@ typedef struct LwpaLogParams void* context; } LwpaLogParams; -#define lwpa_setlogmask(logparamsptr, newlogmask) ((logparamsptr)->log_mask = newlogmask) +#define LWPA_SET_LOG_MASK(logparamsptr, newlogmask) ((logparamsptr)->log_mask = newlogmask) -#define lwpa_canlog(logparamsptr, pri) ((LWPA_LOG_MASK(pri) & (logparamsptr)->log_mask) != 0) +#define LWPA_CAN_LOG(logparamsptr, pri) \ + ((logparamsptr) ? ((LWPA_LOG_MASK(pri) & (logparamsptr)->log_mask) != 0) : false) #ifdef __cplusplus extern "C" { diff --git a/tests/unit/test_log.cpp b/tests/unit/test_log.cpp index b2992bee9..4322e031d 100644 --- a/tests/unit/test_log.cpp +++ b/tests/unit/test_log.cpp @@ -84,6 +84,37 @@ void LogTest::FillDefaultTime(LwpaLogTimeParams& time_params) time_params.utc_offset = 0; // Local offset from UTC in minutes } +// Test the LWPA_SET_LOG_MASK() and LWPA_CAN_LOG() macros +TEST_F(LogTest, log_mask) +{ + // LWPA_CAN_LOG() should always return false (and not crash) on a null pointer + LwpaLogParams* params_ptr = NULL; + EXPECT_FALSE(LWPA_CAN_LOG(params_ptr, LWPA_LOG_EMERG)); + + LwpaLogParams params; + + // Test a zero mask + LWPA_SET_LOG_MASK(¶ms, 0); + EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); + EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); + + // Test some LOG_UPTO() values + LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_UPTO(LWPA_LOG_EMERG)); + EXPECT_TRUE(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); + EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_ALERT)); + EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); + + LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_UPTO(LWPA_LOG_DEBUG)); + EXPECT_TRUE(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); + EXPECT_TRUE(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); + + // Test a weird mask with only one middle value + LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_MASK(LWPA_LOG_ERR)); + EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); + EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); + EXPECT_TRUE(LWPA_CAN_LOG(¶ms, LWPA_LOG_ERR)); +} + // Test the lwpa_sanitize_syslog_params() function. TEST_F(LogTest, sanitize) { @@ -181,7 +212,7 @@ TEST_F(LogTest, log_intval) ASSERT_STREQ(human_buf, expect_human_str.c_str()); // Try logging with the log mask set to 0, should not work. - ASSERT_FALSE(lwpa_canlog(&lparams, LWPA_LOG_EMERG)); + ASSERT_FALSE(LWPA_CAN_LOG(&lparams, LWPA_LOG_EMERG)); lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); // Try logging only syslog @@ -275,7 +306,7 @@ TEST_F(LogTest, log_strval) ASSERT_STREQ(human_buf, expect_human_str.c_str()); // Try logging with the log mask set to 0, should not work. - ASSERT_FALSE(lwpa_canlog(&lparams, LWPA_LOG_NOTICE)); + ASSERT_FALSE(LWPA_CAN_LOG(&lparams, LWPA_LOG_NOTICE)); lwpa_log(&lparams, LWPA_LOG_NOTICE, STRVAL_FORMAT_STR_AND_ARGS); // Now try the actual logging using lwpa_vlog(). @@ -370,7 +401,7 @@ TEST_F(LogTest, log_maxlength) ASSERT_STREQ(human_buf, expect_human_str.c_str()); // Try logging with the log mask set to 0, should not work. - ASSERT_FALSE(lwpa_canlog(&lparams, LWPA_LOG_DEBUG)); + ASSERT_FALSE(LWPA_CAN_LOG(&lparams, LWPA_LOG_DEBUG)); lwpa_log(&lparams, LWPA_LOG_DEBUG, STRVAL_FORMAT_STR_AND_ARGS); // Now try the actual logging using lwpa_vlog(). From 0c126047c4227894f240d7e241e5bc53ae8b00eb Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 16:32:41 -0500 Subject: [PATCH 052/264] Fix comments in macos/os_thread --- include/os/macos/lwpa/os_thread.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/os/macos/lwpa/os_thread.h b/include/os/macos/lwpa/os_thread.h index fa41f39ff..6d4726358 100644 --- a/include/os/macos/lwpa/os_thread.h +++ b/include/os/macos/lwpa/os_thread.h @@ -28,9 +28,9 @@ extern "C" { #endif -#define LWPA_THREAD_DEFAULT_PRIORITY 0 /* Priority ignored on Linux */ +#define LWPA_THREAD_DEFAULT_PRIORITY 0 /* Priority ignored on macOS */ #define LWPA_THREAD_DEFAULT_STACK 0 /* 0 means keep default */ -#define LWPA_THREAD_DEFAULT_NAME NULL /* Name ignored on Linux */ +#define LWPA_THREAD_DEFAULT_NAME NULL /* Name ignored on macOS */ #define LWPA_THREAD_NAME_MAX_LENGTH 0 From b3f368cbc857073a18d3ef15dfab94c394f4d11c Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 18:02:51 -0500 Subject: [PATCH 053/264] noncompiling WIP on mac sockets --- include/os/macos/lwpa/os_socket.h | 2 +- src/os/macos/lwpa/os_socket.c | 244 +++++++++++++++--------------- 2 files changed, 121 insertions(+), 125 deletions(-) diff --git a/include/os/macos/lwpa/os_socket.h b/include/os/macos/lwpa/os_socket.h index accda16a3..0fa2dbb7c 100644 --- a/include/os/macos/lwpa/os_socket.h +++ b/include/os/macos/lwpa/os_socket.h @@ -38,7 +38,7 @@ typedef int lwpa_socket_t; typedef struct LwpaPollContext { bool valid; - int epoll_fd; + int kq_fd; LwpaRbTree sockets; } LwpaPollContext; diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index e18fd5815..26dbcfaef 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -26,7 +26,7 @@ #include #include #include -// #include +#include #include #include #include @@ -42,7 +42,6 @@ typedef struct LwpaPollSocket // shortcut lwpa_socket_t sock; lwpa_poll_events_t events; - void* user_data; } LwpaPollSocket; /**************************** Private variables ******************************/ @@ -114,13 +113,13 @@ static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_v static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); // Helpers for lwpa_poll API -// static void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt); -// static void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, -// lwpa_poll_events_t* events); +static void events_lwpa_to_kqueue(lwpa_poll_events_t events, struct epoll_event* epoll_evt); +static void events_kqueue_to_lwpa(const struct kevent* kevent, const LwpaPollSocket* sock_desc, + lwpa_poll_events_t* events); -// static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); -// static LwpaRbNode* poll_socket_alloc(); -// static void poll_socket_free(LwpaRbNode* node); +static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); +static LwpaRbNode* poll_socket_alloc(); +static void poll_socket_free(LwpaRbNode* node); /*************************** Function definitions ****************************/ @@ -562,79 +561,77 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { - // if (!context) - // return kLwpaErrInvalid; - // - // context->epoll_fd = epoll_create(EPOLL_CREATE_SIZE); - // if (context->epoll_fd >= 0) - // { - // lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); - // context->valid = true; - // return kLwpaErrOk; - // } - // else - // { - // return errno_os_to_lwpa(errno); - // } - return kLwpaErrNotImpl; + if (!context) + return kLwpaErrInvalid; + + context->kq_fd = kqueue(); + if (context->kq_fd >= 0) + { + // lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); + context->valid = true; + return kLwpaErrOk; + } + else + { + return errno_os_to_lwpa(errno); + } } void lwpa_poll_context_deinit(LwpaPollContext* context) { - // if (context && context->valid) - // { - // lwpa_rbtree_clear(&context->sockets); - // close(context->epoll_fd); - // context->valid = false; - // } + if (context && context->valid) + { + // lwpa_rbtree_clear(&context->sockets); + close(context->kq_fd); + context->valid = false; + } } lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, void* user_data) { - // if (context && context->valid && socket != LWPA_SOCKET_INVALID && (events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) - // { - // LwpaPollSocket* sock_desc = (LwpaPollSocket*)malloc(sizeof(LwpaPollSocket)); - // if (sock_desc) - // { - // sock_desc->sock = socket; - // sock_desc->events = events; - // sock_desc->user_data = user_data; - // int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); - // if (insert_res != 0) - // { - // struct epoll_event ep_evt; - // events_lwpa_to_epoll(events, &ep_evt); - // ep_evt.data.fd = socket; - // - // int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_ADD, socket, &ep_evt); - // if (res == 0) - // { - // return kLwpaErrOk; - // } - // else - // { - // // Our node dealloc function also deallocates sock_desc, so no need to free it here. - // lwpa_rbtree_remove(&context->sockets, sock_desc); - // return errno_os_to_lwpa(errno); - // } - // } - // else - // { - // free(sock_desc); - // return kLwpaErrNoMem; - // } - // } - // else - // { - // return kLwpaErrNoMem; - // } - // } - // else - // { - // return kLwpaErrInvalid; - // } - return kLwpaErrNotImpl; + if (context && context->valid && socket != LWPA_SOCKET_INVALID && (events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)malloc(sizeof(LwpaPollSocket)); + if (sock_desc) + { + sock_desc->sock = socket; + sock_desc->events = events; + sock_desc->user_data = user_data; + int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); + if (insert_res != 0) + { + struct epoll_event ep_evt; + events_lwpa_to_kqueue(events, &ep_evt); + ep_evt.data.fd = socket; + + int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_ADD, socket, &ep_evt); + if (res == 0) + { + return kLwpaErrOk; + } + else + { + // Our node dealloc function also deallocates sock_desc, so no need to free it here. + lwpa_rbtree_remove(&context->sockets, sock_desc); + return errno_os_to_lwpa(errno); + } + } + else + { + free(sock_desc); + return kLwpaErrNoMem; + } + } + else + { + return kLwpaErrNoMem; + } + } + else + { + return kLwpaErrInvalid; + } } lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, @@ -646,7 +643,7 @@ lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t soc // if (sock_desc) // { // struct epoll_event ep_evt; - // events_lwpa_to_epoll(new_events, &ep_evt); + // events_lwpa_to_kqueue(new_events, &ep_evt); // ep_evt.data.fd = socket; // // int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_MOD, socket, &ep_evt); @@ -745,57 +742,56 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int return kLwpaErrNotImpl; } -// void events_lwpa_to_epoll(lwpa_poll_events_t events, struct epoll_event* epoll_evt) -//{ -// epoll_evt->events = 0; -// if (events & LWPA_POLL_IN) -// epoll_evt->events |= EPOLLIN; -// if ((events & LWPA_POLL_OUT) || (events & LWPA_POLL_CONNECT)) -// epoll_evt->events |= EPOLLOUT; -// if (events & LWPA_POLL_OOB) -// epoll_evt->events |= EPOLLPRI; -//} -// -// void events_epoll_to_lwpa(const struct epoll_event* epoll_evt, const LwpaPollSocket* sock_desc, -// lwpa_poll_events_t* events_out) -//{ -// *events_out = 0; -// if (epoll_evt->events & EPOLLIN) -// *events_out |= LWPA_POLL_IN; -// if (epoll_evt->events & EPOLLOUT) -// { -// if (sock_desc->events & LWPA_POLL_OUT) -// *events_out |= LWPA_POLL_OUT; -// if (sock_desc->events & LWPA_POLL_CONNECT) -// *events_out |= LWPA_POLL_CONNECT; -// } -// if (epoll_evt->events & EPOLLPRI) -// *events_out |= (LWPA_POLL_OOB); -// if (epoll_evt->events & EPOLLERR) -// *events_out |= (LWPA_POLL_ERR); -//} -// -// int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b) -//{ -// LwpaPollSocket* a = (LwpaPollSocket*)node_a->value; -// LwpaPollSocket* b = (LwpaPollSocket*)node_b->value; -// -// return (a->sock > b->sock) - (a->sock < b->sock); -//} -// -// LwpaRbNode* poll_socket_alloc() -//{ -// return (LwpaRbNode*)malloc(sizeof(LwpaRbNode)); -//} -// -// void poll_socket_free(LwpaRbNode* node) -//{ -// if (node) -// { -// free(node->value); -// free(node); -// } -//} +void events_lwpa_to_kqueue(lwpa_poll_events_t events, struct epoll_event* epoll_evt) +{ + epoll_evt->events = 0; + if (events & LWPA_POLL_IN) + epoll_evt->events |= EPOLLIN; + if ((events & LWPA_POLL_OUT) || (events & LWPA_POLL_CONNECT)) + epoll_evt->events |= EPOLLOUT; + if (events & LWPA_POLL_OOB) + epoll_evt->events |= EPOLLPRI; +} + +void events_kqueue_to_lwpa(const struct kevent* kevent, const LwpaPollSocket* sock_desc, lwpa_poll_events_t* events_out) +{ + *events_out = 0; + if (epoll_evt->events & EPOLLIN) + *events_out |= LWPA_POLL_IN; + if (epoll_evt->events & EPOLLOUT) + { + if (sock_desc->events & LWPA_POLL_OUT) + *events_out |= LWPA_POLL_OUT; + if (sock_desc->events & LWPA_POLL_CONNECT) + *events_out |= LWPA_POLL_CONNECT; + } + if (epoll_evt->events & EPOLLPRI) + *events_out |= (LWPA_POLL_OOB); + if (epoll_evt->events & EPOLLERR) + *events_out |= (LWPA_POLL_ERR); +} + +int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b) +{ + LwpaPollSocket* a = (LwpaPollSocket*)node_a->value; + LwpaPollSocket* b = (LwpaPollSocket*)node_b->value; + + return (a->sock > b->sock) - (a->sock < b->sock); +} + +LwpaRbNode* poll_socket_alloc() +{ + return (LwpaRbNode*)malloc(sizeof(LwpaRbNode)); +} + +void poll_socket_free(LwpaRbNode* node) +{ + if (node) + { + free(node->value); + free(node); + } +} lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, LwpaAddrinfo* result) From 580fb6137c8b71266ca21149100d2c1dfcd15a1e Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 17 Jun 2019 21:53:11 -0500 Subject: [PATCH 054/264] Progress on kqueue/poll, fix small socket bugs --- src/os/macos/lwpa/os_socket.c | 356 +++++++++++++++++++--------------- tests/unit/test_netint.cpp | 24 ++- 2 files changed, 220 insertions(+), 160 deletions(-) diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index 26dbcfaef..ded401054 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -24,15 +24,22 @@ #include #include +#include #include #include #include +#include #include #include #include #include "os_error.h" +/**************************** Private constants ******************************/ + +/* The maximum number of kevents that can be added in one call to an lwpa_poll API function. */ +#define LWPA_SOCKET_MAX_KEVENTS 3 + /****************************** Private types ********************************/ /* A struct to track sockets being polled by the lwpa_poll() API */ @@ -113,9 +120,9 @@ static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_v static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); // Helpers for lwpa_poll API -static void events_lwpa_to_kqueue(lwpa_poll_events_t events, struct epoll_event* epoll_evt); -static void events_kqueue_to_lwpa(const struct kevent* kevent, const LwpaPollSocket* sock_desc, - lwpa_poll_events_t* events); +static int events_lwpa_to_kqueue(lwpa_poll_events_t events, lwpa_socket_t socket, void* user_data, uint16_t flags, + struct kevent* kevents); +static lwpa_poll_events_t events_kqueue_to_lwpa(const struct kevent* kevent, const LwpaPollSocket* sock_desc); static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); static LwpaRbNode* poll_socket_alloc(); @@ -371,6 +378,29 @@ int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_valu return -1; } +/* On Darwin, MCAST_JOIN_GROUP/MCAST_LEAVE_GROUP APIs do not seem to be supported. So we need to + * translate interface indexes to addresses for IPv4 MCAST_JOIN_GROUP sockopts. */ +static int ip4_ifindex_to_addr(unsigned int ifindex, struct in_addr* addr) +{ + struct ifreq req; + if (if_indextoname(ifindex, req.ifr_name) != NULL) + { + int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (ioctl_sock != -1) + { + int ioctl_res = ioctl(ioctl_sock, SIOCGIFADDR, &req); + if (ioctl_res != -1) + { + *addr = ((struct sockaddr_in*)&req.ifr_addr)->sin_addr; + close(ioctl_sock); + return 0; + } + close(ioctl_sock); + } + } + return -1; +} + int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) { switch (option_name) @@ -409,14 +439,11 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s LwpaGroupReq* greq = (LwpaGroupReq*)option_value; if (LWPA_IP_IS_V4(&greq->group) && greq->ifindex >= 0) { - struct group_req val; - val.gr_interface = (uint32_t)greq->ifindex; - - memset(&val.gr_group, 0, sizeof val.gr_group); - struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); - return setsockopt(id, IPPROTO_IP, MCAST_JOIN_GROUP, &val, sizeof val); + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + if (0 != ip4_ifindex_to_addr(greq->ifindex, &val.imr_interface)) + return -1; + return setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &val, sizeof val); } } break; @@ -426,14 +453,11 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s LwpaGroupReq* greq = (LwpaGroupReq*)option_value; if (LWPA_IP_IS_V4(&greq->group) && greq->ifindex >= 0) { - struct group_req val; - val.gr_interface = (uint32_t)greq->ifindex; - - memset(&val.gr_group, 0, sizeof val.gr_group); - struct sockaddr_in* sin = (struct sockaddr_in*)&val.gr_group; - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); - return setsockopt(id, IPPROTO_IP, MCAST_LEAVE_GROUP, &val, sizeof val); + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + if (0 != ip4_ifindex_to_addr(greq->ifindex, &val.imr_interface)) + return -1; + return setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, &val, sizeof val); } } break; @@ -471,14 +495,10 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, LwpaGroupReq* greq = (LwpaGroupReq*)option_value; if (LWPA_IP_IS_V6(&greq->group) && greq->ifindex >= 0) { - struct group_req val; - val.gr_interface = (uint32_t)greq->ifindex; - - memset(&val.gr_group, 0, sizeof val.gr_group); - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; - sin6->sin6_family = AF_INET6; - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); - return setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, sizeof val); + struct ipv6_mreq val; + val.ipv6mr_interface = (uint32_t)greq->ifindex; + memcpy(val.ipv6mr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, IPV6_JOIN_GROUP, &val, sizeof val); } } break; @@ -488,18 +508,14 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, LwpaGroupReq* greq = (LwpaGroupReq*)option_value; if (LWPA_IP_IS_V6(&greq->group) && greq->ifindex >= 0) { - struct group_req val; - val.gr_interface = (uint32_t)greq->ifindex; - - memset(&val.gr_group, 0, sizeof val.gr_group); - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&val.gr_group; - sin6->sin6_family = AF_INET6; - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); - return setsockopt(id, IPPROTO_IPV6, MCAST_LEAVE_GROUP, &val, sizeof val); + struct ipv6_mreq val; + val.ipv6mr_interface = (uint32_t)greq->ifindex; + memcpy(val.ipv6mr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &val, sizeof val); } } break; - default: /* Other IPv6 options TODO on linux. */ + default: /* Other IPv6 options TODO on macOS. */ break; } // If we got here, something was invalid. Set errno accordingly @@ -567,7 +583,7 @@ lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) context->kq_fd = kqueue(); if (context->kq_fd >= 0) { - // lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); + lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); context->valid = true; return kLwpaErrOk; } @@ -581,7 +597,7 @@ void lwpa_poll_context_deinit(LwpaPollContext* context) { if (context && context->valid) { - // lwpa_rbtree_clear(&context->sockets); + lwpa_rbtree_clear(&context->sockets); close(context->kq_fd); context->valid = false; } @@ -597,15 +613,13 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket { sock_desc->sock = socket; sock_desc->events = events; - sock_desc->user_data = user_data; int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); if (insert_res != 0) { - struct epoll_event ep_evt; - events_lwpa_to_kqueue(events, &ep_evt); - ep_evt.data.fd = socket; + struct kevent os_events[LWPA_SOCKET_MAX_KEVENTS]; + int num_events = events_lwpa_to_kqueue(events, socket, user_data, EV_ADD, os_events); - int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_ADD, socket, &ep_evt); + int res = kevent(context->kq_fd, os_events, num_events, NULL, 0, NULL); if (res == 0) { return kLwpaErrOk; @@ -637,138 +651,172 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, void* new_user_data) { - // if (context && context->valid && socket != LWPA_SOCKET_INVALID && (new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) - // { - // LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); - // if (sock_desc) - // { - // struct epoll_event ep_evt; - // events_lwpa_to_kqueue(new_events, &ep_evt); - // ep_evt.data.fd = socket; - // - // int res = epoll_ctl(context->epoll_fd, EPOLL_CTL_MOD, socket, &ep_evt); - // if (res == 0) - // { - // sock_desc->events = new_events; - // sock_desc->user_data = new_user_data; - // return kLwpaErrOk; - // } - // else - // { - // return errno_os_to_lwpa(errno); - // } - // } - // else - // { - // return kLwpaErrNotFound; - // } - // } - // else - // { - // return kLwpaErrInvalid; - // } - return kLwpaErrNotImpl; + if (context && context->valid && socket != LWPA_SOCKET_INVALID && (new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); + if (sock_desc) + { + struct kevent os_events[LWPA_SOCKET_MAX_KEVENTS]; + int num_events = events_lwpa_to_kqueue(new_events, socket, new_user_data, EV_ADD, os_events); + + int res = kevent(context->kq_fd, os_events, num_events, NULL, 0, NULL); + if (res == 0) + { + sock_desc->events = new_events; + return kLwpaErrOk; + } + else + { + return errno_os_to_lwpa(errno); + } + } + else + { + return kLwpaErrNotFound; + } + } + else + { + return kLwpaErrInvalid; + } } void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) { - // if (context && context->valid) - // { - // // Need a dummy struct for portability - some versions require event to always be non-NULL - // // even though it is ignored - // struct epoll_event ep_evt; - // epoll_ctl(context->epoll_fd, EPOLL_CTL_DEL, socket, &ep_evt); - // lwpa_rbtree_remove(&context->sockets, &socket); - // } + if (context && context->valid) + { + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); + if (sock_desc) + { + struct kevent os_events[LWPA_SOCKET_MAX_KEVENTS]; + int num_events = events_lwpa_to_kqueue(sock_desc->events, socket, NULL, EV_DELETE, os_events); + + kevent(context->kq_fd, os_events, num_events, NULL, 0, NULL); + lwpa_rbtree_remove(&context->sockets, &sock_desc); + } + } } lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms) { - // if (context && context->valid && event) - // { - // if (lwpa_rbtree_size(&context->sockets) > 0) - // { - // int sys_timeout = (timeout_ms == LWPA_WAIT_FOREVER ? -1 : timeout_ms); - // - // struct epoll_event epoll_evt; - // int wait_res = epoll_wait(context->epoll_fd, &epoll_evt, 1, sys_timeout); - // if (wait_res > 0) - // { - // LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &epoll_evt.data.fd); - // if (sock_desc) - // { - // event->socket = sock_desc->sock; - // events_epoll_to_lwpa(&epoll_evt, sock_desc, &event->events); - // event->err = kLwpaErrOk; - // event->user_data = sock_desc->user_data; - // - // // Check for errors - // int error; - // socklen_t error_size = sizeof error; - // if (getsockopt(sock_desc->sock, SOL_SOCKET, SO_ERROR, &error, &error_size) == 0) - // { - // if (error != 0) - // { - // event->events |= LWPA_POLL_ERR; - // event->err = errno_os_to_lwpa(error); - // } - // } - // - // return kLwpaErrOk; - // } - // else - // { - // return kLwpaErrSys; - // } - // } - // else if (wait_res == 0) - // { - // return kLwpaErrTimedOut; - // } - // else - // { - // return errno_os_to_lwpa(errno); - // } - // } - // else - // { - // return kLwpaErrNoSockets; - // } - // } - // else - // { - // return kLwpaErrInvalid; - // } - return kLwpaErrNotImpl; + if (context && context->valid && event) + { + if (lwpa_rbtree_size(&context->sockets) > 0) + { + struct timespec os_timeout; + struct timespec* os_timeout_ptr; + if (timeout_ms == LWPA_WAIT_FOREVER) + { + os_timeout_ptr = NULL; + } + else + { + os_timeout.tv_sec = timeout_ms / 1000; + os_timeout.tv_nsec = timeout_ms * 1000000; + os_timeout_ptr = &os_timeout; + } + + struct kevent kevt; + int wait_res = kevent(context->kq_fd, NULL, 0, &kevt, 1, os_timeout_ptr); + if (wait_res > 0) + { + lwpa_socket_t sock = (lwpa_socket_t)kevt.ident; + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &sock); + if (sock_desc) + { + event->socket = sock_desc->sock; + event->events = events_kqueue_to_lwpa(&kevt, sock_desc); + event->err = kLwpaErrOk; + event->user_data = kevt.udata; + + // Check for errors + int error; + socklen_t error_size = sizeof error; + if (getsockopt(sock_desc->sock, SOL_SOCKET, SO_ERROR, &error, &error_size) == 0) + { + if (error != 0) + { + event->events |= LWPA_POLL_ERR; + event->err = errno_os_to_lwpa(error); + } + } + + return kLwpaErrOk; + } + else + { + return kLwpaErrSys; + } + } + else if (wait_res == 0) + { + return kLwpaErrTimedOut; + } + else + { + return errno_os_to_lwpa(errno); + } + } + else + { + return kLwpaErrNoSockets; + } + } + else + { + return kLwpaErrInvalid; + } } -void events_lwpa_to_kqueue(lwpa_poll_events_t events, struct epoll_event* epoll_evt) +int events_lwpa_to_kqueue(lwpa_poll_events_t events, lwpa_socket_t socket, void* user_data, uint16_t flags, + struct kevent* kevents) { - epoll_evt->events = 0; + int num_events = 0; + if (events & LWPA_POLL_IN) - epoll_evt->events |= EPOLLIN; + { + EV_SET(&kevents[num_events], socket, EVFILT_READ, flags, 0, 0, user_data); + ++num_events; + } if ((events & LWPA_POLL_OUT) || (events & LWPA_POLL_CONNECT)) - epoll_evt->events |= EPOLLOUT; + { + EV_SET(&kevents[num_events], socket, EVFILT_WRITE, flags, 0, 0, user_data); + ++num_events; + } if (events & LWPA_POLL_OOB) - epoll_evt->events |= EPOLLPRI; + { + EV_SET(&kevents[num_events], socket, EVFILT_EXCEPT, flags, NOTE_OOB, 0, user_data); + ++num_events; + } + return num_events; } -void events_kqueue_to_lwpa(const struct kevent* kevent, const LwpaPollSocket* sock_desc, lwpa_poll_events_t* events_out) +lwpa_poll_events_t events_kqueue_to_lwpa(const struct kevent* kevent, const LwpaPollSocket* sock_desc) { - *events_out = 0; - if (epoll_evt->events & EPOLLIN) - *events_out |= LWPA_POLL_IN; - if (epoll_evt->events & EPOLLOUT) + lwpa_poll_events_t events_out = 0; + if (kevent->filter == EVFILT_READ) + { + events_out |= LWPA_POLL_IN; + if (kevent->flags & EV_EOF) + events_out |= LWPA_POLL_ERR; + } + if (kevent->filter == EVFILT_WRITE) { if (sock_desc->events & LWPA_POLL_OUT) - *events_out |= LWPA_POLL_OUT; + events_out |= LWPA_POLL_OUT; if (sock_desc->events & LWPA_POLL_CONNECT) - *events_out |= LWPA_POLL_CONNECT; + events_out |= LWPA_POLL_CONNECT; + if (kevent->flags & EV_EOF) + events_out |= LWPA_POLL_ERR; } - if (epoll_evt->events & EPOLLPRI) - *events_out |= (LWPA_POLL_OOB); - if (epoll_evt->events & EPOLLERR) - *events_out |= (LWPA_POLL_ERR); + if (kevent->filter == EVFILT_EXCEPT) + { + events_out |= LWPA_POLL_OOB; + if (kevent->flags & EV_EOF) + events_out |= LWPA_POLL_ERR; + } + + return events_out; } int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b) diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index 301157e49..879eb11b6 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -58,20 +58,32 @@ TEST_F(NetintTest, default) { ASSERT_GT(num_netints, 0u); - LwpaNetintInfo def; + LwpaNetintInfo def_v4; + LwpaNetintInfo def_v6; + memset(&def_v4, 0, sizeof def_v4); + memset(&def_v6, 0, sizeof def_v6); + auto netint_arr = std::make_unique(num_netints); - memset(&def, 0, sizeof def); memset(netint_arr.get(), 0, sizeof(struct LwpaNetintInfo) * num_netints); num_netints = lwpa_netint_get_interfaces(netint_arr.get(), num_netints); - ASSERT_TRUE(lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def)); - ASSERT_TRUE(def.is_default); + + bool have_default_v4 = lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_v4); + bool have_default_v6 = lwpa_netint_get_default_interface(kLwpaIpTypeV6, &def_v6); + + if (have_default_v4) + EXPECT_TRUE(def_v4.is_default); + if (have_default_v6) + EXPECT_TRUE(def_v6.is_default); + for (LwpaNetintInfo* netint = netint_arr.get(); netint < netint_arr.get() + num_netints; ++netint) { if (netint->is_default) { - ASSERT_EQ(0, memcmp(netint, &def, sizeof def)); - break; + if (netint->addr.type == kLwpaIpTypeV4) + EXPECT_EQ(0, memcmp(netint, &def_v4, sizeof def_v4)); + else if (netint->addr.type == kLwpaIpTypeV6) + EXPECT_EQ(0, memcmp(netint, &def_v6, sizeof def_v6)); } } } From 77c5ec7229aa71a712c2c58f9a4329678484e692 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 10:52:43 -0500 Subject: [PATCH 055/264] Mac: all tests passing. --- src/os/macos/lwpa/os_socket.c | 52 +++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index ded401054..ed80a0891 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -120,8 +120,8 @@ static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_v static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); // Helpers for lwpa_poll API -static int events_lwpa_to_kqueue(lwpa_poll_events_t events, lwpa_socket_t socket, void* user_data, uint16_t flags, - struct kevent* kevents); +static int events_lwpa_to_kqueue(lwpa_socket_t socket, lwpa_poll_events_t prev_events, lwpa_poll_events_t new_events, + void* user_data, struct kevent* events); static lwpa_poll_events_t events_kqueue_to_lwpa(const struct kevent* kevent, const LwpaPollSocket* sock_desc); static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); @@ -617,7 +617,7 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket if (insert_res != 0) { struct kevent os_events[LWPA_SOCKET_MAX_KEVENTS]; - int num_events = events_lwpa_to_kqueue(events, socket, user_data, EV_ADD, os_events); + int num_events = events_lwpa_to_kqueue(socket, 0, events, user_data, os_events); int res = kevent(context->kq_fd, os_events, num_events, NULL, 0, NULL); if (res == 0) @@ -657,7 +657,7 @@ lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t soc if (sock_desc) { struct kevent os_events[LWPA_SOCKET_MAX_KEVENTS]; - int num_events = events_lwpa_to_kqueue(new_events, socket, new_user_data, EV_ADD, os_events); + int num_events = events_lwpa_to_kqueue(socket, sock_desc->events, new_events, new_user_data, os_events); int res = kevent(context->kq_fd, os_events, num_events, NULL, 0, NULL); if (res == 0) @@ -689,7 +689,7 @@ void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) if (sock_desc) { struct kevent os_events[LWPA_SOCKET_MAX_KEVENTS]; - int num_events = events_lwpa_to_kqueue(sock_desc->events, socket, NULL, EV_DELETE, os_events); + int num_events = events_lwpa_to_kqueue(socket, sock_desc->events, 0, NULL, os_events); kevent(context->kq_fd, os_events, num_events, NULL, 0, NULL); lwpa_rbtree_remove(&context->sockets, &sock_desc); @@ -712,7 +712,7 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int else { os_timeout.tv_sec = timeout_ms / 1000; - os_timeout.tv_nsec = timeout_ms * 1000000; + os_timeout.tv_nsec = (timeout_ms % 1000) * 1000000; os_timeout_ptr = &os_timeout; } @@ -768,26 +768,50 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int } } -int events_lwpa_to_kqueue(lwpa_poll_events_t events, lwpa_socket_t socket, void* user_data, uint16_t flags, - struct kevent* kevents) +int events_lwpa_to_kqueue(lwpa_socket_t socket, lwpa_poll_events_t prev_events, lwpa_poll_events_t new_events, + void* user_data, struct kevent* kevents) { int num_events = 0; - if (events & LWPA_POLL_IN) + // Process EVFILT_READ changes + if (new_events & LWPA_POLL_IN) { - EV_SET(&kevents[num_events], socket, EVFILT_READ, flags, 0, 0, user_data); + // Re-add the socket even if it was already added before - user data might be modified. + EV_SET(&kevents[num_events], socket, EVFILT_READ, EV_ADD, 0, 0, user_data); ++num_events; } - if ((events & LWPA_POLL_OUT) || (events & LWPA_POLL_CONNECT)) + else if (prev_events & LWPA_POLL_IN) { - EV_SET(&kevents[num_events], socket, EVFILT_WRITE, flags, 0, 0, user_data); + EV_SET(&kevents[num_events], socket, EVFILT_READ, EV_DELETE, 0, 0, user_data); ++num_events; } - if (events & LWPA_POLL_OOB) + + // Process EVFILT_WRITE changes + if (new_events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + { + // Re-add the socket even if it was already added before - user data might be modified. + EV_SET(&kevents[num_events], socket, EVFILT_WRITE, EV_ADD, 0, 0, user_data); + ++num_events; + } + else if (prev_events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + { + EV_SET(&kevents[num_events], socket, EVFILT_WRITE, EV_DELETE, 0, 0, user_data); + ++num_events; + } + + // Process EVFILT_EXCEPT changes + if (new_events & LWPA_POLL_OOB) + { + // Re-add the socket even if it was already added before - user data might be modified. + EV_SET(&kevents[num_events], socket, EVFILT_EXCEPT, EV_ADD, NOTE_OOB, 0, user_data); + ++num_events; + } + else if (prev_events & LWPA_POLL_OOB) { - EV_SET(&kevents[num_events], socket, EVFILT_EXCEPT, flags, NOTE_OOB, 0, user_data); + EV_SET(&kevents[num_events], socket, EVFILT_EXCEPT, EV_DELETE, 0, 0, user_data); ++num_events; } + return num_events; } From 0f9d3096924b25dee42a2227bc55391cd64cb69d Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 11:06:09 -0500 Subject: [PATCH 056/264] Cleanup macOS documentation --- CHANGELOG.md | 1 + README.md | 1 + azure-pipelines.yml | 15 +++++++++++++++ docs/mainpage.md | 4 ++++ src/lwpa/lock.dox | 2 ++ src/os/macos/lwpa/os_uuid.c | 4 ++-- 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b63ac94f3..76402ffc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - OS port: Linux +- OS port: macOS ### Changed - Naming: 'operating system' and 'platform' are used somewhat interchangably by diff --git a/README.md b/README.md index 2159d3d43..3e789e1cb 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ The lwpa library serves two main purposes: lwpa is currently ported for the following platforms: + Linux ++ macOS + Microsoft Windows + MQX RTOS diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d70c53437..b3bdbd267 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -31,6 +31,21 @@ jobs: - script: build\tests\%LWPA_BUILD_CONFIG%\test_lwpa.exe displayName: 'lwpa Windows test' +- job: macos_build + displayName: 'macOS Build and Test' + pool: + vmImage: 'macos-10.14' + steps: + - script: | + mkdir build + cd build + cmake --version + cmake -DLWPA_BUILD_MOCK_LIB=ON .. + cmake --build . + displayName: 'lwpa macOS build' + - script: build/tests/test_lwpa + displayName: 'lwpa macOS test' + - job: linux_build displayName: 'Linux Build and Test' pool: diff --git a/docs/mainpage.md b/docs/mainpage.md index cd828e35a..feb482702 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -41,6 +41,7 @@ identical interface, as documented in that module's documentation. lwpa is currently ported for the following operating systems: ++ macOS + Microsoft Windows + Linux + MQX RTOS @@ -96,6 +97,9 @@ platform. This is currently the only option for MQX RTOS. ### Platform Dependencies The platform ports of lwpa have the following dependencies: ++ macOS + - If compiling with macOS 10.7 or earlier, you might need to install a UUID + package like `ossp-uuid`. + Microsoft Windows - Windows XP SP1 or later + MQX RTOS diff --git a/src/lwpa/lock.dox b/src/lwpa/lock.dox index 7018b354a..756554c5b 100644 --- a/src/lwpa/lock.dox +++ b/src/lwpa/lock.dox @@ -24,6 +24,7 @@ macros, etc.), so the documentation needs somewhere to pull a standard interface * |---------------|------------------| * | FreeRTOS/lwIP | [Mutexes](https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html) | * | Linux | [pthread_mutex](https://linux.die.net/man/3/pthread_mutex_init) | + * | macOS | [pthread_mutex](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/pthread_mutex_init.3.html) * | MQX | Lightweight Semaphores | * | Windows | [Critical Section objects](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx) | * @@ -88,6 +89,7 @@ void lwpa_mutex_destroy(lwpa_mutex_t *id); * |---------------|------------------| * | FreeRTOS/lwIP | [Binary Semaphores](https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html) | * | Linux | [pthread_cond](https://linux.die.net/man/3/pthread_cond_init) | + * | macOS | [pthread_cond](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/pthread_cond_init.3.html) * | MQX | Lightweight Events | * | Windows | [Event objects](https://docs.microsoft.com/en-us/windows/desktop/sync/using-event-objects) | * diff --git a/src/os/macos/lwpa/os_uuid.c b/src/os/macos/lwpa/os_uuid.c index dbd03ce8d..ed6c33c2c 100644 --- a/src/os/macos/lwpa/os_uuid.c +++ b/src/os/macos/lwpa/os_uuid.c @@ -21,8 +21,8 @@ #include -// Use libuuid on Linux to generate UUIDs. -// https://linux.die.net/man/3/uuid_generate +// Use the native UUID functionality in the macOS SDK to generate UUIDs. +// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/uuid.3.html lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) { From e9ae59865ab536d0c68d0dd6f62faf38b093fa20 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 11:20:01 -0500 Subject: [PATCH 057/264] Clean up some tests and warnings --- tests/unit/test_log.cpp | 2 +- tests/unit/test_socket.cpp | 30 +++++++++++++++++------------- tests/unit/test_socket_poll.cpp | 26 +++++++++++++++----------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/tests/unit/test_log.cpp b/tests/unit/test_log.cpp index 4322e031d..64e6df783 100644 --- a/tests/unit/test_log.cpp +++ b/tests/unit/test_log.cpp @@ -151,7 +151,7 @@ TEST_F(LogTest, validate) // Test some normal params lparams.action = kLwpaLogCreateSyslog; lparams.log_fn = log_cb; - lparams.syslog_params = {0, 0, 0, 0}; + lparams.syslog_params = {0, {0}, {0}, {0}}; memcpy(lparams.syslog_params.app_name, special_char_array, sizeof special_char_array); lparams.log_mask = 0; lparams.time_fn = time_cb; diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 803b8eb47..e79943938 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -121,6 +121,8 @@ static void send_thread(SocketTest* fixture) } } +#define UNICAST_UDP_PORT_BASE 6000 + TEST_F(SocketTest, unicast_udp) { lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; @@ -150,17 +152,17 @@ TEST_F(SocketTest, unicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock3)); lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = 8888; + bind_addr.port = UNICAST_UDP_PORT_BASE; // Shouldn't be able to bind to a closed socket. ASSERT_NE(kLwpaErrOk, lwpa_bind(rcvsock3, &bind_addr)); - // Bind socket 1 to the wildcard address and port 8888. + // Bind socket 1 to the wildcard address and a specific port. ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); - // Bind socket 2 to the wildcard address and port 9999. - bind_addr.port = 9999; + // Bind socket 2 to the wildcard address and a different port. + bind_addr.port = UNICAST_UDP_PORT_BASE + 1; ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); LWPA_IP_SET_V4_ADDRESS(&send_addr_1.ip, 0x7f000001u); - send_addr_1.port = 8888; + send_addr_1.port = UNICAST_UDP_PORT_BASE; std::thread send_thr(send_thread, this); ASSERT_TRUE(send_thr.joinable()); @@ -183,7 +185,7 @@ TEST_F(SocketTest, unicast_udp) } EXPECT_TRUE(lwpa_ip_equal(&send_addr_1.ip, &from_addr.ip)); - EXPECT_NE(from_addr.port, 8888); + EXPECT_NE(from_addr.port, UNICAST_UDP_PORT_BASE); buf[SEND_MSG_LEN] = '\0'; EXPECT_EQ(0, strcmp((char*)buf, SEND_MSG)); @@ -205,6 +207,8 @@ TEST_F(SocketTest, unicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_close(send_sock)); } +#define MULTICAST_UDP_PORT_BASE 7000 + TEST_F(SocketTest, multicast_udp) { lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; @@ -214,7 +218,7 @@ TEST_F(SocketTest, multicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); ASSERT_NE(rcvsock1, LWPA_SOCKET_INVALID); - int intval = 10; + int intval = 500; ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); intval = 1; ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); @@ -230,13 +234,13 @@ TEST_F(SocketTest, multicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); - // Bind socket 1 to the wildcard address and port 8888. + // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = 8888; + bind_addr.port = MULTICAST_UDP_PORT_BASE; ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); - // Bind socket 2 to the wildcard address and port 9999. - bind_addr.port = 9999; + // Bind socket 2 to the wildcard address and a different port. + bind_addr.port = MULTICAST_UDP_PORT_BASE + 1; ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); // Subscribe socket 1 to the multicast address. @@ -249,7 +253,7 @@ TEST_F(SocketTest, multicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); LWPA_IP_SET_V4_ADDRESS(&send_addr_1.ip, TEST_MCAST_ADDR); - send_addr_1.port = 8888; + send_addr_1.port = MULTICAST_UDP_PORT_BASE; // Start the send thread. std::thread send_thr(send_thread, this); @@ -272,7 +276,7 @@ TEST_F(SocketTest, multicast_udp) break; } - EXPECT_NE(from_addr.port, 8888); + EXPECT_NE(from_addr.port, MULTICAST_UDP_PORT_BASE); buf[SEND_MSG_LEN] = '\0'; EXPECT_EQ(0, strcmp((char*)buf, SEND_MSG)); diff --git a/tests/unit/test_socket_poll.cpp b/tests/unit/test_socket_poll.cpp index da63156d6..0383d0197 100644 --- a/tests/unit/test_socket_poll.cpp +++ b/tests/unit/test_socket_poll.cpp @@ -130,6 +130,8 @@ TEST_F(SocketPollTest, user_data) ASSERT_EQ(kLwpaErrOk, lwpa_close(sock_2)); } +#define POLL_MODIFY_TEST_PORT_BASE 8000 + // Test the lwpa_poll_modify_socket() functionality, using UDP sockets for simplicity TEST_F(SocketPollTest, modify) { @@ -138,10 +140,10 @@ TEST_F(SocketPollTest, modify) ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock)); ASSERT_NE(sock, LWPA_SOCKET_INVALID); - // Bind the socket to the wildcard address and port 8888. + // Bind the socket to the wildcard address and a specific port. LwpaSockaddr bind_addr; lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = 8888; + bind_addr.port = POLL_MODIFY_TEST_PORT_BASE; ASSERT_EQ(kLwpaErrOk, lwpa_bind(sock, &bind_addr)); // Add it for output polling first @@ -163,7 +165,7 @@ TEST_F(SocketPollTest, modify) // Send data to socket LwpaSockaddr send_addr; send_addr.ip = default_netint_.addr; - send_addr.port = 8888; + send_addr.port = POLL_MODIFY_TEST_PORT_BASE; lwpa_sendto(sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); // Should get the poll in event @@ -234,6 +236,8 @@ TEST_F(SocketPollTest, bulk_poll) } } +#define POLL_UDP_IN_TEST_PORT_BASE 9000 + // Test the lwpa_poll_* API, polling for readability on UDP sockets. TEST_F(SocketPollTest, udp_in) { @@ -250,14 +254,14 @@ TEST_F(SocketPollTest, udp_in) ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); ASSERT_NE(send_sock, LWPA_SOCKET_INVALID); - // Bind socket 1 to the wildcard address and port 8888. + // Bind socket 1 to the wildcard address and a specific port. LwpaSockaddr bind_addr; lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = 8888; + bind_addr.port = POLL_UDP_IN_TEST_PORT_BASE; ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); - // Bind socket 2 to the wildcard address and port 9999. - bind_addr.port = 9999; + // Bind socket 2 to the wildcard address and a different port. + bind_addr.port = POLL_UDP_IN_TEST_PORT_BASE + 1; ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); // Get the poll context set up @@ -270,10 +274,10 @@ TEST_F(SocketPollTest, udp_in) LwpaSockaddr send_addr; send_addr.ip = default_netint_.addr; - send_addr.port = 8888; + send_addr.port = POLL_UDP_IN_TEST_PORT_BASE; lwpa_sendto(send_sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); - send_addr.port = 9999; + send_addr.port = POLL_UDP_IN_TEST_PORT_BASE + 1; lwpa_sendto(send_sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); // Poll once, make sure we get one of the sockets. @@ -287,8 +291,8 @@ TEST_F(SocketPollTest, udp_in) LwpaSockaddr from_addr; ASSERT_EQ(SEND_MSG_LEN, (size_t)lwpa_recvfrom(event.socket, recv_buf.data(), SEND_MSG_LEN, 0, &from_addr)); ASSERT_TRUE(lwpa_ip_equal(&send_addr.ip, &from_addr.ip)); - ASSERT_NE(from_addr.port, 8888); - ASSERT_NE(from_addr.port, 9999); + ASSERT_NE(from_addr.port, POLL_UDP_IN_TEST_PORT_BASE); + ASSERT_NE(from_addr.port, POLL_UDP_IN_TEST_PORT_BASE + 1); recv_buf[SEND_MSG_LEN] = '\0'; ASSERT_EQ(0, strcmp((char*)recv_buf.data(), SEND_MSG)); From ac9dba034ffb0c184b418a7c7fa6f60751bbe600 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 11:31:00 -0500 Subject: [PATCH 058/264] Two changes: - Make SocketTest.multicast_udp more reliable by setting the MULTICAST_IF on the send socket - Fix bug in MULTICAST_IF sockopt implementation on macOS and Linux --- src/os/linux/lwpa/os_socket.c | 2 +- src/os/macos/lwpa/os_socket.c | 2 +- tests/unit/test_socket.cpp | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index bdbd4150b..cb9abacc3 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -450,7 +450,7 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s if (LWPA_IP_IS_V4(netint)) { struct in_addr val; - val.s_addr = LWPA_IP_V4_ADDRESS(netint); + val.s_addr = htonl(LWPA_IP_V4_ADDRESS(netint)); return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); } } diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index ed80a0891..e1bf8b3d5 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -468,7 +468,7 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s if (LWPA_IP_IS_V4(netint)) { struct in_addr val; - val.s_addr = LWPA_IP_V4_ADDRESS(netint); + val.s_addr = htonl(LWPA_IP_V4_ADDRESS(netint)); return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); } } diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index e79943938..23fb2a3ef 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -233,6 +233,8 @@ TEST_F(SocketTest, multicast_udp) ASSERT_NE(send_sock, LWPA_SOCKET_INVALID); ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); + ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &default_netint_.addr, + sizeof default_netint_.addr)); // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); From 368142ace8dd31592285efd6afbd3080776570e7 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 13:20:05 -0500 Subject: [PATCH 059/264] Some fixes for older versions of macOS --- src/os/macos/lwpa/os_netint.c | 10 ++++++++-- src/os/macos/lwpa/os_socket.c | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c index 3c71784cf..a7e99c631 100644 --- a/src/os/macos/lwpa/os_netint.c +++ b/src/os/macos/lwpa/os_netint.c @@ -484,6 +484,12 @@ static void gateway_from_route_entry(const struct sockaddr* os_gw, LwpaIpAddr* l } } +#ifdef RTF_LLDATA +#define RTF_LINK_FLAG RTF_LLDATA +#else +#define RTF_LINK_FLAG RTF_LLINFO +#endif + /* Anyone debugging this code might benefit from this: a mapping of netstat -r flags to * rmsg->rtm_flags values. * @@ -538,9 +544,9 @@ lwpa_error_t parse_routing_table_dump(int family, uint8_t* buf, size_t buf_len, // Filter out entries: // - from the local routing table (RTF_LOCAL) // - Representing broadcast routes (RTF_BROADCAST) - // - Representing ARP routes (RTF_LLDATA) + // - Representing ARP routes (RTF_LLDATA or RTF_LLINFO on older versions) // - Cloned routes (RTF_WASCLONED) - if (!(rmsg->rtm_flags & (RTF_LLDATA | RTF_LOCAL | RTF_BROADCAST | RTF_WASCLONED))) + if (!(rmsg->rtm_flags & (RTF_LINK_FLAG | RTF_LOCAL | RTF_BROADCAST | RTF_WASCLONED))) { struct sockaddr* addr_start = (struct sockaddr*)(rmsg + 1); struct sockaddr* rti_info[RTAX_MAX]; diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index e1bf8b3d5..0ad6d3d05 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -799,6 +799,9 @@ int events_lwpa_to_kqueue(lwpa_socket_t socket, lwpa_poll_events_t prev_events, ++num_events; } + // EVFILT_EXCEPT is not available on older versions of macOS. It was added somewhere between + // 10.11 and 10.14. +#ifdef EVFILT_EXCEPT // Process EVFILT_EXCEPT changes if (new_events & LWPA_POLL_OOB) { @@ -811,6 +814,7 @@ int events_lwpa_to_kqueue(lwpa_socket_t socket, lwpa_poll_events_t prev_events, EV_SET(&kevents[num_events], socket, EVFILT_EXCEPT, EV_DELETE, 0, 0, user_data); ++num_events; } +#endif return num_events; } @@ -823,6 +827,8 @@ lwpa_poll_events_t events_kqueue_to_lwpa(const struct kevent* kevent, const Lwpa events_out |= LWPA_POLL_IN; if (kevent->flags & EV_EOF) events_out |= LWPA_POLL_ERR; + if (kevent->flags & EV_OOBAND && (sock_desc->events & LWPA_POLL_OOB)) + events_out |= LWPA_POLL_OOB; } if (kevent->filter == EVFILT_WRITE) { @@ -833,12 +839,14 @@ lwpa_poll_events_t events_kqueue_to_lwpa(const struct kevent* kevent, const Lwpa if (kevent->flags & EV_EOF) events_out |= LWPA_POLL_ERR; } +#ifdef EVFILT_EXCEPT if (kevent->filter == EVFILT_EXCEPT) { events_out |= LWPA_POLL_OOB; if (kevent->flags & EV_EOF) events_out |= LWPA_POLL_ERR; } +#endif return events_out; } From 7dc976eef6442383f15e64427182dd7335cc00e7 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 13:36:46 -0500 Subject: [PATCH 060/264] Add some test code to debug CI --- azure-pipelines.yml | 6 ++++-- tests/unit/test_socket.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b3bdbd267..84b673cc6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -40,10 +40,12 @@ jobs: mkdir build cd build cmake --version - cmake -DLWPA_BUILD_MOCK_LIB=ON .. + cmake -DLWPA_BUILD_MOCK_LIB=ON -DLWPA_NETINT_DEBUG_OUTPUT=ON .. cmake --build . displayName: 'lwpa macOS build' - - script: build/tests/test_lwpa + - script: | + build/examples/netint/netint_example + build/tests/test_lwpa displayName: 'lwpa macOS test' - job: linux_build diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 23fb2a3ef..016010dbb 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -138,7 +138,7 @@ TEST_F(SocketTest, unicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); ASSERT_NE(rcvsock2, LWPA_SOCKET_INVALID); - int intval = 10; + int intval = 500; ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); intval = 1; ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); From 0d361a96f28e767638f28fc55fa6a482ec4b8f67 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 13:47:43 -0500 Subject: [PATCH 061/264] More CI testing --- azure-pipelines.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 84b673cc6..2d5a45c90 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -40,10 +40,11 @@ jobs: mkdir build cd build cmake --version - cmake -DLWPA_BUILD_MOCK_LIB=ON -DLWPA_NETINT_DEBUG_OUTPUT=ON .. + cmake -DLWPA_BUILD_MOCK_LIB=ON .. cmake --build . displayName: 'lwpa macOS build' - script: | + ifconfig build/examples/netint/netint_example build/tests/test_lwpa displayName: 'lwpa macOS test' From e590098085af8492b9d82d7f8a143568b91d763b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 14:08:33 -0500 Subject: [PATCH 062/264] More CI debugging --- tests/unit/test_socket.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 016010dbb..d912cb968 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -235,6 +235,8 @@ TEST_F(SocketTest, multicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &default_netint_.addr, sizeof default_netint_.addr)); + intval = 2; + ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_TTL, &intval, sizeof(int))); // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); From ea603804ea8d02119941a74deebfa35030e6f76e Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 14:13:41 -0500 Subject: [PATCH 063/264] Yet more CI debugging --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2d5a45c90..f598f274a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -45,6 +45,7 @@ jobs: displayName: 'lwpa macOS build' - script: | ifconfig + netstat -rnlll build/examples/netint/netint_example build/tests/test_lwpa displayName: 'lwpa macOS test' From 839a46cba4e9f0afa066c07c5051df83f307b38a Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 14:36:59 -0500 Subject: [PATCH 064/264] Revert debug changes and disable failing tests for now --- azure-pipelines.yml | 5 +---- tests/unit/test_socket.cpp | 2 -- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f598f274a..3a93c3c2c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -44,10 +44,7 @@ jobs: cmake --build . displayName: 'lwpa macOS build' - script: | - ifconfig - netstat -rnlll - build/examples/netint/netint_example - build/tests/test_lwpa + build/tests/test_lwpa --gtest_filter=-SocketTest.multicast_udp:SocketPollTest.udp_in displayName: 'lwpa macOS test' - job: linux_build diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index d912cb968..016010dbb 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -235,8 +235,6 @@ TEST_F(SocketTest, multicast_udp) ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &default_netint_.addr, sizeof default_netint_.addr)); - intval = 2; - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_TTL, &intval, sizeof(int))); // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); From 40a1099b05ec7d695528e4351345381e32fa946e Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 17:14:27 -0500 Subject: [PATCH 065/264] Implement changes from code review --- include/lwpa/inet.h | 2 +- src/lwpa/common.c | 35 ++++++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index e818776b8..56a5e06ac 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -132,7 +132,7 @@ typedef struct LwpaIpAddr /*! Set an IPv6 address with an explicit scope ID in a LwpaIpAddr. Also sets the type field to * indicate that this LwpaIpAddr contains an IPv6 address. * \param lwpa_ip_ptr Pointer to a LwpaIpAddr. - * \param addr_val IPv6 address to set (uint8_t[]). Must be at least of length LWPA_IPV6_BYTES. + * \param addr_val IPv6 address to set (uint8_t[]). Must be at least of length #LWPA_IPV6_BYTES. * Gets copied into the struct. * \param scope_id_val IPv6 scope ID to set. */ #define LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(lwpa_ip_ptr, addr_val, scope_id_val) \ diff --git a/src/lwpa/common.c b/src/lwpa/common.c index 74c321f25..f96d805a2 100644 --- a/src/lwpa/common.c +++ b/src/lwpa/common.c @@ -26,6 +26,8 @@ #include "lwpa/private/socket.h" #include "lwpa/private/timer.h" +/****************************** Private types ********************************/ + typedef struct LwpaModuleInit { bool initted; @@ -33,23 +35,39 @@ typedef struct LwpaModuleInit void (*deinit_fn)(); } LwpaModuleInit; +/* clang-format off */ + #define LWPA_MODULE_INIT(module_name) { false, module_name##_init, module_name##_deinit } -#define LWPA_MODULE_INIT_ARRAY \ - { \ +#define LWPA_MODULE_INIT_ARRAY \ + { \ LWPA_MODULE_INIT(lwpa_socket), \ LWPA_MODULE_INIT(lwpa_netint), \ - LWPA_MODULE_INIT(lwpa_timer), \ - LWPA_MODULE_INIT(lwpa_log) \ + LWPA_MODULE_INIT(lwpa_timer), \ + LWPA_MODULE_INIT(lwpa_log) \ } +/* clang-format on */ + +/*************************** Function definitions ****************************/ + lwpa_error_t lwpa_init(lwpa_features_t features) { + // In this function and the deinit() function below, we create an array of structs for each lwpa + // module that must be initialized, using the macros defined in lwpa/common.h and above in this + // file. The structs contain the init and deinit functions for each module that is enabled by the + // feature macros. + // + // If any init fails, each struct contains a flag indicating whether it has already been + // initialized, so it can be cleaned up. + LwpaModuleInit init_array[LWPA_NUM_FEATURES] = LWPA_MODULE_INIT_ARRAY; lwpa_error_t init_res = kLwpaErrOk; lwpa_features_t feature_mask = 1u; - for (LwpaModuleInit *init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) + + // Initialize each module in turn. + for (LwpaModuleInit* init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) { if (features & feature_mask) { @@ -64,7 +82,8 @@ lwpa_error_t lwpa_init(lwpa_features_t features) if (init_res != kLwpaErrOk) { - for (LwpaModuleInit *init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) + // Clean up on failure. + for (LwpaModuleInit* init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) { if (init_struct->initted) init_struct->deinit_fn(); @@ -79,7 +98,9 @@ void lwpa_deinit(lwpa_features_t features) LwpaModuleInit init_array[LWPA_NUM_FEATURES] = LWPA_MODULE_INIT_ARRAY; lwpa_features_t feature_mask = 1u; - for (LwpaModuleInit *init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) + + // Deinitialize each module in turn. + for (LwpaModuleInit* init_struct = init_array; init_struct < init_array + LWPA_NUM_FEATURES; ++init_struct) { if (features & feature_mask) { From 3fb526b807ac9976efe4c61d3d3778ce0b513244 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 18 Jun 2019 17:47:41 -0500 Subject: [PATCH 066/264] Begin work on getting MQX building again --- .gitignore | 2 +- include/os/mqx/lwpa/os_inet.h | 29 +++++ include/os/mqx/lwpa/os_lock.h | 12 +- src/os/mqx/lwpa/os_inet.c | 123 ++++++++++++++++++ src/os/mqx/lwpa/os_socket.c | 99 -------------- .../codewarrior-kinetis-mqx.cmake | 24 +++- .../cross-toolchains/iar-kinetis-mqx.cmake | 24 +++- 7 files changed, 201 insertions(+), 112 deletions(-) create mode 100644 include/os/mqx/lwpa/os_inet.h create mode 100644 src/os/mqx/lwpa/os_inet.c diff --git a/.gitignore b/.gitignore index 1e71357b0..c4840b700 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ lib/ ####################### # CMake -build/ +build*/ # MSVC2015 and Qt *.VC.db diff --git a/include/os/mqx/lwpa/os_inet.h b/include/os/mqx/lwpa/os_inet.h new file mode 100644 index 000000000..3dfcc94a9 --- /dev/null +++ b/include/os/mqx/lwpa/os_inet.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_INET_H_ +#define _LWPA_OS_INET_H_ + +#include + +typedef struct sockaddr lwpa_os_sockaddr_t; +typedef struct sockaddr lwpa_os_ipaddr_t; + +#endif /* _LWPA_OS_INET_H_ */ + diff --git a/include/os/mqx/lwpa/os_lock.h b/include/os/mqx/lwpa/os_lock.h index a3626343e..1dce991a2 100644 --- a/include/os/mqx/lwpa/os_lock.h +++ b/include/os/mqx/lwpa/os_lock.h @@ -32,14 +32,16 @@ extern "C" { typedef LWSEM_STRUCT lwpa_mutex_t; bool lwpa_mutex_create(lwpa_mutex_t* id); -bool lwpa_mutex_take(lwpa_mutex_t* id, int wait_ms); +bool lwpa_mutex_take(lwpa_mutex_t* id); +bool lwpa_mutex_try_take(lwpa_mutex_t* id); #define lwpa_mutex_give(idptr) ((void)_lwsem_post((LWSEM_STRUCT_PTR)(idptr))) #define lwpa_mutex_destroy(idptr) ((void)_lwsem_destroy((LWSEM_STRUCT_PTR)(idptr))) typedef LWEVENT_STRUCT lwpa_signal_t; bool lwpa_signal_create(lwpa_signal_t* id); -bool lwpa_signal_wait(lwpa_signal_t* id, int wait_ms); +bool lwpa_signal_wait(lwpa_signal_t* id); +bool lwpa_signal_poll(lwpa_signal_t* id); #define lwpa_signal_post(idptr) ((void)_lwevent_set((LWEVENT_STRUCT_PTR)(idptr), 1u)) #define lwpa_signal_destroy(idptr) ((void)_lwevent_destroy((LWEVENT_STRUCT_PTR)(idptr))) @@ -50,9 +52,11 @@ typedef struct } lwpa_rwlock_t; bool lwpa_rwlock_create(lwpa_rwlock_t* id); -bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms); +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id); void lwpa_rwlock_readunlock(lwpa_rwlock_t* id); -bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms); +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id); void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); #define lwpa_rwlock_destroy(idptr) ((void)_lwsem_destroy(&((idptr)->sem))) diff --git a/src/os/mqx/lwpa/os_inet.c b/src/os/mqx/lwpa/os_inet.c new file mode 100644 index 000000000..1eb4ae5c2 --- /dev/null +++ b/src/os/mqx/lwpa/os_inet.c @@ -0,0 +1,123 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/inet.h" + +#include +#include + +bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) +{ + if (pfsa->sa_family == AF_INET) + { + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; + sa->port = sin->sin_port; + LWPA_IP_SET_V4_ADDRESS(&sa->ip, sin->sin_addr.s_addr); + return true; + } + else if (pfsa->sa_family == AF_INET6) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; + sa->port = sin6->sin6_port; + LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); + return true; + } + return false; +} + +size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) +{ + size_t ret = 0; + if (LWPA_IP_IS_V4(&sa->ip)) + { + struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; + sin->sin_family = AF_INET; + sin->sin_port = sa->port; + sin->sin_addr.s_addr = LWPA_IP_V4_ADDRESS(&sa->ip); + ret = sizeof(struct sockaddr_in); + } + else if (LWPA_IP_IS_V6(&sa->ip)) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = sa->port; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), IPV6_BYTES); + ret = sizeof(struct sockaddr_in6); + } + return ret; +} + +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (src->type) + { + case LWPA_IPV4: + { + struct in_addr addr; + /* RTCS expects host byte order in their in_addrs. Thus no htonl is needed. */ + addr.s_addr = LWPA_IP_V4_ADDRESS(src); + if (NULL != inet_ntop(AF_INET, &addr, dest, size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + case LWPA_IPV6: + { + struct in6_addr addr; + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), IPV6_BYTES); + if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) + return kLwpaErrOk; + return kLwpaErrSys; + } + default: + return kLwpaErrInvalid; + } +} + +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (type) + { + case LWPA_IPV4: + { + struct in_addr addr; + if (RTCS_OK != inet_pton(AF_INET, src, &addr, sizeof addr)) + return kLwpaErrSys; + /* RTCS gives us host byte order in their in_addrs. Thus no htonl is needed. */ + LWPA_IP_SET_V4_ADDRESS(dest, addr.s_addr); + return kLwpaErrOk; + } + case LWPA_IPV6: + { + struct in6_addr addr; + if (RTCS_OK != inet_pton(AF_INET6, src, &addr, sizeof addr)) + return kLwpaErrSys; + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); + return kLwpaErrOk; + } + default: + return kLwpaErrInvalid; + } +} + diff --git a/src/os/mqx/lwpa/os_socket.c b/src/os/mqx/lwpa/os_socket.c index 0353519d0..75fc9a4a7 100644 --- a/src/os/mqx/lwpa/os_socket.c +++ b/src/os/mqx/lwpa/os_socket.c @@ -82,47 +82,6 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /* clang-format on */ -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) -{ - if (pfsa->sa_family == AF_INET) - { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sa->port = sin->sin_port; - LWPA_IP_SET_V4_ADDRESS(&sa->ip, sin->sin_addr.s_addr); - return true; - } - else if (pfsa->sa_family == AF_INET6) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sa->port = sin6->sin6_port; - LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); - return true; - } - return false; -} - -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) -{ - size_t ret = 0; - if (LWPA_IP_IS_V4(&sa->ip)) - { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sin->sin_family = AF_INET; - sin->sin_port = sa->port; - sin->sin_addr.s_addr = LWPA_IP_V4_ADDRESS(&sa->ip); - ret = sizeof(struct sockaddr_in); - } - else if (LWPA_IP_IS_V6(&sa->ip)) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sin6->sin6_family = AF_INET6; - sin6->sin6_port = sa->port; - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), IPV6_BYTES); - ret = sizeof(struct sockaddr_in6); - } - return ret; -} - static lwpa_error_t err_os_to_lwpa(uint32_t rtcserr) { switch (rtcserr) @@ -650,61 +609,3 @@ void lwpa_freeaddrinfo(LwpaAddrinfo* ai) if (ai) freeaddrinfo((struct addrinfo*)ai->pd[0]); } - -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (src->type) - { - case LWPA_IPV4: - { - struct in_addr addr; - /* RTCS expects host byte order in their in_addrs. Thus no htonl is needed. */ - addr.s_addr = LWPA_IP_V4_ADDRESS(src); - if (NULL != inet_ntop(AF_INET, &addr, dest, size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - case LWPA_IPV6: - { - struct in6_addr addr; - memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), IPV6_BYTES); - if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - default: - return kLwpaErrInvalid; - } -} - -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (type) - { - case LWPA_IPV4: - { - struct in_addr addr; - if (RTCS_OK != inet_pton(AF_INET, src, &addr, sizeof addr)) - return kLwpaErrSys; - /* RTCS gives us host byte order in their in_addrs. Thus no htonl is needed. */ - LWPA_IP_SET_V4_ADDRESS(dest, addr.s_addr); - return kLwpaErrOk; - } - case LWPA_IPV6: - { - struct in6_addr addr; - if (RTCS_OK != inet_pton(AF_INET6, src, &addr, sizeof addr)) - return kLwpaErrSys; - LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); - return kLwpaErrOk; - } - default: - return kLwpaErrInvalid; - } -} diff --git a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake index f6db5d15f..f12c5387e 100644 --- a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake +++ b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake @@ -1,14 +1,21 @@ # A CMake toolchain file for cross-compiling for NXP Kinetis (ARM Cortex-M4) with MQX RTOS and the # CodeWarrior 10.6 gcc toolchain. # -# Usage: cmake -DCMAKE_TOOLCHAIN_FILE=../tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake \ +# On Windows, you need to use a non-Visual-Studio generator. This requires you to have some kind of +# non-VS build system installed. Some options are: +# - MinGW64 (must be available on PATH) +# - Strawberry Perl (use 'Unix Makefiles' generator) +# - NMake (comes with VS, but must be in a developer command prompt) +# +# Usage: cmake -G "Unix Makefiles" \ +# -DCMAKE_TOOLCHAIN_FILE=../tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake \ # -DMQX_BOARD_DIR=path/to/mqx/board/dir .. # # MQX_BOARD_DIR can also be set in this file so that it does not have to be provided at the command # line, like so: -# set(MQX_BOARD_DIR path/to/mqx/board/dir) +# set(MQX_BOARD_DIR ${CMAKE_CURRENT_LIST_DIR}/path/to/mqx/board/dir) -set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_NAME Generic) # This is CMake's name for 'bare-metal' or RTOS environments set(CMAKE_SYSTEM_PROCESSOR ARM) if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) @@ -16,7 +23,9 @@ if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) endif() if(NOT DEFINED CODEWARRIOR_INSTALL_DIR) - set(CODEWARRIOR_INSTALL_DIR "C:/Freescale/CW MCU v10.6") # The default install location on Windows. + # The default install location on Windows. + # You may need to tweak the CodeWarrior version. + set(CODEWARRIOR_INSTALL_DIR "C:/Freescale/CW MCU v10.6") endif() set(TOOLS_DIR ${CODEWARRIOR_INSTALL_DIR}/Cross_Tools/arm-none-eabi-gcc-4_7_3) @@ -40,4 +49,11 @@ include_directories( ${CODEWARRIOR_INSTALL_DIR}/MCU/ARM_GCC_Support/ewl/EWL_Runtime/include ) +# This tells CMake to use a static library program to do its minimal compiler +# test instead of an executable - this translates well to embedded toolchains. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# If that doesn't work, you might need to comment the line above and uncomment +# this line to bypass the compiler checks. +# set(CMAKE_C_COMPILER_WORKS 1) +# set(CMAKE_CXX_COMPILER_WORKS 1) diff --git a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake index 01fdcc279..e971df017 100644 --- a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake +++ b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake @@ -1,14 +1,21 @@ # A CMake toolchain file for cross-compiling for NXP Kinetis (ARM Cortex-M4) with MQX RTOS and the # IAR Embedded Workbench toolchain. # -# Usage: cmake -DCMAKE_TOOLCHAIN_FILE=../tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake \ +# On Windows, you need to use a non-Visual-Studio generator. This requires you to have some kind of +# non-VS build system installed. Some options are: +# - MinGW64 (must be available on PATH) +# - Strawberry Perl (use 'Unix Makefiles' generator) +# - NMake (comes with VS, but must be in a developer command prompt) +# +# Usage: cmake -G "Unix Makefiles" \ +# -DCMAKE_TOOLCHAIN_FILE=../tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake \ # -DMQX_BOARD_DIR=path/to/mqx/board/dir .. # # MQX_BOARD_DIR can also be set in this file so that it does not have to be provided at the command # line, like so: -# set(MQX_BOARD_DIR path/to/mqx/board/dir) +# set(MQX_BOARD_DIR ${CMAKE_CURRENT_LIST_DIR}/path/to/mqx/board/dir) -set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_NAME Generic) # This is CMake's name for 'bare-metal' or RTOS environments set(CMAKE_SYSTEM_PROCESSOR ARM) if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) @@ -16,7 +23,9 @@ if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) endif() if(NOT DEFINED IAR_INSTALL_DIR) - set(IAR_INSTALL_DIR "C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.5") # The default install location on Windows. + # The default install location on Windows. + # You may need to tweak the IAR version. + set(IAR_INSTALL_DIR "C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.5") endif() set(CMAKE_C_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe) @@ -30,4 +39,11 @@ add_compile_options( --dlib_config normal ) +# This tells CMake to use a static library program to do its minimal compiler +# test instead of an executable - this translates well to embedded toolchains. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# If that doesn't work, you might need to comment the line above and uncomment +# this line to bypass the compiler checks. +# set(CMAKE_C_COMPILER_WORKS 1) +# set(CMAKE_CXX_COMPILER_WORKS 1) From c335a3a457cf408757986b80a12922799a7508b8 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 19 Jun 2019 14:37:36 -0500 Subject: [PATCH 067/264] Clean up some bugs and documentation --- docs/mainpage.md | 4 +- include/lwpa/common.h | 17 ++++--- src/lwpa/common.c | 22 +++++++++ src/lwpa/log.c | 46 +++++++++--------- src/lwpa/netint.c | 25 +++++----- tests/CMakeLists.txt | 1 + tests/unit/test_common.cpp | 99 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 170 insertions(+), 44 deletions(-) create mode 100644 tests/unit/test_common.cpp diff --git a/docs/mainpage.md b/docs/mainpage.md index feb482702..27971a427 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -92,12 +92,14 @@ To configure and build lwpa on its own using CMake, follow these steps: Alternatively, if you don't want to use CMake, your project can simply build in the lwpa sources directly using the appropriate directories for your target -platform. This is currently the only option for MQX RTOS. +platform. ### Platform Dependencies The platform ports of lwpa have the following dependencies: + macOS + - The macOS port has been tested back to macOS 10.11. It is not guaranteed to + work on older versions. - If compiling with macOS 10.7 or earlier, you might need to install a UUID package like `ossp-uuid`. + Microsoft Windows diff --git a/include/lwpa/common.h b/include/lwpa/common.h index 08c612249..0ad1ba7d4 100644 --- a/include/lwpa/common.h +++ b/include/lwpa/common.h @@ -32,8 +32,8 @@ * libraries by providing a set of modules to abstract common system calls. There are also a few * platform-neutral utilities (e.g. data structures, logging) thrown in here and there for * convenience. lwpa headers can be either platform-neutral (contained in include/) or - * platform-specific (contained in include/[platform]). All platform-specific headers of the same - * lwpa module will conform to an identical interface. + * platform-specific (contained in include/os/[platform]). All platform-specific headers of the + * same lwpa module will conform to an identical interface. * * @{ */ @@ -41,24 +41,28 @@ /*! For lwpa_ functions that take a millisecond timeout, this means to wait indefinitely. */ #define LWPA_WAIT_FOREVER -1 +/*! A mask of desired lwpa features. See "lwpa feature masks". */ typedef uint32_t lwpa_features_t; #define LWPA_FEATURE_SOCKETS_OFFSET 0 #define LWPA_FEATURE_NETINTS_OFFSET 1 -#define LWPA_FEATURE_TIMERS_OFFSET 2 +#define LWPA_FEATURE_TIMERS_OFFSET 2 #define LWPA_FEATURE_LOGGING_OFFSET 3 #define LWPA_NUM_FEATURES 4 /*! \name lwpa feature masks - * Pass one or more of these to lwpa_init() to initialize the relevant lwpa feature. + * Pass one or more of these to lwpa_init() to initialize the relevant lwpa feature. Multiple + * features can be requested using logical OR. + * * lwpa modules not represented here require no initialization and are enabled by default. + * * @{ */ #define LWPA_FEATURE_SOCKETS ((lwpa_features_t)(1u << LWPA_FEATURE_SOCKETS_OFFSET)) /*!< Use the lwpa_socket module. */ #define LWPA_FEATURE_NETINTS ((lwpa_features_t)(1u << LWPA_FEATURE_NETINTS_OFFSET)) /*!< Use the lwpa_netint module. */ -#define LWPA_FEATURE_TIMERS ((lwpa_features_t)(1u << LWPA_FEATURE_TIMERS_OFFSET)) /*!< Use the lwpa_timer module. */ +#define LWPA_FEATURE_TIMERS ((lwpa_features_t)(1u << LWPA_FEATURE_TIMERS_OFFSET)) /*!< Use the lwpa_timer module. */ #define LWPA_FEATURE_LOGGING ((lwpa_features_t)(1u << LWPA_FEATURE_LOGGING_OFFSET)) /*!< Use the lwpa_log module. */ -#define LWPA_FEATURES_ALL 0xffffffffu /*! Use every available module. */ +#define LWPA_FEATURES_ALL 0xffffffffu /*!< Use every available module. */ /*! \brief Use every available module except the ones passed in mask. * \param mask Mask of LWPA_FEATURE_* macros to not include in the feature mask. @@ -67,7 +71,6 @@ typedef uint32_t lwpa_features_t; #define LWPA_FEATURES_ALL_BUT(mask) (((uint32_t)LWPA_FEATURES_ALL) & ((uint32_t)(~((uint32_t)(mask))))) /*! @} */ - #ifdef __cplusplus extern "C" { #endif diff --git a/src/lwpa/common.c b/src/lwpa/common.c index f96d805a2..4adbc3370 100644 --- a/src/lwpa/common.c +++ b/src/lwpa/common.c @@ -51,6 +51,21 @@ typedef struct LwpaModuleInit /*************************** Function definitions ****************************/ +/*! \brief Initialize the lwpa library. + * + * This function can be called multiple times from the same application. Each call to lwpa_init() + * must be paired with a call to lwpa_deinit() with the same argument for features. + * + * If you are using a library that depends on lwpa, and not using lwpa directly, that library will + * call this function for you with the features it needs; you do not need to call it explicitly. + * + * lwpa_init() and lwpa_deinit() are not thread-safe; you should make sure your init-time and + * deinit-time code is serialized. + * + * \param[in] features Mask of lwpa features required. + * \return #kLwpaErrOk: lwpa library initialized successfully. + * \return Various error codes possible from initialization of feature modules. + */ lwpa_error_t lwpa_init(lwpa_features_t features) { // In this function and the deinit() function below, we create an array of structs for each lwpa @@ -93,6 +108,13 @@ lwpa_error_t lwpa_init(lwpa_features_t features) return init_res; } +/*! \brief Deinitialize the lwpa library. + * + * This must be called with the same argument as the corresponding call to lwpa_init() to clean up + * resources held by the feature modules. + * + * \param[in] features Feature mask that was previously passed to lwpa_init(). + */ void lwpa_deinit(lwpa_features_t features) { LwpaModuleInit init_array[LWPA_NUM_FEATURES] = LWPA_MODULE_INIT_ARRAY; diff --git a/src/lwpa/log.c b/src/lwpa/log.c index 82c887913..b67dde1a7 100644 --- a/src/lwpa/log.c +++ b/src/lwpa/log.c @@ -57,7 +57,7 @@ /**************************** Private variables ******************************/ -static bool module_initialized; +static unsigned int init_count; static lwpa_mutex_t buf_lock; /*********************** Private function prototypes *************************/ @@ -70,24 +70,23 @@ static void sanitize_str(char* str); * messages are written into. */ lwpa_error_t lwpa_log_init() { - if (!module_initialized) + if (init_count == 0) { if (!lwpa_mutex_create(&buf_lock)) { return kLwpaErrSys; } - module_initialized = true; } + ++init_count; return kLwpaErrOk; } /* Deinitialize the lwpa_log module. */ void lwpa_log_deinit() { - if (module_initialized) + if (--init_count == 0) { lwpa_mutex_destroy(&buf_lock); - module_initialized = false; } } @@ -347,7 +346,7 @@ void lwpa_log(const LwpaLogParams* params, int pri, const char* format, ...) */ void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list args) { - if (!module_initialized || !params || !params->log_fn || !format || !(LWPA_LOG_MASK(pri) & params->log_mask)) + if (!init_count || !params || !params->log_fn || !format || !(LWPA_LOG_MASK(pri) & params->log_mask)) return; LwpaLogTimeParams time_params; @@ -361,29 +360,28 @@ void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list char* humanlog_msg_ptr = NULL; char* raw_msg_ptr = NULL; - // If we are calling both vcreate functions, we will need to copy the va_list. - // For more info on using a va_list multiple times, see: - // https://wiki.sei.cmu.edu/confluence/display/c/MSC39-C.+Do+not+call+va_arg%28%29+on+a+va_list+that+has+an+indeterminate+value - // https://stackoverflow.com/a/26919307 - va_list args_copy; - bool args_copied = false; - if (params->action == kLwpaLogCreateBoth) - { - va_copy(args_copy, args); - args_copied = true; - } - if (params->action == kLwpaLogCreateBoth || params->action == kLwpaLogCreateSyslog) { - raw_msg_ptr = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, - ¶ms->syslog_params, pri, format, args_copied ? args_copy : args); - if (raw_msg_ptr) + // If we are calling both vcreate functions, we will need to copy the va_list. + // For more info on using a va_list multiple times, see: + // https://wiki.sei.cmu.edu/confluence/display/c/MSC39-C.+Do+not+call+va_arg%28%29+on+a+va_list+that+has+an+indeterminate+value + // https://stackoverflow.com/a/26919307 + if (params->action == kLwpaLogCreateBoth) { - syslog_msg_ptr = syslogmsg; + va_list args_copy; + va_copy(args_copy, args); + raw_msg_ptr = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, + ¶ms->syslog_params, pri, format, args_copy); + va_end(args_copy); } - if (args_copied) + else { - va_end(args_copy); + raw_msg_ptr = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, + ¶ms->syslog_params, pri, format, args); + } + if (raw_msg_ptr) + { + syslog_msg_ptr = syslogmsg; } } diff --git a/src/lwpa/netint.c b/src/lwpa/netint.c index 0aabcb4e4..e6d99d7df 100644 --- a/src/lwpa/netint.c +++ b/src/lwpa/netint.c @@ -24,9 +24,9 @@ /**************************** Private variables ******************************/ -bool module_initialized; -CachedNetintInfo netint_cache; -DefaultNetint default_netint; +static unsigned int init_count; +static CachedNetintInfo netint_cache; +static DefaultNetint default_netint; /*********************** Private function prototypes *************************/ @@ -37,7 +37,7 @@ static int compare_netints(const void* a, const void* b); lwpa_error_t lwpa_netint_init() { lwpa_error_t res = kLwpaErrOk; - if (!module_initialized) + if (init_count == 0) { res = os_enumerate_interfaces(&netint_cache); if (res == kLwpaErrOk) @@ -60,20 +60,21 @@ lwpa_error_t lwpa_netint_init() default_netint.v6_index = i; } } - - module_initialized = true; } } + + if (res == kLwpaErrOk) + ++init_count; + return res; } void lwpa_netint_deinit() { - if (module_initialized) + if (--init_count == 0) { os_free_interfaces(&netint_cache); memset(&netint_cache, 0, sizeof(netint_cache)); - module_initialized = false; } } @@ -82,7 +83,7 @@ void lwpa_netint_deinit() */ size_t lwpa_netint_get_num_interfaces() { - return (module_initialized ? netint_cache.num_netints : 0); + return (init_count ? netint_cache.num_netints : 0); } /*! \brief Enumerate the network interfaces on the system. @@ -94,7 +95,7 @@ size_t lwpa_netint_get_num_interfaces() */ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) { - if (!module_initialized || !netint_arr || netint_arr_size == 0) + if (!init_count || !netint_arr || netint_arr_size == 0) return 0; size_t addrs_copied = (netint_arr_size < netint_cache.num_netints ? netint_arr_size : netint_cache.num_netints); @@ -115,7 +116,7 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ */ bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) { - if (module_initialized && netint) + if (init_count && netint) { if (type == kLwpaIpTypeV4 && default_netint.v4_valid) { @@ -147,7 +148,7 @@ lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNeti { if (!dest || !netint) return kLwpaErrInvalid; - if (!module_initialized) + if (!init_count) return kLwpaErrNotInit; if (netint_cache.num_netints == 0) return kLwpaErrNoNetints; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bfab975ea..160e13846 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,7 @@ if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL macos OR LWPA_TARG add_executable(test_lwpa # lwpa unit test sources ${TEST_SRC_DIR}/main.cpp + ${TEST_SRC_DIR}/test_common.cpp ${TEST_SRC_DIR}/test_inet.cpp ${TEST_SRC_DIR}/test_log.cpp ${TEST_SRC_DIR}/test_mempool.cpp diff --git a/tests/unit/test_common.cpp b/tests/unit/test_common.cpp new file mode 100644 index 000000000..c4eb1c7e2 --- /dev/null +++ b/tests/unit/test_common.cpp @@ -0,0 +1,99 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/common.h" +#include "gmock/gmock.h" + +#include "lwpa/netint.h" +#include "lwpa/log.h" + +class CommonTest : public ::testing::Test +{ +public: + MOCK_METHOD0(LogCallback, void()); +}; + +// Test the LWPA_FEATURES_ALL_BUT() macro +TEST_F(CommonTest, features_all_but) +{ + lwpa_features_t mask = LWPA_FEATURES_ALL_BUT(LWPA_FEATURE_SOCKETS); + EXPECT_TRUE(mask & LWPA_FEATURE_NETINTS); + EXPECT_TRUE(mask & LWPA_FEATURE_TIMERS); + EXPECT_TRUE(mask & LWPA_FEATURE_LOGGING); + EXPECT_FALSE(mask & LWPA_FEATURE_SOCKETS); + + mask = LWPA_FEATURES_ALL_BUT(LWPA_FEATURE_LOGGING); + EXPECT_TRUE(mask & LWPA_FEATURE_SOCKETS); + EXPECT_TRUE(mask & LWPA_FEATURE_NETINTS); + EXPECT_TRUE(mask & LWPA_FEATURE_TIMERS); + EXPECT_FALSE(mask & LWPA_FEATURE_LOGGING); +} + +// Test multiple calls of lwpa_init() for the netint module. +TEST_F(CommonTest, netint_double_init) +{ + ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_NETINTS)); + ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_NETINTS)); + + lwpa_deinit(LWPA_FEATURE_NETINTS); + + // After 2 inits and one deinit, we should still be able to make valid calls to the module. + LwpaNetintInfo def_netint; + EXPECT_TRUE(lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_netint)); + + lwpa_deinit(LWPA_FEATURE_NETINTS); +} + +// A shim from the lwpa_log module to GoogleMock. +extern "C" void log_cb(void* context, const char* syslog_str, const char* human_str, const char* raw_str) +{ + (void)syslog_str; + (void)human_str; + (void)raw_str; + + CommonTest* test_fixture = static_cast(context); + test_fixture->LogCallback(); +} + +// Test multiple calls of lwpa_init() for the log module. +TEST_F(CommonTest, log_double_init) +{ + ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_LOGGING)); + ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_LOGGING)); + + LwpaLogParams params; + params.action = kLwpaLogCreateHumanReadableLog; + params.log_fn = log_cb; + params.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); + params.time_fn = nullptr; + params.context = this; + + ASSERT_TRUE(lwpa_validate_log_params(¶ms)); + + EXPECT_CALL(*this, LogCallback); + lwpa_log(¶ms, LWPA_LOG_INFO, "Log message"); + + lwpa_deinit(LWPA_FEATURE_LOGGING); + + // After 2 inits and one deinit, we should still be able to use the lwpa_log() function and get + // callbacks. + EXPECT_CALL(*this, LogCallback); + lwpa_log(¶ms, LWPA_LOG_INFO, "Log message"); + + lwpa_deinit(LWPA_FEATURE_LOGGING); +} From a945f803cfa5416c10b621ae049e8082e3346157 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 19 Jun 2019 14:42:57 -0500 Subject: [PATCH 068/264] More doc tweaks --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76402ffc1..51f9da076 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - OS port: Linux - OS port: macOS +- lwpa_init() in lwpa/common.h. lwpa_init() must be called before using features + defined by feature macros defined in lwpa/common.h. ### Changed - Naming: 'operating system' and 'platform' are used somewhat interchangably by From e526638ae8f4faca09d875030d64b39c7b7a0c3c Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 19 Jun 2019 14:56:48 -0500 Subject: [PATCH 069/264] Tweak lwpa_log callback interface to be a bit nicer --- CHANGELOG.md | 2 ++ include/lwpa/log.h | 25 ++++++++++++++++++++----- src/lwpa/log.c | 20 +++++++++----------- tests/unit/test_common.cpp | 6 ++---- tests/unit/test_log.cpp | 7 ++++--- 5 files changed, 37 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51f9da076..94cab0494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - lwpa_thread_stop() changed to lwpa_thread_join() to better describe behavior - LwpaNetintInfo: Removed 'gate' member, which has no consistent meaning across platforms. +- lwpa_log_callback interface tweak - combine the various log message pointers + into a struct LwpaLogStrings. ### Removed diff --git a/include/lwpa/log.h b/include/lwpa/log.h index 5c188d492..82eaec2b5 100644 --- a/include/lwpa/log.h +++ b/include/lwpa/log.h @@ -149,19 +149,34 @@ typedef struct LwpaLogTimeParams int utc_offset; } LwpaLogTimeParams; +/*! The set of log strings passed with a call to an lwpa_log_callback function. Any members not + * requested in the corresponding LwpaLogParams struct will be NULL. + */ +typedef struct LwpaLogStrings +{ + /*! Log string formatted compliant to RFC 5424. */ + const char* syslog; + /*! Log string formatted for readability per ETC convention. */ + const char* human_readable; + /*! The original log string that was passed to lwpa_log() or lwpa_vlog(). Will overlap with one of + * syslog_str or human_str. */ + const char* raw; +} LwpaLogStrings; + /*! \brief Log callback function. * * The function that library modules use to log messages. The application developer defines the * function and determines where the messages go. * + * Do not call lwpa_log() or lwpa_vlog() from this function; a deadlock will result. + * * \param[in] context Optional application-provided value that was previously passed to the library * module. - * \param[in] syslog_str Log string, formatted compliant to RFC 5424. - * \param[in] human_str Log string, formatted for readability per ETC convention. - * \param[in] raw_str The original log string that was passed to lwpa_log() or lwpa_vlog(). Will - * overlap with one of syslog_str or human_str. + * \param[in] strings Strings associated with the log message. Will contain valid strings + * corresponding to the log actions requested in the corresponding LwpaLogParams + * struct. */ -typedef void (*lwpa_log_callback)(void* context, const char* syslog_str, const char* human_str, const char* raw_str); +typedef void (*lwpa_log_callback)(void* context, const LwpaLogStrings* strings); /*! \brief Time callback function. * diff --git a/src/lwpa/log.c b/src/lwpa/log.c index b67dde1a7..60a1ab7f2 100644 --- a/src/lwpa/log.c +++ b/src/lwpa/log.c @@ -356,9 +356,7 @@ void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list { static char syslogmsg[LWPA_SYSLOG_STR_MAX_LEN + 1]; static char humanlogmsg[LWPA_HUMAN_LOG_STR_MAX_LEN + 1]; - char* syslog_msg_ptr = NULL; - char* humanlog_msg_ptr = NULL; - char* raw_msg_ptr = NULL; + LwpaLogStrings strings = {NULL, NULL, NULL}; if (params->action == kLwpaLogCreateBoth || params->action == kLwpaLogCreateSyslog) { @@ -370,32 +368,32 @@ void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list { va_list args_copy; va_copy(args_copy, args); - raw_msg_ptr = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, + strings.raw = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, ¶ms->syslog_params, pri, format, args_copy); va_end(args_copy); } else { - raw_msg_ptr = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, + strings.raw = lwpa_vcreate_syslog_str(syslogmsg, LWPA_SYSLOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, ¶ms->syslog_params, pri, format, args); } - if (raw_msg_ptr) + if (strings.raw) { - syslog_msg_ptr = syslogmsg; + strings.syslog = syslogmsg; } } if (params->action == kLwpaLogCreateBoth || params->action == kLwpaLogCreateHumanReadableLog) { - raw_msg_ptr = lwpa_vcreate_human_log_str(humanlogmsg, LWPA_HUMAN_LOG_STR_MAX_LEN + 1, + strings.raw = lwpa_vcreate_human_log_str(humanlogmsg, LWPA_HUMAN_LOG_STR_MAX_LEN + 1, have_time ? &time_params : NULL, format, args); - if (raw_msg_ptr) + if (strings.raw) { - humanlog_msg_ptr = humanlogmsg; + strings.human_readable = humanlogmsg; } } - params->log_fn(params->context, syslog_msg_ptr, humanlog_msg_ptr, raw_msg_ptr); + params->log_fn(params->context, &strings); lwpa_mutex_give(&buf_lock); } diff --git a/tests/unit/test_common.cpp b/tests/unit/test_common.cpp index c4eb1c7e2..977abc47d 100644 --- a/tests/unit/test_common.cpp +++ b/tests/unit/test_common.cpp @@ -60,11 +60,9 @@ TEST_F(CommonTest, netint_double_init) } // A shim from the lwpa_log module to GoogleMock. -extern "C" void log_cb(void* context, const char* syslog_str, const char* human_str, const char* raw_str) +extern "C" void log_cb(void* context, const LwpaLogStrings* strings) { - (void)syslog_str; - (void)human_str; - (void)raw_str; + (void)strings; CommonTest* test_fixture = static_cast(context); test_fixture->LogCallback(); diff --git a/tests/unit/test_log.cpp b/tests/unit/test_log.cpp index 64e6df783..96c1e1eb8 100644 --- a/tests/unit/test_log.cpp +++ b/tests/unit/test_log.cpp @@ -53,16 +53,17 @@ class LogTest : public ::testing::Test bool time_fn_called; }; -static void log_cb(void* context, const char* syslog_str, const char* human_str, const char* raw_str) +extern "C" static void log_cb(void* context, const LwpaLogStrings* strings) { LogTest* lt = static_cast(context); if (lt) { - lt->VerifyLogCallback(syslog_str ? syslog_str : "", human_str ? human_str : "", raw_str ? raw_str : ""); + lt->VerifyLogCallback(strings->syslog ? strings->syslog : "", + strings->human_readable ? strings->human_readable : "", strings->raw ? strings->raw : ""); } } -static void time_cb(void* context, LwpaLogTimeParams* time_params) +extern "C" static void time_cb(void* context, LwpaLogTimeParams* time_params) { LogTest* lt = static_cast(context); if (lt && time_params) From d9ceb84301b4726dcf6630b0e0a15d68e48e2b8f Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 19 Jun 2019 15:17:34 -0500 Subject: [PATCH 070/264] Fix build on mac and linux --- tests/unit/test_log.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_log.cpp b/tests/unit/test_log.cpp index 96c1e1eb8..5cffb9495 100644 --- a/tests/unit/test_log.cpp +++ b/tests/unit/test_log.cpp @@ -53,7 +53,8 @@ class LogTest : public ::testing::Test bool time_fn_called; }; -extern "C" static void log_cb(void* context, const LwpaLogStrings* strings) +extern "C" { +static void log_cb(void* context, const LwpaLogStrings* strings) { LogTest* lt = static_cast(context); if (lt) @@ -63,7 +64,7 @@ extern "C" static void log_cb(void* context, const LwpaLogStrings* strings) } } -extern "C" static void time_cb(void* context, LwpaLogTimeParams* time_params) +static void time_cb(void* context, LwpaLogTimeParams* time_params) { LogTest* lt = static_cast(context); if (lt && time_params) @@ -72,6 +73,7 @@ extern "C" static void time_cb(void* context, LwpaLogTimeParams* time_params) lt->time_fn_called = true; } } +} // extern "C" void LogTest::FillDefaultTime(LwpaLogTimeParams& time_params) { From 8eac4e3ee22c2a52fdee75cf3544a8be34df43e9 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 19 Jun 2019 17:16:58 -0500 Subject: [PATCH 071/264] Bring MQX sources up to new APIs --- include/os/mqx/lwpa/os_lock.h | 23 +- include/os/mqx/lwpa/os_socket.h | 34 +- include/os/mqx/lwpa/os_thread.h | 10 - include/os/windows/lwpa/os_socket.h | 1 - src/lwpa/socket.dox | 22 +- src/os/mqx/lwpa/os_inet.c | 67 ++- src/os/mqx/lwpa/os_lock.c | 208 +++++----- src/os/mqx/lwpa/os_netint.c | 105 +---- src/os/mqx/lwpa/os_socket.c | 380 ++++++++++++++---- src/os/mqx/lwpa/os_thread.c | 33 +- src/os/mqx/lwpa/os_timer.c | 14 +- src/os/windows/lwpa/os_socket.c | 2 + .../codewarrior-kinetis-mqx.cmake | 8 +- .../cross-toolchains/iar-kinetis-mqx.cmake | 8 +- 14 files changed, 553 insertions(+), 362 deletions(-) diff --git a/include/os/mqx/lwpa/os_lock.h b/include/os/mqx/lwpa/os_lock.h index 1dce991a2..fc30bc43e 100644 --- a/include/os/mqx/lwpa/os_lock.h +++ b/include/os/mqx/lwpa/os_lock.h @@ -31,22 +31,23 @@ extern "C" { typedef LWSEM_STRUCT lwpa_mutex_t; -bool lwpa_mutex_create(lwpa_mutex_t* id); -bool lwpa_mutex_take(lwpa_mutex_t* id); -bool lwpa_mutex_try_take(lwpa_mutex_t* id); -#define lwpa_mutex_give(idptr) ((void)_lwsem_post((LWSEM_STRUCT_PTR)(idptr))) -#define lwpa_mutex_destroy(idptr) ((void)_lwsem_destroy((LWSEM_STRUCT_PTR)(idptr))) +#define lwpa_mutex_create(idptr) (MQX_OK == _lwsem_create((idptr), 1)) +#define lwpa_mutex_take(idptr) (MQX_OK == _lwsem_wait(idptr)) +#define lwpa_mutex_try_take(idptr) (MQX_OK == _lwsem_wait_ticks((idptr), 1u)) +#define lwpa_mutex_give(idptr) ((void)_lwsem_post(idptr)) +#define lwpa_mutex_destroy(idptr) ((void)_lwsem_destroy(idptr)) typedef LWEVENT_STRUCT lwpa_signal_t; -bool lwpa_signal_create(lwpa_signal_t* id); -bool lwpa_signal_wait(lwpa_signal_t* id); -bool lwpa_signal_poll(lwpa_signal_t* id); -#define lwpa_signal_post(idptr) ((void)_lwevent_set((LWEVENT_STRUCT_PTR)(idptr), 1u)) -#define lwpa_signal_destroy(idptr) ((void)_lwevent_destroy((LWEVENT_STRUCT_PTR)(idptr))) +#define lwpa_signal_create(idptr) (MQX_OK == _lwevent_create((idptr), LWEVENT_AUTO_CLEAR)) +#define lwpa_signal_wait(idptr) (MQX_OK == _lwevent_wait_ticks((idptr), 1u, true, 0u)) +#define lwpa_signal_poll(idptr) (MQX_OK == _lwevent_wait_ticks((idptr), 1u, true, 1u)) +#define lwpa_signal_post(idptr) ((void)_lwevent_set((idptr), 1u)) +#define lwpa_signal_destroy(idptr) ((void)_lwevent_destroy(idptr)) typedef struct { + bool valid; LWSEM_STRUCT sem; unsigned int reader_count; } lwpa_rwlock_t; @@ -58,7 +59,7 @@ void lwpa_rwlock_readunlock(lwpa_rwlock_t* id); bool lwpa_rwlock_writelock(lwpa_rwlock_t* id); bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id); void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); -#define lwpa_rwlock_destroy(idptr) ((void)_lwsem_destroy(&((idptr)->sem))) +void lwpa_rwlock_destroy(lwpa_rwlock_t* id); #ifdef __cplusplus } diff --git a/include/os/mqx/lwpa/os_socket.h b/include/os/mqx/lwpa/os_socket.h index 8aeb7894f..55f81fa87 100644 --- a/include/os/mqx/lwpa/os_socket.h +++ b/include/os/mqx/lwpa/os_socket.h @@ -23,6 +23,10 @@ #include #include "lwpa/inet.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef uint32_t lwpa_socket_t; /*! An identifier for an invalid socket handle. The ONLY invalid socket descriptor is LWPA_SOCKET_INVALID. */ @@ -30,17 +34,29 @@ typedef uint32_t lwpa_socket_t; #define LWPA_SOCKET_MAX_POLL_SIZE RTCSCFG_FD_SETSIZE -#ifdef __cplusplus -extern "C" { -#endif +typedef struct LwpaPollCtxSocket +{ + lwpa_socket_t socket; + lwpa_poll_events_t events; + void* user_data; +} LwpaPollCtxSocket; + +typedef struct LwpaPollFdSet +{ + rtcs_fd_set set; + size_t count; +} LwpaPollFdSet; + +typedef struct LwpaPollContext +{ + bool valid; -#define IP_OS_TO_LWPA_V4(lwpaipptr, pfipptr) LWPA_IP_SET_V4_ADDRESS((lwpaipptr), (pfipptr)->s_addr) -#define IP_LWPA_TO_OS_V4(pfipptr, lwpaipptr) ((pfipptr)->s_addr = LWPA_IP_V4_ADDRESS(lwpaipptr)) -#define IP_OS_TO_LWPA_V6(lwpaipptr, pfipptr) LWPA_IP_SET_V6_ADDRESS((lwpaipptr), (pfipptr)->s6_addr) -#define IP_LWPA_TO_OS_V6(pfipptr, lwpaipptr) memcpy((pfipptr)->s6_addr, LWPA_IP_V6_ADDRESS(lwpaipptr), IPV6_BYTES) + LwpaPollCtxSocket sockets[LWPA_SOCKET_MAX_POLL_SIZE]; + size_t num_valid_sockets; -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa); -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa); + LwpaPollFdSet readfds; + LwpaPollFdSet writefds; +} LwpaPollContext; #ifdef __cplusplus } diff --git a/include/os/mqx/lwpa/os_thread.h b/include/os/mqx/lwpa/os_thread.h index 535c28c40..8a9a39b67 100644 --- a/include/os/mqx/lwpa/os_thread.h +++ b/include/os/mqx/lwpa/os_thread.h @@ -28,14 +28,6 @@ extern "C" { #endif -typedef struct LwpaThreadParams -{ - unsigned int thread_priority; - unsigned int stack_size; - char* thread_name; - void* platform_data; -} LwpaThreadParams; - typedef struct LwpaThreadParamsMqx { _mqx_uint task_attributes; @@ -56,8 +48,6 @@ typedef struct _task_id tid; } lwpa_thread_t; -bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); -bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); #define lwpa_thread_sleep(sleep_ms) _time_delay(sleep_ms) #ifdef __cplusplus diff --git a/include/os/windows/lwpa/os_socket.h b/include/os/windows/lwpa/os_socket.h index 54781da6a..e1e2b2f60 100644 --- a/include/os/windows/lwpa/os_socket.h +++ b/include/os/windows/lwpa/os_socket.h @@ -70,7 +70,6 @@ typedef struct LwpaPollContext LwpaPollFdSet readfds; LwpaPollFdSet writefds; LwpaPollFdSet exceptfds; - } LwpaPollContext; #ifdef __cplusplus diff --git a/src/lwpa/socket.dox b/src/lwpa/socket.dox index 664890d3f..6c64841e6 100644 --- a/src/lwpa/socket.dox +++ b/src/lwpa/socket.dox @@ -239,6 +239,13 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t * */ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking); +/*! \name lwpa_poll API + * + * The lwpa_poll functions enable monitoring several sockets at once. + * + * @{ + */ + /*! \brief A structure that holds context information for poll operations on multiple sockets. * * See the documentation for lwpa_poll_context_init() and lwpa_poll_wait() for more information. @@ -327,11 +334,18 @@ void lwpa_poll_remove_socket(LwpaPollContext *context, lwpa_socket_t socket); * milliseconds; use #LWPA_WAIT_FOREVER to wait indefinitely. If there are no sockets currently * added to the context structure, returns the special error code #kLwpaErrNoSockets immediately. * + * This function should not be assumed to be thread-safe with respect to the other lwpa_poll API + * functions; for this reason, lwpa_poll_add_socket(), lwpa_poll_modify_socket(), and + * lwpa_poll_remove_socket() should not be called while this function is blocking. + * * Uses OS-specific APIs for monitoring multiple sockets under the hood. Details: * - * | Platform: | API used: | Notes: | - * |------------|-----------|----------| - * | Windows | select() | #LWPA_SOCKET_MAX_POLL_SIZE defaults to 64, but can be increased by setting FD_SETSIZE=[new_value] as a compile-time definition. | + * | Platform: | API used: | Notes: | + * |-----------|-----------|--------| + * | Linux | epoll() | | + * | macOS | kqueue() | | + * | MQX | select() | #LWPA_SOCKET_MAX_POLL_SIZE is controlled by the RTCS config constant RTCSCFG_FD_SETSIZE. | + * | Windows | select() | #LWPA_SOCKET_MAX_POLL_SIZE defaults to 64, but can be increased by setting FD_SETSIZE=[new_value] as a compile-time definition. | * * \param[in] context Pointer to LwpaPollContext for which to wait for events. * \param[out] event On success, contains information about the event that occurred. @@ -346,6 +360,8 @@ void lwpa_poll_remove_socket(LwpaPollContext *context, lwpa_socket_t socket); */ lwpa_error_t lwpa_poll_wait(LwpaPollContext *context, LwpaPollEvent *event, int timeout_ms); +/*! @} */ + /*! \brief Get address information for a named internet host and/or service. * * Refer to your favorite getaddrinfo() man page for more information. One difference between this diff --git a/src/os/mqx/lwpa/os_inet.c b/src/os/mqx/lwpa/os_inet.c index 1eb4ae5c2..1667c8ab9 100644 --- a/src/os/mqx/lwpa/os_inet.c +++ b/src/os/mqx/lwpa/os_inet.c @@ -22,18 +22,57 @@ #include #include -bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) +bool ip_os_to_lwpa(const lwpa_os_ipaddr_t* os_ip, LwpaIpAddr* ip) { - if (pfsa->sa_family == AF_INET) + if (os_ip->sa_family == AF_INET) { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; + const struct sockaddr_in* sin = (const struct sockaddr_in*)os_ip; + LWPA_IP_SET_V4_ADDRESS(ip, ntohl(sin->sin_addr.s_addr)); + return true; + } + else if (os_ip->sa_family == AF_INET6) + { + const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)os_ip; + LWPA_IP_SET_V6_ADDRESS(ip, sin6->sin6_addr.s6_addr); + return true; + } + return false; +} + +size_t ip_lwpa_to_os(const LwpaIpAddr* ip, lwpa_os_ipaddr_t* os_ip) +{ + size_t ret = 0; + if (LWPA_IP_IS_V4(ip)) + { + struct sockaddr_in* sin = (struct sockaddr_in*)os_ip; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = LWPA_IP_V4_ADDRESS(ip); + ret = sizeof(struct sockaddr_in); + } + else if (LWPA_IP_IS_V6(ip)) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_ip; + memset(sin6, 0, sizeof(struct sockaddr_in6)); + sin6->sin6_family = AF_INET6; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(ip), LWPA_IPV6_BYTES); + ret = sizeof(struct sockaddr_in6); + } + return ret; +} + +bool sockaddr_os_to_lwpa(const struct sockaddr* os_sa, LwpaSockaddr *sa) +{ + if (os_sa->sa_family == AF_INET) + { + struct sockaddr_in* sin = (struct sockaddr_in*)os_sa; sa->port = sin->sin_port; LWPA_IP_SET_V4_ADDRESS(&sa->ip, sin->sin_addr.s_addr); return true; } - else if (pfsa->sa_family == AF_INET6) + else if (os_sa->sa_family == AF_INET6) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_sa; sa->port = sin6->sin6_port; LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); return true; @@ -41,12 +80,12 @@ bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) return false; } -size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) +size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, struct sockaddr *os_sa) { size_t ret = 0; if (LWPA_IP_IS_V4(&sa->ip)) { - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; + struct sockaddr_in* sin = (struct sockaddr_in*)os_sa; sin->sin_family = AF_INET; sin->sin_port = sa->port; sin->sin_addr.s_addr = LWPA_IP_V4_ADDRESS(&sa->ip); @@ -54,10 +93,10 @@ size_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) } else if (LWPA_IP_IS_V6(&sa->ip)) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_sa; sin6->sin6_family = AF_INET6; sin6->sin6_port = sa->port; - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), IPV6_BYTES); + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); ret = sizeof(struct sockaddr_in6); } return ret; @@ -70,7 +109,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) switch (src->type) { - case LWPA_IPV4: + case kLwpaIpTypeV4: { struct in_addr addr; /* RTCS expects host byte order in their in_addrs. Thus no htonl is needed. */ @@ -79,10 +118,10 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) return kLwpaErrOk; return kLwpaErrSys; } - case LWPA_IPV6: + case kLwpaIpTypeV6: { struct in6_addr addr; - memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), IPV6_BYTES); + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) return kLwpaErrOk; return kLwpaErrSys; @@ -99,7 +138,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des switch (type) { - case LWPA_IPV4: + case kLwpaIpTypeV4: { struct in_addr addr; if (RTCS_OK != inet_pton(AF_INET, src, &addr, sizeof addr)) @@ -108,7 +147,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des LWPA_IP_SET_V4_ADDRESS(dest, addr.s_addr); return kLwpaErrOk; } - case LWPA_IPV6: + case kLwpaIpTypeV6: { struct in6_addr addr; if (RTCS_OK != inet_pton(AF_INET6, src, &addr, sizeof addr)) diff --git a/src/os/mqx/lwpa/os_lock.c b/src/os/mqx/lwpa/os_lock.c index c1f35e0c0..8018c2754 100644 --- a/src/os/mqx/lwpa/os_lock.c +++ b/src/os/mqx/lwpa/os_lock.c @@ -17,162 +17,140 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_lock.h" -#include "lwpa_int.h" +#include "lwpa/lock.h" +#include "lwpa/int.h" -static _mqx_uint msec_per_tick = 1; -static bool msec_per_tick_initted = false; +/**************************** Private constants ******************************/ -static _mqx_uint convert_ms_to_ticks(int ms) -{ - _mqx_uint ticks; - if (ms == LWPA_WAIT_FOREVER) - ticks = 0; /* 0 means infinite wait in MQX land */ - else - { - ticks = ms / msec_per_tick; - /* Round up to the nearest tick */ - if (ms % msec_per_tick != 0 || ms == 0) - ticks += 1; - } - return ticks; -} - -static bool sem_create(LWSEM_STRUCT_PTR id, _mqx_int count) -{ - if (!msec_per_tick_initted) - { - msec_per_tick = _time_get_resolution(); - msec_per_tick_initted = true; - } - return (MQX_OK == _lwsem_create(id, count)); -} +#define MAX_READERS 20000 -static bool sem_take(LWSEM_STRUCT_PTR id, int wait_ms) -{ - _mqx_uint ticks = convert_ms_to_ticks(wait_ms); - return (MQX_OK == _lwsem_wait_ticks(id, ticks)); -} +/*********************** Private function prototypes *************************/ -bool lwpa_mutex_create(lwpa_mutex_t* id) -{ - return sem_create((LWSEM_STRUCT_PTR)id, 1); -} +static void reader_atomic_increment(lwpa_rwlock_t* id); +static void reader_atomic_decrement(lwpa_rwlock_t* id); -bool lwpa_mutex_take(lwpa_mutex_t* id, int wait_ms) -{ - return sem_take(id, wait_ms); -} +/*************************** Function definitions ****************************/ -bool lwpa_signal_create(lwpa_signal_t* id) +bool lwpa_rwlock_create(lwpa_rwlock_t* id) { - if (!msec_per_tick_initted) + if (id && (MQX_OK == _lwsem_create(&id->sem, 1))) { - msec_per_tick = _time_get_resolution(); - msec_per_tick_initted = true; + id->valid = true; + id->reader_count = 0; + return true; } - - return (MQX_OK == _lwevent_create((LWEVENT_STRUCT_PTR)id, LWEVENT_AUTO_CLEAR)); + return false; } -bool lwpa_signal_wait(lwpa_signal_t* id, int wait_ms) +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id) { - _mqx_uint ticks = convert_ms_to_ticks(wait_ms); - if (MQX_OK == _lwevent_wait_ticks((LWEVENT_STRUCT_PTR)id, 1u, true, ticks)) + bool res = false; + if (id && id->valid) { - _lwevent_clear((LWEVENT_STRUCT_PTR)id, 1u); - return true; + if (MQX_OK == _lwsem_wait(&id->sem)) + { + if (id->reader_count < MAX_READERS) + { + // Add one to the reader count. + reader_atomic_increment(id); + res = true; + } + // Allow other readers to access. + _lwsem_post(&id->sem); + } } - return false; + return res; } -static void atomic_inc(unsigned int* count) +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id) { - _int_disable(); - (*count)++; - _int_enable(); + bool res = false; + if (id && id->valid) + { + if (MQX_OK == _lwsem_wait_ticks(&id->sem, 1u)) + { + if (id->reader_count < MAX_READERS) + { + reader_atomic_increment(id); + res = true; + } + _lwsem_post(&id->sem); + } + } + return res; } -static void atomic_dec(unsigned int* count) +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) { - _int_disable(); - (*count)--; - _int_enable(); + if (id) + reader_atomic_decrement(id); } -bool lwpa_rwlock_create(lwpa_rwlock_t* id) +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) { - if (id && sem_create(&id->sem, 1)) + if (id && id->valid) { - id->reader_count = 0; - return true; + if (_lwsem_wait(&id->sem)) + { + // Wait until there are no readers, keeping the lock so that no new readers can get in. + while (id->reader_count > 0) + { + _time_delay(1); + } + // Hold on to the lock until writeunlock() is called + return true; + } } return false; } -bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms) +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id) { - if (!id) - return false; - - if (sem_take(&id->sem, wait_ms)) + if (id && id->valid) { - /* Add one to the reader count. */ - atomic_inc(&id->reader_count); - /* Allow other readers to access. */ - _lwsem_post(&id->sem); - return true; + if (_lwsem_wait(&id->sem)) + { + // Just check once to see if there are still readers + if (id->reader_count > 0) + { + // Readers are present, give up the lock and return false below. + _lwsem_post(&id->sem); + } + else + { + // Return, holding the lock + return true; + } + } } return false; } -void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) +void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) { - if (id) - atomic_dec(&id->reader_count); + if (id && id->valid) + _lwsem_post(&id->sem); } -bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms) +void lwpa_rwlock_destroy(lwpa_rwlock_t* id) { - uint32_t initial_time; - TIME_STRUCT tm; - - if (!id) - return false; - - /* Start our timer here */ - _time_get_elapsed(&tm); - initial_time = tm.SECONDS * 1000 + tm.MILLISECONDS; - - if (sem_take(&id->sem, wait_ms)) + if (id && id->valid) { - /* Wait until there are no readers, keeping the lock so that no new readers - * can get in. */ - while (id->reader_count > 0) - { - _time_delay(1); - if (wait_ms >= 0) - { - _time_get_elapsed(&tm); - if ((uint32_t)(tm.SECONDS * 1000 + tm.MILLISECONDS) - initial_time > (uint32_t)wait_ms) - { - break; - } - } - } - if (id->reader_count > 0) - { - /* Timed out waiting for readers to leave. Bail. */ - _lwsem_post(&id->sem); - return false; - } - /* Hold on to the lock until writeunlock() is called */ - return true; + _lwsem_destroy(&id->sem); + id->valid = false; } - return false; } -void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) +void reader_atomic_increment(lwpa_rwlock_t* id) +{ + _int_disable(); + ++id->reader_count; + _int_enable(); +} + +void reader_atomic_decrement(lwpa_rwlock_t* id) { - _lwsem_post(&id->sem); + _int_disable(); + --id->reader_count; + _int_enable(); } diff --git a/src/os/mqx/lwpa/os_netint.c b/src/os/mqx/lwpa/os_netint.c index d8dc721fc..e946aec05 100644 --- a/src/os/mqx/lwpa/os_netint.c +++ b/src/os/mqx/lwpa/os_netint.c @@ -17,16 +17,16 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_netint.h" +#include "lwpa/netint.h" #include #include #include -#include "lwpa_int.h" +#include "lwpa/int.h" +#include "lwpa/private/netint.h" -static bool mask_is_empty(const LwpaIpAddr* mask); -static bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask); +static LwpaNetintInfo netints[BSP_ENET_DEVICE_COUNT]; static void copy_interface_info(size_t mqx_index, LwpaNetintInfo* netint) { @@ -41,7 +41,6 @@ static void copy_interface_info(size_t mqx_index, LwpaNetintInfo* netint) ipcfg_get_ip(mqx_index, &ip_data); LWPA_IP_SET_V4_ADDRESS(&netint->addr, ip_data.ip); LWPA_IP_SET_V4_ADDRESS(&netint->mask, ip_data.mask); - LWPA_IP_SET_V4_ADDRESS(&netint->gate, ip_data.gateway); ipcfg_get_mac(mqx_index, netint->mac); sprintf(netint->name, "en%d", mqx_index); @@ -51,97 +50,37 @@ static void copy_interface_info(size_t mqx_index, LwpaNetintInfo* netint) netint->is_default = false; } -size_t netint_get_num_interfaces() +lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) { - return BSP_ENET_DEVICE_COUNT; -} - -size_t netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) -{ - size_t i; - - if (!netint_arr || netint_arr_size == 0) - return 0; - - for (i = 0; i < BSP_ENET_DEVICE_COUNT; ++i) - { - copy_interface_info(i, &netint_arr[i]); - if (i >= netint_arr_size) - break; - } - return i; -} - -bool netint_get_default_interface(LwpaNetintInfo* netint) -{ - if (netint) - { - copy_interface_info(BSP_DEFAULT_ENET_DEVICE, netint); - return true; - } - return false; -} - -bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask) -{ - if (LWPA_IP_IS_V4(ip1) && LWPA_IP_IS_V4(ip2) && LWPA_IP_IS_V4(mask)) + for (size_t i = 0; i < BSP_ENET_DEVICE_COUNT; ++i) { - return ((LWPA_IP_V4_ADDRESS(ip1) & LWPA_IP_V4_ADDRESS(mask)) == (LWPA_IP_V4_ADDRESS(ip2) & LWPA_IP_V4_ADDRESS(mask))); + copy_interface_info(i, &netints[i]); } - else if (LWPA_IP_IS_V6(ip1) && LWPA_IP_IS_V6(ip2) && LWPA_IP_IS_V6(mask)) - { - size_t i; - const uint32_t* p1 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip1); - const uint32_t* p2 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip2); - const uint32_t* pm = (const uint32_t*)LWPA_IP_V6_ADDRESS(mask); - - for (i = 0; i < IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) - { - if ((*p1 & *pm) != (*p2 & *pm)) - return false; - } - return true; - } - return false; + cache->netints = netints; + cache->num_netints = BSP_ENET_DEVICE_COUNT; + return kLwpaErrOk; } -bool mask_is_empty(const LwpaIpAddr* mask) +void os_free_interfaces(CachedNetintInfo* cache) { - uint32_t mask_part = 0; - - if (LWPA_IP_IS_V4(mask)) - mask_part = LWPA_IP_V4_ADDRESS(mask); - else if (LWPA_IP_IS_V6(mask)) - { - size_t i; - const uint32_t* p = (const uint32_t*)LWPA_IP_V6_ADDRESS(mask); - for (i = 0; i < IPV6_BYTES / 4; ++i, ++p) - mask_part |= *p; - } - return (mask_part == 0); + cache->netints = NULL; } -const LwpaNetintInfo* netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, - size_t netint_arr_size) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) { - const LwpaNetintInfo* res = NULL; - const LwpaNetintInfo* def = NULL; - const LwpaNetintInfo* netint; - - if (!dest || !netint_arr || netint_arr_size == 0) - return false; + int index_found = -1; - for (netint = netint_arr; netint < netint_arr + netint_arr_size; ++netint) + for (const LwpaNetintInfo* netint = netints; netint < netints + BSP_ENET_DEVICE_COUNT; ++netint) { - if (netint->is_default) - def = netint; - if (!mask_is_empty(&netint->mask) && mask_compare(&netint->addr, dest, &netint->mask)) + if (!lwpa_ip_is_wildcard(&netint->mask) && lwpa_ip_network_portions_equal(&netint->addr, dest, &netint->mask)) { - res = netint; + index_found = netint->ifindex; break; } } - if (!res) - res = def; - return res; + if (index_found == -1) + index_found = netints[BSP_DEFAULT_ENET_DEVICE].ifindex; + + *index = index_found; + return kLwpaErrOk; } diff --git a/src/os/mqx/lwpa/os_socket.c b/src/os/mqx/lwpa/os_socket.c index 75fc9a4a7..1981f9ce1 100644 --- a/src/os/mqx/lwpa/os_socket.c +++ b/src/os/mqx/lwpa/os_socket.c @@ -17,13 +17,33 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_socket.h" +#include "lwpa/socket.h" #include #include #include #include +#include "lwpa/private/socket.h" + +/***************************** Private macros ********************************/ + +#define LWPA_FD_ZERO(setptr) \ + RTCS_FD_ZERO(&(setptr)->set); \ + (setptr)->count = 0 + +#define LWPA_FD_SET(sock, setptr) \ + RTCS_FD_SET(sock, &(setptr)->set); \ + (setptr)->count++ + +#define LWPA_FD_CLEAR(sock, setptr) \ + RTCS_FD_CLR(sock, &(setptr)->set); \ + (setptr)->count-- + +#define LWPA_FD_ISSET(sock, setptr) RTCS_FD_ISSET(sock, &(setptr)->set) + +/**************************** Private variables ******************************/ + /* clang-format off */ #define LWPA_NUM_SHUT 3 @@ -82,6 +102,21 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /* clang-format on */ +/*********************** Private function prototypes *************************/ + +// Helper functions for lwpa_poll API +static void init_context_socket_array(LwpaPollContext* context); +static LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket); +static LwpaPollCtxSocket* find_hole(LwpaPollContext* context); +static void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock); +static void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock); +static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, lwpa_error_t socket_error); + +// Helper functions for lwpa_setsockopt() +static int32_t join_leave_mcast_group_ipv4(lwpa_socket_t id, const struct LwpaMreq* mreq, bool join); + +/*************************** Function definitions ****************************/ + static lwpa_error_t err_os_to_lwpa(uint32_t rtcserr) { switch (rtcserr) @@ -129,16 +164,15 @@ static lwpa_error_t err_os_to_lwpa(uint32_t rtcserr) } } -lwpa_error_t lwpa_socket_init(void* os_data) +lwpa_error_t lwpa_socket_init() { - /* No initialization is necessary on this os. */ - (void)os_data; + // No initialization is necessary on this platform. return kLwpaErrOk; } void lwpa_socket_deinit() { - /* No deinitialization is necessary on this os. */ + // No deinitialization is necessary on this platform. } lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) @@ -155,7 +189,7 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) if (!address) return kLwpaErrInvalid; - sa_size = sockaddr_lwpa_to_os(&ss, address); + sa_size = sockaddr_lwpa_to_os(address, &ss); if (sa_size == 0) return kLwpaErrInvalid; @@ -191,7 +225,7 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) res = getsockname(id, &ss, &size); if (res == RTCS_OK) { - if (!sockaddr_os_to_lwpa(address, &ss)) + if (!sockaddr_os_to_lwpa(&ss, address)) return kLwpaErrSys; } return err_os_to_lwpa(res); @@ -231,7 +265,7 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa { if (address && fromlen > 0) { - if (!sockaddr_os_to_lwpa(address, &fromaddr)) + if (!sockaddr_os_to_lwpa(&fromaddr, address)) return kLwpaErrInvalid; } } @@ -253,7 +287,7 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, if (!dest_addr || !message) return kLwpaErrInvalid; - if ((ss_size = sockaddr_lwpa_to_os(&ss, dest_addr)) == 0) + if ((ss_size = sockaddr_lwpa_to_os(dest_addr, &ss)) == 0) return kLwpaErrInvalid; res = sendto(id, (char*)message, (uint32_t)length, 0, &ss, ss_size); @@ -317,54 +351,57 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const } break; case LWPA_MCAST_JOIN_GROUP: - if (option_len == sizeof(LwpaMreq)) + if (option_len == sizeof(LwpaGroupReq)) { - LwpaMreq* amreq = (LwpaMreq*)option_value; - if (LWPA_IP_IS_V4(&amreq->group) && level == LWPA_IPPROTO_IP) + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V4(&greq->group) && level == LWPA_IPPROTO_IP) { - /* We don't need htonl -- MQX/RTCS stores IPv4s in host order. */ - struct ip_mreq val; - val.imr_multiaddr.s_addr = LWPA_IP_V4_ADDRESS(&amreq->group); - val.imr_interface.s_addr = LWPA_IP_V4_ADDRESS(&amreq->netint); - res = setsockopt(id, SOL_IGMP, RTCS_SO_IGMP_ADD_MEMBERSHIP, &val, sizeof val); - if (res == RTCS_OK) - { - /* Voodoo to allow locally-sent multicast traffic to be received by local sockets. We - * don't check the result. */ - val.imr_interface.s_addr = 0x7f000001; - setsockopt(id, SOL_IGMP, RTCS_SO_IGMP_ADD_MEMBERSHIP, &val, sizeof val); - } + struct LwpaMreq mreq; + mreq.group = greq->group; + LWPA_IP_SET_V4_ADDRESS(&mreq.netint, RTCS_if_get_addr((_rtcs_if_handle)greq->ifindex)); + res = join_leave_mcast_group_ipv4(id, &mreq, true); } - else if (LWPA_IP_IS_V6(&amreq->group) && level == LWPA_IPPROTO_IPV6) + else if (LWPA_IP_IS_V6(&greq->group) && level == LWPA_IPPROTO_IPV6) { struct ipv6_mreq val; - val.ipv6imr_interface = 0; /* TODO find out what MQX does with interface indexes */ - memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); + val.ipv6imr_interface = greq->ifindex; + memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); res = setsockopt(id, SOL_IP6, RTCS_SO_IP6_JOIN_GROUP, &val, sizeof val); } } break; case LWPA_MCAST_LEAVE_GROUP: - if (option_len == sizeof(LwpaMreq)) + if (option_len == sizeof(LwpaGroupReq)) { - LwpaMreq* amreq = (LwpaMreq*)option_value; - if (LWPA_IP_IS_V4(&amreq->group) && level == LWPA_IPPROTO_IP) + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V4(&greq->group) && level == LWPA_IPPROTO_IP) { - /* We don't need htonl -- MQX/RTCS stores IPv4s in host order. */ - struct ip_mreq val; - val.imr_multiaddr.s_addr = LWPA_IP_V4_ADDRESS(&amreq->group); - val.imr_interface.s_addr = LWPA_IP_V4_ADDRESS(&amreq->netint); - res = setsockopt(id, SOL_IGMP, RTCS_SO_IGMP_DROP_MEMBERSHIP, &val, sizeof val); + struct LwpaMreq mreq; + mreq.group = greq->group; + LWPA_IP_SET_V4_ADDRESS(&mreq.netint, RTCS_if_get_addr((_rtcs_if_handle)greq->ifindex)); + res = join_leave_mcast_group_ipv4(id, &mreq, false); } - else if (LWPA_IP_IS_V6(&amreq->group) && level == LWPA_IPPROTO_IPV6) + else if (LWPA_IP_IS_V6(&greq->group) && level == LWPA_IPPROTO_IPV6) { struct ipv6_mreq val; - val.ipv6imr_interface = 0; /* TODO find out what MQX does with interface indexes */ - memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); + val.ipv6imr_interface = greq->ifindex; + memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); res = setsockopt(id, SOL_IP6, RTCS_SO_IP6_LEAVE_GROUP, &val, sizeof val); } } break; + case LWPA_IP_ADD_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq) && level == LWPA_IPPROTO_IP) + { + res = join_leave_mcast_group_ipv4(id, (LwpaMreq*)option_value, true); + } + break; + case LWPA_IP_DROP_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq) && level == LWPA_IPPROTO_IP) + { + res = join_leave_mcast_group_ipv4(id, (LwpaMreq*)option_value, false); + } + break; case LWPA_SO_REUSEADDR: case LWPA_SO_REUSEPORT: /* Option not supported, but seems to be allowed by default */ @@ -405,6 +442,24 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const return err_os_to_lwpa(res); } +int32_t join_leave_mcast_group_ipv4(lwpa_socket_t id, const struct LwpaMreq* mreq, bool join) +{ + struct ip_mreq os_mreq; + os_mreq.imr_interface.s_addr = LWPA_IP_V4_ADDRESS(&mreq->netint); + os_mreq.imr_multiaddr.s_addr = LWPA_IP_V4_ADDRESS(&mreq->group); + int32_t res = setsockopt(id, SOL_IGMP, join ? RTCS_SO_IGMP_ADD_MEMBERSHIP : RTCS_SO_IGMP_DROP_MEMBERSHIP, &os_mreq, + sizeof os_mreq); + if (res == RTCS_OK) + { + /* Voodoo to allow locally-sent multicast traffic to be received by local sockets. We + * don't check the result. */ + os_mreq.imr_interface.s_addr = 0x7f000001; + setsockopt(id, SOL_IGMP, join ? RTCS_SO_IGMP_ADD_MEMBERSHIP : RTCS_SO_IGMP_DROP_MEMBERSHIP, &os_mreq, + sizeof os_mreq); + } + return res; +} + lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) { if (how >= 0 && how < LWPA_NUM_SHUT) @@ -471,71 +526,228 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) return kLwpaErrSys; } -int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) +lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { - rtcs_fd_set readfds; - rtcs_fd_set writefds; - LwpaPollfd* fd; - int32_t nosfds; - int sel_res; - int32_t nreadfds = 0, nwritefds = 0; - uint32_t os_timeout; + if (!context) + return kLwpaErrInvalid; - if (fds && nfds > 0) - { - RTCS_FD_ZERO(&readfds); - RTCS_FD_ZERO(&writefds); + init_context_socket_array(context); + LWPA_FD_ZERO(&context->readfds); + LWPA_FD_ZERO(&context->writefds); + context->valid = true; + return kLwpaErrOk; +} + +void lwpa_poll_context_deinit(LwpaPollContext* context) +{ + if (!context || !context->valid) + return; + + context->valid = false; +} + +lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, + void* user_data) +{ + if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + return kLwpaErrInvalid; - for (fd = fds; fd < fds + nfds; ++fd) + if (context->num_valid_sockets >= LWPA_SOCKET_MAX_POLL_SIZE) + { + return kLwpaErrNoMem; + } + else + { + LwpaPollCtxSocket* new_sock = find_hole(context); + if (new_sock) { - if (fd->events & LWPA_POLLIN) - { - RTCS_FD_SET(fd->fd, &readfds); - nreadfds++; - } - if (fd->events & LWPA_POLLOUT) - { - RTCS_FD_SET(fd->fd, &writefds); - nwritefds++; - } - /* LWPA_POLLPRI/exceptfds is not handled properly on this OS */ + new_sock->socket = socket; + new_sock->events = events; + new_sock->user_data = user_data; + set_in_fd_sets(context, new_sock); + context->num_valid_sockets++; + return kLwpaErrOk; } + return kLwpaErrNoMem; + } +} + +lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, + void* new_user_data) +{ + if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + return kLwpaErrInvalid; + + LwpaPollCtxSocket* sock_desc = find_socket(context, socket); + if (sock_desc) + { + clear_in_fd_sets(context, sock_desc); + sock_desc->events = new_events; + sock_desc->user_data = new_user_data; + set_in_fd_sets(context, sock_desc); + return kLwpaErrOk; } + else + { + return kLwpaErrNotFound; + } +} +void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) +{ + if (!context || !context->valid || socket == LWPA_SOCKET_INVALID) + return; + + LwpaPollCtxSocket* sock_desc = find_socket(context, socket); + if (sock_desc) + { + clear_in_fd_sets(context, sock_desc); + sock_desc->socket = LWPA_SOCKET_INVALID; + context->num_valid_sockets--; + } +} + +lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms) +{ + if (!context || !context->valid || !event) + return kLwpaErrInvalid; + + if (context->readfds.count == 0 && context->writefds.count == 0) + { + // No valid sockets are currently added to the context. + return kLwpaErrNoSockets; + } + + uint32_t os_timeout; if (timeout_ms == LWPA_WAIT_FOREVER) os_timeout = 0; else if (timeout_ms == 0) os_timeout = 0xffffffff; else os_timeout = (uint32_t)timeout_ms; - nosfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; - sel_res = select(nosfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, NULL, os_timeout); + + int32_t nfds = (context->readfds.count > context->writefds.count) ? context->readfds.count : context->writefds.count; + int32_t sel_res = select(nfds, context->readfds.count ? &context->readfds.set : NULL, + context->writefds.count ? &context->writefds.set : NULL, NULL, os_timeout); if (sel_res == RTCS_ERROR) { - return err_os_to_lwpa(RTCS_get_errno()); + // RTCS handles some socket errors by returning them from select(). + uint32_t rtcs_err = RTCS_get_errno(); + if (rtcs_err == RTCSERR_SOCK_ESHUTDOWN) + return handle_select_result(context, event, kLwpaErrConnClosed); + else if (rtcs_err == RTCSERR_SOCK_CLOSED) + return handle_select_result(context, event, kLwpaErrNotFound); + else + return err_os_to_lwpa(rtcs_err); } else if (sel_res == 0) { return kLwpaErrTimedOut; } - else if (fds && nfds > 0) + else + { + return handle_select_result(context, event, kLwpaErrOk); + } +} + +lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, lwpa_error_t socket_error) +{ + // Init the event data. + event->socket = LWPA_SOCKET_INVALID; + event->events = 0; + event->err = kLwpaErrOk; + + // The default return; if we don't find any sockets set that we passed to select(), something has + // gone wrong. + lwpa_error_t res = kLwpaErrSys; + + for (LwpaPollCtxSocket* sock_desc = context->sockets; sock_desc < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; + ++sock_desc) { - for (fd = fds; fd < fds + nfds; ++fd) + if (sock_desc->socket == LWPA_SOCKET_INVALID) + continue; + + if (LWPA_FD_ISSET(sock_desc->socket, &context->readfds) || LWPA_FD_ISSET(sock_desc->socket, &context->writefds)) { - fd->revents = 0; - if (nreadfds && (fd->events & LWPA_POLLIN) && RTCS_FD_ISSET(fd->fd, &readfds)) + res = kLwpaErrOk; + event->socket = sock_desc->socket; + event->user_data = sock_desc->user_data; + + /* Check for errors */ + if (socket_error != kLwpaErrOk) + { + event->events |= LWPA_POLL_ERR; + event->err = socket_error; + } + + if (LWPA_FD_ISSET(sock_desc->socket, &context->readfds)) { - fd->revents |= LWPA_POLLIN; + if (sock_desc->events & LWPA_POLL_IN) + event->events |= LWPA_POLL_IN; } - if (nwritefds && (fd->events & LWPA_POLLOUT) && RTCS_FD_ISSET(fd->fd, &writefds)) + if (LWPA_FD_ISSET(sock_desc->socket, &context->writefds)) { - fd->revents |= LWPA_POLLOUT; + if (sock_desc->events & LWPA_POLL_CONNECT) + event->events |= LWPA_POLL_CONNECT; + else if (sock_desc->events & LWPA_POLL_OUT) + event->events |= LWPA_POLL_OUT; } - /* LWPA_POLLPRI/exceptfds is not handled properly on this OS */ + // LWPA_POLL_OOB/exceptfds is not handled properly on this OS + + break; // We handle one event at a time. } } - return (int)sel_res; + return res; +} + +void init_context_socket_array(LwpaPollContext* context) +{ + context->num_valid_sockets = 0; + for (LwpaPollCtxSocket* ctx_socket = context->sockets; ctx_socket < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; + ++ctx_socket) + { + ctx_socket->socket = LWPA_SOCKET_INVALID; + } +} + +LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket) +{ + for (LwpaPollCtxSocket* cur = context->sockets; cur < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; ++cur) + { + if (cur->socket == socket) + return cur; + } + return NULL; +} + +LwpaPollCtxSocket* find_hole(LwpaPollContext* context) +{ + return find_socket(context, LWPA_SOCKET_INVALID); +} + +void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) +{ + if (sock->events & LWPA_POLL_IN) + { + LWPA_FD_SET(sock->socket, &context->readfds); + } + if (sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + { + LWPA_FD_SET(sock->socket, &context->writefds); + } +} + +void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) +{ + if (sock->events & LWPA_POLL_IN) + { + LWPA_FD_CLEAR(sock->socket, &context->readfds); + } + if (sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + { + LWPA_FD_CLEAR(sock->socket, &context->writefds); + } } lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, @@ -572,32 +784,32 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) { if (ai && ai->pd[1]) { - struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; + struct addrinfo* os_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; - if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + if (!sockaddr_os_to_lwpa(os_ai->ai_addr, &ai->ai_addr)) return false; /* Can't use reverse maps, because we have no guarantee of the numeric values of the OS * constants. Ugh. */ - if (pf_ai->ai_family == AF_INET) + if (os_ai->ai_family == AF_INET) ai->ai_family = LWPA_AF_INET; - else if (pf_ai->ai_family == AF_INET6) + else if (os_ai->ai_family == AF_INET6) ai->ai_family = LWPA_AF_INET6; else ai->ai_family = LWPA_AF_UNSPEC; - if (pf_ai->ai_socktype == SOCK_DGRAM) + if (os_ai->ai_socktype == SOCK_DGRAM) ai->ai_socktype = LWPA_DGRAM; - else if (pf_ai->ai_socktype == SOCK_STREAM) + else if (os_ai->ai_socktype == SOCK_STREAM) ai->ai_socktype = LWPA_STREAM; else ai->ai_socktype = 0; - if (pf_ai->ai_protocol == IPPROTO_UDP) + if (os_ai->ai_protocol == IPPROTO_UDP) ai->ai_protocol = LWPA_IPPROTO_UDP; - else if (pf_ai->ai_protocol == IPPROTO_TCP) + else if (os_ai->ai_protocol == IPPROTO_TCP) ai->ai_protocol = LWPA_IPPROTO_TCP; else ai->ai_protocol = 0; - ai->ai_canonname = pf_ai->ai_canonname; - ai->pd[1] = pf_ai->ai_next; + ai->ai_canonname = os_ai->ai_canonname; + ai->pd[1] = os_ai->ai_next; return true; } diff --git a/src/os/mqx/lwpa/os_thread.c b/src/os/mqx/lwpa/os_thread.c index 8df48d4b2..47ba43872 100644 --- a/src/os/mqx/lwpa/os_thread.c +++ b/src/os/mqx/lwpa/os_thread.c @@ -17,10 +17,7 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_thread.h" - -static _mqx_uint msec_per_tick = 1; -static bool msec_per_tick_initted = false; +#include "lwpa/thread.h" static void thread_func_internal(uint32_t initial_data) { @@ -34,17 +31,12 @@ static void thread_func_internal(uint32_t initial_data) bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg) { - _task_id t_id; - TASK_TEMPLATE_STRUCT template; - - if (!msec_per_tick_initted) - msec_per_tick = _time_get_resolution(); - if (!id || !params || !thread_fn || (MQX_OK != _lwsem_create(&id->sig, 0))) return false; + TASK_TEMPLATE_STRUCT template; template.TASK_ADDRESS = thread_func_internal; - template.TASK_NAME = (params->thread_name ? params->thread_name : "lwpa_thread"); + template.TASK_NAME = (char*)(params->thread_name ? params->thread_name : "lwpa_thread"); template.TASK_PRIORITY = params->thread_priority; template.TASK_STACKSIZE = params->stack_size; if (params->platform_data) @@ -64,7 +56,7 @@ bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void * It may need to be reexamined in the future. */ template.CREATION_PARAMETER = (uint32_t)id; - t_id = _task_create(0, 0, (uint32_t) & template); + _task_id t_id = _task_create(0, 0, (uint32_t) & template); if (t_id != MQX_NULL_TASK_ID) { id->tid = t_id; @@ -73,25 +65,12 @@ bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void return false; } -bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms) +bool lwpa_thread_join(lwpa_thread_t* id) { - _mqx_uint ticks; - _mqx_uint res; - if (!id) return false; - if (wait_ms == LWPA_WAIT_FOREVER) - ticks = 0; /* 0 means infinite wait in MQX land */ - else - { - ticks = wait_ms / msec_per_tick; - /* Round up to the nearest tick */ - if (wait_ms % msec_per_tick != 0 || wait_ms == 0) - ticks += 1; - } - res = _lwsem_wait_ticks((LWSEM_STRUCT_PTR)&id->sig, ticks); - + _mqx_uint res = _lwsem_wait(&id->sig); if (res == MQX_OK) { _lwsem_destroy(&id->sig); diff --git a/src/os/mqx/lwpa/os_timer.c b/src/os/mqx/lwpa/os_timer.c index fdf8662b9..8325797fa 100644 --- a/src/os/mqx/lwpa/os_timer.c +++ b/src/os/mqx/lwpa/os_timer.c @@ -17,10 +17,22 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_timer.h" +#include "lwpa/timer.h" +#include "lwpa/private/timer.h" #include +lwpa_error_t lwpa_timer_init() +{ + // No initialization necessary on this platform + return kLwpaErrOk; +} + +void lwpa_timer_deinit() +{ + // No deinitialization necessary on this platform +} + uint32_t lwpa_getms() { TIME_STRUCT ts; diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index dfdb66158..6e5a2b798 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -32,6 +32,8 @@ #define POLL_CONTEXT_ARR_CHUNK_SIZE 10 +/***************************** Private macros ********************************/ + #define LWPA_FD_ZERO(setptr) \ FD_ZERO(&(setptr)->set); \ (setptr)->count = 0 diff --git a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake index f12c5387e..4fd1e31e2 100644 --- a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake +++ b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake @@ -29,8 +29,8 @@ if(NOT DEFINED CODEWARRIOR_INSTALL_DIR) endif() set(TOOLS_DIR ${CODEWARRIOR_INSTALL_DIR}/Cross_Tools/arm-none-eabi-gcc-4_7_3) -set(CMAKE_C_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-gcc.exe) -set(CMAKE_CXX_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-g++.exe) +set(CMAKE_C_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-gcc.exe CACHE FILEPATH "CodeWarrior/gcc C Compiler") +set(CMAKE_CXX_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-g++.exe CACHE FILEPATH "CodeWarrior/gcc C++ Compiler") set(LWPA_TARGET_OS mqx) add_compile_options( @@ -57,3 +57,7 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # this line to bypass the compiler checks. # set(CMAKE_C_COMPILER_WORKS 1) # set(CMAKE_CXX_COMPILER_WORKS 1) + +# The unit tests and examples will not build properly from CMake on this platform. +set(LWPA_BUILD_TESTS OFF CACHE BOOL "Build the lwpa unit tests" FORCE) +set(LWPA_BUILD_EXAMPLES OFF CACHE BOOL "Build the lwpa examples" FORCE) diff --git a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake index e971df017..39e938c67 100644 --- a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake +++ b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake @@ -28,8 +28,8 @@ if(NOT DEFINED IAR_INSTALL_DIR) set(IAR_INSTALL_DIR "C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.5") endif() -set(CMAKE_C_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe) -set(CMAKE_CXX_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe) +set(CMAKE_C_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe CACHE FILEPATH "IAR C Compiler") +set(CMAKE_CXX_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe CACHE FILEPATH "IAR C++ Compiler") set(LWPA_TARGET_OS mqx) add_compile_options( @@ -47,3 +47,7 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # this line to bypass the compiler checks. # set(CMAKE_C_COMPILER_WORKS 1) # set(CMAKE_CXX_COMPILER_WORKS 1) + +# The unit tests and examples will not build properly from CMake on this platform. +set(LWPA_BUILD_TESTS OFF CACHE BOOL "Build the lwpa unit tests" FORCE) +set(LWPA_BUILD_EXAMPLES OFF CACHE BOOL "Build the lwpa examples" FORCE) From 592b36058eeaf487b0afa0dc87e4b6891013420e Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 19 Jun 2019 17:38:51 -0500 Subject: [PATCH 072/264] Clean up GCC warnings, clean up unused cruft from pre-CMake days --- port/mqx/cw10gcc/.cproject | 259 ---- port/mqx/cw10gcc/.project | 279 ---- port/mqx/cw10gcc/BUILDING.txt | 23 - port/mqx/iar/BUILDING.txt | 22 - port/mqx/iar/lwpa.ewp | 2064 ----------------------------- src/lwpa/root_layer_pdu.c | 2 +- src/os/mqx/lwpa/os_socket.c | 45 +- tests/unit/mqx/iar/lwpatest.h | 63 - tests/unit/mqx/iar/main.c | 211 --- tests/unit/mqx/iar/test_cid.c | 160 --- tests/unit/mqx/iar/test_lock.c | 31 - tests/unit/mqx/iar/test_log.c | 480 ------- tests/unit/mqx/iar/test_lwpa.ewp | 2000 ---------------------------- tests/unit/mqx/iar/test_mempool.c | 102 -- tests/unit/mqx/iar/test_mutex.c | 156 --- tests/unit/mqx/iar/test_netint.c | 154 --- tests/unit/mqx/iar/test_pack.c | 276 ---- tests/unit/mqx/iar/test_rbtree.c | 356 ----- tests/unit/mqx/iar/test_rwlock.c | 274 ---- tests/unit/mqx/iar/test_signal.c | 154 --- tests/unit/mqx/iar/test_socket.c | 544 -------- tests/unit/mqx/iar/test_thread.c | 206 --- tests/unit/mqx/iar/test_timer.c | 75 -- tests/unit/mqx/testio.h | 25 - 24 files changed, 24 insertions(+), 7937 deletions(-) delete mode 100644 port/mqx/cw10gcc/.cproject delete mode 100644 port/mqx/cw10gcc/.project delete mode 100644 port/mqx/cw10gcc/BUILDING.txt delete mode 100644 port/mqx/iar/BUILDING.txt delete mode 100644 port/mqx/iar/lwpa.ewp delete mode 100644 tests/unit/mqx/iar/lwpatest.h delete mode 100644 tests/unit/mqx/iar/main.c delete mode 100644 tests/unit/mqx/iar/test_cid.c delete mode 100644 tests/unit/mqx/iar/test_lock.c delete mode 100644 tests/unit/mqx/iar/test_log.c delete mode 100644 tests/unit/mqx/iar/test_lwpa.ewp delete mode 100644 tests/unit/mqx/iar/test_mempool.c delete mode 100644 tests/unit/mqx/iar/test_mutex.c delete mode 100644 tests/unit/mqx/iar/test_netint.c delete mode 100644 tests/unit/mqx/iar/test_pack.c delete mode 100644 tests/unit/mqx/iar/test_rbtree.c delete mode 100644 tests/unit/mqx/iar/test_rwlock.c delete mode 100644 tests/unit/mqx/iar/test_signal.c delete mode 100644 tests/unit/mqx/iar/test_socket.c delete mode 100644 tests/unit/mqx/iar/test_thread.c delete mode 100644 tests/unit/mqx/iar/test_timer.c delete mode 100644 tests/unit/mqx/testio.h diff --git a/port/mqx/cw10gcc/.cproject b/port/mqx/cw10gcc/.cproject deleted file mode 100644 index 5190e49eb..000000000 --- a/port/mqx/cw10gcc/.cproject +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/port/mqx/cw10gcc/.project b/port/mqx/cw10gcc/.project deleted file mode 100644 index e4c3508fb..000000000 --- a/port/mqx/cw10gcc/.project +++ /dev/null @@ -1,279 +0,0 @@ - - - lwpa - - - - - - com.freescale.processorexpert.core.expertprojectbuilder - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - - - ?name? - - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.autoBuildTarget - all - - - org.eclipse.cdt.make.core.buildArguments - -j8 - - - org.eclipse.cdt.make.core.buildCommand - ${GNU_Make_Install_Dir}mingw32-make - - - org.eclipse.cdt.make.core.buildLocation - ${ProjDirPath}/Debug - - - org.eclipse.cdt.make.core.cleanBuildTarget - clean - - - org.eclipse.cdt.make.core.contents - org.eclipse.cdt.make.core.activeConfigSettings - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.enableCleanBuild - true - - - org.eclipse.cdt.make.core.enableFullBuild - true - - - org.eclipse.cdt.make.core.fullBuildTarget - all - - - org.eclipse.cdt.make.core.stopOnError - true - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - true - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - com.freescale.processorexpert.core.expertprojectnature - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - - - include - 2 - virtual:/virtual - - - src - 2 - virtual:/virtual - - - include/acn_prot.h - 1 - PARENT-3-PROJECT_LOC/include/acn_prot.h - - - include/estardm.h - 1 - PARENT-3-PROJECT_LOC/include/estardm.h - - - include/estardmnet.h - 1 - PARENT-3-PROJECT_LOC/include/estardmnet.h - - - include/lwpa_bool.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_bool.h - - - include/lwpa_cid.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_cid.h - - - include/lwpa_common.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_common.h - - - include/lwpa_error.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_error.h - - - include/lwpa_inet.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_inet.h - - - include/lwpa_int.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_int.h - - - include/lwpa_lock.h - 1 - PARENT-3-PROJECT_LOC/include/mqx/lwpa_lock.h - - - include/lwpa_log.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_log.h - - - include/lwpa_mempool.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_mempool.h - - - include/lwpa_netint.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_netint.h - - - include/lwpa_pack.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_pack.h - - - include/lwpa_pdu.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_pdu.h - - - include/lwpa_rbtree.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_rbtree.h - - - include/lwpa_rootlayerpdu.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_rootlayerpdu.h - - - include/lwpa_socket.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_socket.h - - - include/lwpa_socket_plat.h - 1 - PARENT-3-PROJECT_LOC/include/mqx/lwpa_socket_plat.h - - - include/lwpa_thread.h - 1 - PARENT-3-PROJECT_LOC/include/mqx/lwpa_thread.h - - - include/lwpa_timer.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_timer.h - - - include/lwpa_uid.h - 1 - PARENT-3-PROJECT_LOC/include/lwpa_uid.h - - - src/lwpa_cid.c - 1 - PARENT-3-PROJECT_LOC/src/lwpa_cid.c - - - src/lwpa_error.c - 1 - PARENT-3-PROJECT_LOC/src/lwpa_error.c - - - src/lwpa_lock.c - 1 - PARENT-3-PROJECT_LOC/src/mqx/lwpa_lock.c - - - src/lwpa_log.c - 1 - PARENT-3-PROJECT_LOC/src/lwpa_log.c - - - src/lwpa_mempool.c - 1 - PARENT-3-PROJECT_LOC/src/lwpa_mempool.c - - - src/lwpa_netint.c - 1 - PARENT-3-PROJECT_LOC/src/mqx/lwpa_netint.c - - - src/lwpa_pdu.c - 1 - PARENT-3-PROJECT_LOC/src/lwpa_pdu.c - - - src/lwpa_rbtree.c - 1 - PARENT-3-PROJECT_LOC/src/lwpa_rbtree.c - - - src/lwpa_rootlayerpdu.c - 1 - PARENT-3-PROJECT_LOC/src/lwpa_rootlayerpdu.c - - - src/lwpa_socket.c - 1 - PARENT-3-PROJECT_LOC/src/mqx/lwpa_socket.c - - - src/lwpa_thread.c - 1 - PARENT-3-PROJECT_LOC/src/mqx/lwpa_thread.c - - - src/lwpa_timer.c - 1 - PARENT-3-PROJECT_LOC/src/mqx/lwpa_timer.c - - - src/lwpa_uid.c - 1 - PARENT-3-PROJECT_LOC/src/lwpa_uid.c - - - src/md5.c - 1 - PARENT-3-PROJECT_LOC/src/md5.c - - - diff --git a/port/mqx/cw10gcc/BUILDING.txt b/port/mqx/cw10gcc/BUILDING.txt deleted file mode 100644 index 28c82c682..000000000 --- a/port/mqx/cw10gcc/BUILDING.txt +++ /dev/null @@ -1,23 +0,0 @@ -Notes on building the Lightweight Platform Abstraction (lwpa) library for -MQX 4.2/CodeWarrior 10.6 (gcc toolchain) - -== Workspace Variables == - -A workspace-level variable is needed to point the lwpa project at the MQX -headers that it needs to build: - MQX_BOARD_DIR: The location of your project's MQX build directory - (of the form .../MQX/v4.2.0/lib/[your board].cw10gcc) -Set this variable in Window -> Preferences -> General -> Workspace -> -Linked Resources. - -== Project Configurations == - -"debug" includes debugging information and has no optimizations. "release" -includes no debugging information and is optimized for size. - -== Output == - -The static lib will be copied to lib/mqx/cw10gcc/liblwpa[d].a. From there it -can be linked into your project. Your project's include paths should include: - lwpa/include - lwpa/include/mqx diff --git a/port/mqx/iar/BUILDING.txt b/port/mqx/iar/BUILDING.txt deleted file mode 100644 index ab41f1df9..000000000 --- a/port/mqx/iar/BUILDING.txt +++ /dev/null @@ -1,22 +0,0 @@ -Notes on building the Lightweight Platform Abstraction (lwpa) library for -MQX 4.2/IAR Embedded Workbench - -== Workspace Variables == - -A workspace-level variable is needed to point the lwpa project at the MQX -headers that it needs to build: - MQX_BOARD_DIR: The location of your project's MQX build directory - (of the form .../MQX/v4.2.0/lib/[your board].iar) -Set this variable in Tools -> Configure Custom Argument Variables -> Workspace. - -== Project Configurations == - -"Debug" includes debugging information and has no optimizations. "Release" -includes no debugging information and is optimized for size. - -== Output == - -The static lib will be copied to lib/mqx/iar/liblwpa[d].a. From there it -can be linked into your project. Your project's include paths should include: - lwpa/include - lwpa/include/mqx diff --git a/port/mqx/iar/lwpa.ewp b/port/mqx/iar/lwpa.ewp deleted file mode 100644 index b7a1274c9..000000000 --- a/port/mqx/iar/lwpa.ewp +++ /dev/null @@ -1,2064 +0,0 @@ - - - - 2 - - Debug - - ARM - - 1 - - General - 3 - - 24 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 1 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - - cmd /c mkdir "$PROJ_DIR$\..\..\..\lib\mqx\iar" & copy "$PROJ_DIR$\debug\lwpa.a" "$PROJ_DIR$\..\..\..\lib\mqx\iar\liblwpad.a" - - - - ILINK - 0 - - 18 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 1 - - - - - - - BILINK - 0 - - - - - Release - - ARM - - 0 - - General - 3 - - 24 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 0 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - - cmd /c mkdir "$PROJ_DIR$\..\..\..\lib\mqx\iar" & copy "$PROJ_DIR$\release\lwpa.a" "$PROJ_DIR$\..\..\..\lib\mqx\iar\liblwpa.a" - - - - ILINK - 0 - - 18 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 0 - - - - - - - BILINK - 0 - - - - - headers - - $PROJ_DIR$\..\..\..\include\acn_prot.h - - - $PROJ_DIR$\..\..\..\include\estardm.h - - - $PROJ_DIR$\..\..\..\include\estardmnet.h - - - $PROJ_DIR$\..\..\..\include\lwpa_bool.h - - - $PROJ_DIR$\..\..\..\include\lwpa_cid.h - - - $PROJ_DIR$\..\..\..\include\lwpa_common.h - - - $PROJ_DIR$\..\..\..\include\lwpa_error.h - - - $PROJ_DIR$\..\..\..\include\lwpa_inet.h - - - $PROJ_DIR$\..\..\..\include\lwpa_int.h - - - $PROJ_DIR$\..\..\..\include\mqx\lwpa_lock.h - - - $PROJ_DIR$\..\..\..\include\lwpa_log.h - - - $PROJ_DIR$\..\..\..\include\lwpa_mempool.h - - - $PROJ_DIR$\..\..\..\include\lwpa_netint.h - - - $PROJ_DIR$\..\..\..\include\lwpa_pack.h - - - $PROJ_DIR$\..\..\..\include\lwpa_pdu.h - - - $PROJ_DIR$\..\..\..\include\lwpa_rbtree.h - - - $PROJ_DIR$\..\..\..\include\lwpa_rootlayerpdu.h - - - $PROJ_DIR$\..\..\..\include\lwpa_socket.h - - - $PROJ_DIR$\..\..\..\include\mqx\lwpa_socket_plat.h - - - $PROJ_DIR$\..\..\..\include\mqx\lwpa_thread.h - - - $PROJ_DIR$\..\..\..\include\lwpa_timer.h - - - $PROJ_DIR$\..\..\..\include\lwpa_uid.h - - - $PROJ_DIR$\..\..\..\src\md5.h - - - - sources - - $PROJ_DIR$\..\..\..\src\lwpa_cid.c - - - $PROJ_DIR$\..\..\..\src\lwpa_error.c - - - $PROJ_DIR$\..\..\..\src\mqx\lwpa_lock.c - - - $PROJ_DIR$\..\..\..\src\lwpa_log.c - - - $PROJ_DIR$\..\..\..\src\lwpa_mempool.c - - - $PROJ_DIR$\..\..\..\src\mqx\lwpa_netint.c - - - $PROJ_DIR$\..\..\..\src\lwpa_pdu.c - - - $PROJ_DIR$\..\..\..\src\lwpa_rbtree.c - - - $PROJ_DIR$\..\..\..\src\lwpa_rootlayerpdu.c - - - $PROJ_DIR$\..\..\..\src\mqx\lwpa_socket.c - - - $PROJ_DIR$\..\..\..\src\mqx\lwpa_thread.c - - - $PROJ_DIR$\..\..\..\src\mqx\lwpa_timer.c - - - $PROJ_DIR$\..\..\..\src\lwpa_uid.c - - - $PROJ_DIR$\..\..\..\src\md5.c - - - - - diff --git a/src/lwpa/root_layer_pdu.c b/src/lwpa/root_layer_pdu.c index 69ef5d802..2bbf2b5f1 100644 --- a/src/lwpa/root_layer_pdu.c +++ b/src/lwpa/root_layer_pdu.c @@ -166,7 +166,7 @@ bool lwpa_parse_root_layer_header(const uint8_t* buf, size_t buflen, LwpaRootLay else { pdu->pdata = cur_ptr; - pdu->datalen = (size_t)(pdu_len - (cur_ptr - buf)); + pdu->datalen = (size_t)(pdu_len - (size_t)(cur_ptr - buf)); } return true; } diff --git a/src/os/mqx/lwpa/os_socket.c b/src/os/mqx/lwpa/os_socket.c index 1981f9ce1..2a040caf9 100644 --- a/src/os/mqx/lwpa/os_socket.c +++ b/src/os/mqx/lwpa/os_socket.c @@ -55,7 +55,7 @@ static const int shutmap[LWPA_NUM_SHUT] = }; #define LWPA_NUM_AF 3 -static const int sfmap[LWPA_NUM_AF] = +static const uint32_t sfmap[LWPA_NUM_AF] = { AF_UNSPEC, PF_INET, @@ -70,7 +70,7 @@ static const uint32_t stmap[LWPA_NUM_TYPE] = }; #define LWPA_NUM_AIF 8 -static const int aiflagmap[LWPA_NUM_AIF] = +static const uint32_t aiflagmap[LWPA_NUM_AIF] = { 0, AI_PASSIVE, @@ -82,7 +82,7 @@ static const int aiflagmap[LWPA_NUM_AIF] = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST }; -static const int aifammap[LWPA_NUM_AF] = +static const uint16_t aifammap[LWPA_NUM_AF] = { AF_UNSPEC, AF_INET, @@ -90,7 +90,7 @@ static const int aifammap[LWPA_NUM_AF] = }; #define LWPA_NUM_IPPROTO 6 -static const int aiprotmap[LWPA_NUM_IPPROTO] = +static const uint16_t aiprotmap[LWPA_NUM_IPPROTO] = { 0, 0, @@ -193,12 +193,12 @@ lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) if (sa_size == 0) return kLwpaErrInvalid; - return err_os_to_lwpa(bind(id, &ss, sa_size)); + return err_os_to_lwpa(bind(id, &ss, (uint16_t)sa_size)); } lwpa_error_t lwpa_close(lwpa_socket_t id) { - return err_os_to_lwpa(closesocket(id)); + return err_os_to_lwpa((uint32_t)closesocket(id)); } lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) @@ -290,13 +290,13 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, if ((ss_size = sockaddr_lwpa_to_os(dest_addr, &ss)) == 0) return kLwpaErrInvalid; - res = sendto(id, (char*)message, (uint32_t)length, 0, &ss, ss_size); + res = sendto(id, (char*)message, (uint32_t)length, 0, &ss, (uint16_t)ss_size); return (res == RTCS_ERROR ? err_os_to_lwpa(RTCS_geterror(id)) : res); } lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) { - uint32_t res = RTCSERR_SOCK_INVALID_OPTION; + int32_t res = RTCSERR_SOCK_INVALID_OPTION; if (!option_value) return kLwpaErrInvalid; @@ -325,7 +325,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const case LWPA_SO_SNDBUF: if (level == LWPA_SOL_SOCKET && option_len >= sizeof(uint32_t)) { - uint32_t val = *(int*)option_value; + uint32_t val = (uint32_t)(*(int*)option_value); res = setsockopt(id, SOL_TCP, OPT_TBSIZE, &val, sizeof val); } break; @@ -364,7 +364,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const else if (LWPA_IP_IS_V6(&greq->group) && level == LWPA_IPPROTO_IPV6) { struct ipv6_mreq val; - val.ipv6imr_interface = greq->ifindex; + val.ipv6imr_interface = (unsigned int)greq->ifindex; memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); res = setsockopt(id, SOL_IP6, RTCS_SO_IP6_JOIN_GROUP, &val, sizeof val); } @@ -384,7 +384,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const else if (LWPA_IP_IS_V6(&greq->group) && level == LWPA_IPPROTO_IPV6) { struct ipv6_mreq val; - val.ipv6imr_interface = greq->ifindex; + val.ipv6imr_interface = (unsigned int)greq->ifindex; memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); res = setsockopt(id, SOL_IP6, RTCS_SO_IP6_LEAVE_GROUP, &val, sizeof val); } @@ -439,7 +439,7 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const break; } - return err_os_to_lwpa(res); + return err_os_to_lwpa((uint32_t)res); } int32_t join_leave_mcast_group_ipv4(lwpa_socket_t id, const struct LwpaMreq* mreq, bool join) @@ -464,7 +464,7 @@ lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) { if (how >= 0 && how < LWPA_NUM_SHUT) { - return err_os_to_lwpa(shutdownsocket(id, (int32_t)shutmap[how])); + return err_os_to_lwpa((uint32_t)shutdownsocket(id, (int32_t)shutmap[how])); } return kLwpaErrInvalid; } @@ -502,21 +502,21 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) socklen_t uint32_size = sizeof(uint32_t); if (RTCS_OK == getsockopt(id, SOL_SOCKET, OPT_SOCKET_TYPE, &sock_type, &uint32_size)) { - uint32_t res; + int32_t res; uint32_t opt_value = (blocking ? FALSE : TRUE); if (sock_type == SOCK_STREAM) { res = setsockopt(id, SOL_TCP, OPT_RECEIVE_NOWAIT, &opt_value, uint32_size); if (res == RTCS_OK) res = setsockopt(id, SOL_TCP, OPT_SEND_NOWAIT, &opt_value, uint32_size); - return err_os_to_lwpa(res); + return err_os_to_lwpa((uint32_t)res); } else if (sock_type == SOCK_DGRAM) { res = setsockopt(id, SOL_UDP, OPT_RECEIVE_NOWAIT, &opt_value, uint32_size); if (res == RTCS_OK) res = setsockopt(id, SOL_UDP, OPT_SEND_NOWAIT, &opt_value, uint32_size); - return err_os_to_lwpa(res); + return err_os_to_lwpa((uint32_t)res); } else { @@ -626,7 +626,8 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int else os_timeout = (uint32_t)timeout_ms; - int32_t nfds = (context->readfds.count > context->writefds.count) ? context->readfds.count : context->writefds.count; + int32_t nfds = + (int32_t)((context->readfds.count > context->writefds.count) ? context->readfds.count : context->writefds.count); int32_t sel_res = select(nfds, context->readfds.count ? &context->readfds.set : NULL, context->writefds.count ? &context->writefds.set : NULL, NULL, os_timeout); @@ -763,10 +764,10 @@ lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const L memset(&pf_hints, 0, sizeof pf_hints); if (hints) { - pf_hints.ai_flags = (hints->ai_flags < LWPA_NUM_AIF) ? aiflagmap[hints->ai_flags] : 0; - pf_hints.ai_family = (hints->ai_family < LWPA_NUM_AF) ? aifammap[hints->ai_family] : AF_UNSPEC; - pf_hints.ai_socktype = (hints->ai_socktype < LWPA_NUM_TYPE) ? stmap[hints->ai_socktype] : 0; - pf_hints.ai_protocol = (hints->ai_protocol < LWPA_NUM_IPPROTO) ? aiprotmap[hints->ai_protocol] : 0; + pf_hints.ai_flags = (uint16_t)((hints->ai_flags < LWPA_NUM_AIF) ? aiflagmap[hints->ai_flags] : 0); + pf_hints.ai_family = (uint16_t)((hints->ai_family < LWPA_NUM_AF) ? aifammap[hints->ai_family] : AF_UNSPEC); + pf_hints.ai_socktype = (uint32_t)((hints->ai_socktype < LWPA_NUM_TYPE) ? stmap[hints->ai_socktype] : 0); + pf_hints.ai_protocol = (uint16_t)((hints->ai_protocol < LWPA_NUM_IPPROTO) ? aiprotmap[hints->ai_protocol] : 0); } res = getaddrinfo(hostname, service, hints ? &pf_hints : NULL, &pf_res); @@ -777,7 +778,7 @@ lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const L if (!lwpa_nextaddr(result)) return kLwpaErrSys; } - return err_os_to_lwpa(res); + return err_os_to_lwpa((uint32_t)res); } bool lwpa_nextaddr(LwpaAddrinfo* ai) diff --git a/tests/unit/mqx/iar/lwpatest.h b/tests/unit/mqx/iar/lwpatest.h deleted file mode 100644 index 8f39fb300..000000000 --- a/tests/unit/mqx/iar/lwpatest.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#ifndef _LWPATEST_H_ -#define _LWPATEST_H_ - -#include -#include -#include "testio.h" - -uint32_t getms(); -void watchdog_kick(); -void watchdog_disable(); - -/* Lock tests */ -void test_lock(); -bool test_mutex(); -bool test_signal(); -bool test_rwlock(); - -/* Thread test */ -void test_thread(); - -/* Mempool test */ -void test_mempool(); - -/* Red-black tree test */ -void test_rbtree(); - -/* Log test */ -void test_log(); - -/* Pack test */ -void test_pack(); - -/* Timer test */ -void test_timer(); - -/* CID test */ -void test_cid(); - -/* Netint test */ -void test_netint(); - -/* Socket test */ -void test_socket(); - -#endif /* _LWPATEST_H_ */ diff --git a/tests/unit/mqx/iar/main.c b/tests/unit/mqx/iar/main.c deleted file mode 100644 index 11b8d6de8..000000000 --- a/tests/unit/mqx/iar/main.c +++ /dev/null @@ -1,211 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" - -#include -#include -#include - -/* NETWORK SETTINGS TO WRITE TO THE DEVICE */ -#define ENET_IPADDR IPADDR(10, 101, 2, 125) -#define ENET_IPMASK IPADDR(255, 255, 0, 0) -#define ENET_IPGATEWAY IPADDR(10, 101, 0, 1) - -// MQX task template -void main_task(uint32_t); -void watchdog_task(uint32_t); -// This is so we can create lower-priority tasks than the main task. -void dummy_task_fn(uint32_t initial_data) -{ -} - -/* clang-format off */ -TASK_TEMPLATE_STRUCT MQX_template_list[] = -{ - /* Task Index, Function, Stack, Priority, Name, Attributes, Param, Time Slice */ - { 1, main_task, 8000, 9, "main", MQX_AUTO_START_TASK, 0, 0 }, - { 2, watchdog_task, 8000, 5, "watchdog", MQX_AUTO_START_TASK, 0, 0 }, - { 3, dummy_task_fn, 500, 15, "dummy", 0, 0, 0 }, - { 0 } -}; - -/* Hacky way to redirect stdout via semihosting over the I-jet debugger. - * This symbol replaces the default MQX_init_struct via a linker override. */ -const MQX_INITIALIZATION_STRUCT MY_MQX_init_struct = -{ - /* PROCESSOR_NUMBER */ BSP_DEFAULT_PROCESSOR_NUMBER, - /* START_OF_KERNEL_MEMORY */ BSP_DEFAULT_START_OF_KERNEL_MEMORY, - /* END_OF_KERNEL_MEMORY */ BSP_DEFAULT_END_OF_KERNEL_MEMORY, - /* INTERRUPT_STACK_SIZE */ BSP_DEFAULT_INTERRUPT_STACK_SIZE, - /* TASK_TEMPLATE_LIST */ MQX_template_list, - /* MQX_HARDWARE_INTERRUPT_LEVEL_MAX*/ BSP_DEFAULT_MQX_HARDWARE_INTERRUPT_LEVEL_MAX, - /* MAX_MSGPOOLS */ BSP_DEFAULT_MAX_MSGPOOLS, - /* MAX_MSGQS */ BSP_DEFAULT_MAX_MSGQS, - /* IO_CHANNEL */ "iodebug:", - /* IO_OPEN_MODE */ BSP_DEFAULT_IO_OPEN_MODE, - 0, - 0, -#if MQX_ENABLE_USER_MODE - BSP_DEFAULT_START_OF_KERNEL_AREA, - BSP_DEFAULT_END_OF_KERNEL_AREA, - - BSP_DEFAULT_START_OF_USER_DEFAULT_MEMORY, - BSP_DEFAULT_END_OF_USER_DEFAULT_MEMORY, - - BSP_DEFAULT_START_OF_USER_HEAP, - BSP_DEFAULT_END_OF_USER_HEAP, - - BSP_DEFAULT_START_OF_USER_RW_MEMORY, - BSP_DEFAULT_END_OF_USER_RW_MEMORY, - - BSP_DEFAULT_START_OF_USER_RO_MEMORY, - BSP_DEFAULT_END_OF_USER_RO_MEMORY, - - BSP_DEFAULT_START_OF_USER_NO_MEMORY, - BSP_DEFAULT_END_OF_USER_NO_MEMORY, - - BSP_DEFAULT_MAX_USER_TASK_PRIORITY, - BSP_DEFAULT_MAX_USER_TASK_COUNT, -#endif -}; -/* clang-format on */ - -/* Write network settings to device */ -uint32_t setup_network() -{ - uint32_t error = 0; - IPCFG_IP_ADDRESS_DATA ip_data; - _enet_address enet_address; - _enet_handle ehandle; - _rtcs_if_handle ihandle; - _rtcs_if_handle lbhandle; - - ip_data.ip = ENET_IPADDR; - ip_data.mask = ENET_IPMASK; - ip_data.gateway = ENET_IPGATEWAY; - - /* Create TCP/IP task */ - error = RTCS_create(); - if (error) - return error; - - /* Get the Ethernet address of the device */ - ENET_get_mac_address(BSP_DEFAULT_ENET_DEVICE, ENET_IPADDR, enet_address); - - error = ENET_initialize(BSP_DEFAULT_ENET_DEVICE, enet_address, 0, &ehandle); - if (error == 0) - { - error = RTCS_if_add(ehandle, RTCS_IF_ENET, &ihandle); - if (error == 0) - { - error = ipcfg_init_interface(BSP_DEFAULT_ENET_DEVICE, ihandle); - if (error != 0) - { - RTCS_if_remove(ihandle); - ENET_shutdown(ehandle); - printf("IPCFG init error: %08x\n", error); - } - } - else - { - ENET_shutdown(ehandle); - printf("ENET Interface add error: %08x\n", error); - } - /* This voodoo was taken from the ACN C++ test app, and apparently is - * necessary in order to receive your own multicast traffic. */ - error = RTCS_if_add(ehandle, RTCS_IF_LOCALHOST, &lbhandle); - if (error == 0) - { - error = RTCS_if_bind(lbhandle, 0x7F000001, 0xFF000000); - if (error != 0) - { - RTCS_if_remove(lbhandle); - ENET_shutdown(ehandle); - printf("Loopback interface bind error: %08x\n", error); - } - } - else - { - ENET_shutdown(ehandle); - printf("LOCALHOST Interface add error: %08x\n", error); - } - } - else if (error == ENETERR_INIT_DEVICE) - printf("Device reinitialization... \n"); - else - printf("Device initialization error: %08x\n", error); - - /* Bind Ethernet device to network using constant (static) IP address information */ - error = ipcfg_bind_staticip(BSP_DEFAULT_ENET_DEVICE, &ip_data); - return error; -} - -uint32_t getms() -{ - TIME_STRUCT ts; - _time_get_elapsed(&ts); - return (ts.SECONDS * 1000 + ts.MILLISECONDS); -} - -bool watchdog_enabled; -uint32_t last_kick_time; - -void watchdog_kick() -{ - watchdog_enabled = true; - last_kick_time = getms(); -} - -void watchdog_disable() -{ - watchdog_enabled = false; -} - -void watchdog_task(uint32_t initial_data) -{ - while (1) - { - _time_delay(100); - if (watchdog_enabled && getms() - last_kick_time > 5000) - break; - } - - /* Watchdog timed out! Signal that the test is over. */ - OUTPUT_TEST_SUITE_TIMEOUT(); - _time_delay(1000); - _mqx_exit(1); -} - -void main_task(uint32_t initial_data) -{ - setup_network(); - OUTPUT_TEST_SUITE_BEGIN(); - test_lock(); - test_thread(); - test_mempool(); - test_rbtree(); - test_log(); - test_pack(); - test_timer(); - test_cid(); - test_netint(); - test_socket(); - watchdog_disable(); - OUTPUT_TEST_SUITE_END(); -} diff --git a/tests/unit/mqx/iar/test_cid.c b/tests/unit/mqx/iar/test_cid.c deleted file mode 100644 index 850814619..000000000 --- a/tests/unit/mqx/iar/test_cid.c +++ /dev/null @@ -1,160 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include -#include "lwpa_cid.h" - -bool test_null() -{ - bool ok; - LwpaCid cid = {{0}}; - - ok = cid_isnull(&cid); - if (ok) - { - size_t i; - for (i = 0; i < CID_BYTES; ++i) - cid.data[i] = i; - ok = !cid_isnull(&cid); - } - return ok; -} - -bool test_compare() -{ - bool ok; - LwpaCid cid1 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; - LwpaCid cid1_dup = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; - LwpaCid cid2 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17}}; - - ok = (0 == cidcmp(&cid1, &cid1_dup)); - if (ok) - ok = (0 < cidcmp(&cid2, &cid1)); - if (ok) - ok = (0 > cidcmp(&cid1, &cid2)); - return ok; -} - -bool test_string() -{ - bool ok; - const char good_str[] = "08090a0b-0C0D-0e0f-1011-121314151617"; - const char short_str[] = "08090a0b-0c0d-0e0f-1011-1213141516"; - const char bad_str[] = "This isn't a CID"; - char str_buf[CID_STRING_BYTES]; - LwpaCid cid = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; - - cid_to_string(str_buf, &cid); - ok = (0 == strcmp(str_buf, "01020304-0506-0708-090a-0b0c0d0e0f10")); - if (ok) - { - cid = NULL_CID; - cid_to_string(str_buf, &cid); - ok = (0 == strcmp(str_buf, "00000000-0000-0000-0000-000000000000")); - } - if (ok) - ok = string_to_cid(&cid, good_str, strlen(good_str)); - if (ok) - { - LwpaCid cid_cmp = {{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}}; - ok = (0 == cidcmp(&cid, &cid_cmp)); - } - if (ok) - { - cid = NULL_CID; - ok = !string_to_cid(&cid, short_str, strlen(short_str)); - } - if (ok) - ok = !string_to_cid(&cid, bad_str, strlen(bad_str)); - return ok; -} - -bool test_generate() -{ - bool ok; - uint8_t mac1[6] = {0x00, 0xc0, 0x16, 0xff, 0xef, 0x12}; - uint8_t mac2[6] = {0x00, 0xc0, 0x16, 0xff, 0xef, 0x13}; - LwpaCid cid1, cid2, cid3, cid4, cid1_dup, rdm1, rdm2, rdm1_dup; - - /* Test the generate_cid() function */ - - generate_cid(&cid1, "Test Device", mac1, 0); - generate_cid(&cid2, "Test Device", mac1, 1); - generate_cid(&cid3, "Tst Device", mac1, 0); - generate_cid(&cid4, "Test Device", mac2, 0); - generate_cid(&cid1_dup, "Test Device", mac1, 0); - - ok = (0 != cidcmp(&cid1, &cid2)); - if (ok) - ok = (0 != cidcmp(&cid1, &cid3)); - if (ok) - ok = (0 != cidcmp(&cid1, &cid4)); - if (ok) - ok = (0 != cidcmp(&cid2, &cid3)); - if (ok) - ok = (0 != cidcmp(&cid2, &cid4)); - if (ok) - ok = (0 != cidcmp(&cid3, &cid4)); - if (ok) - ok = (0 == cidcmp(&cid1, &cid1_dup)); - - /* Test the generate_rdm_cid() function */ - - if (ok) - { - /* We'll reuse the MAC addresses as UIDs. */ - generate_rdm_cid(&rdm1, mac1); - generate_rdm_cid(&rdm2, mac2); - generate_rdm_cid(&rdm1_dup, mac1); - ok = (0 != cidcmp(&rdm1, &rdm2)); - } - if (ok) - ok = (0 == cidcmp(&rdm1, &rdm1_dup)); - - return ok; -} - -void test_cid() -{ - bool ok; - - OUTPUT_TEST_MODULE_BEGIN("CID"); - watchdog_kick(); - OUTPUT_TEST_BEGIN("null"); - OUTPUT_TEST_RESULT((ok = test_null())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("compare"); - OUTPUT_TEST_RESULT((ok = test_compare())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("string"); - OUTPUT_TEST_RESULT((ok = test_string())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("generate"); - OUTPUT_TEST_RESULT((ok = test_generate())); - } - OUTPUT_TEST_MODULE_END("CID", ok); -} diff --git a/tests/unit/mqx/iar/test_lock.c b/tests/unit/mqx/iar/test_lock.c deleted file mode 100644 index 19cf6d2eb..000000000 --- a/tests/unit/mqx/iar/test_lock.c +++ /dev/null @@ -1,31 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" - -void test_lock() -{ - bool ok; - OUTPUT_TEST_MODULE_BEGIN("lock"); - ok = test_mutex(); - if (ok) - ok = test_signal(); - if (ok) - ok = test_rwlock(); - OUTPUT_TEST_MODULE_END("lock", ok); -} diff --git a/tests/unit/mqx/iar/test_log.c b/tests/unit/mqx/iar/test_log.c deleted file mode 100644 index 4a41206ec..000000000 --- a/tests/unit/mqx/iar/test_log.c +++ /dev/null @@ -1,480 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include -#include -#include "lwpa_log.h" - -static void* expect_context; -static bool expect_syslog_str_present, expect_human_str_present; -static char expect_syslog_str[LWPA_SYSLOG_STR_MAX_LEN]; -static char expect_human_str[LWPA_HUMAN_LOG_STR_MAX_LEN]; -static char expect_raw_str[LWPA_LOG_MSG_MAX_LEN]; -static bool log_passed_flag; - -static void log_cb(void* context, const char* syslog_str, const char* human_str, const char* raw_str) -{ - if (context != expect_context || !raw_str || 0 != strcmp(raw_str, expect_raw_str) || - (expect_syslog_str_present && (!syslog_str || 0 != strcmp(syslog_str, expect_syslog_str))) || - (!expect_syslog_str_present && syslog_str) || - (expect_human_str_present && (!human_str || 0 != strcmp(human_str, expect_human_str))) || - (!expect_human_str_present && human_str)) - { - log_passed_flag = false; - } - else - { - log_passed_flag = true; - } -} - -LwpaLogTimeParams tparams; -bool time_fn_called; - -static void time_cb(void* context, LwpaLogTimeParams* time_params) -{ - (void)context; - *time_params = tparams; -} - -static void fill_default_time() -{ - tparams.year = 1970; // absolute year - tparams.month = 1; // month of the year - [1, 12] - tparams.day = 1; // day of the month - [1, 31] - tparams.hour = 0; // hours since midnight - [0, 23] - tparams.minute = 0; // minutes after the hour - [0, 59] - tparams.second = 0; // seconds after the minute - [0, 60] including leap second - tparams.msec = 0; // milliseconds after the second - [0, 999] - tparams.utc_offset = 0; // Local offset from UTC in minutes -} - -static void init_flags() -{ - log_passed_flag = false; - expect_syslog_str_present = false; - expect_human_str_present = false; - time_fn_called = false; - fill_default_time(); -} - -bool test_log_sanitize() -{ - LwpaSyslogParams syslog_params; - const unsigned char special_char_array[] = { - 0x01, 0x10, 0x7f, // Some non-printing chars - 0x41, 0x42, 0x43, // "ABC" - 0x80, 0x81, 0xff, // Some characters out of the ASCII range - 0x00 // Null terminator - }; - memcpy(syslog_params.app_name, special_char_array, sizeof special_char_array); - memcpy(syslog_params.hostname, special_char_array, sizeof special_char_array); - memcpy(syslog_params.procid, special_char_array, sizeof special_char_array); - syslog_params.facility = -1; - - lwpa_sanitize_syslog_params(&syslog_params); - if ((0 != strcmp(syslog_params.app_name, "___ABC???")) || (0 != strcmp(syslog_params.hostname, "___ABC???")) || - (LWPA_LOG_FAC(syslog_params.facility) >= LWPA_LOG_NFACILITIES)) - { - return false; - } - return true; -} - -bool test_log_validate() -{ - LwpaLogParams lparams; - const unsigned char special_char_array[] = { - 0x01, 0x10, 0x7f, // Some non-printing chars - 0x41, 0x42, 0x43, // "ABC" - 0x80, 0x81, 0xff, // Some characters out of the ASCII range - 0x00 // Null terminator - }; - - // Test some normal params - lparams.action = kLwpaLogCreateSyslog; - lparams.log_fn = log_cb; - lparams.syslog_params.hostname[0] = '\0'; - lparams.syslog_params.procid[0] = '\0'; - lparams.syslog_params.facility = LWPA_LOG_KERN; - memcpy(lparams.syslog_params.app_name, special_char_array, sizeof special_char_array); - lparams.log_mask = 0; - lparams.time_fn = time_cb; - lparams.context = NULL; - - // Make sure the validation returned true and the syslog field got sanitized - if (!lwpa_validate_log_params(&lparams)) - return false; - - if (0 != strcmp(lparams.syslog_params.app_name, "___ABC???")) - return false; - - // Invalid log callback - lparams.log_fn = NULL; - if (lwpa_validate_log_params(&lparams)) - return false; - - // It's valid for time_fn to be NULL - lparams.log_fn = log_cb; - lparams.time_fn = NULL; - if (!lwpa_validate_log_params(&lparams)) - return false; - - return true; -} - -// Test logging of: -// - int values -// - time from callback -// - weird and missing value in syslog header -bool test_log_intval() -{ - LwpaLogParams lparams; - // A string with a non-ASCII character: "host\xC8name" - // Should be sanitized to "host?name" - const unsigned char weird_hostname[] = {0x68, 0x6f, 0x73, 0x74, 0xc8, 0x6e, 0x61, 0x6d, 0x65, 0x00}; - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; - - init_flags(); - - lparams.action = kLwpaLogCreateSyslog; - lparams.log_fn = log_cb; - memcpy(lparams.syslog_params.hostname, weird_hostname, sizeof weird_hostname); - strcpy(lparams.syslog_params.app_name, "My_App"); - lparams.syslog_params.procid[0] = '\0'; - lparams.syslog_params.facility = LWPA_LOG_KERN; - lparams.log_mask = 0; - lparams.time_fn = time_cb; - lparams.context = NULL; - - strcpy(expect_syslog_str, - "<0>1 1970-01-01T00:00:00.000Z host?name My_App - - - Here are some int values: 1 42 4294967295"); - strcpy(expect_human_str, "1970-01-01 00:00:00.000Z Here are some int values: 1 42 4294967295"); - strcpy(expect_raw_str, "Here are some int values: 1 42 4294967295"); - - if (!lwpa_validate_log_params(&lparams)) - return false; - -#define INTVAL_FORMAT_STR_AND_ARGS "Here are some int values: %d %d %u", 1, 42, 0xffffffffu - - // Try the functions that simply build the log strings - if (!lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &tparams, &lparams.syslog_params, LWPA_LOG_EMERG, - INTVAL_FORMAT_STR_AND_ARGS)) - { - return false; - } - - if (0 != strcmp(syslog_buf, expect_syslog_str)) - return false; - - if (!lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &tparams, INTVAL_FORMAT_STR_AND_ARGS)) - { - return false; - } - - if (0 != strcmp(human_buf, expect_human_str)) - return false; - - // Try logging with the log mask set to 0, should not work. - if (lwpa_canlog(&lparams, LWPA_LOG_EMERG)) - return false; - lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - if (log_passed_flag) - return false; - - // Try logging only syslog - expect_syslog_str_present = true; - expect_human_str_present = false; - lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_EMERG); - lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - if (!log_passed_flag) - return false; - - // Try logging both - log_passed_flag = false; - lparams.action = kLwpaLogCreateBoth; - expect_human_str_present = true; - lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - if (!log_passed_flag) - return false; - - // Try logging only human-readable - log_passed_flag = false; - lparams.action = kLwpaLogCreateHumanReadableLog; - expect_syslog_str_present = false; - lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - if (!log_passed_flag) - return false; - - return true; -} - -// Used by the following tests. Try using lwpa_vlog() to log various combinations of syslog and -// human-readable logging. -bool vlog_helper(LwpaLogParams* lparams, int pri, const char* format, ...) -{ - va_list args; - va_start(args, format); - - // Try logging only syslog - log_passed_flag = false; - lparams->action = kLwpaLogCreateSyslog; - expect_syslog_str_present = true; - expect_human_str_present = false; - lwpa_vlog(lparams, pri, format, args); - if (!log_passed_flag) - return false; - - // Try logging both - log_passed_flag = false; - lparams->action = kLwpaLogCreateBoth; - expect_human_str_present = true; - lwpa_vlog(lparams, pri, format, args); - if (!log_passed_flag) - return false; - - // Try logging only human-readable - log_passed_flag = false; - lparams->action = kLwpaLogCreateHumanReadableLog; - expect_syslog_str_present = false; - lwpa_vlog(lparams, pri, format, args); - if (!log_passed_flag) - return false; - - va_end(args); - return true; -} - -// Test logging of: -// - string values -// - no time -// - weird and missing value in syslog header -bool test_log_strval() -{ - LwpaLogParams lparams; - // A string with some non-printing and non-ASCII characters: "\x012\x034\xff" - const unsigned char weird_procid[] = {0x01, 0x32, 0x03, 0x34, 0xff, 0x00}; - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; - - init_flags(); - - lparams.action = kLwpaLogCreateSyslog; - lparams.log_fn = log_cb; - strcpy(lparams.syslog_params.hostname, "10.101.17.38"); - memcpy(lparams.syslog_params.procid, weird_procid, sizeof weird_procid); - lparams.syslog_params.app_name[0] = '\0'; - lparams.syslog_params.facility = LWPA_LOG_LOCAL2; - lparams.log_mask = 0; - lparams.time_fn = NULL; - lparams.context = NULL; - - strcpy(expect_syslog_str, "<149>1 - 10.101.17.38 - _2_4? - - Here are some string values: hey wassup hello"); - strcpy(expect_human_str, "Here are some string values: hey wassup hello"); - strcpy(expect_raw_str, "Here are some string values: hey wassup hello"); - - if (!lwpa_validate_log_params(&lparams)) - return false; - -#define STRVAL_FORMAT_STR_AND_ARGS "Here are some string values: %s %s %s", "hey", "wassup", "hello" - - // Try the functions that simply build the log strings - if (!lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, NULL, &lparams.syslog_params, LWPA_LOG_NOTICE, - STRVAL_FORMAT_STR_AND_ARGS)) - { - return false; - } - - if (0 != strcmp(syslog_buf, expect_syslog_str)) - return false; - - if (!lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, NULL, STRVAL_FORMAT_STR_AND_ARGS)) - { - return false; - } - - if (0 != strcmp(human_buf, expect_human_str)) - return false; - - // Try logging with the log mask set to 0, should not work. - if (lwpa_canlog(&lparams, LWPA_LOG_NOTICE)) - return false; - - lwpa_log(&lparams, LWPA_LOG_NOTICE, STRVAL_FORMAT_STR_AND_ARGS); - if (log_passed_flag) - return false; - - // Now try the actual logging using lwpa_vlog(). - lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_NOTICE); - return vlog_helper(&lparams, LWPA_LOG_NOTICE, STRVAL_FORMAT_STR_AND_ARGS); -} - -// Helper to get the proper sanitized character from a loop counter for the -// max length string test -static unsigned char get_sanitized_char(size_t i) -{ - unsigned char ret = (i % 128 == 0 ? 1 : i % 128); - - // We also need to avoid '%' because it is the printf format specifier. - if (ret < 33 || ret == 127 || ret == '%') - ret = '_'; - else if (ret > 127) - ret = '?'; - return ret; -} - -// Test logging a maximum length string. -bool test_log_maxlength() -{ - LwpaLogParams lparams; - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; - char* expect_syslog_str_ptr; - char* expect_human_str_ptr; - char* expect_raw_str_ptr; - - init_flags(); - - lparams.action = kLwpaLogCreateSyslog; - lparams.log_fn = log_cb; - lparams.syslog_params.facility = LWPA_LOG_LOCAL7; - lparams.log_mask = 0; - lparams.time_fn = time_cb; - lparams.context = NULL; - -#define SYSLOG_TIME_HEADER "<191>1 1970-01-01T00:00:00.000-12:00 " -#define HUMAN_TIME_HEADER "1970-01-01 00:00:00.000-12:00 " - - strcpy(expect_syslog_str, SYSLOG_TIME_HEADER); - expect_syslog_str_ptr = expect_syslog_str + sizeof(SYSLOG_TIME_HEADER) - 1; - strcpy(expect_human_str, HUMAN_TIME_HEADER); - expect_human_str_ptr = expect_human_str + sizeof(HUMAN_TIME_HEADER) - 1; - expect_raw_str_ptr = expect_raw_str; - - // Create our very long syslog header components - size_t i; - for (i = 0; i < LWPA_LOG_HOSTNAME_MAX_LEN - 1; ++i) - { - char to_add = get_sanitized_char(i); - lparams.syslog_params.hostname[i] = to_add; - *expect_syslog_str_ptr++ = to_add; - } - lparams.syslog_params.hostname[i] = '\0'; - *expect_syslog_str_ptr++ = ' '; - - for (i = 0; i < LWPA_LOG_APP_NAME_MAX_LEN - 1; ++i) - { - char to_add = get_sanitized_char(i); - lparams.syslog_params.app_name[i] = to_add; - *expect_syslog_str_ptr++ = to_add; - } - - lparams.syslog_params.app_name[i] = '\0'; - *expect_syslog_str_ptr++ = ' '; - - for (i = 0; i < LWPA_LOG_PROCID_MAX_LEN - 1; ++i) - { - char to_add = get_sanitized_char(i); - lparams.syslog_params.procid[i] = to_add; - *expect_syslog_str_ptr++ = to_add; - } - lparams.syslog_params.procid[i] = '\0'; - strcpy(expect_syslog_str_ptr, " - - "); - expect_syslog_str_ptr += sizeof(" - - ") - 1; - - char to_log_str[LWPA_LOG_MSG_MAX_LEN]; - for (i = 0; i < LWPA_LOG_MSG_MAX_LEN - 1; ++i) - { - char to_add = get_sanitized_char(i); - *expect_syslog_str_ptr++ = to_add; - *expect_human_str_ptr++ = to_add; - *expect_raw_str_ptr++ = to_add; - to_log_str[i] = to_add; - } - to_log_str[i] = '\0'; - - if (!lwpa_validate_log_params(&lparams)) - return false; - - // We want to have a non-zero, two-digit UTC offset for the maximum length possible. - tparams.utc_offset = -720; - - // Try the functions that simply build the log strings - if (!lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &tparams, &lparams.syslog_params, LWPA_LOG_DEBUG, - to_log_str)) - { - return false; - } - - if (0 != strcmp(syslog_buf, expect_syslog_str)) - return false; - - if (!lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &tparams, to_log_str)) - return false; - - if (0 != strcmp(human_buf, expect_human_str)) - return false; - - // Try logging with the log mask set to 0, should not work. - if (lwpa_canlog(&lparams, LWPA_LOG_DEBUG)) - return false; - - lwpa_log(&lparams, LWPA_LOG_DEBUG, STRVAL_FORMAT_STR_AND_ARGS); - if (log_passed_flag) - return false; - - // Now try the actual logging using lwpa_vlog(). - lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); - return vlog_helper(&lparams, LWPA_LOG_DEBUG, to_log_str); -} - -void test_log() -{ - bool ok; - OUTPUT_TEST_MODULE_BEGIN("log"); - watchdog_kick(); - OUTPUT_TEST_BEGIN("log_sanitize"); - OUTPUT_TEST_RESULT((ok = test_log_sanitize())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("log_validate"); - OUTPUT_TEST_RESULT((ok = test_log_validate())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("log_int_value"); - OUTPUT_TEST_RESULT((ok = test_log_intval())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("log_str_value"); - OUTPUT_TEST_RESULT((ok = test_log_strval())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("log_max_length"); - OUTPUT_TEST_RESULT((ok = test_log_maxlength())); - } - OUTPUT_TEST_MODULE_END("log", ok); -} diff --git a/tests/unit/mqx/iar/test_lwpa.ewp b/tests/unit/mqx/iar/test_lwpa.ewp deleted file mode 100644 index bd2ced755..000000000 --- a/tests/unit/mqx/iar/test_lwpa.ewp +++ /dev/null @@ -1,2000 +0,0 @@ - - - - 2 - - Debug - - ARM - - 1 - - General - 3 - - 24 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 1 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - - - - - - ILINK - 0 - - 18 - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 1 - - - - - - - BILINK - 0 - - - - - Release - - ARM - - 0 - - General - 3 - - 24 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ICCARM - 2 - - 31 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AARM - 2 - - 9 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OBJCOPY - 0 - - 1 - 1 - 0 - - - - - - - - - CUSTOM - 3 - - - - 0 - - - - BICOMP - 0 - - - - BUILDACTION - 1 - - - - - - - ILINK - 0 - - 18 - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IARCHIVE - 0 - - 0 - 1 - 0 - - - - - - - BILINK - 0 - - - - - $PROJ_DIR$\lwpatest.h - - - $PROJ_DIR$\main.c - - - $PROJ_DIR$\test_cid.c - - - $PROJ_DIR$\test_lock.c - - - $PROJ_DIR$\test_log.c - - - $PROJ_DIR$\test_mempool.c - - - $PROJ_DIR$\test_mutex.c - - - $PROJ_DIR$\test_netint.c - - - $PROJ_DIR$\test_pack.c - - - $PROJ_DIR$\test_rbtree.c - - - $PROJ_DIR$\test_rwlock.c - - - $PROJ_DIR$\test_signal.c - - - $PROJ_DIR$\test_socket.c - - - $PROJ_DIR$\test_thread.c - - - $PROJ_DIR$\test_timer.c - - - - diff --git a/tests/unit/mqx/iar/test_mempool.c b/tests/unit/mqx/iar/test_mempool.c deleted file mode 100644 index e9427186f..000000000 --- a/tests/unit/mqx/iar/test_mempool.c +++ /dev/null @@ -1,102 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include -#include "lwpa_mempool.h" - -struct test_elem -{ - int val1; - char val2; -}; - -#define TEST_ALLOC_MEMP_SIZE 500 -LWPA_MEMPOOL_DEFINE(alloc_test, struct test_elem, TEST_ALLOC_MEMP_SIZE); -struct alloctest -{ - struct test_elem* elem; - bool freed; -} test_array[TEST_ALLOC_MEMP_SIZE]; - -bool test_alloc() -{ - bool ok; - - ok = (kLwpaErrOk == lwpa_mempool_init(alloc_test)); - if (ok) - ok = (TEST_ALLOC_MEMP_SIZE == lwpa_mempool_size(alloc_test)); - if (ok) - { - int i; - /* Allocate the entire pool. */ - for (i = 0; i < TEST_ALLOC_MEMP_SIZE; ++i) - { - test_array[i].elem = (struct test_elem*)lwpa_mempool_alloc(alloc_test); - if (!test_array[i].elem) - { - ok = false; - break; - } - test_array[i].freed = false; - } - } - if (ok) - ok = (TEST_ALLOC_MEMP_SIZE == lwpa_mempool_used(alloc_test)); - if (ok) - { - int num_freed = 0; - /* Free the elements back in random order. */ - while (num_freed < TEST_ALLOC_MEMP_SIZE) - { - int i = (rand() % TEST_ALLOC_MEMP_SIZE); - if (!test_array[i].freed) - { - lwpa_mempool_free(alloc_test, test_array[i].elem); - test_array[i].freed = true; - ++num_freed; - } - } - ok = (0 == lwpa_mempool_used(alloc_test)); - } - if (ok) - { - int i; - /* Make sure we can allocate the entire pool again. */ - for (i = 0; i < TEST_ALLOC_MEMP_SIZE; ++i) - { - test_array[i].elem = (struct test_elem*)lwpa_mempool_alloc(alloc_test); - if (!test_array[i].elem) - { - ok = false; - break; - } - } - } - return ok; -} - -void test_mempool() -{ - bool ok; - OUTPUT_TEST_MODULE_BEGIN("mempool"); - watchdog_kick(); - OUTPUT_TEST_BEGIN("mempool_alloc"); - OUTPUT_TEST_RESULT((ok = test_alloc())); - OUTPUT_TEST_MODULE_END("mempool", ok); -} diff --git a/tests/unit/mqx/iar/test_mutex.c b/tests/unit/mqx/iar/test_mutex.c deleted file mode 100644 index 8011dd003..000000000 --- a/tests/unit/mqx/iar/test_mutex.c +++ /dev/null @@ -1,156 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include "lwpa_lock.h" - -/* Basic test of the four mutex functions. */ -bool test_mutex_create_destroy() -{ - bool ok; - uint32_t start_time; - lwpa_mutex_t mutex1, mutex2; - - ok = lwpa_mutex_create(&mutex1); - if (ok) - ok = lwpa_mutex_create(&mutex2); - if (ok) - ok = lwpa_mutex_take(&mutex1, LWPA_WAIT_FOREVER); - if (ok) - ok = lwpa_mutex_take(&mutex2, LWPA_WAIT_FOREVER); - if (ok) - { - lwpa_mutex_give(&mutex2); - lwpa_mutex_destroy(&mutex2); - /* Take should fail on a destroyed mutex. */ - ok = !lwpa_mutex_take(&mutex2, LWPA_WAIT_FOREVER); - } - if (ok) - { - start_time = getms(); - /* Take should time out on an already-taken mutex. */ - ok = !lwpa_mutex_take(&mutex1, 100); - } - if (ok) - /* It should wait for at least the timeout specified, minus up to one tick. */ - ok = ((getms() - start_time) >= (100 - _time_get_resolution())); - if (ok) - { - lwpa_mutex_give(&mutex1); - lwpa_mutex_destroy(&mutex1); - /* Take should fail on a destroyed mutex. */ - ok = !lwpa_mutex_take(&mutex1, LWPA_WAIT_FOREVER); - } - return ok; -} - -#define MUTEX_TEST_NUM_THREADS 10 -#define MUTEX_TEST_NUM_ITERATIONS 10000 -static bool mt_terminated[MUTEX_TEST_NUM_THREADS]; -static int g_shared_var; -struct thread_data -{ - lwpa_mutex_t* mutex; - int thread_num; -}; - -void mutex_test_thread(uint32_t initial_data) -{ - struct thread_data* td = (struct thread_data*)initial_data; - int i; - - for (i = 0; i < MUTEX_TEST_NUM_ITERATIONS; ++i) - { - lwpa_mutex_take(td->mutex, LWPA_WAIT_FOREVER); - ++g_shared_var; - lwpa_mutex_give(td->mutex); - } - mt_terminated[td->thread_num] = true; -} - -/* Test the actual mutex functionality. Start a number of time-slice threads at the same priority, - * and have them all increment the same variable inside a mutex. At the end of the test, the value - * of the variable should be exactly the number of threads times the number of times each thread - * incremented the variable. - * - * Yes, this test isn't guaranteed to fail if the mutexes don't work. But it's still a good test to - * run. A test on this platform where the mutex lines were commented showed failure very reliably. - */ -bool test_mutex_threads() -{ - TASK_TEMPLATE_STRUCT mtstruct; - int i; - lwpa_mutex_t mutex; - struct thread_data threads[MUTEX_TEST_NUM_THREADS]; - - if (!lwpa_mutex_create(&mutex)) - return false; - - mtstruct.TASK_ADDRESS = mutex_test_thread; - mtstruct.TASK_NAME = "mutex_test"; - mtstruct.TASK_PRIORITY = 10; - mtstruct.TASK_STACKSIZE = 1000; - mtstruct.TASK_ATTRIBUTES = MQX_TIME_SLICE_TASK; - mtstruct.DEFAULT_TIME_SLICE = 1; - - for (i = 0; i < MUTEX_TEST_NUM_THREADS; ++i) - { - _task_id id; - - threads[i].mutex = &mutex; - threads[i].thread_num = i; - mtstruct.CREATION_PARAMETER = (uint32_t)&threads[i]; - id = _task_create(0, 0, (uint32_t)&mtstruct); - if (id == MQX_NULL_TASK_ID) - return false; - } - - while (1) - { - bool keep_running = false; - _time_delay(100); - for (i = 0; i < MUTEX_TEST_NUM_THREADS; ++i) - if (!mt_terminated[i]) - { - keep_running = true; - break; - } - - if (!keep_running) - break; - } - - lwpa_mutex_destroy(&mutex); - return g_shared_var == (MUTEX_TEST_NUM_THREADS * MUTEX_TEST_NUM_ITERATIONS); -} - -bool test_mutex() -{ - bool ok; - - watchdog_kick(); - OUTPUT_TEST_BEGIN("mutex_create_destroy"); - OUTPUT_TEST_RESULT((ok = test_mutex_create_destroy())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("mutex_threads"); - OUTPUT_TEST_RESULT((ok = test_mutex_threads())); - } - return ok; -} diff --git a/tests/unit/mqx/iar/test_netint.c b/tests/unit/mqx/iar/test_netint.c deleted file mode 100644 index bf6a783e7..000000000 --- a/tests/unit/mqx/iar/test_netint.c +++ /dev/null @@ -1,154 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include -#include -#include "lwpa_netint.h" - -static LwpaNetintInfo* g_interfaces; -static size_t g_num_interfaces; - -bool test_enumerate() -{ - bool ok; - /* We are making an assumption that this test will be run on a system with at least one network interface. */ - g_num_interfaces = netint_get_num_interfaces(); - ok = (g_num_interfaces > 0); - if (ok) - { - g_interfaces = _mem_alloc_zero(g_num_interfaces * sizeof(LwpaNetintInfo)); - ok = (g_interfaces != NULL); - } - if (ok) - { - ok = (g_num_interfaces == netint_get_interfaces(g_interfaces, g_num_interfaces)); - } - if (ok) - { - size_t i; - size_t num_defaults = 0; - for (i = 0; i < g_num_interfaces; ++i) - { - ok = (0 < strlen(g_interfaces[i].name)); - if (!ok) - break; - if (g_interfaces[i].is_default) - ++num_defaults; - } - ok = (num_defaults == 1); - } - return ok; -} - -bool test_default() -{ - bool ok; - LwpaNetintInfo def_int; - - memset(&def_int, 0, sizeof def_int); - ok = netint_get_default_interface(&def_int); - if (ok) - ok = def_int.is_default; - if (ok) - { - size_t i; - for (i = 0; i < g_num_interfaces; ++i) - { - if (g_interfaces[i].is_default) - { - ok = (0 == memcmp(&def_int, &g_interfaces[i], sizeof def_int)); - if (!ok) - break; - } - } - } - return ok; -} - -/* TODO - test IPv6 */ -bool test_route() -{ - bool ok = true; - LwpaNetintInfo* iface; - - for (iface = g_interfaces; iface < g_interfaces + g_num_interfaces; ++iface) - { - uint32_t host; - uint32_t net; - uint32_t neighbor; - uint32_t remote; - uint32_t mask; - LwpaIpAddr dest_ip; - const LwpaNetintInfo* dest; - - if (LWPA_IP_IS_V6(&iface->addr)) - continue; - - mask = LWPA_IP_V4_ADDRESS(&iface->mask); - host = LWPA_IP_V4_ADDRESS(&iface->addr) & (~mask); - net = LWPA_IP_V4_ADDRESS(&iface->addr) & mask; - - /* Simulate another host on the same subnet. */ - neighbor = net | ((host + 1) & (~mask)); - - /* Simulate a host on a remote network by flipping the bottom bit of the network portion. */ - remote = 0x1u | (net ^ ((~mask) + 1)); - - /* Test the local neighbor */ - LWPA_IP_SET_V4_ADDRESS(&dest_ip, neighbor); - dest = netint_get_iface_for_dest(&dest_ip, g_interfaces, g_num_interfaces); - ok = (dest == iface); - if (!ok) - break; - - /* Test the remote host */ - LWPA_IP_SET_V4_ADDRESS(&dest_ip, remote); - dest = netint_get_iface_for_dest(&dest_ip, g_interfaces, g_num_interfaces); - ok = (dest->is_default); - if (!ok) - break; - } - - return ok; -} - -void test_netint() -{ - bool ok; - - OUTPUT_TEST_MODULE_BEGIN("netint"); - watchdog_kick(); - OUTPUT_TEST_BEGIN("enumerate"); - OUTPUT_TEST_RESULT((ok = test_enumerate())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("default"); - OUTPUT_TEST_RESULT((ok = test_default())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("route"); - OUTPUT_TEST_RESULT((ok = test_route())); - } - if (g_interfaces) - _mem_free(g_interfaces); - OUTPUT_TEST_MODULE_END("netint", ok); -} diff --git a/tests/unit/mqx/iar/test_pack.c b/tests/unit/mqx/iar/test_pack.c deleted file mode 100644 index e3b69da09..000000000 --- a/tests/unit/mqx/iar/test_pack.c +++ /dev/null @@ -1,276 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include "lwpa_pack.h" - -bool test_pack16b(uint8_t* buffer) -{ - const uint16_t tst = 0x1234; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint16_t)); - - pack_16b(buffer, tst); - if ((ptst[0] == buffer[1]) && (ptst[1] == buffer[0])) - return true; - return false; -} - -bool test_pack16l(uint8_t* buffer) -{ - const uint16_t tst = 0x1234; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint16_t)); - - pack_16l(buffer, tst); - if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1])) - return true; - return false; -} - -bool test_upack16b(uint8_t* buffer) -{ - const uint16_t tst = 0x1234; - uint16_t var; - memset(buffer, 0, sizeof(uint16_t)); - - pack_16b(buffer, tst); - var = upack_16b(buffer); - if (tst == var) - return true; - return false; -} - -bool test_upack16l(uint8_t* buffer) -{ - const uint16_t tst = 0x1234; - uint16_t var; - memset(buffer, 0, sizeof(uint16_t)); - - pack_16l(buffer, tst); - var = upack_16l(buffer); - if (tst == var) - return true; - return false; -} - -bool test_pack32b(uint8_t* buffer) -{ - const uint32_t tst = 0x12345678; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint32_t)); - - pack_32b(buffer, tst); - if ((ptst[0] == buffer[3]) && (ptst[1] == buffer[2]) && (ptst[2] == buffer[1]) && (ptst[3] == buffer[0])) - { - return true; - } - return false; -} - -bool test_pack32l(uint8_t* buffer) -{ - const uint32_t tst = 0x12345678; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint32_t)); - - pack_32l(buffer, tst); - if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1]) && (ptst[2] == buffer[2]) && (ptst[3] == buffer[3])) - { - return true; - } - return false; -} - -bool test_upack32b(uint8_t* buffer) -{ - const uint32_t tst = 0x12345678; - uint32_t var; - memset(buffer, 0, sizeof(uint32_t)); - - pack_32b(buffer, tst); - var = upack_32b(buffer); - if (tst == var) - return true; - return false; -} - -bool test_upack32l(uint8_t* buffer) -{ - const uint32_t tst = 0x12345678; - uint32_t var; - memset(buffer, 0, sizeof(uint32_t)); - - pack_32l(buffer, tst); - var = upack_32l(buffer); - if (tst == var) - return true; - return false; -} - -bool test_pack64b(uint8_t* buffer) -{ - const uint64_t tst = 0x1234567890abcdef; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint64_t)); - - pack_64b(buffer, tst); - if ((ptst[0] == buffer[7]) && (ptst[1] == buffer[6]) && (ptst[2] == buffer[5]) && (ptst[3] == buffer[4]) && - (ptst[4] == buffer[3]) && (ptst[5] == buffer[2]) && (ptst[6] == buffer[1]) && (ptst[7] == buffer[0])) - { - return true; - } - return false; -} - -bool test_pack64l(uint8_t* buffer) -{ - const uint64_t tst = 0x1234567890abcdef; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint64_t)); - - pack_64l(buffer, tst); - if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1]) && (ptst[2] == buffer[2]) && (ptst[3] == buffer[3]) && - (ptst[4] == buffer[4]) && (ptst[5] == buffer[5]) && (ptst[6] == buffer[6]) && (ptst[7] == buffer[7])) - { - return true; - } - return false; -} - -bool test_upack64b(uint8_t* buffer) -{ - const uint64_t tst = 0x1234567890abcdef; - uint64_t var; - memset(buffer, 0, sizeof(uint64_t)); - - pack_64b(buffer, tst); - var = upack_64b(buffer); - if (tst == var) - return true; - return false; -} - -bool test_upack64l(uint8_t* buffer) -{ - const uint64_t tst = 0x1234567890abcdef; - uint64_t var; - memset(buffer, 0, sizeof(uint64_t)); - - pack_64l(buffer, tst); - var = upack_64l(buffer); - if (tst == var) - return true; - return false; -} - -bool test_pack16(uint8_t* buffer) -{ - int offset = 0; - bool ok; - - /* We test the packing and unpacking at weird offsets. */ - for (offset = 0; offset <= 60; ++offset) - { - ok = test_pack16b(buffer + offset); - if (!ok) - break; - ok = test_pack16l(buffer + offset); - if (!ok) - break; - ok = test_upack16b(buffer + offset); - if (!ok) - break; - ok = test_upack16l(buffer + offset); - if (!ok) - break; - } - return ok; -} - -bool test_pack32(uint8_t* buffer) -{ - int offset = 0; - bool ok; - - /* We test the packing and unpacking at weird offsets. */ - for (offset = 0; offset <= 60; ++offset) - { - ok = test_pack32b(buffer + offset); - if (!ok) - break; - ok = test_pack32l(buffer + offset); - if (!ok) - break; - ok = test_upack32b(buffer + offset); - if (!ok) - break; - ok = test_upack32l(buffer + offset); - if (!ok) - break; - } - return ok; -} - -bool test_pack64(uint8_t* buffer) -{ - int offset = 0; - bool ok; - - /* We test the packing and unpacking at weird offsets. */ - for (offset = 0; offset <= 60; ++offset) - { - ok = test_pack64b(buffer + offset); - if (!ok) - break; - ok = test_pack64l(buffer + offset); - if (!ok) - break; - ok = test_upack64b(buffer + offset); - if (!ok) - break; - ok = test_upack64l(buffer + offset); - if (!ok) - break; - } - return ok; -} - -void test_pack() -{ - uint8_t buffer[100]; /* What we pack and unpack from. */ - bool ok; - - OUTPUT_TEST_MODULE_BEGIN("pack"); - watchdog_kick(); - OUTPUT_TEST_BEGIN("pack_16"); - OUTPUT_TEST_RESULT((ok = test_pack16(buffer))); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("pack_32"); - OUTPUT_TEST_RESULT((ok = test_pack32(buffer))); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("pack_64"); - OUTPUT_TEST_RESULT((ok = test_pack64(buffer))); - } - OUTPUT_TEST_MODULE_END("pack", ok); -} diff --git a/tests/unit/mqx/iar/test_rbtree.c b/tests/unit/mqx/iar/test_rbtree.c deleted file mode 100644 index 874b77b4d..000000000 --- a/tests/unit/mqx/iar/test_rbtree.c +++ /dev/null @@ -1,356 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include -#include -#include "lwpa_rbtree.h" - -#define INT_ARRAY_SIZE 100 -int incrementing_int_array[INT_ARRAY_SIZE]; - -static int g_alloc_call_count; -static LwpaRbNode* node_alloc() -{ - ++g_alloc_call_count; - return (LwpaRbNode*)_mem_alloc(sizeof(LwpaRbNode)); -} - -static int g_dealloc_call_count; -static void node_dealloc(LwpaRbNode* node) -{ - ++g_dealloc_call_count; - _mem_free(node); -} - -static int int_cmp(const LwpaRbTree* self, const LwpaRbNode* node_a, const LwpaRbNode* node_b) -{ - int a = *(int*)node_a->value; - int b = *(int*)node_b->value; - return a - b; -} - -static int intval_pool[INT_ARRAY_SIZE]; -static LwpaRbNode node_pool[INT_ARRAY_SIZE]; - -static int g_clearfunc_call_count; -bool remove_one_flag; -#define MAGIC_REMOVE_VALUE (INT_ARRAY_SIZE / 2) -static void clear_func(const LwpaRbTree* self, LwpaRbNode* node) -{ - if (remove_one_flag && *(int*)node->value == MAGIC_REMOVE_VALUE) - remove_one_flag = false; - ++g_clearfunc_call_count; -} - -bool test_insert_static() -{ - int i; - LwpaRbTree tree; - bool ok; - - ok = (NULL != rb_tree_init(&tree, int_cmp, NULL, NULL)); - if (ok) - { - /* Copy and shuffle the integer array */ - memcpy(intval_pool, incrementing_int_array, sizeof intval_pool); - for (i = 0; i < INT_ARRAY_SIZE; ++i) - { - /* Swap the number at this index with the number at a random index later in the array */ - int index = i + rand() / (RAND_MAX / (INT_ARRAY_SIZE - i) + 1); - int t = intval_pool[index]; - intval_pool[index] = intval_pool[i]; - intval_pool[i] = t; - } - /* Now, point each node at its respective value and insert it into the tree */ - for (i = 0; i < INT_ARRAY_SIZE; ++i) - { - LwpaRbNode* node = &node_pool[i]; - ok = (NULL != rb_node_init(node, &intval_pool[i])); - if (!ok) - break; - ok = (0 != rb_tree_insert_node(&tree, node)); - if (!ok) - break; - } - } - if (ok) - ok = (rb_tree_size(&tree) == INT_ARRAY_SIZE); - if (ok) - ok = (0 != rb_tree_test(&tree, tree.root)); - if (ok) - { - int to_find = rand() / (RAND_MAX / INT_ARRAY_SIZE + 1); - int* found = (int*)rb_tree_find(&tree, &to_find); - ok = (found != NULL && *found == to_find); - } - if (ok) - { - g_clearfunc_call_count = 0; - remove_one_flag = true; - int to_remove = MAGIC_REMOVE_VALUE; - ok = (0 != rb_tree_remove_with_cb(&tree, &to_remove, clear_func)) && !remove_one_flag; - } - if (ok) - ok = (0 != rb_tree_clear_with_cb(&tree, clear_func)); - if (ok) - ok = (rb_tree_size(&tree) == 0); - if (ok) - ok = (g_clearfunc_call_count == INT_ARRAY_SIZE); - return ok; -} - -bool test_insert_dynamic() -{ - int i; - LwpaRbTree tree; - bool ok; - - g_alloc_call_count = g_dealloc_call_count = 0; - ok = (NULL != rb_tree_init(&tree, int_cmp, node_alloc, node_dealloc)); - if (ok) - { - /* Copy and shuffle the integer array */ - memcpy(intval_pool, incrementing_int_array, sizeof intval_pool); - for (i = 0; i < INT_ARRAY_SIZE; ++i) - { - /* Swap the number at this index with the number at a random index later in the array */ - int index = i + rand() / (RAND_MAX / (INT_ARRAY_SIZE - i) + 1); - int t = intval_pool[index]; - intval_pool[index] = intval_pool[i]; - intval_pool[i] = t; - } - /* Now, insert each value into the tree; dynamic alloc functions should be called. */ - for (i = 0; i < INT_ARRAY_SIZE; ++i) - { - ok = (0 != rb_tree_insert(&tree, &intval_pool[i])); - if (!ok) - break; - } - } - if (ok) - ok = (rb_tree_size(&tree) == INT_ARRAY_SIZE); - if (ok) - ok = (g_alloc_call_count == INT_ARRAY_SIZE); - if (ok) - ok = (0 != rb_tree_test(&tree, tree.root)); - if (ok) - { - int to_find = rand() / (RAND_MAX / INT_ARRAY_SIZE + 1); - int* found = (int*)rb_tree_find(&tree, &to_find); - ok = (found != NULL && *found == to_find); - } - if (ok) - { - int not_in_tree = INT_ARRAY_SIZE + 1; - ok = (0 == rb_tree_remove(&tree, ¬_in_tree)); - } - if (ok) - ok = (0 != rb_tree_clear(&tree)); - if (ok) - ok = (rb_tree_size(&tree) == 0); - if (ok) - ok = (g_dealloc_call_count == INT_ARRAY_SIZE); - return ok; -} - -bool test_iter() -{ - int i; - LwpaRbTree tree; - LwpaRbIter iter; - int* val = NULL; - bool ok; - - ok = (NULL != rb_tree_init(&tree, int_cmp, node_alloc, node_dealloc)); - if (ok) - { - /* Copy and shuffle the integer array */ - memcpy(intval_pool, incrementing_int_array, sizeof intval_pool); - for (i = 0; i < INT_ARRAY_SIZE; ++i) - { - /* Swap the number at this index with the number at a random index later in the array */ - int index = i + rand() / (RAND_MAX / (INT_ARRAY_SIZE - i) + 1); - int t = intval_pool[index]; - intval_pool[index] = intval_pool[i]; - intval_pool[i] = t; - } - /* Now, insert each value into the tree; dynamic alloc functions should be called. */ - for (i = 0; i < INT_ARRAY_SIZE; ++i) - { - ok = (0 != rb_tree_insert(&tree, &intval_pool[i])); - if (!ok) - break; - } - } - if (ok) - ok = (rb_tree_size(&tree) == INT_ARRAY_SIZE); - if (ok) - ok = (NULL != rb_iter_init(&iter)); - if (ok) - { - val = (int*)rb_iter_first(&iter, &tree); - /* Although the elements were inserted in random order, the tree should be sorted so 0 should be - * the first value. */ - ok = (*val == 0); - } - if (ok) - { - size_t num_iterations = 1; - int last_val = *val; - while ((val = (int*)rb_iter_next(&iter))) - { - ++num_iterations; - /* Each value given by the iterator should be numerically higher than the one that came before - * it. */ - if (*val < last_val) - { - ok = false; - break; - } - last_val = *val; - } - if (ok) - ok = (num_iterations == INT_ARRAY_SIZE); - } - if (ok) - { - val = (int*)rb_iter_last(&iter, &tree); - /* Although the elements were inserted in random order, the tree should be sorted so - * INT_ARRAY_SIZE - 1 should be the last value. */ - ok = (*val == (INT_ARRAY_SIZE - 1)); - } - if (ok) - { - size_t num_iterations = 1; - int last_val = *val; - while ((val = (int*)rb_iter_prev(&iter))) - { - ++num_iterations; - /* Each value given by the reverse iterator should be numerically smaller than the one that - * came before it. */ - if (*val > last_val) - { - ok = false; - break; - } - last_val = *val; - } - if (ok) - ok = (num_iterations == INT_ARRAY_SIZE); - } - if (ok) - { - g_dealloc_call_count = 0; - ok = (0 != rb_tree_clear(&tree)); - } - if (ok) - ok = (rb_tree_size(&tree) == 0); - if (ok) - ok = (g_dealloc_call_count == INT_ARRAY_SIZE); - return ok; -} - -bool test_max_height() -{ - int i; - LwpaRbTree tree; - bool ok; - - ok = (NULL != rb_tree_init(&tree, int_cmp, node_alloc, node_dealloc)); - if (ok) - { - /* Insert monotonically incrementing values into the tree. In a traditional binary tree, this - * would result in a worst-case unbalanced tree of height INT_ARRAY_SIZE. In the red-black tree, - * the maximum height should be determined by the formula 2 * log2(INT_ARRAY_SIZE + 1). */ - for (i = 0; i < INT_ARRAY_SIZE; ++i) - { - ok = (0 != rb_tree_insert(&tree, &incrementing_int_array[i])); - if (!ok) - break; - } - } - if (ok) - ok = (rb_tree_size(&tree) == INT_ARRAY_SIZE); - if (ok) - { - LwpaRbIter iter; - size_t max_height = 0; - size_t theoretical_max_height; - ok = (NULL != rb_iter_init(&iter)); - if (ok) - ok = (NULL != rb_iter_first(&iter, &tree)); - if (ok) - { - do - { - if (iter.top > max_height) - max_height = iter.top; - } while (NULL != rb_iter_next(&iter)); - max_height += 1; - /* http://www.doctrina.org/maximum-height-of-red-black-tree.html */ - theoretical_max_height = 2 * (size_t)(log(INT_ARRAY_SIZE + 1) / log(2)); - ok = (max_height <= theoretical_max_height); - } - } - if (ok) - { - g_dealloc_call_count = 0; - ok = (0 != rb_tree_clear(&tree)); - } - if (ok) - ok = (rb_tree_size(&tree) == 0); - if (ok) - ok = (g_dealloc_call_count == INT_ARRAY_SIZE); - return ok; -} - -void test_rbtree() -{ - bool ok; - int i; - - OUTPUT_TEST_MODULE_BEGIN("rb_tree"); - watchdog_kick(); - - /* Initialize the int array */ - for (i = 0; i < INT_ARRAY_SIZE; ++i) - incrementing_int_array[i] = i; - - OUTPUT_TEST_BEGIN("rb_tree_insert_static"); - OUTPUT_TEST_RESULT((ok = test_insert_static())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("rb_tree_insert_dynamic"); - OUTPUT_TEST_RESULT((ok = test_insert_dynamic())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("rb_tree_iterate"); - OUTPUT_TEST_RESULT((ok = test_iter())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("rb_tree_max_height"); - OUTPUT_TEST_RESULT((ok = test_max_height())); - } - OUTPUT_TEST_MODULE_END("rb_tree", ok); -} diff --git a/tests/unit/mqx/iar/test_rwlock.c b/tests/unit/mqx/iar/test_rwlock.c deleted file mode 100644 index 4767199c3..000000000 --- a/tests/unit/mqx/iar/test_rwlock.c +++ /dev/null @@ -1,274 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include "lwpa_lock.h" - -bool test_rwlock_create_destroy() -{ - lwpa_rwlock_t rwlock1, rwlock2, rwlock3; - uint32_t start_time; - bool ok; - - ok = lwpa_rwlock_create(&rwlock1); - if (ok) - ok = lwpa_rwlock_create(&rwlock2); - if (ok) - ok = lwpa_rwlock_create(&rwlock3); - - /* Should be able to take and give the write locks in any order */ - if (ok) - ok = lwpa_rwlock_writelock(&rwlock1, LWPA_WAIT_FOREVER); - if (ok) - ok = lwpa_rwlock_writelock(&rwlock2, LWPA_WAIT_FOREVER); - if (ok) - ok = lwpa_rwlock_writelock(&rwlock3, LWPA_WAIT_FOREVER); - if (ok) - { - lwpa_rwlock_writeunlock(&rwlock2); - lwpa_rwlock_writeunlock(&rwlock3); - lwpa_rwlock_writeunlock(&rwlock1); - } - if (ok) - ok = lwpa_rwlock_writelock(&rwlock1, LWPA_WAIT_FOREVER); - if (ok) - ok = lwpa_rwlock_writelock(&rwlock2, LWPA_WAIT_FOREVER); - if (ok) - ok = lwpa_rwlock_writelock(&rwlock3, LWPA_WAIT_FOREVER); - if (ok) - { - lwpa_rwlock_writeunlock(&rwlock1); - lwpa_rwlock_writeunlock(&rwlock3); - lwpa_rwlock_writeunlock(&rwlock2); - } - if (ok) - { - int i; - for (i = 0; i < 100; ++i) - { - /* Should be able to get as many read locks as we want at once */ - ok = lwpa_rwlock_readlock(&rwlock1, LWPA_WAIT_FOREVER); - if (!ok) - break; - } - } - if (ok) - { - start_time = getms(); - /* Write lock should fail on a read/write lock with readers */ - ok = !lwpa_rwlock_writelock(&rwlock1, 100); - } - if (ok) - /* It should wait for at least the timeout specified, minus up to one tick. */ - ok = ((getms() - start_time) >= (100 - _time_get_resolution())); - if (ok) - { - int i; - for (i = 0; i < 100; ++i) - lwpa_rwlock_readunlock(&rwlock1); - /* When there are no more readers, write lock should succeed */ - ok = lwpa_rwlock_writelock(&rwlock1, LWPA_WAIT_FOREVER); - } - if (ok) - { - start_time = getms(); - /* Write lock should fail when there is already a write lock */ - ok = !lwpa_rwlock_writelock(&rwlock1, 100); - } - if (ok) - /* It should wait for at least the timeout specified, minus up to one tick. */ - ok = ((getms() - start_time) >= (100 - _time_get_resolution())); - if (ok) - { - lwpa_rwlock_writeunlock(&rwlock1); - lwpa_rwlock_destroy(&rwlock1); - lwpa_rwlock_destroy(&rwlock2); - lwpa_rwlock_destroy(&rwlock3); - /* Read lock should fail on a destroyed read/write lock. */ - ok = !lwpa_rwlock_readlock(&rwlock1, LWPA_WAIT_FOREVER); - } - if (ok) - /* Write lock should fail on a destroyed read/write lock. */ - ok = !lwpa_rwlock_writelock(&rwlock2, LWPA_WAIT_FOREVER); - if (ok) - /* Write lock should fail on a destroyed read/write lock. */ - ok = !lwpa_rwlock_writelock(&rwlock3, LWPA_WAIT_FOREVER); - return ok; -} - -#define RWLOCK_TEST_NUM_WRITE_THREADS 10 -#define RWLOCK_TEST_NUM_READ_THREADS 1 -#define RWLOCK_TEST_NUM_THREADS (RWLOCK_TEST_NUM_WRITE_THREADS + RWLOCK_TEST_NUM_READ_THREADS) -#define RWLOCK_TEST_NUM_ITERATIONS 10000 -static int g_shared_var; -struct thread_data -{ - lwpa_rwlock_t* rwlock; - int thread_num; - bool done; - bool passed; -}; - -void write_test_thread(uint32_t initial_data) -{ - struct thread_data* td = (struct thread_data*)initial_data; - int i; - - for (i = 0; i < RWLOCK_TEST_NUM_ITERATIONS; ++i) - { - lwpa_rwlock_writelock(td->rwlock, LWPA_WAIT_FOREVER); - ++g_shared_var; - lwpa_rwlock_writeunlock(td->rwlock); - } - td->passed = true; - td->done = true; -} - -void read_test_thread(uint32_t initial_data) -{ - struct thread_data* td = (struct thread_data*)initial_data; - int i; - - td->passed = true; - for (i = 0; i < 10; ++i) - { - int val; - lwpa_rwlock_readlock(td->rwlock, LWPA_WAIT_FOREVER); - val = g_shared_var; - _time_delay(50); - /* Make sure the value hasn't changed. */ - if (val != g_shared_var) - { - td->passed = false; - break; - } - lwpa_rwlock_readunlock(td->rwlock); - _time_delay(50); - } - td->done = true; -} - -/* Test the actual read-write lock functionality. Start a number of time-slice threads at the same - * priority, and have them all increment the same variable inside a write lock. Meanwhile, a - * higher-priority task periodically reads the variable. At the end of the test, the value of the - * variable should be exactly the number of threads times the number of times each thread - * incremented the variable. - * - * Yes, this test isn't guaranteed to fail if the read-write locks don't work. But it's still a good - * test to run. A test on this platform where the lock lines were commented showed failure very - * reliably. */ -bool test_rwlock_threads() -{ - TASK_TEMPLATE_STRUCT rtstruct; - int i; - bool ok = true; - lwpa_rwlock_t rwlock; - struct thread_data threads[RWLOCK_TEST_NUM_THREADS]; - - if (!lwpa_rwlock_create(&rwlock)) - return false; - - rtstruct.TASK_ADDRESS = write_test_thread; - rtstruct.TASK_NAME = "lock_write_test"; - rtstruct.TASK_PRIORITY = 11; - rtstruct.TASK_STACKSIZE = 1000; - rtstruct.TASK_ATTRIBUTES = MQX_TIME_SLICE_TASK; - rtstruct.DEFAULT_TIME_SLICE = 1; - - for (i = 0; i < RWLOCK_TEST_NUM_WRITE_THREADS; ++i) - { - _task_id id; - threads[i].rwlock = &rwlock; - threads[i].thread_num = i; - threads[i].done = false; - threads[i].passed = false; - rtstruct.CREATION_PARAMETER = (uint32_t)&threads[i]; - id = _task_create(0, 0, (uint32_t)&rtstruct); - if (id == MQX_NULL_TASK_ID) - return false; - } - - rtstruct.TASK_ADDRESS = read_test_thread; - rtstruct.TASK_NAME = "lock_read_test"; - rtstruct.TASK_PRIORITY = 10; - rtstruct.TASK_ATTRIBUTES = 0; - rtstruct.DEFAULT_TIME_SLICE = 0; - - for (i = 0; i < RWLOCK_TEST_NUM_READ_THREADS; ++i) - { - _task_id id; - int j = i + RWLOCK_TEST_NUM_WRITE_THREADS; - threads[j].rwlock = &rwlock; - threads[j].thread_num = j; - threads[j].done = false; - threads[j].passed = false; - rtstruct.CREATION_PARAMETER = (uint32_t)&threads[j]; - id = _task_create(0, 0, (uint32_t)&rtstruct); - if (id == MQX_NULL_TASK_ID) - return false; - } - - while (1) - { - bool keep_running = false; - _time_delay(100); - for (i = 0; i < RWLOCK_TEST_NUM_THREADS; ++i) - { - if (!threads[i].done) - { - keep_running = true; - break; - } - } - - if (!keep_running) - break; - } - for (i = 0; i < RWLOCK_TEST_NUM_THREADS; ++i) - { - if (!threads[i].passed) - { - ok = false; - break; - } - } - - if (ok) - { - ok = (g_shared_var == (RWLOCK_TEST_NUM_WRITE_THREADS * RWLOCK_TEST_NUM_ITERATIONS)); - } - - lwpa_rwlock_destroy(&rwlock); - return ok; -} - -bool test_rwlock() -{ - bool ok; - - watchdog_kick(); - OUTPUT_TEST_BEGIN("rwlock_create_destroy"); - OUTPUT_TEST_RESULT((ok = test_rwlock_create_destroy())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("rwlock_threads"); - OUTPUT_TEST_RESULT((ok = test_rwlock_threads())); - } - return ok; -} diff --git a/tests/unit/mqx/iar/test_signal.c b/tests/unit/mqx/iar/test_signal.c deleted file mode 100644 index 90eefc79b..000000000 --- a/tests/unit/mqx/iar/test_signal.c +++ /dev/null @@ -1,154 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include "lwpa_lock.h" - -/* Test the basic signal functions. */ -bool test_signal_create_destroy() -{ - bool ok; - uint32_t start_time; - lwpa_signal_t signal1, signal2; - - ok = lwpa_signal_create(&signal1); - if (ok) - ok = lwpa_signal_create(&signal2); - if (ok) - /* Signals shouldn't be created in the signaled state */ - ok = !lwpa_signal_wait(&signal1, 0); - if (ok) - { - /* Wait should succeed on a signal that has previously been posted. */ - lwpa_signal_post(&signal1); - ok = lwpa_signal_wait(&signal1, LWPA_WAIT_FOREVER); - } - if (ok) - { - start_time = getms(); - /* Wait should time out on a signal that hasn't been posted. */ - ok = !lwpa_signal_wait(&signal2, 100); - } - if (ok) - /* It should wait for at least the timeout specified, minus up to one tick. */ - ok = (getms() - start_time >= (100 - _time_get_resolution())); - if (ok) - { - /* Wait should succeed on a signal that has been posted. */ - lwpa_signal_post(&signal2); - ok = lwpa_signal_wait(&signal2, LWPA_WAIT_FOREVER); - } - if (ok) - { - lwpa_signal_destroy(&signal1); - lwpa_signal_destroy(&signal2); - /* Wait should fail on a destroyed signal */ - ok = !lwpa_signal_wait(&signal1, LWPA_WAIT_FOREVER); - } - if (ok) - ok = !lwpa_signal_wait(&signal2, LWPA_WAIT_FOREVER); - return ok; -} - -struct thread_data -{ - lwpa_signal_t* signal; - int thread_num; - bool passed; -}; - -void signal_test_thread(uint32_t initial_data) -{ - struct thread_data* td = (struct thread_data*)initial_data; - int i; - - for (i = 0; i < 3; ++i) - lwpa_signal_wait(td->signal, LWPA_WAIT_FOREVER); - td->passed = true; -} - -/* Two tasks are created with higher priority than the main task. They wait on the same signal 3 - * times. Each post of the signal should wake up only one of the tasks, so 6 posts should end both - * threads. */ -bool test_signal_threads() -{ - TASK_TEMPLATE_STRUCT mtstruct; - lwpa_signal_t signal; - struct thread_data threads[2]; - int i; - - if (!lwpa_signal_create(&signal)) - return false; - - mtstruct.TASK_ADDRESS = signal_test_thread; - mtstruct.TASK_NAME = "signal_test"; - mtstruct.TASK_PRIORITY = 8; - mtstruct.TASK_STACKSIZE = 1000; - mtstruct.TASK_ATTRIBUTES = 0; - mtstruct.DEFAULT_TIME_SLICE = 0; - - for (i = 0; i < 2; ++i) - { - _task_id id; - threads[i].signal = &signal; - threads[i].thread_num = i; - threads[i].passed = false; - mtstruct.CREATION_PARAMETER = (uint32_t)&threads[i]; - id = _task_create(0, 0, (uint32_t)&mtstruct); - if (id == MQX_NULL_TASK_ID) - return false; - } - - for (i = 0; i < 6; ++i) - lwpa_signal_post(&signal); - - while (1) - { - bool keep_running = false; - for (i = 0; i < 2; ++i) - if (!threads[i].passed) - { - keep_running = true; - break; - } - - if (!keep_running) - break; - _time_delay(100); - } - - lwpa_signal_destroy(&signal); - /* If we got here, the threads reported success; the failure mode is a watchdog timeout. */ - return true; -} - -bool test_signal() -{ - bool ok; - - watchdog_kick(); - OUTPUT_TEST_BEGIN("signal_create_destroy"); - OUTPUT_TEST_RESULT((ok = test_signal_create_destroy())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("signal_threads"); - OUTPUT_TEST_RESULT((ok = test_signal_threads())); - } - return ok; -} diff --git a/tests/unit/mqx/iar/test_socket.c b/tests/unit/mqx/iar/test_socket.c deleted file mode 100644 index c3081cbf8..000000000 --- a/tests/unit/mqx/iar/test_socket.c +++ /dev/null @@ -1,544 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include -#include -#include -#include -#include "lwpa_socket.h" - -bool test_inet_xtox() -{ - bool ok; - LwpaIpAddr addr; - char str[LWPA_INET6_ADDRSTRLEN]; - const char* test_ip4_1 = "0.0.0.0"; - const char* test_ip4_2 = "255.255.255.255"; - const char* test_ip4_fail = "256.256.256.256"; - const char* test_ip6_1 = "::"; - const uint8_t test_ip6_1_bin[IPV6_BYTES] = {0}; - const char* test_ip6_2 = "::1"; - const uint8_t test_ip6_2_bin[IPV6_BYTES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - const char* test_ip6_3 = "ffff:FFFF:ffff:FFFF:ffff:FFFF:ffff:FFFF"; - const uint8_t test_ip6_3_bin[IPV6_BYTES] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const char* test_ip6_fail = "abcd::ef01::2345"; - - /* Test lwpa_inet_pton() */ - ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV4, test_ip4_1, &addr)); - if (ok) - ok = (LWPA_IP_V4_ADDRESS(&addr) == 0); - if (ok) - ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV4, test_ip4_2, &addr)); - if (ok) - ok = (LWPA_IP_V4_ADDRESS(&addr) == 0xffffffff); - if (ok) - ok = (kLwpaErrOk != lwpa_inet_pton(LWPA_IPV4, test_ip4_fail, &addr)); - if (ok) - ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV6, test_ip6_1, &addr)); - if (ok) - ok = (0 == memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_1_bin, IPV6_BYTES)); - if (ok) - ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV6, test_ip6_2, &addr)); - if (ok) - ok = (0 == memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_2_bin, IPV6_BYTES)); - if (ok) - ok = (kLwpaErrOk == lwpa_inet_pton(LWPA_IPV6, test_ip6_3, &addr)); - if (ok) - ok = (0 == memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_3_bin, IPV6_BYTES)); - if (ok) - ok = (kLwpaErrOk != lwpa_inet_pton(LWPA_IPV6, test_ip6_fail, &addr)); - - /* Test lwpa_inet_ntop() */ - if (ok) - { - LWPA_IP_SET_V4_ADDRESS(&addr, 0); - ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); - } - if (ok) - ok = (0 == strcmp(str, test_ip4_1)); - if (ok) - { - LWPA_IP_SET_V4_ADDRESS(&addr, 0xffffffff); - ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); - } - if (ok) - ok = (0 == strcmp(str, test_ip4_2)); - if (ok) - { - LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_1_bin); - ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); - } - if (ok) - ok = (0 == strcmp(str, test_ip6_1)); - if (ok) - { - LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_2_bin); - ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); - } - if (ok) - ok = (0 == strcmp(str, test_ip6_2)); - if (ok) - { - LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_3_bin); - ok = (kLwpaErrOk == lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); - } - if (ok) - { - ok = (0 == strcmp(str, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) || - (0 == strcmp(str, "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF")); - } - return ok; -} - -bool test_sockopts() -{ - /* TODO, need getsockopt() implemented for this */ - return true; -} - -#define NUM_TEST_PACKETS 1000 -#define SEND_MSG "testtesttest" -#define SEND_MSG_LEN 12 -struct sendthread_inf -{ - lwpa_socket_t send_sock; - LwpaSockaddr send_addr; -}; - -void send_thread(uint32_t initial_data) -{ - struct sendthread_inf* inf = (struct sendthread_inf*)initial_data; - const uint8_t* send_buf = (const uint8_t*)SEND_MSG; - size_t i; - - for (i = 0; i < NUM_TEST_PACKETS; ++i) - lwpa_sendto(inf->send_sock, send_buf, SEND_MSG_LEN, 0, &inf->send_addr); -} - -/* TODO test IPv6 */ -bool test_unicast_udp() -{ - bool ok; - lwpa_socket_t rcvsock1, rcvsock2, rcvsock3; - struct sendthread_inf stinf; - LwpaSockaddr bind_addr; - IPCFG_IP_ADDRESS_DATA ip_data; - TASK_TEMPLATE_STRUCT ststruct; - _task_id id; - - /* We'll just use the default interface for this test. */ - ipcfg_get_ip(BSP_DEFAULT_ENET_DEVICE, &ip_data); - - rcvsock1 = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (rcvsock1 != LWPA_SOCKET_INVALID); - if (ok) - { - rcvsock2 = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (rcvsock2 != LWPA_SOCKET_INVALID); - } - if (ok) - { - int intval = 1; - ok = (0 == lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); - } - if (ok) - { - rcvsock3 = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (rcvsock3 != LWPA_SOCKET_INVALID); - } - if (ok) - { - stinf.send_sock = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (stinf.send_sock != LWPA_SOCKET_INVALID); - } - if (ok) - ok = (0 == lwpa_close(rcvsock3)); - if (ok) - { - lwpaip_make_any_v4(&bind_addr.ip); - bind_addr.port = 8888; - /* Shouldn't be able to bind to a closed socket. */ - ok = (0 != lwpa_bind(rcvsock3, &bind_addr)); - } - if (ok) - { - /* Bind socket 1 to the wildcard address and port 8888. */ - ok = (0 == lwpa_bind(rcvsock1, &bind_addr)); - } - if (ok) - { - /* Bind socket 2 to the wildcard address and port 9999. */ - bind_addr.port = 9999; - ok = (0 == lwpa_bind(rcvsock2, &bind_addr)); - } - if (ok) - { - LWPA_IP_SET_V4_ADDRESS(&stinf.send_addr.ip, ip_data.ip); - stinf.send_addr.port = 8888; - - /* Start the send thread. */ - ststruct.TASK_ADDRESS = send_thread; - ststruct.TASK_NAME = "socket_test"; - ststruct.TASK_PRIORITY = 10; - ststruct.TASK_STACKSIZE = 1000; - ststruct.TASK_ATTRIBUTES = 0; - ststruct.DEFAULT_TIME_SLICE = 1; - ststruct.CREATION_PARAMETER = (uint32_t)&stinf; - id = _task_create(0, 0, (uint32_t)&ststruct); - if (id == MQX_NULL_TASK_ID) - ok = false; - } - if (ok) - { - size_t i; - for (i = 0; i < NUM_TEST_PACKETS; ++i) - { - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - ok = (SEND_MSG_LEN == lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr)); - if (!ok) - break; - ok = (lwpa_ip_equal(&stinf.send_addr.ip, &from_addr.ip) && (from_addr.port != 8888)); - if (!ok) - break; - buf[SEND_MSG_LEN] = '\0'; - ok = (0 == strcmp((char*)buf, SEND_MSG)); - if (!ok) - break; - } - } - if (ok) - { - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - /* recvfrom should time out because this socket is bound to a different - * port and we set the timeout option on this socket. */ - ok = (0 >= lwpa_recvfrom(rcvsock2, buf, SEND_MSG_LEN, 0, &from_addr)); - } - if (ok) - { - /* Let the send thread end */ - _time_delay(100); - ok = (0 == lwpa_close(rcvsock1)); - } - if (ok) - ok = (0 == lwpa_close(rcvsock2)); - if (ok) - ok = (0 == lwpa_close(stinf.send_sock)); - return ok; -} - -#define TEST_MCAST_ADDR 0xec02054d /* 236.2.5.77 */ - -bool test_multicast_udp() -{ - bool ok; - lwpa_socket_t rcvsock1, rcvsock2; - struct sendthread_inf stinf; - LwpaSockaddr bind_addr; - IPCFG_IP_ADDRESS_DATA ip_data; - TASK_TEMPLATE_STRUCT ststruct; - _task_id id; - - /* We'll just use the default interface for this test. */ - ipcfg_get_ip(BSP_DEFAULT_ENET_DEVICE, &ip_data); - - rcvsock1 = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (rcvsock1 != LWPA_SOCKET_INVALID); - if (ok) - { - int intval = 1; - ok = (0 == lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); - } - if (ok) - { - rcvsock2 = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (rcvsock2 != LWPA_SOCKET_INVALID); - } - if (ok) - { - int intval = 1; - ok = (0 == lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); - } - if (ok) - { - int intval = 1; - ok = (0 == lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); - } - if (ok) - { - stinf.send_sock = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (stinf.send_sock != LWPA_SOCKET_INVALID); - } - if (ok) - { - /* Bind socket 1 to the multicast address and port 8888. */ - LWPA_IP_SET_V4_ADDRESS(&bind_addr.ip, TEST_MCAST_ADDR); - bind_addr.port = 8888; - ok = (0 == lwpa_bind(rcvsock1, &bind_addr)); - } - if (ok) - { - /* Bind socket 2 to the multicast address and port 9999. */ - bind_addr.port = 9999; - ok = (0 == lwpa_bind(rcvsock2, &bind_addr)); - } - if (ok) - { - /* Subscribe socket 1 to the multicast address. */ - LwpaMreq mreq; - LWPA_IP_SET_V4_ADDRESS(&mreq.netint, ip_data.ip); - LWPA_IP_SET_V4_ADDRESS(&mreq.group, TEST_MCAST_ADDR); - ok = (0 == lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &mreq, sizeof mreq)); - /* Subscribe socket 2 to the multicast address */ - if (ok) - { - ok = (0 == lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &mreq, sizeof mreq)); - } - } - if (ok) - { - LWPA_IP_SET_V4_ADDRESS(&stinf.send_addr.ip, TEST_MCAST_ADDR); - stinf.send_addr.port = 8888; - - /* Start the send thread. */ - ststruct.TASK_ADDRESS = send_thread; - ststruct.TASK_NAME = "socket_test"; - ststruct.TASK_PRIORITY = 10; - ststruct.TASK_STACKSIZE = 1000; - ststruct.TASK_ATTRIBUTES = 0; - ststruct.DEFAULT_TIME_SLICE = 1; - ststruct.CREATION_PARAMETER = (uint32_t)&stinf; - id = _task_create(0, 0, (uint32_t)&ststruct); - if (id == MQX_NULL_TASK_ID) - ok = false; - } - if (ok) - { - size_t i; - for (i = 0; i < NUM_TEST_PACKETS; ++i) - { - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - ok = (SEND_MSG_LEN == lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr)); - if (!ok) - break; - ok = (from_addr.port != 8888); - if (!ok) - break; - buf[SEND_MSG_LEN] = '\0'; - ok = (0 == strcmp((char*)buf, SEND_MSG)); - if (!ok) - break; - } - } - if (ok) - { - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - /* recvfrom should time out because this socket is bound to a different - * port and we set the timeout option on this socket. */ - ok = (0 >= lwpa_recvfrom(rcvsock2, buf, SEND_MSG_LEN, 0, &from_addr)); - } - if (ok) - { - /* Let the send thread end */ - _time_delay(100); - ok = (0 == lwpa_close(rcvsock1)); - } - if (ok) - ok = (0 == lwpa_close(rcvsock2)); - if (ok) - ok = (0 == lwpa_close(stinf.send_sock)); - return ok; -} - -struct pt_sendthread_inf -{ - lwpa_socket_t send_sock; - LwpaSockaddr send_addr_1; - LwpaSockaddr send_addr_2; -}; - -void polltest_sendthread(uint32_t initial_data) -{ - struct pt_sendthread_inf* inf = (struct pt_sendthread_inf*)initial_data; - const uint8_t* send_buf = (const uint8_t*)SEND_MSG; - - lwpa_sendto(inf->send_sock, send_buf, SEND_MSG_LEN, 0, &inf->send_addr_1); - lwpa_sendto(inf->send_sock, send_buf, SEND_MSG_LEN, 0, &inf->send_addr_2); -} - -bool test_poll() -{ - bool ok; - lwpa_socket_t rcvsock1, rcvsock2; - struct pt_sendthread_inf stinf; - LwpaSockaddr bind_addr; - IPCFG_IP_ADDRESS_DATA ip_data; - TASK_TEMPLATE_STRUCT ststruct; - _task_id id; - - /* We'll just use the default interface for this test. */ - ipcfg_get_ip(BSP_DEFAULT_ENET_DEVICE, &ip_data); - - rcvsock1 = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (rcvsock1 != LWPA_SOCKET_INVALID); - if (ok) - { - rcvsock2 = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (rcvsock2 != LWPA_SOCKET_INVALID); - } - if (ok) - { - stinf.send_sock = lwpa_socket(LWPA_AF_INET, LWPA_DGRAM); - ok = (stinf.send_sock != LWPA_SOCKET_INVALID); - } - if (ok) - { - /* Bind socket 1 to the wildcard address and port 8888. */ - lwpaip_make_any_v4(&bind_addr.ip); - bind_addr.port = 8888; - ok = (0 == lwpa_bind(rcvsock1, &bind_addr)); - } - if (ok) - { - /* Bind socket 2 to the wildcard address and port 9999. */ - bind_addr.port = 9999; - ok = (0 == lwpa_bind(rcvsock2, &bind_addr)); - } - if (ok) - { - /* Test poll with nothing sending - should time out. */ - LwpaPollfd pfds[2]; - pfds[0].fd = rcvsock1; - pfds[0].events = LWPA_POLLIN; - pfds[1].fd = rcvsock2; - pfds[1].events = LWPA_POLLIN; - ok = (kLwpaErrTimedOut == lwpa_poll(pfds, 2, 100)); - } - if (ok) - { - LWPA_IP_SET_V4_ADDRESS(&stinf.send_addr_1.ip, ip_data.ip); - LWPA_IP_SET_V4_ADDRESS(&stinf.send_addr_2.ip, ip_data.ip); - stinf.send_addr_1.port = 8888; - stinf.send_addr_2.port = 9999; - - /* Start the send thread. */ - ststruct.TASK_ADDRESS = polltest_sendthread; - ststruct.TASK_NAME = "poll_test"; - ststruct.TASK_PRIORITY = 10; - ststruct.TASK_STACKSIZE = 1000; - ststruct.TASK_ATTRIBUTES = 0; - ststruct.DEFAULT_TIME_SLICE = 1; - ststruct.CREATION_PARAMETER = (uint32_t)&stinf; - id = _task_create(0, 0, (uint32_t)&ststruct); - if (id == MQX_NULL_TASK_ID) - ok = false; - } - if (ok) - { - LwpaPollfd pfds[2]; - int poll_res; - bool already_polled = false; - - poll_again: - pfds[0].fd = rcvsock1; - pfds[0].events = LWPA_POLLIN; - pfds[1].fd = rcvsock2; - pfds[1].events = LWPA_POLLIN; - poll_res = lwpa_poll(pfds, 2, LWPA_WAIT_FOREVER); - ok = (0 < poll_res); - if (ok) - { - int i; - for (i = 0; i < 2; ++i) - { - if (pfds[i].revents & LWPA_POLLIN) - { - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - ok = (SEND_MSG_LEN == lwpa_recvfrom(pfds[i].fd, buf, SEND_MSG_LEN, 0, &from_addr)); - if (!ok) - break; - ok = (lwpa_ip_equal(&stinf.send_addr_1.ip, &from_addr.ip) && (from_addr.port != 8888)); - if (!ok) - break; - buf[SEND_MSG_LEN] = '\0'; - ok = (0 == strcmp((char*)buf, SEND_MSG)); - if (!ok) - break; - } - } - } - if (poll_res < 2 && !already_polled) - { - already_polled = true; - goto poll_again; /* Yeah, yeah, shut up. It's a test app. */ - } - } - if (ok) - { - /* Let the send thread end */ - _time_delay(100); - ok = (0 == lwpa_close(rcvsock1)); - } - if (ok) - ok = (0 == lwpa_close(rcvsock2)); - if (ok) - ok = (0 == lwpa_close(stinf.send_sock)); - return ok; -} - -void test_socket() -{ - bool ok; - - OUTPUT_TEST_MODULE_BEGIN("socket"); - watchdog_kick(); - OUTPUT_TEST_BEGIN("inet_xtox"); - OUTPUT_TEST_RESULT((ok = test_inet_xtox())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("sockopts"); - OUTPUT_TEST_RESULT((ok = test_sockopts())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("unicast_udp"); - OUTPUT_TEST_RESULT((ok = test_unicast_udp())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("multicast_udp"); - OUTPUT_TEST_RESULT((ok = test_multicast_udp())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("poll"); - OUTPUT_TEST_RESULT((ok = test_poll())); - } - /* TODO tcp */ - OUTPUT_TEST_MODULE_END("socket", ok); -} diff --git a/tests/unit/mqx/iar/test_thread.c b/tests/unit/mqx/iar/test_thread.c deleted file mode 100644 index e7dcbed6a..000000000 --- a/tests/unit/mqx/iar/test_thread.c +++ /dev/null @@ -1,206 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include "lwpa_thread.h" - -static bool g_waitthread_run; - -void wait_and_exit(void* param) -{ - while (g_waitthread_run) - lwpa_thread_sleep(50); -} - -/* Basic test of the three thread functions. */ -bool test_thread_create_destroy() -{ - bool ok; - uint32_t start_time; - LwpaThreadParams params = { - 10, /* thread_priority */ - 1000, /* stack_size */ - "cd_thread", /* thread_name */ - NULL /* platform_data */ - }; - lwpa_thread_t wait_thread; - - g_waitthread_run = true; - ok = lwpa_thread_create(&wait_thread, ¶ms, wait_and_exit, NULL); - if (ok) - { - start_time = getms(); - /* Stop should time out if the thread is still looping. */ - ok = !lwpa_thread_stop(&wait_thread, 100); - } - if (ok) - /* It should wait for at least the timeout specified, minus up to one - * tick. */ - ok = ((getms() - start_time) >= (100 - _time_get_resolution())); - if (ok) - { - g_waitthread_run = false; - /* Stop should work if the thread has exited. */ - ok = lwpa_thread_stop(&wait_thread, LWPA_WAIT_FOREVER); - } - return ok; -} - -static volatile bool spin_task_run, oneshot_task_run; -static volatile bool spin_task_ran = false; -static volatile bool oneshot_task_ran = false; - -void increment_and_spin(void* param) -{ - spin_task_ran = true; - while (spin_task_run) - ; -} - -void oneshot(void* param) -{ - if (oneshot_task_run) - oneshot_task_ran = true; -} - -/* Test time slicing. One thread spins constantly; if time slicing works, the - * second thread should get a chance to set its flag. Failure mode could be the - * flag not being set or a full test timeout. */ -bool test_thread_time_slice() -{ - bool ok; - LwpaThreadParamsMqx mqx_params = { - MQX_TIME_SLICE_TASK, /* task_attributes */ - 1 /* time_slice */ - }; - LwpaThreadParams params = { - 10, /* thread_priority */ - 1000, /* stack_size */ - "ts_thread", /* thread_name */ - &mqx_params /* platform_data */ - }; - lwpa_thread_t spin_task, oneshot_task; - spin_task_run = true; - oneshot_task_run = true; - - /* Start the spin task */ - ok = lwpa_thread_create(&spin_task, ¶ms, increment_and_spin, NULL); - /* Start the one-shot task */ - if (ok) - ok = lwpa_thread_create(&oneshot_task, ¶ms, oneshot, NULL); - /* Give both tasks time to run */ - _time_delay(100); - /* Stop the oneshot task */ - oneshot_task_run = false; - lwpa_thread_stop(&oneshot_task, LWPA_WAIT_FOREVER); - /* Stop the spin task */ - spin_task_run = false; - lwpa_thread_stop(&spin_task, LWPA_WAIT_FOREVER); - - if (ok) - /* Both tasks should have gotten a chance to run. */ - ok = (spin_task_ran && oneshot_task_ran); - return ok; -} - -static int shared_var; -static bool lp_thread_done, lp_thread_passed, hp_thread_done; - -void low_priority_thread(void* param) -{ - lp_thread_passed = (shared_var == 1000); - lp_thread_done = true; -} - -void high_priority_thread(void* param) -{ - int i; - for (i = 0; i < 1000; ++i) - { - int j; - ++shared_var; - /* Simulate some other work being done */ - for (j = 0; j < 5000; ++j) - ; - } - hp_thread_done = true; -} - -/* Test priorities. The high priority thread should be able to increment the - * variable 1000 times before the low priority thread runs once, even though - * the threads are time-sliced. */ -bool test_thread_priorities() -{ - bool ok; - LwpaThreadParamsMqx mqx_params = { - MQX_TIME_SLICE_TASK, /* task_attributes */ - 1 /* time_slice */ - }; - LwpaThreadParams lp_params = { - 11, /* thread_priority */ - 1000, /* stack_size */ - "lp_thread", /* thread_name */ - &mqx_params /* platform_data */ - }; - LwpaThreadParams hp_params = { - 10, /* thread_priority */ - 1000, /* stack_size */ - "hp_thread", /* thread_name */ - &mqx_params /* platform_data */ - }; - lwpa_thread_t lp_thread, hp_thread; - - /* Start the low-priority thread */ - ok = lwpa_thread_create(&lp_thread, &lp_params, low_priority_thread, NULL); - /* Start the high-priority thread */ - if (ok) - ok = lwpa_thread_create(&hp_thread, &hp_params, high_priority_thread, NULL); - while (!hp_thread_done || !lp_thread_done) - /* Wait for both threads to finish. */ - _time_delay(50); - /* Threads should already be finished, stop just cleans up */ - lwpa_thread_stop(&lp_thread, LWPA_WAIT_FOREVER); - lwpa_thread_stop(&hp_thread, LWPA_WAIT_FOREVER); - if (ok) - /* The low-priority indicates that the shared value was as it expected. */ - ok = lp_thread_passed; - return ok; -} - -void test_thread() -{ - bool ok; - - OUTPUT_TEST_MODULE_BEGIN("thread"); - watchdog_kick(); - OUTPUT_TEST_BEGIN("thread_create_destroy"); - OUTPUT_TEST_RESULT((ok = test_thread_create_destroy())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("thread_time_slice"); - OUTPUT_TEST_RESULT((ok = test_thread_time_slice())); - } - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("thread_priorities"); - OUTPUT_TEST_RESULT((ok = test_thread_priorities())); - } - OUTPUT_TEST_MODULE_END("thread", ok); -} diff --git a/tests/unit/mqx/iar/test_timer.c b/tests/unit/mqx/iar/test_timer.c deleted file mode 100644 index c038f880f..000000000 --- a/tests/unit/mqx/iar/test_timer.c +++ /dev/null @@ -1,75 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpatest.h" -#include "lwpa_timer.h" - -bool test_getms() -{ - uint32_t t1, t2; - t1 = lwpa_getms(); - _time_delay(10); - t2 = lwpa_getms(); - - return (t1 != 0 && t2 != 0 && (((int32_t)t2 - (int32_t)t1) >= 0)); -} - -bool test_timeouts() -{ - LwpaTimer t1, t2; - bool ok; - - lwpa_timer_start(&t1, 0); - lwpa_timer_start(&t2, 100); - ok = lwpa_timer_isexpired(&t1); - if (ok) - ok = !lwpa_timer_isexpired(&t2); - if (ok) - { - _time_delay(110); - ok = lwpa_timer_isexpired(&t2) && lwpa_timer_elapsed(&t2) >= 100; - } - if (ok) - { - lwpa_timer_reset(&t2); - ok = !lwpa_timer_isexpired(&t2); - } - if (ok) - { - _time_delay(110); - ok = lwpa_timer_isexpired(&t2) && lwpa_timer_elapsed(&t2) >= 100; - } - return ok; -} - -void test_timer() -{ - bool ok; - - OUTPUT_TEST_MODULE_BEGIN("timer"); - watchdog_kick(); - OUTPUT_TEST_BEGIN("getms"); - OUTPUT_TEST_RESULT((ok = test_getms())); - if (ok) - { - watchdog_kick(); - OUTPUT_TEST_BEGIN("timeouts"); - OUTPUT_TEST_RESULT((ok = test_timeouts())); - } - OUTPUT_TEST_MODULE_END("timer", ok); -} diff --git a/tests/unit/mqx/testio.h b/tests/unit/mqx/testio.h deleted file mode 100644 index b75ff4d3a..000000000 --- a/tests/unit/mqx/testio.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _TEST_IO_H_ -#define _TEST_IO_H_ - -#include -#include - -/* A standard way for the embedded test apps to communicate test status back to - * a script, by way of simple parse-able output through the debugger - * semihosting console. */ - -#define OUTPUT_TEST_SUITE_BEGIN() printf("[TestSuiteBegin]\n") - -#define OUTPUT_TEST_SUITE_END() printf("[TestSuiteEnd]\n") - -#define OUTPUT_TEST_SUITE_TIMEOUT() printf("[TestSuiteTimeout]\n") - -#define OUTPUT_TEST_MODULE_BEGIN(name) printf("[TestModuleBegin:" name "]\n") - -#define OUTPUT_TEST_MODULE_END(name, did_pass) printf("[TestModuleEnd:" name ":%s]\n", did_pass ? "PASS" : "FAIL") - -#define OUTPUT_TEST_BEGIN(name) printf("[TestBegin:" name "]\n") - -#define OUTPUT_TEST_RESULT(did_pass) ((did_pass) ? printf("[TestResult:PASS]\n") : printf("[TestResult:FAIL]\n")) - -#endif /* _TEST_IO_H_ */ From 129696a8d3d2371192f1c4ba46c9ac65b4e009d9 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 19 Jun 2019 17:42:15 -0500 Subject: [PATCH 073/264] Update version files for lwpa build 0.3.0.1 --- include/lwpa/version.h | 8 ++++---- tools/version/current_version.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/lwpa/version.h b/include/lwpa/version.h index 9e8d29053..3d8ff58df 100644 --- a/include/lwpa/version.h +++ b/include/lwpa/version.h @@ -30,16 +30,16 @@ * @{ */ #define LWPA_VERSION_MAJOR 0 -#define LWPA_VERSION_MINOR 2 +#define LWPA_VERSION_MINOR 3 #define LWPA_VERSION_PATCH 0 -#define LWPA_VERSION_BUILD 3 +#define LWPA_VERSION_BUILD 1 /*! @} */ /*! \name lwpa version strings * @{ */ -#define LWPA_VERSION_STRING "0.2.0.3" -#define LWPA_VERSION_DATESTR "29.May.2019" +#define LWPA_VERSION_STRING "0.3.0.1" +#define LWPA_VERSION_DATESTR "19.Jun.2019" #define LWPA_VERSION_COPYRIGHT "Copyright 2019 ETC Inc." #define LWPA_VERSION_PRODUCTNAME "lwpa" /*! @} */ diff --git a/tools/version/current_version.txt b/tools/version/current_version.txt index e87283e4b..fd72fe621 100644 --- a/tools/version/current_version.txt +++ b/tools/version/current_version.txt @@ -1 +1 @@ -0.2.0.3 +0.3.0.1 From 544757fa25b506a126ddc32d38ef2b68307f7cb7 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 2 Jul 2019 10:25:13 -0500 Subject: [PATCH 074/264] Add EditorConfig file --- .editorconfig | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..58b8a6b44 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,24 @@ +# EditorConfig file for ETC R&D Network Products dept. +# +# To learn more about EditorConfig, go to https://editorconfig.org +# +# To enforce the settings in this file, you may need to download a plugin for +# your editor of choice: https://editorconfig.org/#download +# +# Currently covers C, C++ and Python +# Revision 1: 2019-07-01 + +# This is the top-level EditorConfig file for this project. +root = true + +# Settings to apply to every file affected by this EditorConfig +# Sections lower than this override this section. +[*.{c,cpp,cxx,c++,cc,h,hh,hpp,inl,ipp,py}] +indent_style = space # Indent using spaces +indent_size = 2 # Each indentation level is 2 spaces +trim_trailing_whitespace = true # Trim trailing whitespace from each line +insert_final_newline = true # Add a final newline to each file if missing + +# Specific overrides for Python only +[*.py] +indent_size = 4 # For Python, use 4 space indentation per PEP-8 From 4b5b3d4178a730a8409a5a3e036a58b7d8816e6b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 3 Jul 2019 14:35:58 -0500 Subject: [PATCH 075/264] Fix netint interface indexes --- CHANGELOG.md | 2 + examples/netint/netint_example.c | 4 +- include/lwpa/inet.h | 6 +-- include/lwpa/socket.h | 8 ++-- src/lwpa/netint.c | 6 +-- src/lwpa/private/netint.h | 2 +- src/os/linux/lwpa/os_netint.c | 18 ++++----- src/os/lwip/lwpa/os_netint.c | 5 ++- src/os/macos/lwpa/os_netint.c | 26 ++++++------ src/os/mqx/lwpa/os_inet.c | 68 +++++++++++++++++--------------- src/os/mqx/lwpa/os_netint.c | 26 ++++++------ src/os/mqx/lwpa/os_socket.c | 67 +++++++++++++++++++------------ src/os/windows/lwpa/os_netint.c | 6 +-- 13 files changed, 136 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94cab0494..1273a7ae5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 platforms. - lwpa_log_callback interface tweak - combine the various log message pointers into a struct LwpaLogStrings. +- LwpaNetintInfo: 'ifindex' renamed to 'index' and changed to type unsigned int + for better compliance with RFC 3493 ### Removed diff --git a/examples/netint/netint_example.c b/examples/netint/netint_example.c index 10c785ea5..83a365ba0 100644 --- a/examples/netint/netint_example.c +++ b/examples/netint/netint_example.c @@ -75,7 +75,7 @@ void create_format_strings(const LwpaNetintInfo* netint_arr, size_t num_interfac snprintf(header_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-17s %%s\n", longest_name, longest_addr, longest_netmask); - snprintf(line_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-17s %%8d\n", longest_name, longest_addr, + snprintf(line_format, FORMAT_BUF_SIZE, "%%-%zus %%-%zus %%-%zus %%-17s %%8u\n", longest_name, longest_addr, longest_netmask); } @@ -114,7 +114,7 @@ int main() snprintf(mac_str, 18, "%02x:%02x:%02x:%02x:%02x:%02x", netint->mac[0], netint->mac[1], netint->mac[2], netint->mac[3], netint->mac[4], netint->mac[5]); - printf(line_format, netint->name, addr_str, netmask_str, mac_str, netint->ifindex); + printf(line_format, netint->name, addr_str, netmask_str, mac_str, netint->index); } LwpaNetintInfo default_v4; diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index 56a5e06ac..936fc8040 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -162,9 +162,9 @@ typedef struct LwpaSockaddr /*! A description of a network interface. */ typedef struct LwpaNetintInfo { - /*! The OS-specific network interface number. Not used on all OSes. May need to be casted away - * from int (e.g. unsigned int) on your OS. */ - int ifindex; + /*! The OS-specific network interface number. Used for IPv6 and IP-version-neutral APIs, as + * specified in Section 4 of RFC 3493. */ + unsigned int index; /*! The interface ip address. */ LwpaIpAddr addr; /*! The subnet mask for this interface. */ diff --git a/include/lwpa/socket.h b/include/lwpa/socket.h index 1897b0ca9..94641dcab 100644 --- a/include/lwpa/socket.h +++ b/include/lwpa/socket.h @@ -88,7 +88,7 @@ typedef uint32_t lwpa_poll_events_t; * Refer to the similarly-named option on your favorite man page for more details. * @{ */ /*! Get/Set, value is int. Value indicates TTL for IPv4 or hop limit for IPv6. */ -#define LWPA_IP_TTL 11 +#define LWPA_IP_TTL 11 /*! Get/Set, value is LwpaIpAddr indicating interface IP address for IPv4, or int representing * interface index for IPv6. */ #define LWPA_IP_MULTICAST_IF 12 @@ -97,7 +97,7 @@ typedef uint32_t lwpa_poll_events_t; #define LWPA_IP_MULTICAST_LOOP 14 /*!< Get/Set, value is boolean int */ /*! [Legacy IPv4-only option, use of #LWPA_MCAST_JOIN_GROUP is preferred] Set only, value is * LwpaMreq. */ -#define LWPA_IP_ADD_MEMBERSHIP 15 +#define LWPA_IP_ADD_MEMBERSHIP 15 /*! [Legacy IPv4-only option, use of #LWPA_MCAST_LEAVE_GROUP is preferred] Set only, value is * LwpaMreq. */ #define LWPA_IP_DROP_MEMBERSHIP 16 @@ -129,9 +129,9 @@ typedef struct LwpaMreq /*! Option value for #LWPA_MCAST_JOIN_GROUP and #LWPA_MCAST_LEAVE_GROUP. */ typedef struct LwpaGroupReq { - /*! Index of newtork interface on which to join the multicast group. This index is provided in + /*! Index of network interface on which to join the multicast group. This index is provided in * LwpaNetintInfo structures. */ - int ifindex; + unsigned int ifindex; /*! Multicast group to join. */ LwpaIpAddr group; } LwpaGroupReq; diff --git a/src/lwpa/netint.c b/src/lwpa/netint.c index e6d99d7df..98e3dd05d 100644 --- a/src/lwpa/netint.c +++ b/src/lwpa/netint.c @@ -153,14 +153,14 @@ lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNeti if (netint_cache.num_netints == 0) return kLwpaErrNoNetints; - int index; + unsigned int index; lwpa_error_t res = os_resolve_route(dest, &index); if (res == kLwpaErrOk) { for (LwpaNetintInfo* netint_entry = netint_cache.netints; netint_entry < netint_cache.netints + netint_cache.num_netints; ++netint_entry) { - if (netint_entry->addr.type == dest->type && netint_entry->ifindex == index) + if (netint_entry->addr.type == dest->type && netint_entry->index == index) { *netint = *netint_entry; return kLwpaErrOk; @@ -176,5 +176,5 @@ int compare_netints(const void* a, const void* b) LwpaNetintInfo* netint1 = (LwpaNetintInfo*)a; LwpaNetintInfo* netint2 = (LwpaNetintInfo*)b; - return (netint1->ifindex > netint2->ifindex) - (netint1->ifindex < netint2->ifindex); + return (netint1->index > netint2->index) - (netint1->index < netint2->index); } diff --git a/src/lwpa/private/netint.h b/src/lwpa/private/netint.h index a1b4775a5..7abd7685a 100644 --- a/src/lwpa/private/netint.h +++ b/src/lwpa/private/netint.h @@ -43,6 +43,6 @@ void lwpa_netint_deinit(); lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache); void os_free_interfaces(CachedNetintInfo* cache); -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index); +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index); #endif /* _LWPA_PRIVATE_NETINT_H_ */ diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 2db13a185..31a16b92a 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -192,18 +192,18 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) // Interface index ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); if (ioctl_res == 0) - current_info->ifindex = if_req.ifr_ifindex; + current_info->index = if_req.ifr_ifindex; else - current_info->ifindex = -1; + current_info->index = 0; // Is Default if (LWPA_IP_IS_V4(¤t_info->addr) && routing_table_v4.default_route && - current_info->ifindex == routing_table_v4.default_route->interface_index) + current_info->index == routing_table_v4.default_route->interface_index) { current_info->is_default = true; } else if (LWPA_IP_IS_V6(¤t_info->addr) && routing_table_v6.default_route && - current_info->ifindex == routing_table_v6.default_route->interface_index) + current_info->index == routing_table_v6.default_route->interface_index) { current_info->is_default = true; } @@ -227,14 +227,14 @@ void os_free_interfaces(CachedNetintInfo* cache) free_routing_tables(); } -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) { RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &routing_table_v6 : &routing_table_v4); - int index_found = -1; + unsigned int index_found = 0; for (RoutingTableEntry* entry = table_to_use->entries; entry < table_to_use->entries + table_to_use->size; ++entry) { - if (entry->interface_index < 0 || LWPA_IP_IS_INVALID(&entry->mask)) + if (entry->interface_index <= 0 || LWPA_IP_IS_INVALID(&entry->mask)) continue; // Check each route to see if it matches the destination address explicitly @@ -249,7 +249,7 @@ lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) if (index_found < 0 && table_to_use->default_route) index_found = table_to_use->default_route->interface_index; - if (index_found >= 0) + if (index_found > 0) { *index = index_found; return kLwpaErrOk; @@ -316,7 +316,7 @@ lwpa_error_t build_routing_table(int family, RoutingTable* table) done = true; break; case kLwpaErrBufSize: - recv_buf_size *= 2; + recv_buf_size *= 2; // Double the buffer size and try again. result = kLwpaErrOk; break; default: diff --git a/src/os/lwip/lwpa/os_netint.c b/src/os/lwip/lwpa/os_netint.c index 2fc425ad8..48ceaf881 100644 --- a/src/os/lwip/lwpa/os_netint.c +++ b/src/os/lwip/lwpa/os_netint.c @@ -26,7 +26,7 @@ static bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const Lwp static void copy_interface_info(struct netif* lwip_netint, LwpaNetintInfo* netint) { - netint->ifindex = (int)lwip_netint->num; + netint->index = (int)lwip_netint->num; if (lwip_netint->hwaddr_len == NETINTINFO_MAC_LEN) memcpy(netint->mac, lwip_netint->hwaddr, NETINTINFO_MAC_LEN); else @@ -130,7 +130,8 @@ bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr { if (LWPA_IP_IS_V4(ip1) && LWPA_IP_IS_V4(ip2) && LWPA_IP_IS_V4(mask)) { - return ((LWPA_IP_V4_ADDRESS(ip1) & LWPA_IP_V4_ADDRESS(mask)) == (LWPA_IP_V4_ADDRESS(ip2) & LWPA_IP_V4_ADDRESS(mask))); + return ((LWPA_IP_V4_ADDRESS(ip1) & LWPA_IP_V4_ADDRESS(mask)) == + (LWPA_IP_V4_ADDRESS(ip2) & LWPA_IP_V4_ADDRESS(mask))); } else if (LWPA_IP_IS_V6(ip1) && LWPA_IP_IS_V6(ip2) && LWPA_IP_IS_V6(mask)) { diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c index a7e99c631..b2d2312c6 100644 --- a/src/os/macos/lwpa/os_netint.c +++ b/src/os/macos/lwpa/os_netint.c @@ -65,7 +65,7 @@ typedef struct RoutingTableEntry LwpaIpAddr addr; LwpaIpAddr mask; LwpaIpAddr gateway; - int interface_index; + unsigned int interface_index; /* Darwin seems to set this flag on default entries that are not chosen as *the* system-wide * default. I have not seen this behavior documented anywhere, but it's the only way I can tell * to determine which route is truly the default route. */ @@ -194,24 +194,24 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) // Make sure we match the corresponding link information if (link_name && link_addr && 0 == strcmp(ifaddr->ifa_name, link_name)) { - current_info->ifindex = link_addr->sdl_index; + current_info->index = link_addr->sdl_index; memcpy(current_info->mac, link_addr->sdl_data + link_addr->sdl_nlen, LWPA_NETINTINFO_MAC_LEN); } else { // Backup - get the interface index using if_nametoindex - current_info->ifindex = if_nametoindex(ifaddr->ifa_name); + current_info->index = if_nametoindex(ifaddr->ifa_name); memset(current_info->mac, 0, LWPA_NETINTINFO_MAC_LEN); } // Is Default if (LWPA_IP_IS_V4(¤t_info->addr) && routing_table_v4.default_route && - current_info->ifindex == routing_table_v4.default_route->interface_index) + current_info->index == routing_table_v4.default_route->interface_index) { current_info->is_default = true; } else if (LWPA_IP_IS_V6(¤t_info->addr) && routing_table_v6.default_route && - current_info->ifindex == routing_table_v6.default_route->interface_index) + current_info->index == routing_table_v6.default_route->interface_index) { current_info->is_default = true; } @@ -234,14 +234,14 @@ void os_free_interfaces(CachedNetintInfo* cache) free_routing_tables(); } -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) { RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &routing_table_v6 : &routing_table_v4); - int index_found = -1; + unsigned int index_found = 0; for (RoutingTableEntry* entry = table_to_use->entries; entry < table_to_use->entries + table_to_use->size; ++entry) { - if (entry->interface_index < 0 || LWPA_IP_IS_INVALID(&entry->mask)) + if (entry->interface_index == 0 || LWPA_IP_IS_INVALID(&entry->mask)) continue; // Check each route to see if it matches the destination address explicitly @@ -253,10 +253,10 @@ lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) } // Fall back to the default route - if (index_found < 0 && table_to_use->default_route) + if (index_found == 0 && table_to_use->default_route) index_found = table_to_use->default_route->interface_index; - if (index_found >= 0) + if (index_found > 0) { *index = index_found; return kLwpaErrOk; @@ -629,7 +629,7 @@ void init_routing_table_entry(RoutingTableEntry* entry) LWPA_IP_SET_INVALID(&entry->addr); LWPA_IP_SET_INVALID(&entry->mask); LWPA_IP_SET_INVALID(&entry->gateway); - entry->interface_index = -1; + entry->interface_index = 0; entry->interface_scope = false; } @@ -698,14 +698,14 @@ void debug_print_routing_table(RoutingTable* table) if_indextoname(entry->interface_index, ifname_str); - printf("%-40s %-40s %-40s %-5d %s\n", addr_str, mask_str, gw_str, entry->interface_index, ifname_str); + printf("%-40s %-40s %-40s %-5u %s\n", addr_str, mask_str, gw_str, entry->interface_index, ifname_str); } if (table->default_route) { char gw_str[LWPA_INET6_ADDRSTRLEN]; lwpa_inet_ntop(&table->default_route->gateway, gw_str, LWPA_INET6_ADDRSTRLEN); - printf("Default route: %s (%d)\n", gw_str, table->default_route->interface_index); + printf("Default route: %s (%u)\n", gw_str, table->default_route->interface_index); } else { diff --git a/src/os/mqx/lwpa/os_inet.c b/src/os/mqx/lwpa/os_inet.c index 1667c8ab9..56b07e428 100644 --- a/src/os/mqx/lwpa/os_inet.c +++ b/src/os/mqx/lwpa/os_inet.c @@ -33,7 +33,23 @@ bool ip_os_to_lwpa(const lwpa_os_ipaddr_t* os_ip, LwpaIpAddr* ip) else if (os_ip->sa_family == AF_INET6) { const struct sockaddr_in6* sin6 = (const struct sockaddr_in6*)os_ip; - LWPA_IP_SET_V6_ADDRESS(ip, sin6->sin6_addr.s6_addr); + unsigned int scope_id = 0; + // Translate the scope ID if nonzero + if (sin6->sin6_scope_id != 0) + { + for (uint32_t i = 0; i < BSP_ENET_DEVICE_COUNT; ++i) + { + // We translate the scope ID into our fake MQX interface index, which is the MQX device + // index plus 1 (because 0 indexes are not permitted). + uint32_t mqx_scope_id = ipcfg6_get_scope_id(i); + if (mqx_scope_id == sin6->sin6_scope_id) + { + scope_id = i + 1; + break; + } + } + } + LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(ip, sin6->sin6_addr.s6_addr, scope_id); return true; } return false; @@ -55,49 +71,40 @@ size_t ip_lwpa_to_os(const LwpaIpAddr* ip, lwpa_os_ipaddr_t* os_ip) struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_ip; memset(sin6, 0, sizeof(struct sockaddr_in6)); sin6->sin6_family = AF_INET6; + sin6->sin6_scope_id = (ip->addr.v6.scope_id > 0 ? ipcfg6_get_scope_id(ip->addr.v6.scope_id - 1) : 0); memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(ip), LWPA_IPV6_BYTES); ret = sizeof(struct sockaddr_in6); } return ret; } -bool sockaddr_os_to_lwpa(const struct sockaddr* os_sa, LwpaSockaddr *sa) +bool sockaddr_os_to_lwpa(const struct sockaddr* os_sa, LwpaSockaddr* sa) { - if (os_sa->sa_family == AF_INET) - { - struct sockaddr_in* sin = (struct sockaddr_in*)os_sa; - sa->port = sin->sin_port; - LWPA_IP_SET_V4_ADDRESS(&sa->ip, sin->sin_addr.s_addr); - return true; - } - else if (os_sa->sa_family == AF_INET6) + if (ip_os_to_lwpa(os_sa, &sa->ip)) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_sa; - sa->port = sin6->sin6_port; - LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); - return true; + if (os_sa->sa_family == AF_INET) + { + sa->port = ((const struct sockaddr_in*)os_sa)->sin_port; + return true; + } + else if (os_sa->sa_family == AF_INET6) + { + sa->port = ((const struct sockaddr_in6*)os_sa)->sin6_port; + return true; + } } return false; } -size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, struct sockaddr *os_sa) +size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, struct sockaddr* os_sa) { - size_t ret = 0; - if (LWPA_IP_IS_V4(&sa->ip)) + size_t ret = ip_lwpa_to_os(&sa->ip, os_sa); + if (ret != 0) { - struct sockaddr_in* sin = (struct sockaddr_in*)os_sa; - sin->sin_family = AF_INET; - sin->sin_port = sa->port; - sin->sin_addr.s_addr = LWPA_IP_V4_ADDRESS(&sa->ip); - ret = sizeof(struct sockaddr_in); - } - else if (LWPA_IP_IS_V6(&sa->ip)) - { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_sa; - sin6->sin6_family = AF_INET6; - sin6->sin6_port = sa->port; - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); - ret = sizeof(struct sockaddr_in6); + if (LWPA_IP_IS_V4(&sa->ip)) + ((struct sockaddr_in*)os_sa)->sin_port = sa->port; + else if (LWPA_IP_IS_V6(&sa->ip)) + ((struct sockaddr_in6*)os_sa)->sin6_port = sa->port; } return ret; } @@ -159,4 +166,3 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des return kLwpaErrInvalid; } } - diff --git a/src/os/mqx/lwpa/os_netint.c b/src/os/mqx/lwpa/os_netint.c index e946aec05..b7e45c3af 100644 --- a/src/os/mqx/lwpa/os_netint.c +++ b/src/os/mqx/lwpa/os_netint.c @@ -28,15 +28,17 @@ static LwpaNetintInfo netints[BSP_ENET_DEVICE_COUNT]; -static void copy_interface_info(size_t mqx_index, LwpaNetintInfo* netint) +static void copy_interface_info(uint32_t mqx_index, LwpaNetintInfo* netint) { IPCFG_IP_ADDRESS_DATA ip_data; - /* This module is quick and dirty and needs some work. - * - We are ignoring IPv6. - * - We don't check for loopback interfaces or invalid data. - */ - netint->ifindex = (int)RTCS_if_get_handle(mqx_index); + // This module is quick and dirty and needs some work. + // - We are ignoring IPv6. + // - We don't check for loopback interfaces or invalid data. + + // In MQX, interfaces are kept in a linked list and retrieved using an index from 0. + // To provide an RFC-3493-compliant index, we'll just offset that index by 1. + netint->index = mqx_index + 1; ipcfg_get_ip(mqx_index, &ip_data); LWPA_IP_SET_V4_ADDRESS(&netint->addr, ip_data.ip); @@ -52,7 +54,7 @@ static void copy_interface_info(size_t mqx_index, LwpaNetintInfo* netint) lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) { - for (size_t i = 0; i < BSP_ENET_DEVICE_COUNT; ++i) + for (uint32_t i = 0; i < BSP_ENET_DEVICE_COUNT; ++i) { copy_interface_info(i, &netints[i]); } @@ -66,20 +68,20 @@ void os_free_interfaces(CachedNetintInfo* cache) cache->netints = NULL; } -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) { - int index_found = -1; + unsigned int index_found = 0; for (const LwpaNetintInfo* netint = netints; netint < netints + BSP_ENET_DEVICE_COUNT; ++netint) { if (!lwpa_ip_is_wildcard(&netint->mask) && lwpa_ip_network_portions_equal(&netint->addr, dest, &netint->mask)) { - index_found = netint->ifindex; + index_found = netint->index; break; } } - if (index_found == -1) - index_found = netints[BSP_DEFAULT_ENET_DEVICE].ifindex; + if (index_found == 0) + index_found = netints[BSP_DEFAULT_ENET_DEVICE].index; *index = index_found; return kLwpaErrOk; diff --git a/src/os/mqx/lwpa/os_socket.c b/src/os/mqx/lwpa/os_socket.c index 2a040caf9..ff4a7e563 100644 --- a/src/os/mqx/lwpa/os_socket.c +++ b/src/os/mqx/lwpa/os_socket.c @@ -351,25 +351,6 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const } break; case LWPA_MCAST_JOIN_GROUP: - if (option_len == sizeof(LwpaGroupReq)) - { - LwpaGroupReq* greq = (LwpaGroupReq*)option_value; - if (LWPA_IP_IS_V4(&greq->group) && level == LWPA_IPPROTO_IP) - { - struct LwpaMreq mreq; - mreq.group = greq->group; - LWPA_IP_SET_V4_ADDRESS(&mreq.netint, RTCS_if_get_addr((_rtcs_if_handle)greq->ifindex)); - res = join_leave_mcast_group_ipv4(id, &mreq, true); - } - else if (LWPA_IP_IS_V6(&greq->group) && level == LWPA_IPPROTO_IPV6) - { - struct ipv6_mreq val; - val.ipv6imr_interface = (unsigned int)greq->ifindex; - memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); - res = setsockopt(id, SOL_IP6, RTCS_SO_IP6_JOIN_GROUP, &val, sizeof val); - } - } - break; case LWPA_MCAST_LEAVE_GROUP: if (option_len == sizeof(LwpaGroupReq)) { @@ -377,16 +358,52 @@ lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const if (LWPA_IP_IS_V4(&greq->group) && level == LWPA_IPPROTO_IP) { struct LwpaMreq mreq; - mreq.group = greq->group; - LWPA_IP_SET_V4_ADDRESS(&mreq.netint, RTCS_if_get_addr((_rtcs_if_handle)greq->ifindex)); - res = join_leave_mcast_group_ipv4(id, &mreq, false); + bool keep_going = true; + + if (greq->ifindex != 0) + { + IPCFG_IP_ADDRESS_DATA ip_data; + if (ipcfg_get_ip(greq->ifindex - 1, &ip_data)) + LWPA_IP_SET_V4_ADDRESS(&mreq.netint, ip_data.ip); + else + keep_going = false; + } + else + { + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &mreq.netint); + } + + if (keep_going) + { + mreq.group = greq->group; + res = join_leave_mcast_group_ipv4(id, &mreq, option_name == LWPA_MCAST_JOIN_GROUP ? true : false); + } } else if (LWPA_IP_IS_V6(&greq->group) && level == LWPA_IPPROTO_IPV6) { struct ipv6_mreq val; - val.ipv6imr_interface = (unsigned int)greq->ifindex; - memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); - res = setsockopt(id, SOL_IP6, RTCS_SO_IP6_LEAVE_GROUP, &val, sizeof val); + bool keep_going = true; + + if (greq->ifindex != 0) + { + uint32_t scope_id = ipcfg6_get_scope_id(greq->ifindex - 1); + if (scope_id != 0) + val.ipv6imr_interface = scope_id; + else + keep_going = false; + } + else + { + val.ipv6imr_interface = 0; + } + + if (keep_going) + { + memcpy(&val.ipv6imr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + res = setsockopt(id, SOL_IP6, + option_name == LWPA_MCAST_JOIN_GROUP ? RTCS_SO_IP6_JOIN_GROUP : RTCS_SO_IP6_LEAVE_GROUP, + &val, sizeof val); + } } } break; diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index b2abb8823..1456d85fa 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -39,7 +39,7 @@ static void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNet /*************************** Function definitions ****************************/ -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) { struct sockaddr_storage os_addr; if (ip_lwpa_to_os(dest, (lwpa_os_ipaddr_t*)&os_addr)) @@ -207,7 +207,7 @@ void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNetintInfo { info->is_default = false; } - info->ifindex = pcur->IfIndex; + info->index = pcur->IfIndex; break; case AF_INET6: copy_ipv6_info(pip, info); @@ -220,7 +220,7 @@ void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNetintInfo { info->is_default = false; } - info->ifindex = pcur->Ipv6IfIndex; + info->index = pcur->Ipv6IfIndex; break; default: pip = pip->Next; From 57d65a189245bc6ad32cc12f566f37f489700370 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 3 Jul 2019 14:38:19 -0500 Subject: [PATCH 076/264] Fix build on mac --- tests/unit/test_socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 016010dbb..d019043ca 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -247,7 +247,7 @@ TEST_F(SocketTest, multicast_udp) // Subscribe socket 1 to the multicast address. LwpaGroupReq greq; - greq.ifindex = default_netint_.ifindex; + greq.ifindex = default_netint_.index; LWPA_IP_SET_V4_ADDRESS(&greq.group, TEST_MCAST_ADDR); ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); From 7575fccb7267f3b3261ef624bbdbeabca24448a7 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 3 Jul 2019 14:51:17 -0500 Subject: [PATCH 077/264] And fix Linux --- src/os/linux/lwpa/os_netint.c | 8 ++++---- tests/unit/test_netint.cpp | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 31a16b92a..17fd91827 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -192,7 +192,7 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) // Interface index ioctl_res = ioctl(ioctl_sock, SIOCGIFINDEX, &if_req); if (ioctl_res == 0) - current_info->index = if_req.ifr_ifindex; + current_info->index = (unsigned int)if_req.ifr_ifindex; else current_info->index = 0; @@ -240,14 +240,14 @@ lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) // Check each route to see if it matches the destination address explicitly if (lwpa_ip_network_portions_equal(&entry->addr, dest, &entry->mask)) { - index_found = entry->interface_index; + index_found = (unsigned int)entry->interface_index; break; } } // Fall back to the default route - if (index_found < 0 && table_to_use->default_route) - index_found = table_to_use->default_route->interface_index; + if (index_found == 0 && table_to_use->default_route) + index_found = (unsigned int)table_to_use->default_route->interface_index; if (index_found > 0) { diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index 879eb11b6..4e3ba0f84 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -72,18 +72,26 @@ TEST_F(NetintTest, default) bool have_default_v6 = lwpa_netint_get_default_interface(kLwpaIpTypeV6, &def_v6); if (have_default_v4) + { EXPECT_TRUE(def_v4.is_default); + } if (have_default_v6) + { EXPECT_TRUE(def_v6.is_default); + } for (LwpaNetintInfo* netint = netint_arr.get(); netint < netint_arr.get() + num_netints; ++netint) { if (netint->is_default) { if (netint->addr.type == kLwpaIpTypeV4) + { EXPECT_EQ(0, memcmp(netint, &def_v4, sizeof def_v4)); + } else if (netint->addr.type == kLwpaIpTypeV6) + { EXPECT_EQ(0, memcmp(netint, &def_v6, sizeof def_v6)); + } } } } From 93a8d57efb3528b5bb82b6b30c48f74480626b01 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 3 Jul 2019 15:50:22 -0500 Subject: [PATCH 078/264] Change signature of lwpa_netint_get_interface_for_dest() --- CHANGELOG.md | 1 + examples/netint/netint_example.c | 4 ++-- include/lwpa/netint.h | 3 ++- src/lwpa/netint.c | 34 +++++++++++++++++++++++--------- tests/unit/test_common.cpp | 2 +- tests/unit/test_netint.cpp | 4 ++-- 6 files changed, 33 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1273a7ae5..5f77d0444 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 into a struct LwpaLogStrings. - LwpaNetintInfo: 'ifindex' renamed to 'index' and changed to type unsigned int for better compliance with RFC 3493 +- lwpa_netint_get_interface_for_dest(): Signature changed to return lwpa_error_t ### Removed diff --git a/examples/netint/netint_example.c b/examples/netint/netint_example.c index 83a365ba0..3750922fb 100644 --- a/examples/netint/netint_example.c +++ b/examples/netint/netint_example.c @@ -118,14 +118,14 @@ int main() } LwpaNetintInfo default_v4; - if (lwpa_netint_get_default_interface(kLwpaIpTypeV4, &default_v4)) + if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV4, &default_v4)) { char addr_str[LWPA_INET_ADDRSTRLEN] = {'\0'}; lwpa_inet_ntop(&default_v4.addr, addr_str, LWPA_INET_ADDRSTRLEN); printf("Default IPv4 interface: %s (%s)\n", addr_str, default_v4.name); } LwpaNetintInfo default_v6; - if (lwpa_netint_get_default_interface(kLwpaIpTypeV6, &default_v6)) + if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV6, &default_v6)) { char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; lwpa_inet_ntop(&default_v6.addr, addr_str, LWPA_INET6_ADDRSTRLEN); diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index 67c65ea93..6ed99f143 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -41,7 +41,8 @@ extern "C" { size_t lwpa_netint_get_num_interfaces(); size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size); -bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint); + +lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint); lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint); #ifdef __cplusplus diff --git a/src/lwpa/netint.c b/src/lwpa/netint.c index 98e3dd05d..349fc41f1 100644 --- a/src/lwpa/netint.c +++ b/src/lwpa/netint.c @@ -112,24 +112,40 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ * * \param[out] netint Pointer to network interface description struct to fill with the information * about the default interface. - * \return true (netint was filled in) or false (error occurred). + * \return #kLwpaErrOk: netint was filled in. + * \return #kLwpaErrInvalid: Invalid argument provided. + * \return #kLwpaErrNotFound: No default interface found for this type. */ -bool lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) +lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) { if (init_count && netint) { - if (type == kLwpaIpTypeV4 && default_netint.v4_valid) + if (type == kLwpaIpTypeV4) { - *netint = netint_cache.netints[default_netint.v4_index]; - return true; + if (default_netint.v4_valid) + { + *netint = netint_cache.netints[default_netint.v4_index]; + return kLwpaErrOk; + } + else + { + return kLwpaErrNotFound; + } } - else if (type == kLwpaIpTypeV6 && default_netint.v6_valid) + else if (type == kLwpaIpTypeV6) { - *netint = netint_cache.netints[default_netint.v6_index]; - return true; + if (default_netint.v6_valid) + { + *netint = netint_cache.netints[default_netint.v6_index]; + return kLwpaErrOk; + } + else + { + return kLwpaErrNotFound; + } } } - return false; + return kLwpaErrInvalid; } /*! \brief Get the network interface that the system will choose when routing an IP packet to the diff --git a/tests/unit/test_common.cpp b/tests/unit/test_common.cpp index 977abc47d..169a47156 100644 --- a/tests/unit/test_common.cpp +++ b/tests/unit/test_common.cpp @@ -54,7 +54,7 @@ TEST_F(CommonTest, netint_double_init) // After 2 inits and one deinit, we should still be able to make valid calls to the module. LwpaNetintInfo def_netint; - EXPECT_TRUE(lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_netint)); + EXPECT_EQ(kLwpaErrOk, lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_netint)); lwpa_deinit(LWPA_FEATURE_NETINTS); } diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.cpp index 4e3ba0f84..302d70f0b 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.cpp @@ -68,8 +68,8 @@ TEST_F(NetintTest, default) num_netints = lwpa_netint_get_interfaces(netint_arr.get(), num_netints); - bool have_default_v4 = lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_v4); - bool have_default_v6 = lwpa_netint_get_default_interface(kLwpaIpTypeV6, &def_v6); + bool have_default_v4 = (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_v4)); + bool have_default_v6 = (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV6, &def_v6)); if (have_default_v4) { From d19a1669ba39663a881264e4e2dcace0109f5483 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 8 Jul 2019 15:15:52 -0500 Subject: [PATCH 079/264] Better documentation for interface indexes --- docs/Doxyfile | 6 +- docs/DoxygenLayout.xml | 194 ++++++++++++++ docs/additional_docs.md | 7 + docs/interface_indexes.md | 38 +++ docs/lwpa.tag | 527 +++++++++++++++++++++++++++----------- include/lwpa/inet.h | 4 +- include/lwpa/socket.h | 7 +- src/lwpa/netint.c | 8 + 8 files changed, 628 insertions(+), 163 deletions(-) create mode 100644 docs/DoxygenLayout.xml create mode 100644 docs/additional_docs.md create mode 100644 docs/interface_indexes.md diff --git a/docs/Doxyfile b/docs/Doxyfile index 61990604d..646d2d15c 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -703,7 +703,7 @@ FILE_VERSION_FILTER = # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. -LAYOUT_FILE = +LAYOUT_FILE = DoxygenLayout.xml # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib @@ -792,7 +792,9 @@ WARN_LOGFILE = INPUT = ../src/lwpa \ ../include/lwpa \ - mainpage.md + mainpage.md \ + additional_docs.md \ + interface_indexes.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/docs/DoxygenLayout.xml b/docs/DoxygenLayout.xml new file mode 100644 index 000000000..de0aa5232 --- /dev/null +++ b/docs/DoxygenLayout.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/additional_docs.md b/docs/additional_docs.md new file mode 100644 index 000000000..061526e17 --- /dev/null +++ b/docs/additional_docs.md @@ -0,0 +1,7 @@ +# Additional Documentation {#additional_docs} + +Miscellaneous documentation that does not fit with one particular function or +code construct is found here. + +**Page List:** +* @subpage interface_indexes diff --git a/docs/interface_indexes.md b/docs/interface_indexes.md new file mode 100644 index 000000000..93e0a5146 --- /dev/null +++ b/docs/interface_indexes.md @@ -0,0 +1,38 @@ +# Network Interface Indexes {#interface_indexes} + +Some lwpa APIs make use of an index value to identify network interfaces. +Almost all underlying network stacks have the notion of a network interface +index, which is standardized for IPv6 by +[RFC 3493](https://tools.ietf.org/html/rfc3493). + +Interface indexes _may_ also be used for specifying the _zone index_ or +_scope ID_ of an IPv6 address (see +[RFC 4007](https://tools.ietf.org/html/rfc4007)). However, depending on the +address scope, this doesn't always apply. It also seems to currently be a +lightly-specified area of the IPv6 protocol, so it should not be treated as a +guarantee. + +In our protocols, we use the interface index mostly for multicasting purposes. +When used this way, it is used to specify an interface on which to send or +receive multicast traffic for a given socket. The @ref lwpa_socket API uses +them to specify network interfaces for the @ref LWPA_MCAST_JOIN_GROUP, +@ref LWPA_MCAST_LEAVE_GROUP, and @ref LWPA_IP_MULTICAST_IF socket options. + +The interface index is of type `unsigned int`; 0 is an invalid value for +specifying a specific interface, but can be used as a wildcard (signaling the +kernel to pick the "best" or most appropriate interface). Interface indexes for +each connected interface can be obtained from the @ref lwpa_netint API (in the +@ref LwpaNetintInfo structure returned from lwpa_netint calls), or from the +relevant OS APIs on OSes that support them (many conform to the standard +interface specified by RFC 3493). + +Some embedded stacks have limited or nonstandard ways to obtain a network +interface index. For clarity, the exact way that interface indexes are obtained +or derived in each stack is listed below. + +| OS/Stack | Method | +|----------|--------| +| macOS | Standard / RFC 3493, can also be inferred from data in `ifconfig` and `netstat -rn` | +| Microsoft Windows | Indicated in [IP_ADAPTER_ADDRESSES](https://docs.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh) structure, also visible via `route print` at command line | +| Linux | Standard / RFC 3493, visible via `ip link` on newer/systemd systems, or can be inferred from data in `ifconfig` | +| MQX RTOS | The index is derived from the RTCS _device identifier_ (an index starting from 0 into a linked list of network interfaces) plus 1. This is translated internally for relevant socket calls. | diff --git a/docs/lwpa.tag b/docs/lwpa.tag index 712a5f9eb..d4d2082d7 100644 --- a/docs/lwpa.tag +++ b/docs/lwpa.tag @@ -2,12 +2,21 @@ version.h - D:/git/ETCLabs/RDMnetWS/lwpa/include/lwpa/ + D:/git/ETCLabs/lwpa/include/lwpa/ version_8h LwpaIpAddr::AddrUnion union_lwpa_ip_addr_1_1_addr_union.html + LwpaIpAddr::AddrUnion::LwpaIpv6Addr + + + CachedNetintInfo + struct_cached_netint_info.html + + + DefaultNetint + struct_default_netint.html LwpaAddrinfo @@ -62,6 +71,24 @@ [2] + + LwpaGroupReq + struct_lwpa_group_req.html + + unsigned int + ifindex + struct_lwpa_group_req.html + a452f46bf9904a02408a12d9e406b4de7 + + + + LwpaIpAddr + group + struct_lwpa_group_req.html + a9d92abf5e7c4488e5d9dfc5ab9376e89 + + + LwpaIpAddr struct_lwpa_ip_addr.html @@ -74,6 +101,10 @@ + + LwpaIpAddr::AddrUnion::LwpaIpv6Addr + struct_lwpa_ip_addr_1_1_addr_union_1_1_lwpa_ipv6_addr.html + LwpaLinger struct_lwpa_linger.html @@ -138,6 +169,31 @@ + + LwpaLogStrings + struct_lwpa_log_strings.html + + const char * + syslog + struct_lwpa_log_strings.html + a5911dbe6a47cb2b9cfbab87a8881b5b6 + + + + const char * + human_readable + struct_lwpa_log_strings.html + a4ac8b9667178849660fd3b1f99e93366 + + + + const char * + raw + struct_lwpa_log_strings.html + a8129637af8920bc9328bbce2a00bfeb4 + + + LwpaLogTimeParams struct_lwpa_log_time_params.html @@ -248,6 +304,10 @@ + + LwpaModuleInit + struct_lwpa_module_init.html + LwpaMreq struct_lwpa_mreq.html @@ -270,10 +330,10 @@ LwpaNetintInfo struct_lwpa_netint_info.html - int - ifindex + unsigned int + index struct_lwpa_netint_info.html - a01e636f8746c84f1cf3d45c4afbfde35 + a589d64202487f78e3cc30dd2e04c5201 @@ -290,13 +350,6 @@ abff5b2b0f50f02db2d130bb3c59cd5b0 - - LwpaIpAddr - gate - struct_lwpa_netint_info.html - aab794a1d7268e4cf399af0600c73e0d8 - - uint8_t mac @@ -532,13 +585,6 @@ aaafd70d57737ab374198d3d754411129 - - uint32_t - scope_id - struct_lwpa_sockaddr.html - a1d93077fdccdb6e377b421b79e1ba15c - - LwpaSyslogParams @@ -611,7 +657,7 @@ char * thread_name struct_lwpa_thread_params.html - aff53d286a69bd6b453eeb29ab3a75326 + a9c15c6e0b10239673fa9d8be6ad08128 @@ -718,8 +764,15 @@ bool lwpa_mutex_take group__lwpa__mutex.html - ga7726931cda1cdbf1307283b3894c4af2 - (lwpa_mutex_t *id, int wait_ms) + gaddfd883159e43fd194fbf3b355411263 + (lwpa_mutex_t *id) + + + bool + lwpa_mutex_try_take + group__lwpa__mutex.html + gadc322cce9079e4f7f7ab9e9e685633b0 + (lwpa_mutex_t *id) void @@ -758,8 +811,15 @@ bool lwpa_signal_wait group__lwpa__signal.html - ga64d1e2d7b517cdb5f2c3d33081ff6d7c - (lwpa_signal_t *id, int wait_ms) + gad1e8c49a266c700a182c907ef7aa29bf + (lwpa_signal_t *id) + + + bool + lwpa_signal_poll + group__lwpa__signal.html + ga704ec739497e224a990037524a9086ab + (lwpa_signal_t *id) void @@ -798,8 +858,15 @@ bool lwpa_rwlock_readlock group__lwpa__rwlock.html - gab5db36f592b621b305c7808c1496a3ae - (lwpa_rwlock_t *id, int wait_ms) + gac4f4763199bad441330867f975316393 + (lwpa_rwlock_t *id) + + + bool + lwpa_rwlock_try_readlock + group__lwpa__rwlock.html + ga9f6b8671a52e91200447ad2912c1a6a3 + (lwpa_rwlock_t *id) void @@ -812,8 +879,15 @@ bool lwpa_rwlock_writelock group__lwpa__rwlock.html - ga33b3938c8392576c3d780f759c975ec5 - (lwpa_rwlock_t *id, int wait_ms) + gaba4a0078be86e6fc1408cfbe602c0fba + (lwpa_rwlock_t *id) + + + bool + lwpa_rwlock_try_writelock + group__lwpa__rwlock.html + ga7f42819fdf2e713b03bf74325e2823f3 + (lwpa_rwlock_t *id) void @@ -886,10 +960,10 @@ bool - lwpa_thread_stop + lwpa_thread_join group__lwpa__thread.html - gac98ab5b271d1fdf59b2df4d04f38f7f3 - (lwpa_thread_t *id, int wait_ms) + gac43cbc0cdfd62e365ad76e1110fe359c + (lwpa_thread_t *id) void @@ -951,6 +1025,69 @@ ga1c2b0e972201228ff6c55879bab82861 + + uint32_t + lwpa_features_t + group__lwpa.html + gad114d8d0d8fc2b500bbe5cd815f050c6 + + + + lwpa_error_t + lwpa_init + group__lwpa.html + gad3f4f0f94eeaede46d9f5f089129446b + (lwpa_features_t features) + + + void + lwpa_deinit + group__lwpa.html + gaa5af7daa1612ac3fc98f49a166a0c669 + (lwpa_features_t features) + + + #define + LWPA_FEATURE_SOCKETS + group__lwpa.html + ga51e7968caa7cc29fad18ec872c739cbb + + + + #define + LWPA_FEATURE_NETINTS + group__lwpa.html + ga4830c5a79855564b312b2c12e869702a + + + + #define + LWPA_FEATURE_TIMERS + group__lwpa.html + ga14efb0458ae41274fe96f0797d35e1f1 + + + + #define + LWPA_FEATURE_LOGGING + group__lwpa.html + ga20bf4148474b69f45813f818e16ea0d7 + + + + #define + LWPA_FEATURES_ALL + group__lwpa.html + ga1c807b4b9009a27514f7895791ecf49a + + + + #define + LWPA_FEATURES_ALL_BUT + group__lwpa.html + ga1effd03384104d4edff4ea16a1c26c9b + (mask) + lwpa_error @@ -1084,6 +1221,12 @@ gga4de447127cf0baaa9afb0188e1e6afbfa5411409d0e04a1291da3130d90c54a66 + + kLwpaErrConnAborted + group__lwpa__error.html + gga4de447127cf0baaa9afb0188e1e6afbfa6d3e2a994acb0c378ce59660db281084 + + kLwpaErrConnRefused group__lwpa__error.html @@ -1132,6 +1275,12 @@ gga4de447127cf0baaa9afb0188e1e6afbfa88c03c75f09818b154ac60720977adcf + + kLwpaErrPerm + group__lwpa__error.html + gga4de447127cf0baaa9afb0188e1e6afbfab2b2faed88fad885e984309f9c6423b7 + + kLwpaErrSys group__lwpa__error.html @@ -1155,10 +1304,17 @@ #define - lwpasock_ip_port_equal + LWPA_INET_ADDRSTRLEN + group__lwpa__inet.html + gac9a7a8dbe7def9af922af1a99b4c6569 + + + + #define + LWPA_INET6_ADDRSTRLEN group__lwpa__inet.html - gacdc07c9ddec218067a54d87f017b256c - (sockptr1, sockptr2) + ga078d3101f67934bce6f13f193a4832ea + struct LwpaIpAddr @@ -1206,95 +1362,144 @@ gga75918e41a21a5b4511b2b3c797e6f048a60f28e3cdc84c51debfd05e05b4578da - - #define - lwpaip_is_v4 + + bool + lwpa_ip_is_link_local group__lwpa__inet.html - ga99ca443ff7adfc20ef3dfff1f668a563 - (lwpa_ip_ptr) + gace949c44b216e2dd8d81de6b57aafb13 + (const LwpaIpAddr *ip) - - #define - lwpaip_is_v6 + + bool + lwpa_ip_is_loopback group__lwpa__inet.html - ga60fa1dee3547985e5419d7f3d4f8b233 - (lwpa_ip_ptr) + ga700cb0526cde413cca61f970231d4806 + (const LwpaIpAddr *ip) - - #define - lwpaip_is_invalid + + bool + lwpa_ip_is_multicast group__lwpa__inet.html - ga512afd056b57c62b511e44a93972f4d5 - (lwpa_ip_ptr) + ga3b0cdd32380a0dd44d67fef6800ba95f + (const LwpaIpAddr *ip) - - #define - lwpaip_v4_address + + bool + lwpa_ip_is_wildcard group__lwpa__inet.html - ga731ba4e4b7760993fe3f4658066b9fcd - (lwpa_ip_ptr) + gaaad2d470c8be885c55f8eaf4c89710eb + (const LwpaIpAddr *ip) + + + void + lwpa_ip_set_wildcard + group__lwpa__inet.html + ga8f5ba7636a445882d3bd09e45f97c285 + (lwpa_iptype_t type, LwpaIpAddr *ip) + + + bool + lwpa_ip_equal + group__lwpa__inet.html + gac1805623603318386ea74815b694f021 + (const LwpaIpAddr *ip1, const LwpaIpAddr *ip2) + + + int + lwpa_ip_cmp + group__lwpa__inet.html + ga3aba9897afc056a10b81d4f2d6451d0f + (const LwpaIpAddr *ip1, const LwpaIpAddr *ip2) + + + bool + lwpa_ip_and_port_equal + group__lwpa__inet.html + gad78b7fcae748568c74ecb2c08bfbace4 + (const LwpaSockaddr *sock1, const LwpaSockaddr *sock2) + + + unsigned int + lwpa_ip_mask_length + group__lwpa__inet.html + ga16facd74441deb055bfffaf7c8d7f7ee + (const LwpaIpAddr *netmask) + + + LwpaIpAddr + lwpa_ip_mask_from_length + group__lwpa__inet.html + ga9ef3d4b831b3c9e598f9e568fd17ffe3 + (lwpa_iptype_t type, unsigned int mask_length) + + + bool + lwpa_ip_network_portions_equal + group__lwpa__inet.html + ga5c416c166428a88fc03f4be742ed6e78 + (const LwpaIpAddr *ip1, const LwpaIpAddr *ip2, const LwpaIpAddr *netmask) #define - lwpaip_v6_address + LWPA_IP_IS_V4 group__lwpa__inet.html - ga6f3e7c1f5539712019154ffeed900d07 + ga0b1e21bccece957bb0a4986c51fd7d3a (lwpa_ip_ptr) #define - lwpaip_set_v4_address + LWPA_IP_IS_V6 group__lwpa__inet.html - ga8cefecedef40877115c050848fd9a1d5 - (lwpa_ip_ptr, val) + ga6e008633fe046017e20ad036175400a4 + (lwpa_ip_ptr) #define - lwpaip_set_v6_address + LWPA_IP_IS_INVALID group__lwpa__inet.html - ga82919752f2428a78edfb26f745481e5d - (lwpa_ip_ptr, val) + gae45f4d73820e647d45f4a6c1346fcb0f + (lwpa_ip_ptr) #define - lwpaip_set_invalid + LWPA_IP_V4_ADDRESS group__lwpa__inet.html - ga85259d4019be76ee5067cb744cb4cb76 + gab58ee5657f5ec2e0a33fe6108d15acfc (lwpa_ip_ptr) #define - lwpaip_is_multicast + LWPA_IP_V6_ADDRESS group__lwpa__inet.html - ga2a3be69f1ef99486ad72ab4b8eae966d + ga505ee023d06f2a90976dd50b596ba963 (lwpa_ip_ptr) #define - lwpaip_equal + LWPA_IP_SET_V4_ADDRESS group__lwpa__inet.html - ga1961dd86bd985153be3afa3bf3bebefa - (ipptr1, ipptr2) + ga7a29e94ac67df250504e56ac9257a8c8 + (lwpa_ip_ptr, val) #define - lwpaip_cmp + LWPA_IP_SET_V6_ADDRESS group__lwpa__inet.html - ga7bcd89c614dbfb588d5c6bb54ce67872 - (ipptr1, ipptr2) + ga4217ea63c7520ea2fe349be430c8cfec + (lwpa_ip_ptr, addr_val) #define - lwpaip_make_any_v4 + LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID group__lwpa__inet.html - gafff526c280a904c4f27372a000e37859 - (lwpa_ip_ptr) + ga2d1a4c527a80069754dbc3f08b66723b + (lwpa_ip_ptr, addr_val, scope_id_val) #define - lwpaip_make_any_v6 + LWPA_IP_SET_INVALID group__lwpa__inet.html - gaf0433f37c8aedbd049388bb7c08f5172 + gaf8587cfa1476afaae1c34081f2b9e061 (lwpa_ip_ptr) @@ -1315,6 +1520,7 @@ lwpa_log group__lwpa__log.html LwpaLogTimeParams + LwpaLogStrings LwpaSyslogParams LwpaLogParams @@ -1401,12 +1607,19 @@ gad274aa6b5c42d1ff594200232ccbc0ab + + struct LwpaLogStrings + LwpaLogStrings + group__lwpa__log.html + ga25c13b78ecd42cad3de3341f66199974 + + void(* lwpa_log_callback group__lwpa__log.html - gacd26df727c6a5f6d0d6fcfa4c2ac3755 - )(void *context, const char *syslog_str, const char *human_str, const char *raw_str) + gab5ffbb4d8e2168a0c51b10e5b3099de8 + )(void *context, const LwpaLogStrings *strings) void(* @@ -1789,32 +2002,18 @@ (LwpaNetintInfo *netint_arr, size_t netint_arr_size) - bool + lwpa_error_t lwpa_netint_get_default_interface group__lwpa__netint.html - gaa829c4964206f21bf51f0171a9c81ff8 - (LwpaNetintInfo *netint) - - - const LwpaNetintInfo * - lwpa_netint_get_iface_for_dest - group__lwpa__netint.html - ga20eaf09781921e196281ad94de07022a - (const LwpaIpAddr *dest, const LwpaNetintInfo *netint_arr, size_t netint_arr_size) + ga1ef8afff7ab8a6c8f36c4201139afa75 + (lwpa_iptype_t type, LwpaNetintInfo *netint) - int - lwpa_netint_register_change_cb - group__lwpa__netint.html - ga8a6fef891935e1c359d7e41beda2fb32 - (netint_change_notification fn, void *context) - - - void - lwpa_netint_unregister_change_cb + lwpa_error_t + lwpa_netint_get_interface_for_dest group__lwpa__netint.html - gae5eca4ae57153b10efee9fbce09ec684 - (int handle) + ga00eec072ad464f8c19835154ee683cf6 + (const LwpaIpAddr *dest, LwpaNetintInfo *netint) @@ -2300,6 +2499,7 @@ group__lwpa__socket.html LwpaLinger LwpaMreq + LwpaGroupReq LwpaPollEvent LwpaAddrinfo @@ -2316,20 +2516,6 @@ gab36e47297a2a48f28c080608c5643c25 - - #define - LWPA_INET_ADDRSTRLEN - group__lwpa__socket.html - gac9a7a8dbe7def9af922af1a99b4c6569 - - - - #define - LWPA_INET6_ADDRSTRLEN - group__lwpa__socket.html - ga078d3101f67934bce6f13f193a4832ea - - PLATFORM_DEFINED lwpa_socket_t @@ -2337,13 +2523,6 @@ ga0fea2946114e0a2617a086c2139fb9f6 - - PLATFORM_DEFINED - LwpaPollContext - group__lwpa__socket.html - ga78118eb52c46ee1c731ac66c443a4690 - - uint32_t lwpa_poll_events_t @@ -2365,6 +2544,13 @@ gaf4b1e36ceb83d78b0e4aa513d9fc7af1 + + struct LwpaGroupReq + LwpaGroupReq + group__lwpa__socket.html + gaf497966f431d877d7219574b42e94f4c + + struct LwpaPollEvent LwpaPollEvent @@ -2491,6 +2677,48 @@ ga846cd48d4882273a10d6f781128f03ea (lwpa_socket_t id, bool blocking) + + lwpa_error_t + lwpa_getaddrinfo + group__lwpa__socket.html + ga7c1c76581b63ab7c5b383e25dc200990 + (const char *hostname, const char *service, const LwpaAddrinfo *hints, LwpaAddrinfo *result) + + + bool + lwpa_nextaddr + group__lwpa__socket.html + gafe366acfdbaa9d98d9459660798c73fd + (LwpaAddrinfo *ai) + + + void + lwpa_freeaddrinfo + group__lwpa__socket.html + ga85eeba64809a88e6a246e9471d5e2cd6 + (LwpaAddrinfo *ai) + + + lwpa_error_t + lwpa_inet_ntop + group__lwpa__socket.html + gac6b5fcff898be3bbf7789a8c480082b1 + (const LwpaIpAddr *src, char *dest, size_t size) + + + lwpa_error_t + lwpa_inet_pton + group__lwpa__socket.html + ga4110e753475f9505e87b88e0097befb4 + (lwpa_iptype_t type, const char *src, LwpaIpAddr *dest) + + + PLATFORM_DEFINED + LwpaPollContext + group__lwpa__socket.html + ga78118eb52c46ee1c731ac66c443a4690 + + lwpa_error_t lwpa_poll_context_init @@ -2533,41 +2761,6 @@ ga24182f58155e7894da11e4f621ad42c8 (LwpaPollContext *context, LwpaPollEvent *event, int timeout_ms) - - lwpa_error_t - lwpa_getaddrinfo - group__lwpa__socket.html - ga7c1c76581b63ab7c5b383e25dc200990 - (const char *hostname, const char *service, const LwpaAddrinfo *hints, LwpaAddrinfo *result) - - - bool - lwpa_nextaddr - group__lwpa__socket.html - gafe366acfdbaa9d98d9459660798c73fd - (LwpaAddrinfo *ai) - - - void - lwpa_freeaddrinfo - group__lwpa__socket.html - ga85eeba64809a88e6a246e9471d5e2cd6 - (LwpaAddrinfo *ai) - - - lwpa_error_t - lwpa_inet_ntop - group__lwpa__socket.html - gac6b5fcff898be3bbf7789a8c480082b1 - (const LwpaIpAddr *src, char *dest, size_t size) - - - lwpa_error_t - lwpa_inet_pton - group__lwpa__socket.html - ga4110e753475f9505e87b88e0097befb4 - (lwpa_iptype_t type, const char *src, LwpaIpAddr *dest) - #define LWPA_SOL_SOCKET @@ -2715,6 +2908,20 @@ gad0175e8affc43157d2487763ef6660fc + + #define + LWPA_IP_ADD_MEMBERSHIP + group__lwpa__socket.html + ga5c54cc7bb91aa5d1d06491b74515fb45 + + + + #define + LWPA_IP_DROP_MEMBERSHIP + group__lwpa__socket.html + gaffd798a26996201a08ae7489f69adb57 + + #define LWPA_MCAST_JOIN_GROUP @@ -2910,6 +3117,16 @@ + + additional_docs + Additional Documentation + additional_docs + + + interface_indexes + Network Interface Indexes + interface_indexes + index LightWeight Platform Abstraction diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index 936fc8040..bfb50eb85 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -162,8 +162,8 @@ typedef struct LwpaSockaddr /*! A description of a network interface. */ typedef struct LwpaNetintInfo { - /*! The OS-specific network interface number. Used for IPv6 and IP-version-neutral APIs, as - * specified in Section 4 of RFC 3493. */ + /*! The OS-specific network interface number. Used for IPv6, multicast and IP-version-neutral + * APIs. See \ref interface_indexes for more information. */ unsigned int index; /*! The interface ip address. */ LwpaIpAddr addr; diff --git a/include/lwpa/socket.h b/include/lwpa/socket.h index 94641dcab..866b9f37e 100644 --- a/include/lwpa/socket.h +++ b/include/lwpa/socket.h @@ -89,8 +89,7 @@ typedef uint32_t lwpa_poll_events_t; * @{ */ /*! Get/Set, value is int. Value indicates TTL for IPv4 or hop limit for IPv6. */ #define LWPA_IP_TTL 11 -/*! Get/Set, value is LwpaIpAddr indicating interface IP address for IPv4, or int representing - * interface index for IPv6. */ +/*! Get/Set, value is unsigned int representing interface index (see \ref interface_indexes). */ #define LWPA_IP_MULTICAST_IF 12 /*! Get/Set, value is int. Value indicates TTL for IPv4 or hop limit for IPv6. */ #define LWPA_IP_MULTICAST_TTL 13 @@ -129,8 +128,8 @@ typedef struct LwpaMreq /*! Option value for #LWPA_MCAST_JOIN_GROUP and #LWPA_MCAST_LEAVE_GROUP. */ typedef struct LwpaGroupReq { - /*! Index of network interface on which to join the multicast group. This index is provided in - * LwpaNetintInfo structures. */ + /*! Index of network interface on which to join the multicast group (see + * \ref interface_indexes). */ unsigned int ifindex; /*! Multicast group to join. */ LwpaIpAddr group; diff --git a/src/lwpa/netint.c b/src/lwpa/netint.c index 349fc41f1..4eafaec07 100644 --- a/src/lwpa/netint.c +++ b/src/lwpa/netint.c @@ -87,6 +87,11 @@ size_t lwpa_netint_get_num_interfaces() } /*! \brief Enumerate the network interfaces on the system. + * + * For NICs with multiple IP addresses assigned, this module separates each address into its own + * entry in the netint array. Because of this, multiple array entries could have the same value + * for the index, mac and name parameters. + * * \param[out] netint_arr Array of network interface description structs to fill in with interface * info. * \param[in] netint_arr_size Size of the netint array. @@ -110,6 +115,9 @@ size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_ * lwpa_netint_get_interfaces(), it is more efficient to inspect the is_default flag of each * interface in that existing array. * + * \param[in] type The IP protocol for which to get the default network interface, either + * #kLwpaIpTypeV4 or #kLwpaIpTypeV6. A separate default interface is maintained for + * each. * \param[out] netint Pointer to network interface description struct to fill with the information * about the default interface. * \return #kLwpaErrOk: netint was filled in. From 6e98a5d8bc40441ea576192d058af4fc1f085612 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 9 Jul 2019 15:45:23 -0500 Subject: [PATCH 080/264] Some changes and bugfixes related to network interface indexes. Changes implemented on windows only rn, this build will probably fail --- CHANGELOG.md | 3 ++ docs/mainpage.md | 15 +++++--- include/os/linux/lwpa/os_socket.h | 6 ++++ include/os/macos/lwpa/os_socket.h | 6 ++++ include/os/mqx/lwpa/os_socket.h | 10 +++++- include/os/windows/lwpa/os_socket.h | 12 +++++-- src/CMakeLists.txt | 9 +++-- .../lwpa/{winsock_error.c => os_error.c} | 5 +-- .../lwpa/{winsock_error.h => os_error.h} | 3 +- src/os/windows/lwpa/os_netint.c | 1 + src/os/windows/lwpa/os_socket.c | 36 ++++++++++++++----- tests/unit/test_socket.cpp | 4 +-- 12 files changed, 87 insertions(+), 23 deletions(-) rename src/os/windows/lwpa/{winsock_error.c => os_error.c} (98%) rename src/os/windows/lwpa/{winsock_error.h => os_error.h} (96%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f77d0444..2a5c4eae1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - OS port: macOS - lwpa_init() in lwpa/common.h. lwpa_init() must be called before using features defined by feature macros defined in lwpa/common.h. +- Extra documentation page for network interface indexes. ### Changed - Naming: 'operating system' and 'platform' are used somewhat interchangably by @@ -25,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - LwpaNetintInfo: 'ifindex' renamed to 'index' and changed to type unsigned int for better compliance with RFC 3493 - lwpa_netint_get_interface_for_dest(): Signature changed to return lwpa_error_t +- lwpa_socket: Multicast socket options now refer to network interfaces only by + interface index, for portability and compatibility with IPv6. ### Removed diff --git a/docs/mainpage.md b/docs/mainpage.md index 27971a427..05d361195 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -104,11 +104,18 @@ The platform ports of lwpa have the following dependencies: package like `ossp-uuid`. + Microsoft Windows - Windows XP SP1 or later + - Windows SDK library dependencies for optional features (if building using + CMake, these dependencies are handled automatically): + * lwpa_netint (network interfaces): Iphlpapi.lib + * lwpa_socket (socket interface): Iphlpapi.lib, Ws2_32.lib + * lwpa_uuid (UUID creation): Rpcrt4.lib + * lwpa_timer (system timers): Winmm.lib + MQX RTOS - MQX 4.2.0 + Linux - - libuuid (if compiling lwpa, use `sudo apt-get install uuid-dev` or the - equivalent method for your distribution) - Optional Features: - * lwpa_netint (Network Interfaces): Linux 2.2, glibc 2.3.3 - * lwpa_socket (Socket interface): Linux 2.6 + * lwpa_netint (network interfaces): Linux 2.2, glibc 2.3.3 + * lwpa_socket (socket interface): Linux 2.6 + * lwpa_uuid (UUID creation): libuuid (if compiling lwpa, use + `sudo apt-get install uuid-dev` or the equivalent method for your + distribution) diff --git a/include/os/linux/lwpa/os_socket.h b/include/os/linux/lwpa/os_socket.h index bcc288b04..5e3ee2142 100644 --- a/include/os/linux/lwpa/os_socket.h +++ b/include/os/linux/lwpa/os_socket.h @@ -27,12 +27,18 @@ extern "C" { #endif +/* Definitions for the lwpa socket type */ + typedef int lwpa_socket_t; +#define PRIlwpasockt "d" + #define LWPA_SOCKET_INVALID -1 #define LWPA_SOCKET_MAX_POLL_SIZE -1 +/* Definitions for lwpa_poll API */ + typedef struct LwpaPollContext { bool valid; diff --git a/include/os/macos/lwpa/os_socket.h b/include/os/macos/lwpa/os_socket.h index 0fa2dbb7c..bf689cf42 100644 --- a/include/os/macos/lwpa/os_socket.h +++ b/include/os/macos/lwpa/os_socket.h @@ -29,12 +29,18 @@ extern "C" { #endif +/* Definitions for the lwpa socket type */ + typedef int lwpa_socket_t; +#define PRIlwpasockt "d" + #define LWPA_SOCKET_INVALID -1 #define LWPA_SOCKET_MAX_POLL_SIZE -1 +/* Definitions for lwpa_poll API */ + typedef struct LwpaPollContext { bool valid; diff --git a/include/os/mqx/lwpa/os_socket.h b/include/os/mqx/lwpa/os_socket.h index 55f81fa87..b88b43177 100644 --- a/include/os/mqx/lwpa/os_socket.h +++ b/include/os/mqx/lwpa/os_socket.h @@ -22,14 +22,22 @@ #include #include "lwpa/inet.h" +#include "lwpa/int.h" #ifdef __cplusplus extern "C" { #endif +/* Definitions for the lwpa socket type */ + typedef uint32_t lwpa_socket_t; -/*! An identifier for an invalid socket handle. The ONLY invalid socket descriptor is LWPA_SOCKET_INVALID. */ +#ifdef PRIu32 +#define PRIlwpasockt PRIu32 +#else +#define PRIlwpasockt "u" +#endif + #define LWPA_SOCKET_INVALID RTCS_SOCKET_ERROR #define LWPA_SOCKET_MAX_POLL_SIZE RTCSCFG_FD_SETSIZE diff --git a/include/os/windows/lwpa/os_socket.h b/include/os/windows/lwpa/os_socket.h index e1e2b2f60..854af7f34 100644 --- a/include/os/windows/lwpa/os_socket.h +++ b/include/os/windows/lwpa/os_socket.h @@ -37,14 +37,22 @@ extern "C" { #endif +/* Definitions for the lwpa socket type */ + typedef SOCKET lwpa_socket_t; -/*! An identifier for an invalid socket handle. The ONLY invalid socket descriptor is - * LWPA_SOCKET_INVALID. */ +#if defined(_WIN64) +#define PRIlwpasockt "I64u" +#else +#define PRIlwpasockt "u" +#endif + #define LWPA_SOCKET_INVALID INVALID_SOCKET #define LWPA_SOCKET_MAX_POLL_SIZE FD_SETSIZE +/* Definitions for the lwpa_poll API */ + typedef struct LwpaPollCtxSocket { lwpa_socket_t socket; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 479c49377..9fff273bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -107,8 +107,8 @@ endif() # Add include paths and library dependencies based on OS for which we are being compiled if(LWPA_TARGET_OS STREQUAL windows) target_sources(lwpa PRIVATE - ${LWPA_ROOT}/src/os/windows/lwpa/winsock_error.h - ${LWPA_ROOT}/src/os/windows/lwpa/winsock_error.c + ${LWPA_ROOT}/src/os/windows/lwpa/os_error.h + ${LWPA_ROOT}/src/os/windows/lwpa/os_error.c ) target_link_libraries(lwpa PUBLIC winmm ws2_32 Iphlpapi Rpcrt4) elseif(LWPA_TARGET_OS STREQUAL macos) @@ -145,6 +145,11 @@ endif() set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) +# Installation +install(TARGETS lwpa LIBRARY DESTINATION lib) +install(DIRECTORY ${LWPA_ROOT}/include/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") +install(DIRECTORY ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") + ############################################################################### # Mock lwpa library ############################################################################### diff --git a/src/os/windows/lwpa/winsock_error.c b/src/os/windows/lwpa/os_error.c similarity index 98% rename from src/os/windows/lwpa/winsock_error.c rename to src/os/windows/lwpa/os_error.c index b77833b91..fa88de2d8 100644 --- a/src/os/windows/lwpa/winsock_error.c +++ b/src/os/windows/lwpa/os_error.c @@ -17,11 +17,13 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "winsock_error.h" +#include "os_error.h" #include #include +#include "lwpa/int.h" + // Convert Windows sockets errors to lwpa_error_t values. lwpa_error_t err_winsock_to_lwpa(int wsaerror) { @@ -99,4 +101,3 @@ lwpa_error_t err_winsock_to_lwpa(int wsaerror) return kLwpaErrSys; } } - diff --git a/src/os/windows/lwpa/winsock_error.h b/src/os/windows/lwpa/os_error.h similarity index 96% rename from src/os/windows/lwpa/winsock_error.h rename to src/os/windows/lwpa/os_error.h index d2a6e8baf..a8709af6d 100644 --- a/src/os/windows/lwpa/winsock_error.h +++ b/src/os/windows/lwpa/os_error.h @@ -20,9 +20,10 @@ #ifndef _LWPA_OS_ERROR_H_ #define _LWPA_OS_ERROR_H_ +#include +#include #include "lwpa/error.h" lwpa_error_t err_winsock_to_lwpa(int wsaerror); #endif /* _LWPA_OS_ERROR_H_ */ - diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index 1456d85fa..917f12f5d 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -29,6 +29,7 @@ #include "lwpa/int.h" #include "lwpa/socket.h" #include "lwpa/private/netint.h" +#include "os_error.h" /*********************** Private function prototypes *************************/ diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index 6e5a2b798..a75f2cc45 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -26,8 +26,6 @@ #include #include -#include "winsock_error.h" - /*************************** Private constants *******************************/ #define POLL_CONTEXT_ARR_CHUNK_SIZE 10 @@ -477,14 +475,13 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s } break; case LWPA_IP_MULTICAST_IF: - if (option_len == sizeof(LwpaIpAddr)) + if (option_len == sizeof(unsigned int)) { - LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (LWPA_IP_IS_V4(netint)) - { - DWORD val = htonl(LWPA_IP_V4_ADDRESS(netint)); - return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, sizeof val); - } + unsigned int ifindex = *(unsigned int*)option_value; + // On Windows, this socket option takes either an IPv4 address or an interface index in + // network byte order. We use the latter option. + DWORD val = htonl(ifindex); + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, (char*)&val, sizeof val); } break; case LWPA_IP_MULTICAST_TTL: @@ -547,6 +544,27 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, } } break; + case LWPA_IP_MULTICAST_IF: + if (option_len == sizeof(unsigned int)) + { + DWORD val = (DWORD) * (unsigned int*)option_value; + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char*)&val, sizeof val); + } + break; + case LWPA_IP_MULTICAST_TTL: + if (option_len == sizeof(int)) + { + DWORD val = (DWORD) * (int*)option_value; + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&val, sizeof val); + } + break; + case LWPA_IP_MULTICAST_LOOP: + if (option_len == sizeof(int)) + { + DWORD val = (DWORD) * (int*)option_value; + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char*)&val, sizeof val); + } + break; case LWPA_IPV6_V6ONLY: if (option_len == sizeof(int)) { diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index d019043ca..b591ba5c4 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -233,8 +233,8 @@ TEST_F(SocketTest, multicast_udp) ASSERT_NE(send_sock, LWPA_SOCKET_INVALID); ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &default_netint_.addr, - sizeof default_netint_.addr)); + ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &default_netint_.index, + sizeof default_netint_.index)); // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); From 628ae4af7414f0ee387d827a4266e9d69eabdac2 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 9 Jul 2019 15:50:34 -0500 Subject: [PATCH 081/264] Fix macOS --- src/CMakeLists.txt | 2 +- src/os/macos/lwpa/os_socket.c | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9fff273bd..307044804 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -146,7 +146,7 @@ endif() set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) # Installation -install(TARGETS lwpa LIBRARY DESTINATION lib) +install(TARGETS lwpa ARCHIVE DESTINATION lib) install(DIRECTORY ${LWPA_ROOT}/include/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") install(DIRECTORY ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index 0ad6d3d05..ed9713763 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -462,15 +462,12 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s } break; case LWPA_IP_MULTICAST_IF: - if (option_len == sizeof(LwpaIpAddr)) + if (option_len == sizeof(unsigned int)) { - LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (LWPA_IP_IS_V4(netint)) - { - struct in_addr val; - val.s_addr = htonl(LWPA_IP_V4_ADDRESS(netint)); - return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); - } + struct in_addr val; + if (0 != ip4_ifindex_to_addr(*(unsigned int*)option_value, &val)) + return -1; + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); } break; case LWPA_IP_MULTICAST_TTL: @@ -515,6 +512,14 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, } } break; + case LWPA_IP_MULTICAST_IF: + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_IF, option_value, (socklen_t)option_len); + case LWPA_IP_MULTICAST_TTL: + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, option_value, (socklen_t)option_len); + case LWPA_IP_MULTICAST_LOOP: + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, option_value, (socklen_t)option_len); + case LWPA_IPV6_V6ONLY: + return setsockopt(id, IPPROTO_IPV6, IPV6_V6ONLY, option_value, (socklen_t)option_len); default: /* Other IPv6 options TODO on macOS. */ break; } From 6f2449717c62fc1adc5390b83b32076429e70f60 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 10 Jul 2019 17:10:04 -0500 Subject: [PATCH 082/264] Tweak docs and API functions to conform with style and best practice --- CMakeLists.txt | 8 +- azure-pipelines.yml | 11 +- include/lwpa/bool.h | 2 +- include/lwpa/common.h | 2 +- include/lwpa/error.h | 2 +- include/lwpa/int.h | 2 +- include/lwpa/log.h | 32 +-- include/lwpa/mempool.h | 8 +- include/lwpa/netint.h | 2 +- include/lwpa/pack.h | 206 ++-------------- include/lwpa/pdu.h | 32 +-- include/lwpa/rbtree.h | 4 +- include/lwpa/root_layer_pdu.h | 4 +- include/lwpa/timer.h | 45 +--- include/lwpa/uuid.h | 10 +- src/CMakeLists.txt | 2 + src/lwpa/pack.c | 226 ++++++++++++++++++ src/lwpa/pdu.c | 10 +- src/lwpa/root_layer_pdu.c | 52 ++-- src/lwpa/thread.dox | 2 +- src/lwpa/timer.c | 92 +++++++ src/os/windows/lwpa/os_socket.c | 2 + src/os/windows/lwpa/os_timer.c | 12 - tests/CMakeLists.txt | 34 +-- tests/unit/CMakeLists.txt | 4 + tests/unit/lwpa/CMakeLists.txt | 34 +++ tests/unit/{ => lwpa}/test_common.cpp | 0 tests/unit/{ => lwpa}/test_inet.cpp | 0 tests/unit/{ => lwpa}/test_log.cpp | 0 tests/unit/{ => lwpa}/test_mempool.cpp | 0 tests/unit/{ => lwpa}/test_mutex.cpp | 0 tests/unit/{ => lwpa}/test_netint.cpp | 0 tests/unit/{ => lwpa}/test_pack.cpp | 0 tests/unit/{ => lwpa}/test_rbtree.cpp | 0 tests/unit/{ => lwpa}/test_rwlock.cpp | 0 tests/unit/{ => lwpa}/test_signal.cpp | 0 tests/unit/{ => lwpa}/test_socket.cpp | 0 tests/unit/{ => lwpa}/test_socket_poll.cpp | 0 tests/unit/{ => lwpa}/test_thread.cpp | 0 tests/unit/{ => lwpa}/test_timer.cpp | 51 +--- tests/unit/{ => lwpa}/test_uuid.cpp | 32 +-- .../unit/lwpa_timer_wraparound/CMakeLists.txt | 11 + .../test_timer_wraparound.cpp} | 58 ++--- 43 files changed, 541 insertions(+), 451 deletions(-) create mode 100644 src/lwpa/pack.c create mode 100644 src/lwpa/timer.c create mode 100644 tests/unit/CMakeLists.txt create mode 100644 tests/unit/lwpa/CMakeLists.txt rename tests/unit/{ => lwpa}/test_common.cpp (100%) rename tests/unit/{ => lwpa}/test_inet.cpp (100%) rename tests/unit/{ => lwpa}/test_log.cpp (100%) rename tests/unit/{ => lwpa}/test_mempool.cpp (100%) rename tests/unit/{ => lwpa}/test_mutex.cpp (100%) rename tests/unit/{ => lwpa}/test_netint.cpp (100%) rename tests/unit/{ => lwpa}/test_pack.cpp (100%) rename tests/unit/{ => lwpa}/test_rbtree.cpp (100%) rename tests/unit/{ => lwpa}/test_rwlock.cpp (100%) rename tests/unit/{ => lwpa}/test_signal.cpp (100%) rename tests/unit/{ => lwpa}/test_socket.cpp (100%) rename tests/unit/{ => lwpa}/test_socket_poll.cpp (100%) rename tests/unit/{ => lwpa}/test_thread.cpp (100%) rename tests/unit/{ => lwpa}/test_timer.cpp (64%) rename tests/unit/{ => lwpa}/test_uuid.cpp (87%) create mode 100644 tests/unit/lwpa_timer_wraparound/CMakeLists.txt rename tests/unit/{main.cpp => lwpa_timer_wraparound/test_timer_wraparound.cpp} (51%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2adc1b8e..0abcd4d06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,10 @@ else() endif() option(LWPA_BUILD_MOCK_LIB "Build the lwpa_mock library" OFF) -if(LWPA_BUILD_MOCK_LIB) +option(LWPA_BUILD_TESTS "Build the lwpa unit tests" ${OPTION_DEFAULTS}) +option(LWPA_BUILD_EXAMPLES "Build the lwpa example apps" ${OPTION_DEFAULTS}) + +if(LWPA_BUILD_MOCK_LIB OR LWPA_BUILD_TESTS) add_subdirectory(external/fff) endif() @@ -33,15 +36,12 @@ add_subdirectory(src) #################################### Tests #################################### -option(LWPA_BUILD_TESTS "Build the lwpa unit tests" ${OPTION_DEFAULTS}) if(LWPA_BUILD_TESTS) - enable_testing() add_subdirectory(tests) endif() ################################## Examples ################################### -option(LWPA_BUILD_EXAMPLES "Build the lwpa example apps" ${OPTION_DEFAULTS}) if(LWPA_BUILD_EXAMPLES) add_subdirectory(examples) endif() diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 3a93c3c2c..ee8aad5de 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -28,7 +28,9 @@ jobs: cmake -G "Visual Studio 15 2017 Win64" -DLWPA_BUILD_MOCK_LIB=ON .. cmake --build . --config %LWPA_BUILD_CONFIG% displayName: 'lwpa Windows build' - - script: build\tests\%LWPA_BUILD_CONFIG%\test_lwpa.exe + - script: | + cd build + ctest --output-on-failure -C %LWPA_BUILD_CONFIG% displayName: 'lwpa Windows test' - job: macos_build @@ -44,7 +46,8 @@ jobs: cmake --build . displayName: 'lwpa macOS build' - script: | - build/tests/test_lwpa --gtest_filter=-SocketTest.multicast_udp:SocketPollTest.udp_in + cd build + ctest --output-on-failure displayName: 'lwpa macOS test' - job: linux_build @@ -61,7 +64,9 @@ jobs: cmake -G "Unix Makefiles" -DLWPA_BUILD_MOCK_LIB=ON .. cmake --build . displayName: 'lwpa Linux build' - - script: build/tests/test_lwpa + - script: | + cd build + ctest --output-on-failure displayName: 'lwpa Linux test' # Generate documentation with doxygen. Documentation is generated from the diff --git a/include/lwpa/bool.h b/include/lwpa/bool.h index 5392c34b2..9faa00411 100644 --- a/include/lwpa/bool.h +++ b/include/lwpa/bool.h @@ -70,6 +70,6 @@ #endif /* __cplusplus || DOXYGEN */ -/*!@}*/ +/*! @} */ #endif /* _LWPA_BOOL_H_ */ diff --git a/include/lwpa/common.h b/include/lwpa/common.h index 0ad1ba7d4..b83affc64 100644 --- a/include/lwpa/common.h +++ b/include/lwpa/common.h @@ -82,6 +82,6 @@ void lwpa_deinit(lwpa_features_t features); } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_COMMON_H_ */ diff --git a/include/lwpa/error.h b/include/lwpa/error.h index 4de8d9ff2..30e858672 100644 --- a/include/lwpa/error.h +++ b/include/lwpa/error.h @@ -121,6 +121,6 @@ extern const char* lwpa_error_strings[LWPA_NUM_ERROR_CODES]; } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_ERROR_H_ */ diff --git a/include/lwpa/int.h b/include/lwpa/int.h index f93d8a6e0..a68062a1f 100644 --- a/include/lwpa/int.h +++ b/include/lwpa/int.h @@ -78,6 +78,6 @@ #endif /* __cplusplus */ -/*!@}*/ +/*! @} */ #endif /* _LWPA_INT_H_ */ diff --git a/include/lwpa/log.h b/include/lwpa/log.h index 82eaec2b5..7ee072ed8 100644 --- a/include/lwpa/log.h +++ b/include/lwpa/log.h @@ -72,7 +72,7 @@ #define LWPA_LOG_LOCAL5 (21 << 3) /*!< Reserved for local use. */ #define LWPA_LOG_LOCAL6 (22 << 3) /*!< Reserved for local use. */ #define LWPA_LOG_LOCAL7 (23 << 3) /*!< Reserved for local use. */ -/*!@}*/ +/*! @} */ #define LWPA_LOG_NFACILITIES 24 /*!< Current number of facilities. */ #define LWPA_LOG_FACMASK 0x03f8 /* Mask to extract facility part of a prival. */ @@ -89,10 +89,10 @@ #define LWPA_LOG_NOTICE 5 /*!< Normal but significant condition. */ #define LWPA_LOG_INFO 6 /*!< Informational. */ #define LWPA_LOG_DEBUG 7 /*!< Debug-level messages. */ -/*!@}*/ +/*! @} */ #define LWPA_LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ -#define LWPA_LOG_PRI(p) ((p)&LWPA_LOG_PRIMASK) /* extract priority */ +#define LWPA_LOG_PRI(p) ((p) & LWPA_LOG_PRIMASK) /* extract priority */ #define LWPA_LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) #define LWPA_LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ @@ -131,22 +131,14 @@ /*! A set of parameters which represent the current local time with millisecond resolution. */ typedef struct LwpaLogTimeParams { - /*! Absolute year. Valid range 0-9999. */ - int year; - /*! Month of the year. Valid range 1-12 (starting with 1 for January). */ - int month; - /*! Day of the month. Valid range 1-31. */ - int day; - /*! Hours since midnight. Valid range 0-23. */ - int hour; - /*! Minutes past the current hour. Valid range 0-59. */ - int minute; - /*! Seconds past the current minute. Valid range 0-60 (to handle leap seconds). */ - int second; - /*! Milliseconds past the current second. Valid range 0-999. */ - int msec; - /*! The local offset from UTC in minutes. */ - int utc_offset; + int year; /*!< Absolute year. Valid range 0-9999. */ + int month; /*!< Month of the year. Valid range 1-12 (starting with 1 for January). */ + int day; /*!< Day of the month. Valid range 1-31. */ + int hour; /*!< Hours since midnight. Valid range 0-23. */ + int minute; /*!< Minutes past the current hour. Valid range 0-59. */ + int second; /*!< Seconds past the current minute. Valid range 0-60 (to handle leap seconds). */ + int msec; /*!< Milliseconds past the current second. Valid range 0-999. */ + int utc_offset; /*!< The local offset from UTC in minutes. */ } LwpaLogTimeParams; /*! The set of log strings passed with a call to an lwpa_log_callback function. Any members not @@ -282,6 +274,6 @@ void lwpa_vlog(const LwpaLogParams* params, int pri, const char* format, va_list } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_LOG_H_ */ diff --git a/include/lwpa/mempool.h b/include/lwpa/mempool.h index 73103af7a..8076aa266 100644 --- a/include/lwpa/mempool.h +++ b/include/lwpa/mempool.h @@ -110,9 +110,9 @@ typedef struct LwpaMempoolDesc /*! \brief Initialize a memory pool. * - * This macro must be called on a pool before using lwpa_mempool_alloc() or lwpa_mempool_free() on - * it. There is no deinitialization function because there is no cleanup necessary; to reset a - * pool, simply call this function again. + * Must be called on a pool before using lwpa_mempool_alloc() or lwpa_mempool_free() on it. There + * is no deinitialization function because there is no cleanup necessary; to reset a pool, simply + * call this function again. * * \param name The name of the memory pool to initialize. * \return #kLwpaErrOk: The memory pool was initialized successfully.\n @@ -165,6 +165,6 @@ size_t lwpa_mempool_used_priv(LwpaMempoolDesc* desc); } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_MEMPOOL_H_ */ diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index 6ed99f143..d99567f5b 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -49,6 +49,6 @@ lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNeti } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_NETINT_H_ */ diff --git a/include/lwpa/pack.h b/include/lwpa/pack.h index bcf1550c4..45cb04bc9 100644 --- a/include/lwpa/pack.h +++ b/include/lwpa/pack.h @@ -37,194 +37,30 @@ * @{ */ -/* clang-format off */ - -/*! \brief Unpack a uint16_t from a known big-endian buffer. - * \param ptr Pointer to the buffer from which to unpack a uint16_t. - * \return Unpacked uint16_t. - */ -#define lwpa_upack_16b(ptr) \ - ( \ - (uint16_t)(0u | \ - (uint16_t)( \ - (((uint16_t)((uint8_t *)(ptr))[0]) << 8) | \ - ((uint16_t)((uint8_t *)(ptr))[1]) \ - ) \ - ) \ - ) - -/*! \brief Pack a uint16_t to a known big-endian buffer. - * \param ptr Pointer to the buffer into which to pack a uint16_t. - * \param val uint16_t value to pack into the buffer. - */ -#define lwpa_pack_16b(ptr, val) \ - do \ - { \ - ((uint8_t *)(ptr))[1] = (uint8_t) ((val) & 0xff); \ - ((uint8_t *)(ptr))[0] = (uint8_t)(((val) & 0xff00) >> 8); \ - } while (0) - -/*! \brief Unpack a uint16_t from a known little-endian buffer. - * \param ptr Pointer to the buffer from which to unpack a uint16_t. - * \return Unpacked uint16_t. - */ -#define lwpa_upack_16l(ptr) \ - ( \ - (uint16_t)(0u | \ - (uint16_t)( \ - (((uint16_t)((uint8_t *)(ptr))[1]) << 8) | \ - ((uint16_t)((uint8_t *)(ptr))[0]) \ - ) \ - ) \ - ) - -/*! \brief Pack a uint16_t to a known little-endian buffer. - * \param ptr Pointer to the buffer into which to pack a uint16_t. - * \param val uint16_t value to pack into the buffer. - */ -#define lwpa_pack_16l(ptr, val) \ - do \ - { \ - ((uint8_t *)(ptr))[0] = (uint8_t) ((val) & 0xff); \ - ((uint8_t *)(ptr))[1] = (uint8_t)(((val) & 0xff00) >> 8); \ - } while (0) - -/*! \brief Unpack a uint32_t from a known big-endian buffer. - * \param ptr Pointer to the buffer from which to unpack a uint32_t. - * \return Unpacked uint32_t. - */ -#define lwpa_upack_32b(ptr) \ - ( \ - (uint32_t)(0u | \ - (uint32_t)( \ - (((uint32_t)((uint8_t *)(ptr))[0]) << 24) | \ - (((uint32_t)((uint8_t *)(ptr))[1]) << 16) | \ - (((uint32_t)((uint8_t *)(ptr))[2]) << 8) | \ - ((uint32_t)((uint8_t *)(ptr))[3]) \ - ) \ - ) \ - ) - -/*! \brief Pack a uint32_t to a known big-endian buffer. - * \param ptr Pointer to the buffer into which to pack a uint32_t. - * \param val uint32_t value to pack into the buffer. - */ -#define lwpa_pack_32b(ptr, val) \ - do \ - { \ - ((uint8_t *)(ptr))[3] = (uint8_t) ((val) & 0xff); \ - ((uint8_t *)(ptr))[2] = (uint8_t)(((val) & 0xff00) >> 8); \ - ((uint8_t *)(ptr))[1] = (uint8_t)(((val) & 0xff0000) >> 16); \ - ((uint8_t *)(ptr))[0] = (uint8_t)(((val) & 0xff000000) >> 24); \ - } while (0) - -/*! \brief Unpack a uint32_t from a known little-endian buffer. - * \param ptr Pointer to the buffer from which to unpack a uint32_t. - * \return Unpacked uint32_t. - */ -#define lwpa_upack_32l(ptr) \ - ( \ - (uint32_t)(0u | \ - (uint32_t)( \ - (((uint32_t)((uint8_t *)(ptr))[3]) << 24) | \ - (((uint32_t)((uint8_t *)(ptr))[2]) << 16) | \ - (((uint32_t)((uint8_t *)(ptr))[1]) << 8) | \ - ((uint32_t)((uint8_t *)(ptr))[0]) \ - ) \ - ) \ - ) - -/*! \brief Pack a uint32_t to a known little-endian buffer. - * \param ptr Pointer to the buffer into which to pack a uint32_t. - * \param val uint32_t value to pack into the buffer. - */ -#define lwpa_pack_32l(ptr, val) \ - do \ - { \ - ((uint8_t *)(ptr))[0] = (uint8_t) ((val) & 0xff); \ - ((uint8_t *)(ptr))[1] = (uint8_t)(((val) & 0xff00) >> 8); \ - ((uint8_t *)(ptr))[2] = (uint8_t)(((val) & 0xff0000) >> 16); \ - ((uint8_t *)(ptr))[3] = (uint8_t)(((val) & 0xff000000) >> 24); \ - } while (0) +#ifdef __cplusplus +extern "C" { +#endif + +uint16_t lwpa_upack_16b(const uint8_t* buf); +void lwpa_pack_16b(uint8_t* buf, uint16_t val); +uint16_t lwpa_upack_16l(const uint8_t* buf); +void lwpa_pack_16l(uint8_t* buf, uint16_t val); +uint32_t lwpa_upack_32b(const uint8_t* buf); +void lwpa_pack_32b(uint8_t* buf, uint32_t val); +uint32_t lwpa_upack_32l(const uint8_t* buf); +void lwpa_pack_32l(uint8_t* buf, uint32_t val); #if LWPA_64BIT_SUPPORT +uint64_t lwpa_upack_64b(const uint8_t* buf); +void lwpa_pack_64b(uint8_t* buf, uint64_t val); +uint64_t lwpa_upack_64l(const uint8_t* buf); +void lwpa_pack_64l(uint8_t* buf, uint64_t val); +#endif -/*! \brief Unpack a uint64_t from a known big-endian buffer. - * \param ptr Pointer to the buffer from which to unpack a uint64_t. - * \return Unpacked uint64_t. - */ -#define lwpa_upack_64b(ptr) \ - ( \ - (uint64_t)(0u | \ - (uint64_t)( \ - (((uint64_t)((uint8_t *)(ptr))[0]) << 56) | \ - (((uint64_t)((uint8_t *)(ptr))[1]) << 48) | \ - (((uint64_t)((uint8_t *)(ptr))[2]) << 40) | \ - (((uint64_t)((uint8_t *)(ptr))[3]) << 32) | \ - (((uint64_t)((uint8_t *)(ptr))[4]) << 24) | \ - (((uint64_t)((uint8_t *)(ptr))[5]) << 16) | \ - (((uint64_t)((uint8_t *)(ptr))[6]) << 8) | \ - ((uint64_t)((uint8_t *)(ptr))[7]) \ - ) \ - ) \ - ) - -/*! \brief Pack a uint64_t to a known big-endian buffer. - * \param ptr Pointer to the buffer into which to pack a uint64_t. - * \param val uint64_t value to pack into the buffer. - */ -#define lwpa_pack_64b(ptr, val) \ - do \ - { \ - ((uint8_t *)(ptr))[7] = (uint8_t) ((val) & 0xff); \ - ((uint8_t *)(ptr))[6] = (uint8_t)(((val) & 0xff00) >> 8); \ - ((uint8_t *)(ptr))[5] = (uint8_t)(((val) & 0xff0000) >> 16); \ - ((uint8_t *)(ptr))[4] = (uint8_t)(((val) & 0xff000000) >> 24); \ - ((uint8_t *)(ptr))[3] = (uint8_t)(((val) & 0xff00000000) >> 32); \ - ((uint8_t *)(ptr))[2] = (uint8_t)(((val) & 0xff0000000000) >> 40); \ - ((uint8_t *)(ptr))[1] = (uint8_t)(((val) & 0xff000000000000) >> 48); \ - ((uint8_t *)(ptr))[0] = (uint8_t)(((val) & 0xff00000000000000) >> 56); \ - } while (0) - -/*! \brief Unpack a uint64_t from a known little-endian buffer. - * \param ptr Pointer to the buffer from which to unpack a uint64_t. - * \return Unpacked uint64_t. - */ -#define lwpa_upack_64l(ptr) \ - ( \ - (uint64_t)(0u | \ - (uint64_t)( \ - (((uint64_t)((uint8_t *)(ptr))[7]) << 56) | \ - (((uint64_t)((uint8_t *)(ptr))[6]) << 48) | \ - (((uint64_t)((uint8_t *)(ptr))[5]) << 40) | \ - (((uint64_t)((uint8_t *)(ptr))[4]) << 32) | \ - (((uint64_t)((uint8_t *)(ptr))[3]) << 24) | \ - (((uint64_t)((uint8_t *)(ptr))[2]) << 16) | \ - (((uint64_t)((uint8_t *)(ptr))[1]) << 8) | \ - ((uint64_t)((uint8_t *)(ptr))[0]) \ - ) \ - ) \ - ) - -/*! \brief Pack a uint64_t to a known little-endian buffer. - * \param ptr Pointer to the buffer into which to pack a uint64_t. - * \param val uint64_t value to pack into the buffer. - */ -#define lwpa_pack_64l(ptr, val) \ - do \ - { \ - ((uint8_t *)(ptr))[0] = (uint8_t) ((val) & 0xff); \ - ((uint8_t *)(ptr))[1] = (uint8_t)(((val) & 0xff00) >> 8); \ - ((uint8_t *)(ptr))[2] = (uint8_t)(((val) & 0xff0000) >> 16); \ - ((uint8_t *)(ptr))[3] = (uint8_t)(((val) & 0xff000000) >> 24); \ - ((uint8_t *)(ptr))[4] = (uint8_t)(((val) & 0xff00000000) >> 32); \ - ((uint8_t *)(ptr))[5] = (uint8_t)(((val) & 0xff0000000000) >> 40); \ - ((uint8_t *)(ptr))[6] = (uint8_t)(((val) & 0xff000000000000) >> 48); \ - ((uint8_t *)(ptr))[7] = (uint8_t)(((val) & 0xff00000000000000) >> 56); \ - } while (0) - -#endif /* LWPA_64BIT_SUPPORT */ +#ifdef __cplusplus +} +#endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_PACK_H_ */ diff --git a/include/lwpa/pdu.h b/include/lwpa/pdu.h index dab6fc5c5..e31c8f419 100644 --- a/include/lwpa/pdu.h +++ b/include/lwpa/pdu.h @@ -42,26 +42,26 @@ /*! Determine whether the L flag is set in a PDU flags field. * \param flags_byte The first byte of the PDU. * \return true (the L flag is set) or false (the L flags is not set). */ -#define lwpa_pdu_l_flag_set(flags_byte) ((bool)(flags_byte & 0x80u)) +#define LWPA_PDU_L_FLAG_SET(flags_byte) ((bool)(flags_byte & 0x80u)) /*! Determine whether the V flag is set in a PDU flags field. * \param flags_byte The first byte of the PDU. * \return true (the V flag is set) or false (the V flag is not set). */ -#define lwpa_pdu_v_flag_set(flags_byte) ((bool)(flags_byte & 0x40u)) +#define LWPA_PDU_V_FLAG_SET(flags_byte) ((bool)(flags_byte & 0x40u)) /*! Determine whether the H flag is set in a PDU flags field. * \param flags_byte The first byte of the PDU. * \return true (the H flag is set) or false (the H flag is not set). */ -#define lwpa_pdu_h_flag_set(flags_byte) ((bool)(flags_byte & 0x20u)) +#define LWPA_PDU_H_FLAG_SET(flags_byte) ((bool)(flags_byte & 0x20u)) /*! Determine whether the D flag is set in a PDU flags field. * \param flags_byte The first byte of the PDU. * \return true (the D flag is set) or false (the D flag is not set). */ -#define lwpa_pdu_d_flag_set(flags_byte) ((bool)(flags_byte & 0x10u)) -/*!@}*/ +#define LWPA_PDU_D_FLAG_SET(flags_byte) ((bool)(flags_byte & 0x10u)) +/*! @} */ /*! Get the length from the Length field of a PDU. * \param pdu_buf Pointer to the start of the PDU buffer. * \return The length of the PDU. */ -#define lwpa_pdu_length(pdu_buf) \ - ((uint32_t)(lwpa_pdu_l_flag_set(pdu_buf[0]) \ +#define LWPA_PDU_LENGTH(pdu_buf) \ + ((uint32_t)(LWPA_PDU_L_FLAG_SET(pdu_buf[0]) \ ? ((uint32_t)((pdu_buf[0] & 0x0fu) << 16) | (uint32_t)(pdu_buf[1] << 8) | (uint32_t)pdu_buf[2]) \ : ((uint32_t)((pdu_buf[0] & 0x0fu) << 8) | (uint32_t)pdu_buf[1]))) @@ -72,24 +72,24 @@ */ /*! Set the L flag in a PDU flags field. * \param flags_byte The first byte of the PDU. */ -#define lwpa_pdu_set_l_flag(flags_byte) (flags_byte |= 0x80u) +#define LWPA_PDU_SET_L_FLAG(flags_byte) (flags_byte |= 0x80u) /*! Set the V flag in a PDU flags field. * \param flags_byte The first byte of the PDU. */ -#define lwpa_pdu_set_v_flag(flags_byte) (flags_byte |= 0x40u) +#define LWPA_PDU_SET_V_FLAG(flags_byte) (flags_byte |= 0x40u) /*! Set the H flag in a PDU flags field. * \param flags_byte The first byte of the PDU. */ -#define lwpa_pdu_set_h_flag(flags_byte) (flags_byte |= 0x20u) +#define LWPA_PDU_SET_H_FLAG(flags_byte) (flags_byte |= 0x20u) /*! Set the D flag in a PDU flags field. * \param flags_byte The first byte of the PDU. */ -#define lwpa_pdu_set_d_flag(flags_byte) (flags_byte |= 0x10u) -/*!@}*/ +#define LWPA_PDU_SET_D_FLAG(flags_byte) (flags_byte |= 0x10u) +/*! @} */ /*! Fill in the Length field of a PDU which has a length less than 4096. The L flag of this PDU must * be set to 0. * \param pdu_buf Pointer to the start of the PDU buffer. * \param length Length of this PDU. */ -#define lwpa_pdu_pack_normal_len(pdu_buf, length) \ +#define LWPA_PDU_PACK_NORMAL_LEN(pdu_buf, length) \ do \ { \ (pdu_buf)[0] = (uint8_t)(((pdu_buf)[0] & 0xf0) | (((length) >> 8) & 0x0fu)); \ @@ -101,7 +101,7 @@ * \param pdu_buf Pointer to the start of the PDU buffer. * \param length Length of this PDU. */ -#define lwpa_pdu_pack_ext_len(pdu_buf, length) \ +#define LWPA_PDU_PACK_EXT_LEN(pdu_buf, length) \ do \ { \ (pdu_buf)[0] = (uint8_t)(((pdu_buf)[0] & 0xf0) | (((length) >> 16) & 0x0fu)); \ @@ -129,7 +129,7 @@ typedef struct LwpaPdu /*! An alternative to #LWPA_PDU_INIT which can be used on an existing LwpaPdu to re-initialize its * values. * \param pduptr Pointer to LwpaPdu to initialize. */ -#define lwpa_init_pdu(pduptr) \ +#define LWPA_INIT_PDU(pduptr) \ do \ { \ (pduptr)->pvector = NULL; \ @@ -156,6 +156,6 @@ bool lwpa_parse_pdu(const uint8_t* buf, size_t buflen, const LwpaPduConstraints* } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_PDU_H_ */ diff --git a/include/lwpa/rbtree.h b/include/lwpa/rbtree.h index 6f13a8234..281840d64 100644 --- a/include/lwpa/rbtree.h +++ b/include/lwpa/rbtree.h @@ -109,7 +109,7 @@ typedef LwpaRbNode* (*lwpa_rbnode_alloc_f)(); */ typedef void (*lwpa_rbnode_dealloc_f)(LwpaRbNode* node); -/*!@}*/ +/*! @} */ /*! \brief A red-black tree node. */ struct LwpaRbNode @@ -179,6 +179,6 @@ void* lwpa_rbiter_prev(LwpaRbIter* self); } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_RBTREE_H_ */ diff --git a/include/lwpa/root_layer_pdu.h b/include/lwpa/root_layer_pdu.h index 7b6faa3ec..e1a6dcf22 100644 --- a/include/lwpa/root_layer_pdu.h +++ b/include/lwpa/root_layer_pdu.h @@ -60,7 +60,7 @@ #define ACN_VECTOR_ROOT_BROKER ACN_PROTOCOL_BROKER #define ACN_VECTOR_ROOT_RPT ACN_PROTOCOL_RPT #define ACN_VECTOR_ROOT_EPT ACN_PROTOCOL_EPT -/*!@}*/ +/*! @} */ /*! Holds the information contained in an ACN TCP Preamble. */ typedef struct LwpaTcpPreamble @@ -112,6 +112,6 @@ size_t lwpa_pack_root_layer_block(uint8_t* buf, size_t buflen, const LwpaRootLay } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_ROOT_LAYER_PDU_H_ */ diff --git a/include/lwpa/timer.h b/include/lwpa/timer.h index c4944d804..7de9ac9e9 100644 --- a/include/lwpa/timer.h +++ b/include/lwpa/timer.h @@ -49,54 +49,25 @@ typedef struct LwpaTimer extern "C" { #endif +/* Function with platform-specific definition */ + /*! \brief Get a monotonically-increasing millisecond value * \return The current timestamp in milliseconds. */ uint32_t lwpa_getms(); -/*! \brief Start a timer. - * \param lwpatimerptr Pointer to the LwpaTimer to start. - * \param intval Timer interval in milliseconds. An interval of 0 will result in a timer that is - * always expired. - */ -#define lwpa_timer_start(lwpatimerptr, intval) \ - do \ - { \ - (lwpatimerptr)->reset_time = lwpa_getms(); \ - (lwpatimerptr)->interval = intval; \ - } while (0) +/* Functions with platform-neutral definitions */ -/*! \brief Reset a timer while keeping the same interval. - * \param lwpatimerptr Pointer to the LwpaTimer to reset. - */ -#define lwpa_timer_reset(lwpatimerptr) (((lwpatimerptr)->reset_time) = lwpa_getms()) - -/*! \brief Get the time since a timer was reset. - * \param lwpatimerptr Pointer to the LwpaTimer of which to get the elapsed time. - * \return Number of milliseconds since the timer was reset. - */ -#define lwpa_timer_elapsed(lwpatimerptr) (lwpa_getms() - (lwpatimerptr)->reset_time) - -/*! \brief Check to see if a timer is expired. - * \param lwpatimerptr Pointer to the LwpaTimer of which to check the expiration. - * \return true (more than \link LwpaTimer::interval interval \endlink milliseconds have passed - * since the timer was started/reset) or false (less than or equal to - * \link LwpaTimer::interval interval \endlink milliseconds have passed since the timer was - * started/reset) - */ -#define lwpa_timer_isexpired(lwpatimerptr) \ - (((lwpatimerptr)->interval == 0) || (lwpa_timer_elapsed(lwpatimerptr) > (lwpatimerptr)->interval)) - -/*! \brief Get the amount of time remaining in a timer. - * \param timer Pointer to the LwpaTimer of which to get the remaining time. - * \return Remaining time in milliseconds or 0 (timer is expired). - */ +void lwpa_timer_start(LwpaTimer* timer, uint32_t interval); +void lwpa_timer_reset(LwpaTimer* timer); +uint32_t lwpa_timer_elapsed(const LwpaTimer* timer); +bool lwpa_timer_is_expired(const LwpaTimer* timer); uint32_t lwpa_timer_remaining(const LwpaTimer* timer); #ifdef __cplusplus } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_TIMER_H_ */ diff --git a/include/lwpa/uuid.h b/include/lwpa/uuid.h index b7bfdf135..7f46d75b0 100644 --- a/include/lwpa/uuid.h +++ b/include/lwpa/uuid.h @@ -58,7 +58,7 @@ typedef struct LwpaUuid * 0 (uuid1ptr is equal to uuid2ptr)\n * > 0 (uuid1ptr is greater than uuid2ptr) */ -#define lwpa_uuid_cmp(uuid1ptr, uuid2ptr) memcmp((uuid1ptr)->data, (uuid2ptr)->data, LWPA_UUID_BYTES) +#define LWPA_UUID_CMP(uuid1ptr, uuid2ptr) memcmp((uuid1ptr)->data, (uuid2ptr)->data, LWPA_UUID_BYTES) /*! A null (all 0's) UUID, used by uuid_isnull() for comparison. */ extern const LwpaUuid kLwpaNullUuid; @@ -70,7 +70,7 @@ extern const LwpaUuid kLwpaNullUuid; * \param uuidptr Pointer to UUID to null-check. * \return true (UUID is null) or false (UUID is not null). */ -#define lwpa_uuid_is_null(uuidptr) (memcmp((uuidptr)->data, kLwpaNullUuid.data, LWPA_UUID_BYTES) == 0) +#define LWPA_UUID_IS_NULL(uuidptr) (memcmp((uuidptr)->data, kLwpaNullUuid.data, LWPA_UUID_BYTES) == 0) /*! The maximum number of bytes required to hold an ASCII string representation of a UUID. */ #define LWPA_UUID_STRING_BYTES 37 @@ -96,16 +96,16 @@ lwpa_error_t lwpa_generate_os_preferred_uuid(LwpaUuid* uuid); inline bool operator<(const LwpaUuid& a, const LwpaUuid& b) { - return (lwpa_uuid_cmp(&a, &b) < 0); + return (LWPA_UUID_CMP(&a, &b) < 0); } inline bool operator==(const LwpaUuid& a, const LwpaUuid& b) { - return (lwpa_uuid_cmp(&a, &b) == 0); + return (LWPA_UUID_CMP(&a, &b) == 0); } #endif -/*!@}*/ +/*! @} */ #endif /* _LWPA_UUID_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9fff273bd..fef60dcbc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,9 +79,11 @@ add_library(lwpa ${LWPA_ROOT}/src/lwpa/md5.c ${LWPA_ROOT}/src/lwpa/mempool.c ${LWPA_ROOT}/src/lwpa/netint.c + ${LWPA_ROOT}/src/lwpa/pack.c ${LWPA_ROOT}/src/lwpa/pdu.c ${LWPA_ROOT}/src/lwpa/rbtree.c ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c + ${LWPA_ROOT}/src/lwpa/timer.c ${LWPA_ROOT}/src/lwpa/uuid.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_inet.c ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c diff --git a/src/lwpa/pack.c b/src/lwpa/pack.c new file mode 100644 index 000000000..e83c1f53d --- /dev/null +++ b/src/lwpa/pack.c @@ -0,0 +1,226 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/pack.h" + +/*************************** Function definitions ****************************/ + +/*! \brief Unpack a uint16_t from a known big-endian buffer. + * \param buf Pointer to the buffer from which to unpack a uint16_t. + * \return Unpacked uint16_t. + */ +uint16_t lwpa_upack_16b(const uint8_t* buf) +{ + uint16_t val = 0; + if (buf) + { + val |= ((uint16_t)buf[0] << 8); + val |= ((uint16_t)buf[1]); + } + return val; +} + +/*! \brief Pack a uint16_t to a known big-endian buffer. + * \param buf Pointer to the buffer into which to pack a uint16_t. + * \param val uint16_t value to pack into the buffer. + */ +void lwpa_pack_16b(uint8_t* buf, uint16_t val) +{ + if (buf) + { + buf[1] = (uint8_t)(val & 0xff); + buf[0] = (uint8_t)((val & 0xff00) >> 8); + } +} + +/*! \brief Unpack a uint16_t from a known little-endian buffer. + * \param buf Pointer to the buffer from which to unpack a uint16_t. + * \return Unpacked uint16_t. + */ +uint16_t lwpa_upack_16l(const uint8_t* buf) +{ + uint16_t val = 0; + if (buf) + { + val |= ((uint16_t)buf[1] << 8); + val |= ((uint16_t)buf[0]); + } + return val; +} + +/*! \brief Pack a uint16_t to a known little-endian buffer. + * \param buf Pointer to the buffer into which to pack a uint16_t. + * \param val uint16_t value to pack into the buffer. + */ +void lwpa_pack_16l(uint8_t* buf, uint16_t val) +{ + if (buf) + { + buf[0] = (uint8_t) (val & 0xff); + buf[1] = (uint8_t)((val & 0xff00) >> 8); + } +} + +/*! \brief Unpack a uint32_t from a known big-endian buffer. + * \param buf Pointer to the buffer from which to unpack a uint32_t. + * \return Unpacked uint32_t. + */ +uint32_t lwpa_upack_32b(const uint8_t* buf) +{ + uint32_t val = 0; + if (buf) + { + val |= ((uint32_t)buf[0] << 24); + val |= ((uint32_t)buf[1] << 16); + val |= ((uint32_t)buf[2] << 8); + val |= ((uint32_t)buf[3]); + } + return val; +} + +/*! \brief Pack a uint32_t to a known big-endian buffer. + * \param buf Pointer to the buffer into which to pack a uint32_t. + * \param val uint32_t value to pack into the buffer. + */ +void lwpa_pack_32b(uint8_t* buf, uint32_t val) +{ + if (buf) + { + buf[3] = (uint8_t)(val & 0xff); + buf[2] = (uint8_t)((val & 0xff00) >> 8); + buf[1] = (uint8_t)((val & 0xff0000) >> 16); + buf[0] = (uint8_t)((val & 0xff000000) >> 24); + } +} + +/*! \brief Unpack a uint32_t from a known little-endian buffer. + * \param buf Pointer to the buffer from which to unpack a uint32_t. + * \return Unpacked uint32_t. + */ +uint32_t lwpa_upack_32l(const uint8_t* buf) +{ + uint32_t val = 0; + if (buf) + { + val |= ((uint32_t)buf[3] << 24); + val |= ((uint32_t)buf[2] << 16); + val |= ((uint32_t)buf[1] << 8); + val |= ((uint32_t)buf[0]); + } + return val; +} + +/*! \brief Pack a uint32_t to a known little-endian buffer. + * \param buf Pointer to the buffer into which to pack a uint32_t. + * \param val uint32_t value to pack into the buffer. + */ +void lwpa_pack_32l(uint8_t* buf, uint32_t val) +{ + if (buf) + { + buf[0] = (uint8_t)(val & 0xff); + buf[1] = (uint8_t)((val & 0xff00) >> 8); + buf[2] = (uint8_t)((val & 0xff0000) >> 16); + buf[3] = (uint8_t)((val & 0xff000000) >> 24); + } +} + +#if LWPA_64BIT_SUPPORT + +/*! \brief Unpack a uint64_t from a known big-endian buffer. + * \param buf Pointer to the buffer from which to unpack a uint64_t. + * \return Unpacked uint64_t. + */ +uint64_t lwpa_upack_64b(const uint8_t* buf) +{ + uint64_t val = 0; + if (buf) + { + val |= ((uint64_t)buf[0] << 56); + val |= ((uint64_t)buf[1] << 48); + val |= ((uint64_t)buf[2] << 40); + val |= ((uint64_t)buf[3] << 32); + val |= ((uint64_t)buf[4] << 24); + val |= ((uint64_t)buf[5] << 16); + val |= ((uint64_t)buf[6] << 8); + val |= ((uint64_t)buf[7]); + } + return val; +} + +/*! \brief Pack a uint64_t to a known big-endian buffer. + * \param buf Pointer to the buffer into which to pack a uint64_t. + * \param val uint64_t value to pack into the buffer. + */ +void lwpa_pack_64b(uint8_t* buf, uint64_t val) +{ + if (buf) + { + buf[7] = (uint8_t)(val & 0xff); + buf[6] = (uint8_t)((val & 0xff00) >> 8); + buf[5] = (uint8_t)((val & 0xff0000) >> 16); + buf[4] = (uint8_t)((val & 0xff000000) >> 24); + buf[3] = (uint8_t)((val & 0xff00000000) >> 32); + buf[2] = (uint8_t)((val & 0xff0000000000) >> 40); + buf[1] = (uint8_t)((val & 0xff000000000000) >> 48); + buf[0] = (uint8_t)((val & 0xff00000000000000) >> 56); + } +} + +/*! \brief Unpack a uint64_t from a known little-endian buffer. + * \param buf Pointer to the buffer from which to unpack a uint64_t. + * \return Unpacked uint64_t. + */ +uint64_t lwpa_upack_64l(const uint8_t* buf) +{ + uint64_t val = 0; + if (buf) + { + val |= ((uint64_t)buf[7] << 56); + val |= ((uint64_t)buf[6] << 48); + val |= ((uint64_t)buf[5] << 40); + val |= ((uint64_t)buf[4] << 32); + val |= ((uint64_t)buf[3] << 24); + val |= ((uint64_t)buf[2] << 16); + val |= ((uint64_t)buf[1] << 8); + val |= ((uint64_t)buf[0]); + } + return val; +} + +/*! \brief Pack a uint64_t to a known little-endian buffer. + * \param buf Pointer to the buffer into which to pack a uint64_t. + * \param val uint64_t value to pack into the buffer. + */ +void lwpa_pack_64l(uint8_t* buf, uint64_t val) +{ + if (buf) + { + buf[0] = (uint8_t)(val & 0xff); + buf[1] = (uint8_t)((val & 0xff00) >> 8); + buf[2] = (uint8_t)((val & 0xff0000) >> 16); + buf[3] = (uint8_t)((val & 0xff000000) >> 24); + buf[4] = (uint8_t)((val & 0xff00000000) >> 32); + buf[5] = (uint8_t)((val & 0xff0000000000) >> 40); + buf[6] = (uint8_t)((val & 0xff000000000000) >> 48); + buf[7] = (uint8_t)((val & 0xff00000000000000) >> 56); + } +} + +#endif diff --git a/src/lwpa/pdu.c b/src/lwpa/pdu.c index 0c78b2ade..91b88c8e8 100644 --- a/src/lwpa/pdu.c +++ b/src/lwpa/pdu.c @@ -62,10 +62,10 @@ bool lwpa_parse_pdu(const uint8_t* buf, size_t buflen, const LwpaPduConstraints* /* Check the inheritance and the size of the length field */ flags_byte = *this_pdu; - extlength = lwpa_pdu_l_flag_set(flags_byte); - inheritvect = !lwpa_pdu_v_flag_set(flags_byte); - inherithead = !lwpa_pdu_h_flag_set(flags_byte); - inheritdata = !lwpa_pdu_d_flag_set(flags_byte); + extlength = LWPA_PDU_L_FLAG_SET(flags_byte); + inheritvect = !LWPA_PDU_V_FLAG_SET(flags_byte); + inherithead = !LWPA_PDU_H_FLAG_SET(flags_byte); + inheritdata = !LWPA_PDU_D_FLAG_SET(flags_byte); cur_ptr = this_pdu; if (cur_ptr + (extlength ? 3 : 2) >= buf_end) @@ -74,7 +74,7 @@ bool lwpa_parse_pdu(const uint8_t* buf, size_t buflen, const LwpaPduConstraints* return false; } - pdu_len = lwpa_pdu_length(this_pdu); + pdu_len = LWPA_PDU_LENGTH(this_pdu); min_pdu_len = (uint32_t)((extlength ? 3 : 2) + (inheritvect ? 0 : constraints->vector_size) + (inherithead ? 0 : constraints->header_size)); diff --git a/src/lwpa/root_layer_pdu.c b/src/lwpa/root_layer_pdu.c index 2bbf2b5f1..ad31a85ca 100644 --- a/src/lwpa/root_layer_pdu.c +++ b/src/lwpa/root_layer_pdu.c @@ -25,10 +25,10 @@ #define ACN_RLP_HEADER_SIZE 16u #define RLP_VECTOR_SIZE 4u -#define rlp_extended_length(inheritvec, inherithead, datalen) \ +#define RLP_EXTENDED_LENGTH(inheritvec, inherithead, datalen) \ ((datalen + (inheritvec ? 0 : RLP_VECTOR_SIZE) + (inherithead ? 0 : ACN_RLP_HEADER_SIZE)) > 4095) -#define prot_mandates_l_flag(vector) \ +#define PROT_MANDATES_L_FLAG(vector) \ ((vector == ACN_VECTOR_ROOT_LLRP) || (vector == ACN_VECTOR_ROOT_BROKER) || (vector == ACN_VECTOR_ROOT_RPT) || \ (vector == ACN_VECTOR_ROOT_EPT)) @@ -120,10 +120,10 @@ bool lwpa_parse_root_layer_header(const uint8_t* buf, size_t buflen, LwpaRootLay buf_end = buf + buflen; flags_byte = *buf; - extlength = lwpa_pdu_l_flag_set(flags_byte); - inheritvect = !lwpa_pdu_v_flag_set(flags_byte); - inherithead = !lwpa_pdu_h_flag_set(flags_byte); - inheritdata = !lwpa_pdu_d_flag_set(flags_byte); + extlength = LWPA_PDU_L_FLAG_SET(flags_byte); + inheritvect = !LWPA_PDU_V_FLAG_SET(flags_byte); + inherithead = !LWPA_PDU_H_FLAG_SET(flags_byte); + inheritdata = !LWPA_PDU_D_FLAG_SET(flags_byte); cur_ptr = buf; if (cur_ptr + (extlength ? 3 : 2) >= buf_end) @@ -132,7 +132,7 @@ bool lwpa_parse_root_layer_header(const uint8_t* buf, size_t buflen, LwpaRootLay return false; } - pdu_len = lwpa_pdu_length(buf); + pdu_len = LWPA_PDU_LENGTH(buf); min_pdu_len = (uint32_t)((extlength ? 3 : 2) + (inheritvect ? 0 : 4) + (inherithead ? 0 : 16)); if (((inheritvect || inherithead || inheritdata) && !last_pdu) || (pdu_len < min_pdu_len)) { @@ -146,7 +146,7 @@ bool lwpa_parse_root_layer_header(const uint8_t* buf, size_t buflen, LwpaRootLay { pdu->vector = lwpa_upack_32b(cur_ptr); cur_ptr += 4; - if (prot_mandates_l_flag(pdu->vector) && !extlength) + if (PROT_MANDATES_L_FLAG(pdu->vector) && !extlength) return false; } if (inherithead) @@ -271,7 +271,7 @@ size_t lwpa_pack_tcp_preamble(uint8_t* buf, size_t buflen, size_t rlp_block_len) cur_ptr = buf; memcpy(cur_ptr, ACN_PACKET_IDENT, ACN_PACKET_IDENT_SIZE); cur_ptr += ACN_PACKET_IDENT_SIZE; - lwpa_pack_32b(cur_ptr, rlp_block_len); + lwpa_pack_32b(cur_ptr, (uint32_t)rlp_block_len); cur_ptr += 4; return (size_t)(cur_ptr - buf); } @@ -294,7 +294,7 @@ size_t lwpa_root_layer_buf_size(const LwpaRootLayerPdu* pdu_block, size_t num_pd { block_size += pdu->datalen; /* We assume no inheritance here, so the largest possible buffer is allocated. */ - block_size += (prot_mandates_l_flag(pdu->vector) || rlp_extended_length(false, false, pdu->datalen)) + block_size += (PROT_MANDATES_L_FLAG(pdu->vector) || RLP_EXTENDED_LENGTH(false, false, pdu->datalen)) ? ACN_RLP_HEADER_SIZE_EXT_LEN : ACN_RLP_HEADER_SIZE_NORMAL_LEN; } @@ -319,15 +319,15 @@ size_t lwpa_pack_root_layer_header(uint8_t* buf, size_t buflen, const LwpaRootLa return 0; *cur_ptr = 0x70; - if (prot_mandates_l_flag(pdu->vector) || rlp_extended_length(false, false, pdu->datalen)) + if (PROT_MANDATES_L_FLAG(pdu->vector) || RLP_EXTENDED_LENGTH(false, false, pdu->datalen)) { - lwpa_pdu_set_l_flag(*cur_ptr); - lwpa_pdu_pack_ext_len(cur_ptr, ACN_RLP_HEADER_SIZE_EXT_LEN + pdu->datalen); + LWPA_PDU_SET_L_FLAG(*cur_ptr); + LWPA_PDU_PACK_EXT_LEN(cur_ptr, ACN_RLP_HEADER_SIZE_EXT_LEN + pdu->datalen); cur_ptr += 3; } else { - lwpa_pdu_pack_normal_len(cur_ptr, ACN_RLP_HEADER_SIZE_NORMAL_LEN + pdu->datalen); + LWPA_PDU_PACK_NORMAL_LEN(cur_ptr, ACN_RLP_HEADER_SIZE_NORMAL_LEN + pdu->datalen); cur_ptr += 2; } lwpa_pack_32b(cur_ptr, pdu->vector); @@ -370,15 +370,15 @@ size_t lwpa_pack_root_layer_block(uint8_t* buf, size_t buflen, const LwpaRootLay if (pdu == pdu_block) { /* First PDU in the block - no inheritance */ - lwpa_pdu_set_v_flag(*cur_ptr); + LWPA_PDU_SET_V_FLAG(*cur_ptr); inheritvec = false; last_pdu.vector = pdu->vector; - lwpa_pdu_set_h_flag(*cur_ptr); + LWPA_PDU_SET_H_FLAG(*cur_ptr); inherithead = false; last_pdu.sender_cid = pdu->sender_cid; - lwpa_pdu_set_d_flag(*cur_ptr); + LWPA_PDU_SET_D_FLAG(*cur_ptr); inheritdata = false; last_pdu.pdata = pdu->pdata; last_pdu.datalen = pdu->datalen; @@ -388,19 +388,19 @@ size_t lwpa_pack_root_layer_block(uint8_t* buf, size_t buflen, const LwpaRootLay /* Check if we can use some inheritance */ if (pdu->vector != last_pdu.vector) { - lwpa_pdu_set_v_flag(*cur_ptr); + LWPA_PDU_SET_V_FLAG(*cur_ptr); inheritvec = false; last_pdu.vector = pdu->vector; } - if (0 != lwpa_uuid_cmp(&pdu->sender_cid, &last_pdu.sender_cid)) + if (0 != LWPA_UUID_CMP(&pdu->sender_cid, &last_pdu.sender_cid)) { - lwpa_pdu_set_h_flag(*cur_ptr); + LWPA_PDU_SET_H_FLAG(*cur_ptr); inherithead = false; last_pdu.sender_cid = pdu->sender_cid; } if ((pdu->datalen != last_pdu.datalen) || (0 != memcmp(pdu->pdata, last_pdu.pdata, last_pdu.datalen))) { - lwpa_pdu_set_d_flag(*cur_ptr); + LWPA_PDU_SET_D_FLAG(*cur_ptr); inheritdata = false; last_pdu.pdata = pdu->pdata; last_pdu.datalen = pdu->datalen; @@ -409,20 +409,20 @@ size_t lwpa_pack_root_layer_block(uint8_t* buf, size_t buflen, const LwpaRootLay /* Check if we are required to use the 3-byte length field, either by the * higher-level protocol or because the length is greater than 4096 */ - if (prot_mandates_l_flag(pdu->vector) || - rlp_extended_length(inheritvec, inherithead, inheritdata ? 0 : pdu->datalen)) + if (PROT_MANDATES_L_FLAG(pdu->vector) || + RLP_EXTENDED_LENGTH(inheritvec, inherithead, inheritdata ? 0 : pdu->datalen)) { size_t len = 3u + (inheritvec ? 0u : RLP_VECTOR_SIZE) + (inherithead ? 0u : ACN_RLP_HEADER_SIZE) + (inheritdata ? 0u : pdu->datalen); - lwpa_pdu_set_l_flag(*cur_ptr); - lwpa_pdu_pack_ext_len(cur_ptr, len); + LWPA_PDU_SET_L_FLAG(*cur_ptr); + LWPA_PDU_PACK_EXT_LEN(cur_ptr, len); cur_ptr += 3; } else { size_t len = 2 + (inheritvec ? 0u : RLP_VECTOR_SIZE) + (inherithead ? 0u : ACN_RLP_HEADER_SIZE) + (inheritdata ? 0u : pdu->datalen); - lwpa_pdu_pack_normal_len(cur_ptr, len); + LWPA_PDU_PACK_NORMAL_LEN(cur_ptr, len); cur_ptr += 2; } diff --git a/src/lwpa/thread.dox b/src/lwpa/thread.dox index 2964d31f3..09f09574b 100644 --- a/src/lwpa/thread.dox +++ b/src/lwpa/thread.dox @@ -81,4 +81,4 @@ bool lwpa_thread_join(lwpa_thread_t *id); */ void lwpa_thread_sleep(int sleep_ms); -/*!@}*/ +/*! @} */ diff --git a/src/lwpa/timer.c b/src/lwpa/timer.c new file mode 100644 index 000000000..e7ed3aa57 --- /dev/null +++ b/src/lwpa/timer.c @@ -0,0 +1,92 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/timer.h" + +/*************************** Function definitions ****************************/ + +/*! \brief Start a timer. + * \param timer Pointer to the LwpaTimer to start. + * \param interval Timer interval in milliseconds. An interval of 0 will result in a timer that is + * always expired. + */ +void lwpa_timer_start(LwpaTimer* timer, uint32_t interval) +{ + if (timer) + { + timer->reset_time = lwpa_getms(); + timer->interval = interval; + } +} + +/*! \brief Reset a timer while keeping the same interval. + * \param timer Pointer to the LwpaTimer to reset. + */ +void lwpa_timer_reset(LwpaTimer* timer) +{ + if (timer) + { + timer->reset_time = lwpa_getms(); + } +} + +/*! \brief Get the time since a timer was reset. + * \param timer Pointer to the LwpaTimer of which to get the elapsed time. + * \return Number of milliseconds since the timer was reset. + */ +uint32_t lwpa_timer_elapsed(const LwpaTimer* timer) +{ + if (timer) + { + return lwpa_getms() - timer->reset_time; + } + return 0; +} + +/*! \brief Check to see if a timer is expired. + * \param timer Pointer to the LwpaTimer of which to check the expiration. + * \return true: More than \link LwpaTimer::interval interval \endlink milliseconds have passed + * since the timer was started/reset. + * \return false: Less than or equal to \link LwpaTimer::interval interval \endlink milliseconds + * have passed since the timer was started/reset) + */ +bool lwpa_timer_is_expired(const LwpaTimer* timer) +{ + if (timer) + { + return ((timer->interval == 0) || ((lwpa_getms() - timer->reset_time) > timer->interval)); + } + return true; +} + +/*! \brief Get the amount of time remaining in a timer. + * \param timer Pointer to the LwpaTimer of which to get the remaining time. + * \return Remaining time in milliseconds or 0 (timer is expired). + */ +uint32_t lwpa_timer_remaining(const LwpaTimer* timer) +{ + uint32_t res = 0; + if (timer->interval != 0) + { + uint32_t cur_ms = lwpa_getms(); + if (cur_ms - timer->reset_time < timer->interval) + res = timer->reset_time + timer->interval - cur_ms; + } + return res; +} diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index a75f2cc45..80f9899bc 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -26,6 +26,8 @@ #include #include +#include "os_error.h" + /*************************** Private constants *******************************/ #define POLL_CONTEXT_ARR_CHUNK_SIZE 10 diff --git a/src/os/windows/lwpa/os_timer.c b/src/os/windows/lwpa/os_timer.c index e5caaa583..483ea7cb9 100644 --- a/src/os/windows/lwpa/os_timer.c +++ b/src/os/windows/lwpa/os_timer.c @@ -41,15 +41,3 @@ uint32_t lwpa_getms() { return timeGetTime(); } - -uint32_t lwpa_timer_remaining(const LwpaTimer* timer) -{ - uint32_t res = 0; - if (timer->interval != 0) - { - uint32_t cur_ms = lwpa_getms(); - if (cur_ms - timer->reset_time < timer->interval) - res = timer->reset_time + timer->interval - cur_ms; - } - return res; -} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 160e13846..b8335faa0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,33 +1,11 @@ -################################### testing ################################### +# Main test module. + +set(LWPA_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) +set(LWPA_SRC ${CMAKE_CURRENT_LIST_DIR}/../src) if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL macos OR LWPA_TARGET_OS STREQUAL linux) + enable_testing() message(STATUS "Adding GoogleTest dependency...") include(AddGoogleTest) - - set(TEST_SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/unit) - - add_executable(test_lwpa - # lwpa unit test sources - ${TEST_SRC_DIR}/main.cpp - ${TEST_SRC_DIR}/test_common.cpp - ${TEST_SRC_DIR}/test_inet.cpp - ${TEST_SRC_DIR}/test_log.cpp - ${TEST_SRC_DIR}/test_mempool.cpp - ${TEST_SRC_DIR}/test_mutex.cpp - ${TEST_SRC_DIR}/test_netint.cpp - ${TEST_SRC_DIR}/test_pack.cpp - ${TEST_SRC_DIR}/test_rbtree.cpp - ${TEST_SRC_DIR}/test_rwlock.cpp - ${TEST_SRC_DIR}/test_signal.cpp - ${TEST_SRC_DIR}/test_socket.cpp - ${TEST_SRC_DIR}/test_socket_poll.cpp - ${TEST_SRC_DIR}/test_thread.cpp - ${TEST_SRC_DIR}/test_timer.cpp - ${TEST_SRC_DIR}/test_uuid.cpp - ) - set_target_properties(test_lwpa PROPERTIES CXX_STANDARD 14) - target_link_libraries(test_lwpa lwpa gmock) - if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - target_compile_options(test_lwpa PRIVATE -Wno-format-security) - endif() + add_subdirectory(unit) endif() diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt new file mode 100644 index 000000000..93b41b7b1 --- /dev/null +++ b/tests/unit/CMakeLists.txt @@ -0,0 +1,4 @@ +include(GoogleTest) + +add_subdirectory(lwpa) +add_subdirectory(lwpa_timer_wraparound) diff --git a/tests/unit/lwpa/CMakeLists.txt b/tests/unit/lwpa/CMakeLists.txt new file mode 100644 index 000000000..b924a1124 --- /dev/null +++ b/tests/unit/lwpa/CMakeLists.txt @@ -0,0 +1,34 @@ +# test_lwpa +# Main lwpa test module, does "live" tests which use system calls of the underlying OS to ensure +# consistent behavior across platforms. + +add_executable(test_lwpa + # lwpa unit test sources + test_common.cpp + test_inet.cpp + test_log.cpp + test_mempool.cpp + test_mutex.cpp + test_netint.cpp + test_pack.cpp + test_rbtree.cpp + test_rwlock.cpp + test_signal.cpp + test_socket.cpp + test_socket_poll.cpp + test_thread.cpp + test_timer.cpp + test_uuid.cpp +) +set_target_properties(test_lwpa PROPERTIES CXX_STANDARD 14) +target_link_libraries(test_lwpa PRIVATE lwpa gmock_main) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_compile_options(test_lwpa PRIVATE -Wno-format-security) +endif() +gtest_add_tests(TARGET test_lwpa TEST_LIST LWPA_TEST_LIST) + +# TODO diagnose consistent failure of these tests on the Azure Pipelines macOS hosted agent. +if(APPLE) + set(LWPA_MACOS_FAILING_TESTS SocketTest.multicast_udp SocketPollTest.udp_in) + set_tests_properties(${LWPA_MACOS_FAILING_TESTS} PROPERTIES WILL_FAIL TRUE) +endif() diff --git a/tests/unit/test_common.cpp b/tests/unit/lwpa/test_common.cpp similarity index 100% rename from tests/unit/test_common.cpp rename to tests/unit/lwpa/test_common.cpp diff --git a/tests/unit/test_inet.cpp b/tests/unit/lwpa/test_inet.cpp similarity index 100% rename from tests/unit/test_inet.cpp rename to tests/unit/lwpa/test_inet.cpp diff --git a/tests/unit/test_log.cpp b/tests/unit/lwpa/test_log.cpp similarity index 100% rename from tests/unit/test_log.cpp rename to tests/unit/lwpa/test_log.cpp diff --git a/tests/unit/test_mempool.cpp b/tests/unit/lwpa/test_mempool.cpp similarity index 100% rename from tests/unit/test_mempool.cpp rename to tests/unit/lwpa/test_mempool.cpp diff --git a/tests/unit/test_mutex.cpp b/tests/unit/lwpa/test_mutex.cpp similarity index 100% rename from tests/unit/test_mutex.cpp rename to tests/unit/lwpa/test_mutex.cpp diff --git a/tests/unit/test_netint.cpp b/tests/unit/lwpa/test_netint.cpp similarity index 100% rename from tests/unit/test_netint.cpp rename to tests/unit/lwpa/test_netint.cpp diff --git a/tests/unit/test_pack.cpp b/tests/unit/lwpa/test_pack.cpp similarity index 100% rename from tests/unit/test_pack.cpp rename to tests/unit/lwpa/test_pack.cpp diff --git a/tests/unit/test_rbtree.cpp b/tests/unit/lwpa/test_rbtree.cpp similarity index 100% rename from tests/unit/test_rbtree.cpp rename to tests/unit/lwpa/test_rbtree.cpp diff --git a/tests/unit/test_rwlock.cpp b/tests/unit/lwpa/test_rwlock.cpp similarity index 100% rename from tests/unit/test_rwlock.cpp rename to tests/unit/lwpa/test_rwlock.cpp diff --git a/tests/unit/test_signal.cpp b/tests/unit/lwpa/test_signal.cpp similarity index 100% rename from tests/unit/test_signal.cpp rename to tests/unit/lwpa/test_signal.cpp diff --git a/tests/unit/test_socket.cpp b/tests/unit/lwpa/test_socket.cpp similarity index 100% rename from tests/unit/test_socket.cpp rename to tests/unit/lwpa/test_socket.cpp diff --git a/tests/unit/test_socket_poll.cpp b/tests/unit/lwpa/test_socket_poll.cpp similarity index 100% rename from tests/unit/test_socket_poll.cpp rename to tests/unit/lwpa/test_socket_poll.cpp diff --git a/tests/unit/test_thread.cpp b/tests/unit/lwpa/test_thread.cpp similarity index 100% rename from tests/unit/test_thread.cpp rename to tests/unit/lwpa/test_thread.cpp diff --git a/tests/unit/test_timer.cpp b/tests/unit/lwpa/test_timer.cpp similarity index 64% rename from tests/unit/test_timer.cpp rename to tests/unit/lwpa/test_timer.cpp index 30103309e..2d494fdb6 100644 --- a/tests/unit/test_timer.cpp +++ b/tests/unit/lwpa/test_timer.cpp @@ -18,10 +18,6 @@ ******************************************************************************/ #include "lwpa/common.h" -// Do some C-style mocking -#include "lwpa/int.h" -extern "C" uint32_t lwpa_getms(); -#define lwpa_getms lwpa_fake_getms #include "lwpa/timer.h" #include "gtest/gtest.h" @@ -33,24 +29,6 @@ class TimerTest : public ::testing::Test void TearDown() override { lwpa_deinit(LWPA_FEATURE_TIMERS); } }; -static bool mocking_getms; -static uint32_t getms_returnval; - -// The getms mock -extern "C" uint32_t lwpa_fake_getms() -{ - if (mocking_getms) - { - return getms_returnval; - } - else - { -#undef lwpa_getms - return lwpa_getms(); -#define lwpa_getms lwpa_fake_getms - } -} - using namespace std::chrono_literals; TEST_F(TimerTest, getms) @@ -73,42 +51,23 @@ TEST_F(TimerTest, timeouts) lwpa_timer_start(&t2, 100); // A timer with a timeout of 0 should start expired. - ASSERT_TRUE(lwpa_timer_isexpired(&t1)); + ASSERT_TRUE(lwpa_timer_is_expired(&t1)); // The nonzero timeout should not be expired yet. - ASSERT_FALSE(lwpa_timer_isexpired(&t2)); + ASSERT_FALSE(lwpa_timer_is_expired(&t2)); std::this_thread::sleep_for(110ms); // Now it should. - ASSERT_TRUE(lwpa_timer_isexpired(&t2)); + ASSERT_TRUE(lwpa_timer_is_expired(&t2)); ASSERT_GE(lwpa_timer_elapsed(&t2), 100u); // Test resetting the timer. lwpa_timer_reset(&t2); - ASSERT_FALSE(lwpa_timer_isexpired(&t2)); + ASSERT_FALSE(lwpa_timer_is_expired(&t2)); // And test the timeout one more time. std::this_thread::sleep_for(110ms); - ASSERT_TRUE(lwpa_timer_isexpired(&t2)); + ASSERT_TRUE(lwpa_timer_is_expired(&t2)); ASSERT_GE(lwpa_timer_elapsed(&t2), 100u); } - -TEST_F(TimerTest, wraparound) -{ - LwpaTimer t1; - - // Test the wraparound case by forcing a wraparound value returned from lwpa_getms() - mocking_getms = true; - getms_returnval = 0xfffffff0u; - - lwpa_timer_start(&t1, 0x20); - - // We've wrapped around but have not exceeded the interval yet - getms_returnval = 0x0f; - ASSERT_FALSE(lwpa_timer_isexpired(&t1)); - ASSERT_EQ(lwpa_timer_elapsed(&t1), 0x1fu); - - getms_returnval = 0x11; - ASSERT_TRUE(lwpa_timer_isexpired(&t1)); -} \ No newline at end of file diff --git a/tests/unit/test_uuid.cpp b/tests/unit/lwpa/test_uuid.cpp similarity index 87% rename from tests/unit/test_uuid.cpp rename to tests/unit/lwpa/test_uuid.cpp index 31d78485a..9df0c636f 100644 --- a/tests/unit/test_uuid.cpp +++ b/tests/unit/lwpa/test_uuid.cpp @@ -31,12 +31,12 @@ class UuidTest : public ::testing::Test TEST_F(UuidTest, null) { LwpaUuid uuid = {{0}}; - ASSERT_TRUE(lwpa_uuid_is_null(&uuid)); + ASSERT_TRUE(LWPA_UUID_IS_NULL(&uuid)); uuid = kLwpaNullUuid; - ASSERT_TRUE(lwpa_uuid_is_null(&uuid)); + ASSERT_TRUE(LWPA_UUID_IS_NULL(&uuid)); for (size_t i = 0; i < LWPA_UUID_BYTES; ++i) uuid.data[i] = static_cast(i); - ASSERT_FALSE(lwpa_uuid_is_null(&uuid)); + ASSERT_FALSE(LWPA_UUID_IS_NULL(&uuid)); } TEST_F(UuidTest, compare) @@ -45,9 +45,9 @@ TEST_F(UuidTest, compare) LwpaUuid uuid1_dup = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; LwpaUuid uuid2 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17}}; - ASSERT_EQ(0, lwpa_uuid_cmp(&uuid1, &uuid1_dup)); - ASSERT_LT(0, lwpa_uuid_cmp(&uuid2, &uuid1)); - ASSERT_GT(0, lwpa_uuid_cmp(&uuid1, &uuid2)); + ASSERT_EQ(0, LWPA_UUID_CMP(&uuid1, &uuid1_dup)); + ASSERT_LT(0, LWPA_UUID_CMP(&uuid2, &uuid1)); + ASSERT_GT(0, LWPA_UUID_CMP(&uuid1, &uuid2)); // Test the C++ operators ASSERT_LT(uuid1, uuid2); @@ -69,7 +69,7 @@ TEST_F(UuidTest, string) ASSERT_EQ(0, strcmp(str_buf, "00000000-0000-0000-0000-000000000000")); ASSERT_TRUE(lwpa_string_to_uuid(&uuid, good_str, strlen(good_str))); LwpaUuid uuid_cmp = {{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}}; - ASSERT_EQ(0, lwpa_uuid_cmp(&uuid, &uuid_cmp)); + ASSERT_EQ(0, LWPA_UUID_CMP(&uuid, &uuid_cmp)); uuid = kLwpaNullUuid; ASSERT_FALSE(lwpa_string_to_uuid(&uuid, short_str, strlen(short_str))); ASSERT_FALSE(lwpa_string_to_uuid(&uuid, bad_str, strlen(bad_str))); @@ -95,7 +95,7 @@ TEST_F(UuidTest, generate_v1) ASSERT_EQ((uuid.data[8] & 0xc0u), 0x80u) << failure_msg; // Should be unique from the last one generated. - ASSERT_NE(0, lwpa_uuid_cmp(&uuid, &last_uuid)) << failure_msg; + ASSERT_NE(0, LWPA_UUID_CMP(&uuid, &last_uuid)) << failure_msg; last_uuid = uuid; } @@ -115,13 +115,13 @@ TEST_F(UuidTest, generate_v3) lwpa_generate_v3_uuid(&uuid4, "Test Device", mac2, 0); lwpa_generate_v3_uuid(&uuid1_dup, "Test Device", mac1, 0); - ASSERT_NE(0, lwpa_uuid_cmp(&uuid1, &uuid2)); - ASSERT_NE(0, lwpa_uuid_cmp(&uuid1, &uuid3)); - ASSERT_NE(0, lwpa_uuid_cmp(&uuid1, &uuid4)); - ASSERT_NE(0, lwpa_uuid_cmp(&uuid2, &uuid3)); - ASSERT_NE(0, lwpa_uuid_cmp(&uuid2, &uuid4)); - ASSERT_NE(0, lwpa_uuid_cmp(&uuid3, &uuid4)); - ASSERT_EQ(0, lwpa_uuid_cmp(&uuid1, &uuid1_dup)); + ASSERT_NE(0, LWPA_UUID_CMP(&uuid1, &uuid2)); + ASSERT_NE(0, LWPA_UUID_CMP(&uuid1, &uuid3)); + ASSERT_NE(0, LWPA_UUID_CMP(&uuid1, &uuid4)); + ASSERT_NE(0, LWPA_UUID_CMP(&uuid2, &uuid3)); + ASSERT_NE(0, LWPA_UUID_CMP(&uuid2, &uuid4)); + ASSERT_NE(0, LWPA_UUID_CMP(&uuid3, &uuid4)); + ASSERT_EQ(0, LWPA_UUID_CMP(&uuid1, &uuid1_dup)); // Make sure the Variant Version bits are correct. // We should always have Variant 1, Version 3. @@ -152,7 +152,7 @@ TEST_F(UuidTest, generate_v4) ASSERT_EQ((uuid.data[8] & 0xc0u), 0x80u) << failure_msg; // Should be unique from the last one generated. - ASSERT_NE(0, lwpa_uuid_cmp(&uuid, &last_uuid)) << failure_msg; + ASSERT_NE(0, LWPA_UUID_CMP(&uuid, &last_uuid)) << failure_msg; last_uuid = uuid; } diff --git a/tests/unit/lwpa_timer_wraparound/CMakeLists.txt b/tests/unit/lwpa_timer_wraparound/CMakeLists.txt new file mode 100644 index 000000000..60d73f937 --- /dev/null +++ b/tests/unit/lwpa_timer_wraparound/CMakeLists.txt @@ -0,0 +1,11 @@ +# Test the lwpa_timer module against wraparound errors. +# This needs to be a separate executable because the lwpa_getms() symbol is stubbed at link time. + +add_executable(test_lwpa_timer_wraparound + test_timer_wraparound.cpp + ${LWPA_SRC}/lwpa/timer.c +) +set_target_properties(test_lwpa_timer_wraparound PROPERTIES CXX_STANDARD 14) +target_include_directories(test_lwpa_timer_wraparound PRIVATE ${LWPA_INCLUDE}) +target_link_libraries(test_lwpa_timer_wraparound PRIVATE gtest_main meekrosoft::fff) +gtest_add_tests(TARGET test_lwpa_timer_wraparound) diff --git a/tests/unit/main.cpp b/tests/unit/lwpa_timer_wraparound/test_timer_wraparound.cpp similarity index 51% rename from tests/unit/main.cpp rename to tests/unit/lwpa_timer_wraparound/test_timer_wraparound.cpp index 3233ddbf3..02993035d 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/lwpa_timer_wraparound/test_timer_wraparound.cpp @@ -16,42 +16,32 @@ * This file is a part of lwpa. For more information, go to: * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include -#include + +#include "lwpa/timer.h" #include "gtest/gtest.h" -#include "lwpa/common.h" -#include "lwpa/netint.h" -#include "lwpa/socket.h" -#include "lwpa/common.h" +#include "fff.h" + +DEFINE_FFF_GLOBALS; -//LwpaIpAddr g_netint; +FAKE_VALUE_FUNC(uint32_t, lwpa_getms); + +class TimerWraparoundTest : public ::testing::Test +{ +}; -int main(int argc, char** argv) +TEST_F(TimerWraparoundTest, wraparound) { - testing::InitGoogleTest(&argc, argv); - - // Only check our custom argument if we haven't been given the "list_tests" flag -// if (!testing::GTEST_FLAG(list_tests)) -// { -// if (argc == 2) -// { -// if (0 >= lwpa_inet_pton(kLwpaIpTypeV4, argv[1], &g_netint)) -// { -// printf( -// "Usage: %s \n" -// " interface_addr: IP address of network interface to use for test.\n", -// argv[0]); -// -// return 1; -// } -// } -// else -// { -// LwpaNetintInfo default_netint; -// lwpa_netint_get_default_interface(&default_netint); -// g_netint = default_netint.addr; -// } -// } - - return RUN_ALL_TESTS(); + LwpaTimer t1; + + // Test the wraparound case by forcing a wraparound value returned from lwpa_getms() + lwpa_getms_fake.return_val = 0xfffffff0u; + lwpa_timer_start(&t1, 0x20); + + // We've wrapped around but have not exceeded the interval yet + lwpa_getms_fake.return_val = 0x0f; + ASSERT_FALSE(lwpa_timer_is_expired(&t1)); + ASSERT_EQ(lwpa_timer_elapsed(&t1), 0x1fu); + + lwpa_getms_fake.return_val = 0x11; + ASSERT_TRUE(lwpa_timer_is_expired(&t1)); } From 0af307cf2c8f1c93ffeef55b1ab1eeb6be36ea94 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 10 Jul 2019 17:16:45 -0500 Subject: [PATCH 083/264] But like, actually run the tests. --- CMakeLists.txt | 1 + tests/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0abcd4d06..c1974bf12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ add_subdirectory(src) #################################### Tests #################################### if(LWPA_BUILD_TESTS) + enable_testing() add_subdirectory(tests) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b8335faa0..614ae6c81 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,7 +4,6 @@ set(LWPA_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) set(LWPA_SRC ${CMAKE_CURRENT_LIST_DIR}/../src) if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL macos OR LWPA_TARGET_OS STREQUAL linux) - enable_testing() message(STATUS "Adding GoogleTest dependency...") include(AddGoogleTest) add_subdirectory(unit) From ab471b30f170e4697dd09accdb1cede2c72e7715 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 11 Jul 2019 12:51:55 -0500 Subject: [PATCH 084/264] Windows - better error codes from lwpa_inet_ntop() and lwpa_inet_pton() --- src/os/windows/lwpa/os_inet.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/os/windows/lwpa/os_inet.c b/src/os/windows/lwpa/os_inet.c index 11cb92ef8..ba5e443d9 100644 --- a/src/os/windows/lwpa/os_inet.c +++ b/src/os/windows/lwpa/os_inet.c @@ -19,6 +19,7 @@ #include "lwpa/inet.h" #include +#include "os_error.h" bool ip_os_to_lwpa(const lwpa_os_ipaddr_t* os_ip, LwpaIpAddr* ip) { @@ -103,7 +104,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); if (NULL != inet_ntop(AF_INET, &addr, dest, size)) return kLwpaErrOk; - return kLwpaErrSys; + return err_winsock_to_lwpa(WSAGetLastError()); } case kLwpaIpTypeV6: { @@ -111,7 +112,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) return kLwpaErrOk; - return kLwpaErrSys; + return err_winsock_to_lwpa(WSAGetLastError()); } default: return kLwpaErrInvalid; @@ -128,16 +129,24 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des case kLwpaIpTypeV4: { struct in_addr addr; - if (1 != inet_pton(AF_INET, src, &addr)) - return kLwpaErrSys; + INT res = inet_pton(AF_INET, src, &addr); + if (res == 0) + return kLwpaErrInvalid; + else if (res < 0) + return err_winsock_to_lwpa(WSAGetLastError()); + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); return kLwpaErrOk; } case kLwpaIpTypeV6: { struct in6_addr addr; - if (1 != inet_pton(AF_INET6, src, &addr)) - return kLwpaErrSys; + INT res = inet_pton(AF_INET6, src, &addr); + if (res == 0) + return kLwpaErrInvalid; + else if (res < 0) + return err_winsock_to_lwpa(WSAGetLastError()); + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); return kLwpaErrOk; } From 2bbdb60561e081bee59e2ee87f69b943dec955ec Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 11 Jul 2019 12:52:08 -0500 Subject: [PATCH 085/264] Add a 'friendly name' field to LwpaNetintInfo --- include/lwpa/inet.h | 9 ++++++++- src/os/linux/lwpa/os_netint.c | 2 ++ src/os/macos/lwpa/os_netint.c | 2 ++ src/os/mqx/lwpa/os_netint.c | 1 + src/os/windows/lwpa/os_netint.c | 6 ++++++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index bfb50eb85..bef13b2fe 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -158,6 +158,7 @@ typedef struct LwpaSockaddr #define LWPA_NETINTINFO_MAC_LEN 6 #define LWPA_NETINTINFO_NAME_LEN 64 +#define LWPA_NETINTINFO_FRIENDLY_NAME_LEN 64 /*! A description of a network interface. */ typedef struct LwpaNetintInfo @@ -171,8 +172,14 @@ typedef struct LwpaNetintInfo LwpaIpAddr mask; /*! The adapter MAC address. */ uint8_t mac[LWPA_NETINTINFO_MAC_LEN]; - /*! The adapter name as a string. */ + /*! The system name for the interface. This name will not change unless the adapter is removed or + * reconfigured. */ char name[LWPA_NETINTINFO_NAME_LEN]; + /*! A user-friendly name for the interface. On some systems, this is the same as the name field. + * Others allow users to create and change a friendly name for network interfaces that's + * different than the system name. This field should be used when printing the adapter list in a + * UI. */ + char friendly_name[LWPA_NETINTINFO_FRIENDLY_NAME_LEN]; /*! Whether this is the default network interface. The default network interface is defined as * the network interface chosen for the default IP route on a system. */ bool is_default; diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 17fd91827..18ae6ffdf 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -171,6 +171,8 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) // Interface name strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; + strncpy(current_info->friendly_name, ifaddr->ifa_name, LWPA_NETINTINFO_FRIENDLY_NAME_LEN); + current_info->friendly_name[LWPA_NETINTINFO_FRIENDLY_NAME_LEN - 1] = '\0'; // Interface address ip_os_to_lwpa(ifaddr->ifa_addr, ¤t_info->addr); diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c index b2d2312c6..aeb72fa97 100644 --- a/src/os/macos/lwpa/os_netint.c +++ b/src/os/macos/lwpa/os_netint.c @@ -184,6 +184,8 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) // Interface name strncpy(current_info->name, ifaddr->ifa_name, LWPA_NETINTINFO_NAME_LEN); current_info->name[LWPA_NETINTINFO_NAME_LEN - 1] = '\0'; + strncpy(current_info->friendly_name, ifaddr->ifa_name, LWPA_NETINTINFO_FRIENDLY_NAME_LEN); + current_info->friendly_name[LWPA_NETINTINFO_FRIENDLY_NAME_LEN - 1] = '\0'; // Interface address ip_os_to_lwpa(ifaddr->ifa_addr, ¤t_info->addr); diff --git a/src/os/mqx/lwpa/os_netint.c b/src/os/mqx/lwpa/os_netint.c index b7e45c3af..222ab3705 100644 --- a/src/os/mqx/lwpa/os_netint.c +++ b/src/os/mqx/lwpa/os_netint.c @@ -46,6 +46,7 @@ static void copy_interface_info(uint32_t mqx_index, LwpaNetintInfo* netint) ipcfg_get_mac(mqx_index, netint->mac); sprintf(netint->name, "en%d", mqx_index); + sprintf(netint->friendly_name, "en%d", mqx_index); if (mqx_index == BSP_DEFAULT_ENET_DEVICE) netint->is_default = true; else diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index 917f12f5d..6738aa516 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -229,6 +229,12 @@ void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNetintInfo } strncpy_s(info->name, LWPA_NETINTINFO_NAME_LEN, pcur->AdapterName, _TRUNCATE); + + // The friendly name requires special handling because it must be converted to UTF-8 + memset(info->friendly_name, 0, LWPA_NETINTINFO_FRIENDLY_NAME_LEN); + WideCharToMultiByte(CP_UTF8, 0, pcur->FriendlyName, -1, info->friendly_name, + LWPA_NETINTINFO_FRIENDLY_NAME_LEN - 1, NULL, NULL); + if (pcur->PhysicalAddressLength == LWPA_NETINTINFO_MAC_LEN) memcpy(info->mac, pcur->PhysicalAddress, LWPA_NETINTINFO_MAC_LEN); else From 2eb654ac86abbc72b17d8dc83cc318682758a49e Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 12 Jul 2019 10:27:14 -0500 Subject: [PATCH 086/264] Change lwpa_netint_get_interfaces() to not require copying the array. Add lwpa_netint_copy_interfaces() to retain that option. --- CHANGELOG.md | 4 ++++ include/lwpa/netint.h | 3 ++- src/lwpa/netint.c | 22 +++++++++++++---- tests/unit/lwpa/test_netint.cpp | 42 ++++++++++++++++++++------------- 4 files changed, 49 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a5c4eae1..cd5f83901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - lwpa_init() in lwpa/common.h. lwpa_init() must be called before using features defined by feature macros defined in lwpa/common.h. - Extra documentation page for network interface indexes. +- New function lwpa_netint_copy_interfaces() to perform the old behavior of + lwpa_netint_get_interfaces() (see Changed below) ### Changed - Naming: 'operating system' and 'platform' are used somewhat interchangably by @@ -28,6 +30,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - lwpa_netint_get_interface_for_dest(): Signature changed to return lwpa_error_t - lwpa_socket: Multicast socket options now refer to network interfaces only by interface index, for portability and compatibility with IPv6. +- lwpa_netint_get_interfaces() simply provides const access to the cached array + of network interfaces built at init time. ### Removed diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index d99567f5b..a1a687805 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -40,7 +40,8 @@ extern "C" { #endif size_t lwpa_netint_get_num_interfaces(); -size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size); +const LwpaNetintInfo* lwpa_netint_get_interfaces(); +size_t lwpa_netint_copy_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size); lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint); lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint); diff --git a/src/lwpa/netint.c b/src/lwpa/netint.c index 4eafaec07..116cdf0df 100644 --- a/src/lwpa/netint.c +++ b/src/lwpa/netint.c @@ -86,7 +86,21 @@ size_t lwpa_netint_get_num_interfaces() return (init_count ? netint_cache.num_netints : 0); } -/*! \brief Enumerate the network interfaces on the system. +/*! \brief Get a list of network interfaces on the system. + * + * For NICs with multiple IP addresses assigned, this module separates each address into its own + * entry in the netint array. Because of this, multiple array entries could have the same value + * for the index, mac and name parameters. + * + * \return Pointer to an array of network interfaces of length lwpa_netint_get_num_interfaces(), + * or NULL if there are no interfaces present or the module is not initialized. + */ +const LwpaNetintInfo* lwpa_netint_get_interfaces() +{ + return (init_count ? netint_cache.netints : NULL); +} + +/*! \brief Copy the list of network interfaces on the system into an array. * * For NICs with multiple IP addresses assigned, this module separates each address into its own * entry in the netint array. Because of this, multiple array entries could have the same value @@ -95,10 +109,10 @@ size_t lwpa_netint_get_num_interfaces() * \param[out] netint_arr Array of network interface description structs to fill in with interface * info. * \param[in] netint_arr_size Size of the netint array. - * \return Number of network interfaces that were enumerated, up to a maximum of netint_arr_size, - * or 0 if there are no interfaces present or an error occurred. + * \return Number of network interfaces that were copied, up to a maximum of netint_arr_size, + * or 0 if there are no interfaces present or the module is not initialized. */ -size_t lwpa_netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) +size_t lwpa_netint_copy_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) { if (!init_count || !netint_arr || netint_arr_size == 0) return 0; diff --git a/tests/unit/lwpa/test_netint.cpp b/tests/unit/lwpa/test_netint.cpp index 302d70f0b..c82eb04d1 100644 --- a/tests/unit/lwpa/test_netint.cpp +++ b/tests/unit/lwpa/test_netint.cpp @@ -39,19 +39,30 @@ class NetintTest : public ::testing::Test TEST_F(NetintTest, enumerate) { ASSERT_GT(num_netints, 0u); - auto netint_arr = std::make_unique(num_netints); - size_t num_netints_returned = lwpa_netint_get_interfaces(netint_arr.get(), num_netints); - ASSERT_EQ(num_netints_returned, num_netints); size_t num_defaults = 0; - for (LwpaNetintInfo* netint = netint_arr.get(); netint < netint_arr.get() + num_netints_returned; ++netint) + const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); + ASSERT_NE(netint_list, nullptr); + for (auto netint = netint_list; netint < netint_list + num_netints; ++netint) { if (netint->is_default) ++num_defaults; - ASSERT_GT(strlen(netint->name), 0u); + EXPECT_GT(strlen(netint->name), 0u); + EXPECT_GT(strlen(netint->friendly_name), 0u); } // There can be a maximum of two default interfaces: one each for IPv4 and IPv6. - ASSERT_TRUE(num_defaults <= 2); + EXPECT_LE(num_defaults, 2u); +} + +TEST_F(NetintTest, copy) +{ + // Test copying the full array + auto netint_arr = std::make_unique(num_netints); + size_t num_netints_returned = lwpa_netint_copy_interfaces(netint_arr.get(), num_netints); + ASSERT_EQ(num_netints_returned, num_netints); + + // Make sure the array is equal to the list obtained from lwpa_netint_get_interfaces() + EXPECT_EQ(0, memcmp(netint_arr.get(), lwpa_netint_get_interfaces(), num_netints)); } TEST_F(NetintTest, default) @@ -63,11 +74,6 @@ TEST_F(NetintTest, default) memset(&def_v4, 0, sizeof def_v4); memset(&def_v6, 0, sizeof def_v6); - auto netint_arr = std::make_unique(num_netints); - memset(netint_arr.get(), 0, sizeof(struct LwpaNetintInfo) * num_netints); - - num_netints = lwpa_netint_get_interfaces(netint_arr.get(), num_netints); - bool have_default_v4 = (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_v4)); bool have_default_v6 = (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV6, &def_v6)); @@ -80,7 +86,9 @@ TEST_F(NetintTest, default) EXPECT_TRUE(def_v6.is_default); } - for (LwpaNetintInfo* netint = netint_arr.get(); netint < netint_arr.get() + num_netints; ++netint) + const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); + ASSERT_NE(netint_list, nullptr); + for (auto netint = netint_list; netint < netint_list + num_netints; ++netint) { if (netint->is_default) { @@ -100,13 +108,13 @@ TEST_F(NetintTest, ipv4_routing) { ASSERT_GT(num_netints, 0u); - auto netint_arr = std::make_unique(num_netints); - num_netints = lwpa_netint_get_interfaces(netint_arr.get(), num_netints); + const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); + ASSERT_NE(netint_list, nullptr); // For each normally routable (non-loopback, non-link-local) network interface, check to make sure // that lwpa_netint_get_interface_for_dest() resolves to that interface when asked for a route to // the interface address itself. - for (LwpaNetintInfo* netint = netint_arr.get(); netint < netint_arr.get() + num_netints; ++netint) + for (auto netint = netint_list; netint < netint_list + num_netints; ++netint) { if (!LWPA_IP_IS_V4(&netint->addr) || lwpa_ip_is_loopback(&netint->addr) || lwpa_ip_is_link_local(&netint->addr)) continue; @@ -128,6 +136,6 @@ TEST_F(NetintTest, ipv4_routing) LwpaIpAddr ext_addr; LWPA_IP_SET_V4_ADDRESS(&ext_addr, 0xc8dc0302); // 200.220.3.2 LwpaNetintInfo def; - ASSERT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&ext_addr, &def)); - ASSERT_TRUE(def.is_default); + EXPECT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&ext_addr, &def)); + EXPECT_TRUE(def.is_default); } From e49efe73f57126588bea5c26d89cb4524793914b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 12 Jul 2019 10:39:13 -0500 Subject: [PATCH 087/264] Fix example app --- examples/netint/netint_example.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/netint/netint_example.c b/examples/netint/netint_example.c index 3750922fb..5e253cebe 100644 --- a/examples/netint/netint_example.c +++ b/examples/netint/netint_example.c @@ -23,7 +23,6 @@ */ #include -#include #include #include "lwpa/netint.h" #include "lwpa/socket.h" @@ -96,15 +95,14 @@ int main() return 1; } - LwpaNetintInfo* netint_arr = (LwpaNetintInfo*)calloc(num_interfaces, sizeof(LwpaNetintInfo)); + const LwpaNetintInfo* netint_arr = lwpa_netint_get_interfaces(); assert(netint_arr); - num_interfaces = lwpa_netint_get_interfaces(netint_arr, num_interfaces); create_format_strings(netint_arr, num_interfaces); printf("Network interfaces found:\n"); printf(header_format, NAME_COL_HEADER, ADDR_COL_HEADER, NETMASK_COL_HEADER, MAC_COL_HEADER, INDEX_COL_HEADER); - for (LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_interfaces; ++netint) + for (const LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_interfaces; ++netint) { char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; char netmask_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; From e956b7462d67ba079cb4534efc14ea80ec85adea Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 12 Jul 2019 12:54:26 -0500 Subject: [PATCH 088/264] Fix linux build --- src/lwpa/pack.c | 42 +++++++++++++++++------------------ src/os/linux/lwpa/os_socket.c | 40 ++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/lwpa/pack.c b/src/lwpa/pack.c index e83c1f53d..323735243 100644 --- a/src/lwpa/pack.c +++ b/src/lwpa/pack.c @@ -30,8 +30,8 @@ uint16_t lwpa_upack_16b(const uint8_t* buf) uint16_t val = 0; if (buf) { - val |= ((uint16_t)buf[0] << 8); - val |= ((uint16_t)buf[1]); + val |= (uint16_t)((uint16_t)buf[0] << 8); + val |= (uint16_t)buf[1]; } return val; } @@ -58,8 +58,8 @@ uint16_t lwpa_upack_16l(const uint8_t* buf) uint16_t val = 0; if (buf) { - val |= ((uint16_t)buf[1] << 8); - val |= ((uint16_t)buf[0]); + val |= (uint16_t)((uint16_t)buf[1] << 8); + val |= (uint16_t)buf[0]; } return val; } @@ -72,7 +72,7 @@ void lwpa_pack_16l(uint8_t* buf, uint16_t val) { if (buf) { - buf[0] = (uint8_t) (val & 0xff); + buf[0] = (uint8_t)(val & 0xff); buf[1] = (uint8_t)((val & 0xff00) >> 8); } } @@ -86,10 +86,10 @@ uint32_t lwpa_upack_32b(const uint8_t* buf) uint32_t val = 0; if (buf) { - val |= ((uint32_t)buf[0] << 24); - val |= ((uint32_t)buf[1] << 16); - val |= ((uint32_t)buf[2] << 8); - val |= ((uint32_t)buf[3]); + val |= (uint32_t)((uint32_t)buf[0] << 24); + val |= (uint32_t)((uint32_t)buf[1] << 16); + val |= (uint32_t)((uint32_t)buf[2] << 8); + val |= (uint32_t)buf[3]; } return val; } @@ -118,10 +118,10 @@ uint32_t lwpa_upack_32l(const uint8_t* buf) uint32_t val = 0; if (buf) { - val |= ((uint32_t)buf[3] << 24); - val |= ((uint32_t)buf[2] << 16); - val |= ((uint32_t)buf[1] << 8); - val |= ((uint32_t)buf[0]); + val |= (uint32_t)((uint32_t)buf[3] << 24); + val |= (uint32_t)((uint32_t)buf[2] << 16); + val |= (uint32_t)((uint32_t)buf[1] << 8); + val |= (uint32_t)buf[0]; } return val; } @@ -152,14 +152,14 @@ uint64_t lwpa_upack_64b(const uint8_t* buf) uint64_t val = 0; if (buf) { - val |= ((uint64_t)buf[0] << 56); - val |= ((uint64_t)buf[1] << 48); - val |= ((uint64_t)buf[2] << 40); - val |= ((uint64_t)buf[3] << 32); - val |= ((uint64_t)buf[4] << 24); - val |= ((uint64_t)buf[5] << 16); - val |= ((uint64_t)buf[6] << 8); - val |= ((uint64_t)buf[7]); + val |= (uint64_t)((uint64_t)buf[0] << 56); + val |= (uint64_t)((uint64_t)buf[1] << 48); + val |= (uint64_t)((uint64_t)buf[2] << 40); + val |= (uint64_t)((uint64_t)buf[3] << 32); + val |= (uint64_t)((uint64_t)buf[4] << 24); + val |= (uint64_t)((uint64_t)buf[5] << 16); + val |= (uint64_t)((uint64_t)buf[6] << 8); + val |= (uint64_t)buf[7]; } return val; } diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index cb9abacc3..bab4283ac 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -23,9 +23,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -377,6 +379,27 @@ int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_valu return -1; } +static int ip4_ifindex_to_addr(unsigned int ifindex, struct in_addr* addr) +{ + struct ifreq req; + if (if_indextoname(ifindex, req.ifr_name) != NULL) + { + int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (ioctl_sock != -1) + { + int ioctl_res = ioctl(ioctl_sock, SIOCGIFADDR, &req); + if (ioctl_res != -1) + { + *addr = ((struct sockaddr_in*)&req.ifr_addr)->sin_addr; + close(ioctl_sock); + return 0; + } + close(ioctl_sock); + } + } + return -1; +} + int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) { switch (option_name) @@ -444,15 +467,12 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s } break; case LWPA_IP_MULTICAST_IF: - if (option_len == sizeof(LwpaIpAddr)) + if (option_len == sizeof(unsigned int)) { - LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (LWPA_IP_IS_V4(netint)) - { - struct in_addr val; - val.s_addr = htonl(LWPA_IP_V4_ADDRESS(netint)); - return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); - } + struct in_addr val; + if (0 != ip4_ifindex_to_addr(*(unsigned int*)option_value, &val)) + return -1; + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); } break; case LWPA_IP_MULTICAST_TTL: @@ -505,6 +525,10 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, } } break; + case LWPA_IP_MULTICAST_TTL: + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, option_value, (socklen_t)option_len); + case LWPA_IP_MULTICAST_LOOP: + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, option_value, (socklen_t)option_len); default: /* Other IPv6 options TODO on linux. */ break; } From d2844a2f8b570d228f64258dd5b37813d1102cab Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 14 Jul 2019 22:39:49 -0500 Subject: [PATCH 089/264] Modify lwpa_rbtree with more meaningful function return values --- CHANGELOG.md | 2 + include/lwpa/rbtree.h | 17 ++-- src/lwpa/rbtree.c | 86 +++++++++++------- tests/unit/lwpa/test_rbtree.cpp | 155 +++++++++++++++++++------------- 4 files changed, 157 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd5f83901..30dba15c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 interface index, for portability and compatibility with IPv6. - lwpa_netint_get_interfaces() simply provides const access to the cached array of network interfaces built at init time. +- lwpa_rbtree: Change some function signatures to give more meaningful return + information. ### Removed diff --git a/include/lwpa/rbtree.h b/include/lwpa/rbtree.h index 281840d64..ea455a0e3 100644 --- a/include/lwpa/rbtree.h +++ b/include/lwpa/rbtree.h @@ -4,10 +4,10 @@ * 2018-02-28. * ****************************************************************************** - * Based on Julienne Walker's lwpa_rbtree + * Based on Julienne Walker's rb_tree * implementation. * - * Modified by Mirek Rusin . + * Modified by Mirek Rusin . * * This is free and unencumbered software released into the public domain. * @@ -38,6 +38,7 @@ #define _LWPA_RBTREE_H_ #include +#include "lwpa/error.h" /*! \defgroup lwpa_rbtree lwpa_rbtree * \ingroup lwpa @@ -158,14 +159,14 @@ LwpaRbNode* lwpa_rbnode_init(LwpaRbNode* self, void* value); LwpaRbTree* lwpa_rbtree_init(LwpaRbTree* self, lwpa_rbtree_node_cmp_f cmp, lwpa_rbnode_alloc_f alloc_f, lwpa_rbnode_dealloc_f dealloc_f); void* lwpa_rbtree_find(LwpaRbTree* self, void* value); -int lwpa_rbtree_insert(LwpaRbTree* self, void* value); -int lwpa_rbtree_remove(LwpaRbTree* self, void* value); -int lwpa_rbtree_clear(LwpaRbTree* self); +lwpa_error_t lwpa_rbtree_insert(LwpaRbTree* self, void* value); +lwpa_error_t lwpa_rbtree_remove(LwpaRbTree* self, void* value); +lwpa_error_t lwpa_rbtree_clear(LwpaRbTree* self); size_t lwpa_rbtree_size(LwpaRbTree* self); -int lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node); -int lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f node_cb); -int lwpa_rbtree_clear_with_cb(LwpaRbTree* self, lwpa_rbtree_node_f node_cb); +lwpa_error_t lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node); +lwpa_error_t lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f node_cb); +lwpa_error_t lwpa_rbtree_clear_with_cb(LwpaRbTree* self, lwpa_rbtree_node_f node_cb); int lwpa_rbtree_test(LwpaRbTree* self, LwpaRbNode* root); diff --git a/src/lwpa/rbtree.c b/src/lwpa/rbtree.c index 69814a8fd..93663c736 100644 --- a/src/lwpa/rbtree.c +++ b/src/lwpa/rbtree.c @@ -34,8 +34,11 @@ * * For more information, please refer to */ + #include "lwpa/rbtree.h" +#include "lwpa/bool.h" + /* lwpa_rbnode */ static LwpaRbNode* lwpa_rbnode_alloc(LwpaRbTree* tree) @@ -47,9 +50,9 @@ static LwpaRbNode* lwpa_rbnode_alloc(LwpaRbTree* tree) /*! \brief Initialize a red-black tree node. * - * This function must be called on a new node before inserting it manually - * using lwpa_rbtree_insert_node(). When using lwpa_rbtree_insert(), this function is - * called on the new node automatically. + * This function must be called on a new node before inserting it manually using + * lwpa_rbtree_insert_node(). When using lwpa_rbtree_insert(), this function is called on the new + * node automatically. * * \param[in] self The node to be initialized. * \param[in] value Pointer to the value to assign to the node. @@ -204,12 +207,18 @@ void* lwpa_rbtree_find(LwpaRbTree* self, void* value) * * \param[in] self Tree in which to insert the value. * \param[in] value Value to insert. - * \return 1 (the value was inserted or the value already existed in the tree) or 0 (an error - * occurred). + * \return #kLwpaErrOk: the value was inserted. + * \return #kLwpaErrExists: the value already existed in the tree. + * \return #kLwpaErrNoMem: Couldn't allocate new node. + * \return #kLwpaErrInvalid: Invalid argument provided. */ -int lwpa_rbtree_insert(LwpaRbTree* self, void* value) +lwpa_error_t lwpa_rbtree_insert(LwpaRbTree* self, void* value) { - return lwpa_rbtree_insert_node(self, rb_node_create(self, value)); + LwpaRbNode* new_node = rb_node_create(self, value); + if (new_node) + return lwpa_rbtree_insert_node(self, new_node); + else + return kLwpaErrNoMem; } /*! \brief Insert a node containing a new value into a red-black tree. @@ -221,18 +230,19 @@ int lwpa_rbtree_insert(LwpaRbTree* self, void* value) * \param[in] self Tree in which to insert the value. * \param[in] node Node containing value to insert. Must have been previously initialized using * lwpa_rbnode_init(). - * \return 1 (the value was inserted or the value already existed in the tree) or 0 (an error - * occurred). + * \return #kLwpaErrOk: The value was inserted. + * \return #kLwpaErrExists: The value already existed in the tree. + * \return #kLwpaErrInvalid: Invalid argument provided. */ -int lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node) +lwpa_error_t lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node) { - int result = 0; + lwpa_error_t result = kLwpaErrInvalid; if (self && node) { if (self->root == NULL) { self->root = node; - result = 1; + result = kLwpaErrOk; } else { @@ -249,10 +259,13 @@ int lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node) /* Search down the tree for a place to insert */ while (1) { + bool inserted = false; + if (q == NULL) { /* Insert node at the first null link. */ p->link[dir] = q = node; + inserted = true; } else if (rb_node_is_red(q->link[0]) && rb_node_is_red(q->link[1])) { @@ -275,7 +288,7 @@ int lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node) /* Stop working if we inserted a node. This check also disallows duplicates in the tree */ if (self->cmp(self, q, node) == 0) { - result = 1; + result = inserted ? kLwpaErrOk : kLwpaErrExists; break; } @@ -310,12 +323,13 @@ int lwpa_rbtree_insert_node(LwpaRbTree* self, LwpaRbNode* node) * * \param[in] self Tree from which to remove the value. * \param[in] value Value to remove. - * \return 1 (the value was removed) or 0 (the value did not exist in the tree or an error - * occurred). + * \return #kLwpaErrOk: The value was removed. + * \return #kLwpaErrInvalid: Invalid argument provided. + * \return #kLwpaErrNotFound: The value did not exist in the tree. */ -int lwpa_rbtree_remove(LwpaRbTree* self, void* value) +lwpa_error_t lwpa_rbtree_remove(LwpaRbTree* self, void* value) { - int result = 0; + lwpa_error_t result = kLwpaErrInvalid; if (self) result = lwpa_rbtree_remove_with_cb(self, value, lwpa_rbtree_node_dealloc_cb); return result; @@ -331,10 +345,11 @@ int lwpa_rbtree_remove(LwpaRbTree* self, void* value) * \param[in] self Tree from which to remove the value. * \param[in] value Value to remove. * \param[in] node_cb Callback function to call with the node and value being removed. - * \return 1 (the value was removed) or 0 (the value did not exist in the tree or an error - * occurred). + * \return #kLwpaErrOk: The value was removed. + * \return #kLwpaErrInvalid: Invalid argument provided. + * \return #kLwpaErrNotFound: The value did not exist in the tree. */ -int lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f node_cb) +lwpa_error_t lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f node_cb) { LwpaRbNode head = {0}; /* False tree root */ LwpaRbNode node; /* Value wrapper node */ @@ -342,13 +357,15 @@ int lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f LwpaRbNode* f = NULL; /* Found item */ int dir = 1; - if (!self || self->root == NULL) - return 0; + if (!self) + return kLwpaErrInvalid; + if (self->root == NULL) + return kLwpaErrNotFound; /* SMK added this check, because the removal code seems to fail badly in the case where the node * being removed didn't previously exist in the tree. */ if (NULL == lwpa_rbtree_find(self, value)) - return 0; + return kLwpaErrNotFound; /* Set up our helpers */ node.value = value; @@ -429,7 +446,7 @@ int lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f self->root->red = 0; --self->size; - return 1; + return kLwpaErrOk; } /*! \brief Clear all values from a red-black tree. @@ -438,11 +455,12 @@ int lwpa_rbtree_remove_with_cb(LwpaRbTree* self, void* value, lwpa_rbtree_node_f * the user is responsible for deallocating the value memory. * * \param[in] self Tree to clear. - * \return 1 (the tree was cleared) or 0 (an error occurred). + * \return #kLwpaErrOk: The tree was cleared. + * \return #kLwpaErrInvalid: Invalid argument provided. */ -int lwpa_rbtree_clear(LwpaRbTree* self) +lwpa_error_t lwpa_rbtree_clear(LwpaRbTree* self) { - int result = 0; + lwpa_error_t result = kLwpaErrInvalid; if (self) result = lwpa_rbtree_clear_with_cb(self, lwpa_rbtree_node_dealloc_cb); return result; @@ -456,11 +474,12 @@ int lwpa_rbtree_clear(LwpaRbTree* self) * * \param[in] self Tree to clear. * \param[in] node_cb Callback function to call with each node and value being removed. - * \return 1 (the tree was cleared) or 0 (an error occurred). + * \return #kLwpaErrOk: The tree was cleared. + * \return #kLwpaErrInvalid: Invalid argument provided. */ -int lwpa_rbtree_clear_with_cb(LwpaRbTree* self, lwpa_rbtree_node_f node_cb) +lwpa_error_t lwpa_rbtree_clear_with_cb(LwpaRbTree* self, lwpa_rbtree_node_f node_cb) { - int result = 0; + lwpa_error_t result = kLwpaErrInvalid; if (self && node_cb) { LwpaRbNode* node = self->root; @@ -487,7 +506,7 @@ int lwpa_rbtree_clear_with_cb(LwpaRbTree* self, lwpa_rbtree_node_f node_cb) } self->root = NULL; self->size = 0; - result = 1; + result = kLwpaErrOk; } return result; } @@ -511,7 +530,10 @@ size_t lwpa_rbtree_size(LwpaRbTree* self) * * \param[in] self Tree to test. * \param[in] root Node at which to start the test. All nodes beneath this node will be tested. - * \return 1 (no violations were found) or 0 (a violation was found). + * \return The "black height" of the tree; the number of black nodes present in the traversal + * from the root to each leaf. A valid red-black tree requires this number to be the same + * for every possible traversal. + * \return 0: Invalid tree. */ int lwpa_rbtree_test(LwpaRbTree* self, LwpaRbNode* root) { diff --git a/tests/unit/lwpa/test_rbtree.cpp b/tests/unit/lwpa/test_rbtree.cpp index 4400fb7da..ad2d7866c 100644 --- a/tests/unit/lwpa/test_rbtree.cpp +++ b/tests/unit/lwpa/test_rbtree.cpp @@ -27,7 +27,7 @@ class RbTreeTest : public ::testing::Test { protected: - RbTreeTest() : clearfunc_call_count(0), remove_one_flag(false) + RbTreeTest() { // Initialize the static variables. They need to be static because they are accessed from the // non-member functions (which need to be non-member functions because they are passed as @@ -37,33 +37,35 @@ class RbTreeTest : public ::testing::Test // Initialize an array of monotonically increasing ints for (int i = 0; i < kIntArraySize; ++i) - incrementing_int_array[i] = i; + incrementing_int_array_[i] = i; // Copy and shuffle the integer array - random_int_array = incrementing_int_array; - std::random_device seed; - std::default_random_engine rand(seed()); - std::shuffle(random_int_array.begin(), random_int_array.end(), rand); + random_int_array_ = incrementing_int_array_; + std::shuffle(random_int_array_.begin(), random_int_array_.end(), rand_); } - static constexpr size_t kIntArraySize = 100; - std::array incrementing_int_array; - std::array random_int_array; - std::array node_pool; + static constexpr int kIntArraySize = 100; + std::array incrementing_int_array_; + std::array random_int_array_; + std::array node_pool_; + + std::random_device seed_; + std::default_random_engine rand_{seed_()}; public: - static unsigned int alloc_call_count; - static unsigned int dealloc_call_count; + static int alloc_call_count; + static int dealloc_call_count; - unsigned int clearfunc_call_count; - bool remove_one_flag; + int clearfunc_call_count{0}; + bool remove_one_flag{false}; static const int kMagicRemoveValue = kIntArraySize / 2; }; -unsigned int RbTreeTest::alloc_call_count; -unsigned int RbTreeTest::dealloc_call_count; -constexpr size_t RbTreeTest::kIntArraySize; +int RbTreeTest::alloc_call_count; +int RbTreeTest::dealloc_call_count; +constexpr int RbTreeTest::kIntArraySize; +extern "C" { LwpaRbNode* node_alloc() { ++RbTreeTest::alloc_call_count; @@ -96,93 +98,119 @@ static void clear_func(const LwpaRbTree* self, LwpaRbNode* node) ++rbtt->clearfunc_call_count; } } +} TEST_F(RbTreeTest, insert_static) { LwpaRbTree tree; - ASSERT_TRUE(NULL != lwpa_rbtree_init(&tree, int_cmp, NULL, NULL)); + ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, nullptr, nullptr)); tree.info = this; // Point each node at its respective value and insert it into the tree - for (size_t i = 0; i < kIntArraySize; ++i) + for (int i = 0; i < kIntArraySize; ++i) { - LwpaRbNode* node = &node_pool[i]; - ASSERT_TRUE(NULL != lwpa_rbnode_init(node, &random_int_array[i])); - ASSERT_NE(0, lwpa_rbtree_insert_node(&tree, node)); + LwpaRbNode* node = &node_pool_[i]; + ASSERT_TRUE(nullptr != lwpa_rbnode_init(node, &random_int_array_[i])); + ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert_node(&tree, node)); } - ASSERT_EQ(kIntArraySize, lwpa_rbtree_size(&tree)); - ASSERT_NE(0, lwpa_rbtree_test(&tree, tree.root)); + ASSERT_EQ(static_cast(kIntArraySize), lwpa_rbtree_size(&tree)); + EXPECT_GT(lwpa_rbtree_test(&tree, tree.root), 0); // Find a random number - int to_find = rand() / (int)(RAND_MAX / kIntArraySize + 1); + std::uniform_int_distribution dist(0, kIntArraySize - 1); + int to_find = dist(rand_); int* found = (int*)lwpa_rbtree_find(&tree, &to_find); - ASSERT_TRUE(found != NULL); - ASSERT_EQ(*found, to_find); + ASSERT_TRUE(found != nullptr); + EXPECT_EQ(*found, to_find); // Try removing one item remove_one_flag = true; int to_remove = kMagicRemoveValue; - ASSERT_NE(0, lwpa_rbtree_remove_with_cb(&tree, &to_remove, clear_func)); + ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_remove_with_cb(&tree, &to_remove, clear_func)); ASSERT_FALSE(remove_one_flag); - // Clear the tre - ASSERT_NE(0, lwpa_rbtree_clear_with_cb(&tree, clear_func)); - ASSERT_EQ(0u, lwpa_rbtree_size(&tree)); - ASSERT_EQ(clearfunc_call_count, kIntArraySize); + // Clear the tree + EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear_with_cb(&tree, clear_func)); + EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); + EXPECT_EQ(clearfunc_call_count, kIntArraySize); } TEST_F(RbTreeTest, insert_dynamic) { LwpaRbTree tree; - ASSERT_TRUE(NULL != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); + ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); // Insert each value into the tree; dynamic alloc functions should be called. - for (size_t i = 0; i < kIntArraySize; ++i) - ASSERT_NE(0, lwpa_rbtree_insert(&tree, &random_int_array[i])); - ASSERT_EQ(kIntArraySize, lwpa_rbtree_size(&tree)); + for (int i = 0; i < kIntArraySize; ++i) + ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &random_int_array_[i])); + ASSERT_EQ(static_cast(kIntArraySize), lwpa_rbtree_size(&tree)); ASSERT_EQ(kIntArraySize, alloc_call_count); - ASSERT_NE(0, lwpa_rbtree_test(&tree, tree.root)); + ASSERT_GT(lwpa_rbtree_test(&tree, tree.root), 0); // Find a random number int to_find = rand() / (int)(RAND_MAX / kIntArraySize + 1); int* found = (int*)lwpa_rbtree_find(&tree, &to_find); - ASSERT_TRUE(found != NULL); + ASSERT_TRUE(found != nullptr); ASSERT_EQ(*found, to_find); // Make sure removing something that wasn't in the tree fails. int not_in_tree = kIntArraySize + 1; - ASSERT_EQ(0, lwpa_rbtree_remove(&tree, ¬_in_tree)); + ASSERT_EQ(kLwpaErrNotFound, lwpa_rbtree_remove(&tree, ¬_in_tree)); + + // Clear the tree + EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear(&tree)); + EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); + EXPECT_EQ(dealloc_call_count, kIntArraySize); +} + +TEST_F(RbTreeTest, element_already_exists) +{ + LwpaRbTree tree; + ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); + + // Insert a few values into the tree. Enough so we have some branches to traverse + for (int i = 0; i < 10; ++i) + ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &incrementing_int_array_[i])); + ASSERT_EQ(10u, lwpa_rbtree_size(&tree)); + + // Try inserting a duplicate value - should fail with error 'already exists' + int duplicate = 5; + ASSERT_EQ(kLwpaErrExists, lwpa_rbtree_insert(&tree, &duplicate)); + + // Remove the offending value and try inserting it again, should succeed + ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_remove(&tree, &duplicate)); + ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &duplicate)); // Clear the tree - ASSERT_NE(0, lwpa_rbtree_clear(&tree)); - ASSERT_EQ(0u, lwpa_rbtree_size(&tree)); - ASSERT_EQ(dealloc_call_count, kIntArraySize); + EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear(&tree)); + EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); } TEST_F(RbTreeTest, iter) { LwpaRbTree tree; - ASSERT_TRUE(NULL != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); + ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); // Insert each value into the tree; dynamic alloc functions should be called. - for (size_t i = 0; i < kIntArraySize; ++i) - ASSERT_NE(0, lwpa_rbtree_insert(&tree, &random_int_array[i])); - ASSERT_EQ(kIntArraySize, lwpa_rbtree_size(&tree)); + for (int i = 0; i < kIntArraySize; ++i) + ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &random_int_array_[i])); + ASSERT_EQ(static_cast(kIntArraySize), lwpa_rbtree_size(&tree)); // Initialize an iterator LwpaRbIter iter; - ASSERT_TRUE(NULL != lwpa_rbiter_init(&iter)); + ASSERT_TRUE(nullptr != lwpa_rbiter_init(&iter)); // Get the first value. int* val = (int*)lwpa_rbiter_first(&iter, &tree); // Although the elements were inserted in random order, the tree should be sorted so 0 should be // the first value. + ASSERT_TRUE(val != nullptr); ASSERT_EQ(*val, 0); // Test iterating through the tree in forward order. - size_t num_iterations = 1; + int num_iterations = 1; int last_val = *val; - while ((val = (int*)lwpa_rbiter_next(&iter)) != NULL) + while ((val = (int*)lwpa_rbiter_next(&iter)) != nullptr) { ++num_iterations; // Each value given by the iterator should be numerically higher than the one that came before @@ -194,12 +222,13 @@ TEST_F(RbTreeTest, iter) // Get the last value. val = (int*)lwpa_rbiter_last(&iter, &tree); + ASSERT_TRUE(val != nullptr); ASSERT_EQ(*val, static_cast(kIntArraySize - 1)); // Test iterating through the tree in reverse order. num_iterations = 1; last_val = *val; - while ((val = (int*)lwpa_rbiter_prev(&iter)) != NULL) + while ((val = (int*)lwpa_rbiter_prev(&iter)) != nullptr) { ++num_iterations; // Each value given by the iterator should be numerically lower than the one that came before @@ -210,40 +239,40 @@ TEST_F(RbTreeTest, iter) ASSERT_EQ(num_iterations, kIntArraySize); // Clear the tree. - ASSERT_NE(0, lwpa_rbtree_clear(&tree)); - ASSERT_EQ(0u, lwpa_rbtree_size(&tree)); - ASSERT_EQ(kIntArraySize, dealloc_call_count); + EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear(&tree)); + EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); + EXPECT_EQ(kIntArraySize, dealloc_call_count); } TEST_F(RbTreeTest, max_height) { LwpaRbTree tree; - ASSERT_TRUE(NULL != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); + ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); // Insert monotonically incrementing values into the tree. In a traditional binary tree, this // would result in a worst-case unbalanced tree of height kIntArraySize. In the red-black tree, // the maximum height should be determined by the formula 2 * log2(kIntArraySize + 1). - for (size_t i = 0; i < kIntArraySize; ++i) - ASSERT_NE(0, lwpa_rbtree_insert(&tree, &incrementing_int_array[i])); - ASSERT_EQ(kIntArraySize, lwpa_rbtree_size(&tree)); + for (int i = 0; i < kIntArraySize; ++i) + ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &incrementing_int_array_[i])); + ASSERT_EQ(static_cast(kIntArraySize), lwpa_rbtree_size(&tree)); // Get the height of the tree and compare it against the theoretical maximum. LwpaRbIter iter; size_t max_height = 0; size_t theoretical_max_height; - ASSERT_TRUE(NULL != lwpa_rbiter_init(&iter)); - ASSERT_TRUE(NULL != lwpa_rbiter_first(&iter, &tree)); + ASSERT_TRUE(nullptr != lwpa_rbiter_init(&iter)); + ASSERT_TRUE(nullptr != lwpa_rbiter_first(&iter, &tree)); do { if (iter.top > max_height) max_height = iter.top; - } while (NULL != lwpa_rbiter_next(&iter)); + } while (nullptr != lwpa_rbiter_next(&iter)); max_height += 1; // http://www.doctrina.org/maximum-height-of-red-black-tree.html theoretical_max_height = 2 * (size_t)(log(kIntArraySize + 1) / log(2)); ASSERT_LE(max_height, theoretical_max_height); // Clear the tree - ASSERT_NE(0, lwpa_rbtree_clear(&tree)); - ASSERT_EQ(0u, lwpa_rbtree_size(&tree)); - ASSERT_EQ(kIntArraySize, dealloc_call_count); + EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear(&tree)); + EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); + EXPECT_EQ(kIntArraySize, dealloc_call_count); } From ed013e375eb6453c4690d94de935161df1244692 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 15 Jul 2019 09:36:15 -0500 Subject: [PATCH 090/264] Fix build on macOS and Linux after rbtree change --- src/lwpa/socket.dox | 1 + src/os/linux/lwpa/os_socket.c | 6 +++--- src/os/macos/lwpa/os_socket.c | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lwpa/socket.dox b/src/lwpa/socket.dox index 6c64841e6..30733123d 100644 --- a/src/lwpa/socket.dox +++ b/src/lwpa/socket.dox @@ -294,6 +294,7 @@ void lwpa_poll_context_deinit(LwpaPollContext *context); * \param[in] events Events to monitor for on this socket. * \param[in] user_data Opaque data pointer that is passed back with events on this socket. * \return #kLwpaErrOk: Socket added successfully. + * \return #kLwpaErrExists: The socket has already been added to this context. * \return #kLwpaErrInvalid: Invalid argument. * \return #kLwpaErrNoMem: #LWPA_SOCKET_MAX_POLL_SIZE is exceeded in this context. * \return #kLwpaErrSys: System call failed. diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index bab4283ac..c28d8c1bb 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -628,8 +628,8 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket sock_desc->sock = socket; sock_desc->events = events; sock_desc->user_data = user_data; - int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); - if (insert_res != 0) + lwpa_error_t insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); + if (insert_res == kLwpaErrOk) { struct epoll_event ep_evt; events_lwpa_to_epoll(events, &ep_evt); @@ -650,7 +650,7 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket else { free(sock_desc); - return kLwpaErrNoMem; + return insert_res; } } else diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index ed9713763..7b010e519 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -618,8 +618,8 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket { sock_desc->sock = socket; sock_desc->events = events; - int insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); - if (insert_res != 0) + lwpa_error_t insert_res = lwpa_rbtree_insert(&context->sockets, sock_desc); + if (insert_res == kLwpaErrOk) { struct kevent os_events[LWPA_SOCKET_MAX_KEVENTS]; int num_events = events_lwpa_to_kqueue(socket, 0, events, user_data, os_events); @@ -639,7 +639,7 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket else { free(sock_desc); - return kLwpaErrNoMem; + return insert_res; } } else From a5ffcfd26a462f67cf8ea6de4f25cee6405cbd17 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 15 Jul 2019 11:15:25 -0500 Subject: [PATCH 091/264] And modify Windows socket polling to use correct behavior --- include/os/windows/lwpa/os_socket.h | 12 +- src/os/windows/lwpa/os_socket.c | 195 ++++++++++++---------------- 2 files changed, 88 insertions(+), 119 deletions(-) diff --git a/include/os/windows/lwpa/os_socket.h b/include/os/windows/lwpa/os_socket.h index 854af7f34..46c585d1c 100644 --- a/include/os/windows/lwpa/os_socket.h +++ b/include/os/windows/lwpa/os_socket.h @@ -32,6 +32,7 @@ #include "lwpa/inet.h" #include "lwpa/lock.h" +#include "lwpa/rbtree.h" #ifdef __cplusplus extern "C" { @@ -53,13 +54,6 @@ typedef SOCKET lwpa_socket_t; /* Definitions for the lwpa_poll API */ -typedef struct LwpaPollCtxSocket -{ - lwpa_socket_t socket; - lwpa_poll_events_t events; - void* user_data; -} LwpaPollCtxSocket; - typedef struct LwpaPollFdSet { fd_set set; @@ -71,9 +65,7 @@ typedef struct LwpaPollContext bool valid; lwpa_mutex_t lock; - LwpaPollCtxSocket* sockets; - size_t socket_arr_size; - size_t num_valid_sockets; + LwpaRbTree sockets; LwpaPollFdSet readfds; LwpaPollFdSet writefds; diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index 80f9899bc..e4afa53a2 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -32,6 +32,18 @@ #define POLL_CONTEXT_ARR_CHUNK_SIZE 10 +/****************************** Private types ********************************/ + +/* A struct to track sockets being polled by the lwpa_poll() API */ +typedef struct LwpaPollSocket +{ + // 'sock' must always remain as the first member in the struct to facilitate an LwpaRbTree lookup + // shortcut + lwpa_socket_t sock; + lwpa_poll_events_t events; + void* user_data; +} LwpaPollSocket; + /***************************** Private macros ********************************/ #define LWPA_FD_ZERO(setptr) \ @@ -115,14 +127,15 @@ static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_v static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); // Helper functions for the lwpa_poll API -static void init_socket_chunk(LwpaPollCtxSocket* chunk); -static LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket); -static LwpaPollCtxSocket* find_hole(LwpaPollContext* context); -static void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock); -static void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock); +static void set_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* sock); +static void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* sock); static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, const LwpaPollFdSet* readfds, const LwpaPollFdSet* writefds, const LwpaPollFdSet* exceptfds); +static int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b); +static LwpaRbNode* poll_socket_alloc(); +static void poll_socket_free(LwpaRbNode* node); + /*************************** Function definitions ****************************/ #if !defined(LWPA_BUILDING_MOCK_LIB) @@ -633,12 +646,10 @@ lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) if (!lwpa_mutex_create(&context->lock)) return kLwpaErrSys; + lwpa_rbtree_init(&context->sockets, poll_socket_compare, poll_socket_alloc, poll_socket_free); LWPA_FD_ZERO(&context->readfds); LWPA_FD_ZERO(&context->writefds); LWPA_FD_ZERO(&context->exceptfds); - context->sockets = NULL; - context->socket_arr_size = 0; - context->num_valid_sockets = 0; context->valid = true; return kLwpaErrOk; } @@ -648,105 +659,40 @@ void lwpa_poll_context_deinit(LwpaPollContext* context) if (!context || !context->valid) return; - if (context->sockets) - { - free(context->sockets); - } + lwpa_rbtree_clear(&context->sockets); lwpa_mutex_destroy(&context->lock); context->valid = false; } -LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket) -{ - for (LwpaPollCtxSocket* cur = context->sockets; cur < context->sockets + context->socket_arr_size; ++cur) - { - if (cur->socket == socket) - return cur; - } - return NULL; -} - -void init_socket_chunk(LwpaPollCtxSocket* chunk) -{ - for (LwpaPollCtxSocket* cur = chunk; cur < chunk + POLL_CONTEXT_ARR_CHUNK_SIZE; ++cur) - { - cur->socket = LWPA_SOCKET_INVALID; - } -} - -LwpaPollCtxSocket* find_hole(LwpaPollContext* context) -{ - LwpaPollCtxSocket* hole = NULL; - - if (!context->sockets) - { - // No sockets have been added yet. Create the first chunk. - context->sockets = (LwpaPollCtxSocket*)calloc(POLL_CONTEXT_ARR_CHUNK_SIZE, sizeof(LwpaPollCtxSocket)); - if (context->sockets) - { - init_socket_chunk(context->sockets); - context->socket_arr_size = POLL_CONTEXT_ARR_CHUNK_SIZE; - hole = &context->sockets[0]; - } - } - else - { - // Find an invalid socket in the list - for (LwpaPollCtxSocket* cur = context->sockets; cur < context->sockets + context->socket_arr_size; ++cur) - { - if (cur->socket == LWPA_SOCKET_INVALID) - { - hole = cur; - break; - } - } - // No hole found; need to do a realloc - if (!hole) - { - // Expand the socket array by another chunk. - size_t new_size = context->socket_arr_size + POLL_CONTEXT_ARR_CHUNK_SIZE; - context->sockets = (LwpaPollCtxSocket*)realloc(context->sockets, new_size * sizeof(LwpaPollCtxSocket)); - if (context->sockets) - { - init_socket_chunk(&context->sockets[context->socket_arr_size]); - hole = &context->sockets[context->socket_arr_size]; - context->socket_arr_size += POLL_CONTEXT_ARR_CHUNK_SIZE; - } - } - } - - return hole; -} - -void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) +void set_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* sock_desc) { - if (sock->events & LWPA_POLL_IN) + if (sock_desc->events & LWPA_POLL_IN) { - LWPA_FD_SET(sock->socket, &context->readfds); + LWPA_FD_SET(sock_desc->sock, &context->readfds); } - if (sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + if (sock_desc->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) { - LWPA_FD_SET(sock->socket, &context->writefds); + LWPA_FD_SET(sock_desc->sock, &context->writefds); } - if (sock->events & (LWPA_POLL_OOB | LWPA_POLL_CONNECT)) + if (sock_desc->events & (LWPA_POLL_OOB | LWPA_POLL_CONNECT)) { - LWPA_FD_SET(sock->socket, &context->exceptfds); + LWPA_FD_SET(sock_desc->sock, &context->exceptfds); } } -void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) +void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* sock_desc) { - if (sock->events & LWPA_POLL_IN) + if (sock_desc->events & LWPA_POLL_IN) { - LWPA_FD_CLEAR(sock->socket, &context->readfds); + LWPA_FD_CLEAR(sock_desc->sock, &context->readfds); } - if (sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + if (sock_desc->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) { - LWPA_FD_CLEAR(sock->socket, &context->writefds); + LWPA_FD_CLEAR(sock_desc->sock, &context->writefds); } - if (sock->events & (LWPA_POLL_OOB | LWPA_POLL_CONNECT)) + if (sock_desc->events & (LWPA_POLL_OOB | LWPA_POLL_CONNECT)) { - LWPA_FD_CLEAR(sock->socket, &context->exceptfds); + LWPA_FD_CLEAR(sock_desc->sock, &context->exceptfds); } } @@ -759,21 +705,27 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket lwpa_error_t res = kLwpaErrSys; if (lwpa_mutex_take(&context->lock)) { - if (context->num_valid_sockets >= LWPA_SOCKET_MAX_POLL_SIZE) + if (lwpa_rbtree_size(&context->sockets) >= LWPA_SOCKET_MAX_POLL_SIZE) { res = kLwpaErrNoMem; } else { - LwpaPollCtxSocket* new_sock = find_hole(context); + LwpaPollSocket* new_sock = (LwpaPollSocket*)malloc(sizeof(LwpaPollSocket)); if (new_sock) { - new_sock->socket = socket; + new_sock->sock = socket; new_sock->events = events; new_sock->user_data = user_data; - set_in_fd_sets(context, new_sock); - context->num_valid_sockets++; - res = kLwpaErrOk; + res = lwpa_rbtree_insert(&context->sockets, new_sock); + if (res == kLwpaErrOk) + { + set_in_fd_sets(context, new_sock); + } + else + { + free(new_sock); + } } else { @@ -794,7 +746,7 @@ lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t soc lwpa_error_t res = kLwpaErrSys; if (lwpa_mutex_take(&context->lock)) { - LwpaPollCtxSocket* sock_desc = find_socket(context, socket); + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); if (sock_desc) { clear_in_fd_sets(context, sock_desc); @@ -819,12 +771,11 @@ void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) if (lwpa_mutex_take(&context->lock)) { - LwpaPollCtxSocket* sock_desc = find_socket(context, socket); + LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbtree_find(&context->sockets, &socket); if (sock_desc) { clear_in_fd_sets(context, sock_desc); - sock_desc->socket = LWPA_SOCKET_INVALID; - context->num_valid_sockets--; + lwpa_rbtree_remove(&context->sockets, sock_desc); } lwpa_mutex_give(&context->lock); } @@ -842,7 +793,7 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int LWPA_FD_ZERO(&exceptfds); if (lwpa_mutex_take(&context->lock)) { - if (context->num_valid_sockets != 0) + if (lwpa_rbtree_size(&context->sockets) > 0) { readfds = context->readfds; writefds = context->writefds; @@ -902,23 +853,25 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event // gone wrong. lwpa_error_t res = kLwpaErrSys; - for (LwpaPollCtxSocket* sock_desc = context->sockets; sock_desc < context->sockets + context->socket_arr_size; - ++sock_desc) + LwpaRbIter iter; + lwpa_rbiter_init(&iter); + for (LwpaPollSocket* sock_desc = (LwpaPollSocket*)lwpa_rbiter_first(&iter, &context->sockets); sock_desc; + sock_desc = (LwpaPollSocket*)lwpa_rbiter_next(&iter)) { - if (sock_desc->socket == LWPA_SOCKET_INVALID) + if (sock_desc->sock == LWPA_SOCKET_INVALID) continue; - if (LWPA_FD_ISSET(sock_desc->socket, readfds) || LWPA_FD_ISSET(sock_desc->socket, writefds) || - LWPA_FD_ISSET(sock_desc->socket, exceptfds)) + if (LWPA_FD_ISSET(sock_desc->sock, readfds) || LWPA_FD_ISSET(sock_desc->sock, writefds) || + LWPA_FD_ISSET(sock_desc->sock, exceptfds)) { res = kLwpaErrOk; - event->socket = sock_desc->socket; + event->socket = sock_desc->sock; event->user_data = sock_desc->user_data; /* Check for errors */ int error; int error_size = sizeof(error); - if (getsockopt(sock_desc->socket, SOL_SOCKET, SO_ERROR, (char*)&error, &error_size) == 0) + if (getsockopt(sock_desc->sock, SOL_SOCKET, SO_ERROR, (char*)&error, &error_size) == 0) { if (error != 0) { @@ -931,19 +884,19 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event res = err_winsock_to_lwpa(WSAGetLastError()); break; } - if (LWPA_FD_ISSET(sock_desc->socket, readfds)) + if (LWPA_FD_ISSET(sock_desc->sock, readfds)) { if (sock_desc->events & LWPA_POLL_IN) event->events |= LWPA_POLL_IN; } - if (LWPA_FD_ISSET(sock_desc->socket, writefds)) + if (LWPA_FD_ISSET(sock_desc->sock, writefds)) { if (sock_desc->events & LWPA_POLL_CONNECT) event->events |= LWPA_POLL_CONNECT; else if (sock_desc->events & LWPA_POLL_OUT) event->events |= LWPA_POLL_OUT; } - if (LWPA_FD_ISSET(sock_desc->socket, exceptfds)) + if (LWPA_FD_ISSET(sock_desc->sock, exceptfds)) { if (sock_desc->events & LWPA_POLL_CONNECT) event->events |= LWPA_POLL_CONNECT; // Async connect errors are handled above @@ -956,6 +909,30 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event return res; } +int poll_socket_compare(const LwpaRbTree* tree, const LwpaRbNode* node_a, const LwpaRbNode* node_b) +{ + (void)tree; + + LwpaPollSocket* a = (LwpaPollSocket*)node_a->value; + LwpaPollSocket* b = (LwpaPollSocket*)node_b->value; + + return (a->sock > b->sock) - (a->sock < b->sock); +} + +LwpaRbNode* poll_socket_alloc() +{ + return (LwpaRbNode*)malloc(sizeof(LwpaRbNode)); +} + +void poll_socket_free(LwpaRbNode* node) +{ + if (node) + { + free(node->value); + free(node); + } +} + lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, LwpaAddrinfo* result) { From 0bdc54fc82a76fad22284e158e33ab18eefabacc Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 15 Jul 2019 11:24:16 -0500 Subject: [PATCH 092/264] Fix warning on macOS --- tests/unit/lwpa/test_rbtree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/lwpa/test_rbtree.cpp b/tests/unit/lwpa/test_rbtree.cpp index ad2d7866c..6cde41d85 100644 --- a/tests/unit/lwpa/test_rbtree.cpp +++ b/tests/unit/lwpa/test_rbtree.cpp @@ -117,7 +117,7 @@ TEST_F(RbTreeTest, insert_static) EXPECT_GT(lwpa_rbtree_test(&tree, tree.root), 0); // Find a random number - std::uniform_int_distribution dist(0, kIntArraySize - 1); + std::uniform_int_distribution<> dist(0, kIntArraySize - 1); int to_find = dist(rand_); int* found = (int*)lwpa_rbtree_find(&tree, &to_find); ASSERT_TRUE(found != nullptr); From d64a31aeced92252891e277acbb0c55abebcf573 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 16 Jul 2019 17:08:11 -0500 Subject: [PATCH 093/264] Linux - add pthread dependency --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7fbea88e2..6d2331503 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -119,7 +119,7 @@ elseif(LWPA_TARGET_OS STREQUAL macos) ${LWPA_ROOT}/src/os/macos/lwpa/os_error.c ) elseif(LWPA_TARGET_OS STREQUAL linux) - target_link_libraries(lwpa PUBLIC uuid) + target_link_libraries(lwpa PUBLIC uuid pthread) target_sources(lwpa PRIVATE ${LWPA_ROOT}/src/os/linux/lwpa/os_error.h ${LWPA_ROOT}/src/os/linux/lwpa/os_error.c From d43d7055f995cc5a6d57f2114f5c9ed8479aab32 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 16 Jul 2019 18:52:44 -0500 Subject: [PATCH 094/264] Add some missing Linux socket options --- src/os/linux/lwpa/os_socket.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index c28d8c1bb..6ad5a20db 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -525,10 +525,14 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, } } break; + case LWPA_IP_MULTICAST_IF: + return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_IF, option_value, (socklen_t)option_len); case LWPA_IP_MULTICAST_TTL: return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, option_value, (socklen_t)option_len); case LWPA_IP_MULTICAST_LOOP: return setsockopt(id, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, option_value, (socklen_t)option_len); + case LWPA_IPV6_V6ONLY: + return setsockopt(id, IPPROTO_IPV6, IPV6_V6ONLY, option_value, (socklen_t)option_len); default: /* Other IPv6 options TODO on linux. */ break; } From fd5b52c45e20aa02f8d6daf7cc3bdc3f08c60ca1 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 9 Aug 2019 16:57:22 -0500 Subject: [PATCH 095/264] Checking in WIP port to unity --- CMakeLists.txt | 1 + external/unity/CMakeLists.txt | 9 + external/unity/extras/fixture/readme.txt | 9 + .../unity/extras/fixture/src/unity_fixture.c | 453 ++++ .../unity/extras/fixture/src/unity_fixture.h | 83 + .../fixture/src/unity_fixture_internals.h | 52 + .../src/unity_fixture_malloc_overrides.h | 47 + external/unity/src/unity.c | 2015 +++++++++++++++++ external/unity/src/unity.h | 581 +++++ external/unity/src/unity_internals.h | 1003 ++++++++ tests/unit/CMakeLists.txt | 13 +- tests/unit/entrypoint_non_embedded/main.c | 25 + tests/unit/lwpa/CMakeLists.txt | 34 - .../unit/lwpa_timer_wraparound/CMakeLists.txt | 11 - tests/unit/test_lwpa/CMakeLists.txt | 34 + .../test_common.c} | 72 +- tests/unit/test_lwpa/test_common.h | 25 + tests/unit/{lwpa => test_lwpa}/test_inet.cpp | 0 tests/unit/{lwpa => test_lwpa}/test_log.cpp | 0 tests/unit/test_lwpa/test_main.c | 44 + tests/unit/test_lwpa/test_main.h | 25 + .../unit/{lwpa => test_lwpa}/test_mempool.cpp | 0 tests/unit/{lwpa => test_lwpa}/test_mutex.cpp | 0 .../unit/{lwpa => test_lwpa}/test_netint.cpp | 0 tests/unit/{lwpa => test_lwpa}/test_pack.cpp | 0 .../unit/{lwpa => test_lwpa}/test_rbtree.cpp | 0 .../unit/{lwpa => test_lwpa}/test_rwlock.cpp | 0 .../unit/{lwpa => test_lwpa}/test_signal.cpp | 0 .../unit/{lwpa => test_lwpa}/test_socket.cpp | 0 .../{lwpa => test_lwpa}/test_socket_poll.cpp | 0 .../unit/{lwpa => test_lwpa}/test_thread.cpp | 0 tests/unit/{lwpa => test_lwpa}/test_timer.cpp | 0 tests/unit/{lwpa => test_lwpa}/test_uuid.cpp | 0 .../test_lwpa_timer_wraparound/CMakeLists.txt | 11 + .../test_main.c} | 29 +- .../test_lwpa_timer_wraparound/test_main.h | 25 + 36 files changed, 4509 insertions(+), 92 deletions(-) create mode 100644 external/unity/CMakeLists.txt create mode 100644 external/unity/extras/fixture/readme.txt create mode 100644 external/unity/extras/fixture/src/unity_fixture.c create mode 100644 external/unity/extras/fixture/src/unity_fixture.h create mode 100644 external/unity/extras/fixture/src/unity_fixture_internals.h create mode 100644 external/unity/extras/fixture/src/unity_fixture_malloc_overrides.h create mode 100644 external/unity/src/unity.c create mode 100644 external/unity/src/unity.h create mode 100644 external/unity/src/unity_internals.h create mode 100644 tests/unit/entrypoint_non_embedded/main.c delete mode 100644 tests/unit/lwpa/CMakeLists.txt delete mode 100644 tests/unit/lwpa_timer_wraparound/CMakeLists.txt create mode 100644 tests/unit/test_lwpa/CMakeLists.txt rename tests/unit/{lwpa/test_common.cpp => test_lwpa/test_common.c} (58%) create mode 100644 tests/unit/test_lwpa/test_common.h rename tests/unit/{lwpa => test_lwpa}/test_inet.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_log.cpp (100%) create mode 100644 tests/unit/test_lwpa/test_main.c create mode 100644 tests/unit/test_lwpa/test_main.h rename tests/unit/{lwpa => test_lwpa}/test_mempool.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_mutex.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_netint.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_pack.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_rbtree.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_rwlock.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_signal.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_socket.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_socket_poll.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_thread.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_timer.cpp (100%) rename tests/unit/{lwpa => test_lwpa}/test_uuid.cpp (100%) create mode 100644 tests/unit/test_lwpa_timer_wraparound/CMakeLists.txt rename tests/unit/{lwpa_timer_wraparound/test_timer_wraparound.cpp => test_lwpa_timer_wraparound/test_main.c} (78%) create mode 100644 tests/unit/test_lwpa_timer_wraparound/test_main.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c1974bf12..b2a26abd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ add_subdirectory(src) #################################### Tests #################################### if(LWPA_BUILD_TESTS) + add_subdirectory(external/unity) enable_testing() add_subdirectory(tests) endif() diff --git a/external/unity/CMakeLists.txt b/external/unity/CMakeLists.txt new file mode 100644 index 000000000..19687ba0d --- /dev/null +++ b/external/unity/CMakeLists.txt @@ -0,0 +1,9 @@ +if(NOT TARGET ThrowTheSwitch::Unity) + add_library(unity + unity.h + unity_internals.h + unity.c + ) + target_include_directories(unity PUBLIC ${CMAKE_CURRENT_LIST_DIR}) + add_library(ThrowTheSwitch::Unity ALIAS unity) +endif() diff --git a/external/unity/extras/fixture/readme.txt b/external/unity/extras/fixture/readme.txt new file mode 100644 index 000000000..6b9a78c17 --- /dev/null +++ b/external/unity/extras/fixture/readme.txt @@ -0,0 +1,9 @@ +Copyright (c) 2010 James Grenning and Contributed to Unity Project + +Unity Project - A Test Framework for C +Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +[Released under MIT License. Please refer to license.txt for details] + +This Framework is an optional add-on to Unity. By including unity_framework.h in place of unity.h, +you may now work with Unity in a manner similar to CppUTest. This framework adds the concepts of +test groups and gives finer control of your tests over the command line. \ No newline at end of file diff --git a/external/unity/extras/fixture/src/unity_fixture.c b/external/unity/extras/fixture/src/unity_fixture.c new file mode 100644 index 000000000..67807e151 --- /dev/null +++ b/external/unity/extras/fixture/src/unity_fixture.c @@ -0,0 +1,453 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * Unity Project - A Test Framework for C + * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams + * [Released under MIT License. Please refer to license.txt for details] + * ========================================== */ + +#include "unity_fixture.h" +#include "unity_internals.h" +#include + +struct UNITY_FIXTURE_T UnityFixture; + +/* If you decide to use the function pointer approach. + * Build with -D UNITY_OUTPUT_CHAR=outputChar and include + * int (*outputChar)(int) = putchar; */ + +void setUp(void) { /*does nothing*/ } +void tearDown(void) { /*does nothing*/ } + +static void announceTestRun(unsigned int runNumber) +{ + UnityPrint("Unity test run "); + UnityPrintNumberUnsigned(runNumber+1); + UnityPrint(" of "); + UnityPrintNumberUnsigned(UnityFixture.RepeatCount); + UNITY_PRINT_EOL(); +} + +int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)) +{ + int result = UnityGetCommandLineOptions(argc, argv); + unsigned int r; + if (result != 0) + return result; + + for (r = 0; r < UnityFixture.RepeatCount; r++) + { + UnityBegin(argv[0]); + announceTestRun(r); + runAllTests(); + if (!UnityFixture.Verbose) UNITY_PRINT_EOL(); + UnityEnd(); + } + + return (int)Unity.TestFailures; +} + +static int selected(const char* filter, const char* name) +{ + if (filter == 0) + return 1; + return strstr(name, filter) ? 1 : 0; +} + +static int testSelected(const char* test) +{ + return selected(UnityFixture.NameFilter, test); +} + +static int groupSelected(const char* group) +{ + return selected(UnityFixture.GroupFilter, group); +} + +void UnityTestRunner(unityfunction* setup, + unityfunction* testBody, + unityfunction* teardown, + const char* printableName, + const char* group, + const char* name, + const char* file, + unsigned int line) +{ + if (testSelected(name) && groupSelected(group)) + { + Unity.TestFile = file; + Unity.CurrentTestName = printableName; + Unity.CurrentTestLineNumber = line; + if (UnityFixture.Verbose) + { + UnityPrint(printableName); + #ifndef UNITY_REPEAT_TEST_NAME + Unity.CurrentTestName = NULL; + #endif + } + else if (UnityFixture.Silent) + { + /* Do Nothing */ + } + else + { + UNITY_OUTPUT_CHAR('.'); + } + + Unity.NumberOfTests++; + UnityMalloc_StartTest(); + UnityPointer_Init(); + + UNITY_EXEC_TIME_START(); + + if (TEST_PROTECT()) + { + setup(); + testBody(); + } + if (TEST_PROTECT()) + { + teardown(); + } + if (TEST_PROTECT()) + { + UnityPointer_UndoAllSets(); + if (!Unity.CurrentTestFailed) + UnityMalloc_EndTest(); + } + UnityConcludeFixtureTest(); + } +} + +void UnityIgnoreTest(const char* printableName, const char* group, const char* name) +{ + if (testSelected(name) && groupSelected(group)) + { + Unity.NumberOfTests++; + Unity.TestIgnores++; + if (UnityFixture.Verbose) + { + UnityPrint(printableName); + UNITY_PRINT_EOL(); + } + else if (UnityFixture.Silent) + { + /* Do Nothing */ + } + else + { + UNITY_OUTPUT_CHAR('!'); + } + } +} + + +/*------------------------------------------------- */ +/* Malloc and free stuff */ +#define MALLOC_DONT_FAIL -1 +static int malloc_count; +static int malloc_fail_countdown = MALLOC_DONT_FAIL; + +void UnityMalloc_StartTest(void) +{ + malloc_count = 0; + malloc_fail_countdown = MALLOC_DONT_FAIL; +} + +void UnityMalloc_EndTest(void) +{ + malloc_fail_countdown = MALLOC_DONT_FAIL; + if (malloc_count != 0) + { + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!"); + } +} + +void UnityMalloc_MakeMallocFailAfterCount(int countdown) +{ + malloc_fail_countdown = countdown; +} + +/* These definitions are always included from unity_fixture_malloc_overrides.h */ +/* We undef to use them or avoid conflict with per the C standard */ +#undef malloc +#undef free +#undef calloc +#undef realloc + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC +static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES]; +static size_t heap_index; +#else +#include +#endif + +typedef struct GuardBytes +{ + size_t size; + size_t guard_space; +} Guard; + + +static const char end[] = "END"; + +void* unity_malloc(size_t size) +{ + char* mem; + Guard* guard; + size_t total_size = size + sizeof(Guard) + sizeof(end); + + if (malloc_fail_countdown != MALLOC_DONT_FAIL) + { + if (malloc_fail_countdown == 0) + return NULL; + malloc_fail_countdown--; + } + + if (size == 0) return NULL; +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES) + { + guard = NULL; + } + else + { + guard = (Guard*)&unity_heap[heap_index]; + heap_index += total_size; + } +#else + guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size); +#endif + if (guard == NULL) return NULL; + malloc_count++; + guard->size = size; + guard->guard_space = 0; + mem = (char*)&(guard[1]); + memcpy(&mem[size], end, sizeof(end)); + + return (void*)mem; +} + +static int isOverrun(void* mem) +{ + Guard* guard = (Guard*)mem; + char* memAsChar = (char*)mem; + guard--; + + return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0; +} + +static void release_memory(void* mem) +{ + Guard* guard = (Guard*)mem; + guard--; + + malloc_count--; +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + if (mem == unity_heap + heap_index - guard->size - sizeof(end)) + { + heap_index -= (guard->size + sizeof(Guard) + sizeof(end)); + } +#else + UNITY_FIXTURE_FREE(guard); +#endif +} + +void unity_free(void* mem) +{ + int overrun; + + if (mem == NULL) + { + return; + } + + overrun = isOverrun(mem); + release_memory(mem); + if (overrun) + { + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()"); + } +} + +void* unity_calloc(size_t num, size_t size) +{ + void* mem = unity_malloc(num * size); + if (mem == NULL) return NULL; + memset(mem, 0, num * size); + return mem; +} + +void* unity_realloc(void* oldMem, size_t size) +{ + Guard* guard = (Guard*)oldMem; + void* newMem; + + if (oldMem == NULL) return unity_malloc(size); + + guard--; + if (isOverrun(oldMem)) + { + release_memory(oldMem); + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()"); + } + + if (size == 0) + { + release_memory(oldMem); + return NULL; + } + + if (guard->size >= size) return oldMem; + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */ + if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) && + heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES) + { + release_memory(oldMem); /* Not thread-safe, like unity_heap generally */ + return unity_malloc(size); /* No memcpy since data is in place */ + } +#endif + newMem = unity_malloc(size); + if (newMem == NULL) return NULL; /* Do not release old memory */ + memcpy(newMem, oldMem, guard->size); + release_memory(oldMem); + return newMem; +} + + +/*-------------------------------------------------------- */ +/*Automatic pointer restoration functions */ +struct PointerPair +{ + void** pointer; + void* old_value; +}; + +static struct PointerPair pointer_store[UNITY_MAX_POINTERS]; +static int pointer_index = 0; + +void UnityPointer_Init(void) +{ + pointer_index = 0; +} + +void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line) +{ + if (pointer_index >= UNITY_MAX_POINTERS) + { + UNITY_TEST_FAIL(line, "Too many pointers set"); + } + else + { + pointer_store[pointer_index].pointer = pointer; + pointer_store[pointer_index].old_value = *pointer; + *pointer = newValue; + pointer_index++; + } +} + +void UnityPointer_UndoAllSets(void) +{ + while (pointer_index > 0) + { + pointer_index--; + *(pointer_store[pointer_index].pointer) = + pointer_store[pointer_index].old_value; + } +} + +int UnityGetCommandLineOptions(int argc, const char* argv[]) +{ + int i; + UnityFixture.Verbose = 0; + UnityFixture.Silent = 0; + UnityFixture.GroupFilter = 0; + UnityFixture.NameFilter = 0; + UnityFixture.RepeatCount = 1; + + if (argc == 1) + return 0; + + for (i = 1; i < argc; ) + { + if (strcmp(argv[i], "-v") == 0) + { + UnityFixture.Verbose = 1; + i++; + } + else if (strcmp(argv[i], "-s") == 0) + { + UnityFixture.Silent = 1; + i++; + } + else if (strcmp(argv[i], "-g") == 0) + { + i++; + if (i >= argc) + return 1; + UnityFixture.GroupFilter = argv[i]; + i++; + } + else if (strcmp(argv[i], "-n") == 0) + { + i++; + if (i >= argc) + return 1; + UnityFixture.NameFilter = argv[i]; + i++; + } + else if (strcmp(argv[i], "-r") == 0) + { + UnityFixture.RepeatCount = 2; + i++; + if (i < argc) + { + if (*(argv[i]) >= '0' && *(argv[i]) <= '9') + { + unsigned int digit = 0; + UnityFixture.RepeatCount = 0; + while (argv[i][digit] >= '0' && argv[i][digit] <= '9') + { + UnityFixture.RepeatCount *= 10; + UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0'; + } + i++; + } + } + } + else + { + /* ignore unknown parameter */ + i++; + } + } + return 0; +} + +void UnityConcludeFixtureTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + UNITY_PRINT_EOL(); + } + else if (!Unity.CurrentTestFailed) + { + if (UnityFixture.Verbose) + { + UnityPrint(" "); + UnityPrint(UnityStrPass); + UNITY_EXEC_TIME_STOP(); + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + } + } + else /* Unity.CurrentTestFailed */ + { + Unity.TestFailures++; + UNITY_PRINT_EOL(); + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; +} diff --git a/external/unity/extras/fixture/src/unity_fixture.h b/external/unity/extras/fixture/src/unity_fixture.h new file mode 100644 index 000000000..2dcf473c7 --- /dev/null +++ b/external/unity/extras/fixture/src/unity_fixture.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * Unity Project - A Test Framework for C + * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams + * [Released under MIT License. Please refer to license.txt for details] + * ========================================== */ + +#ifndef UNITY_FIXTURE_H_ +#define UNITY_FIXTURE_H_ + +#include "unity.h" +#include "unity_internals.h" +#include "unity_fixture_malloc_overrides.h" +#include "unity_fixture_internals.h" + +int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)); + + +#define TEST_GROUP(group)\ + static const char* TEST_GROUP_##group = #group + +#define TEST_SETUP(group) void TEST_##group##_SETUP(void);\ + void TEST_##group##_SETUP(void) + +#define TEST_TEAR_DOWN(group) void TEST_##group##_TEAR_DOWN(void);\ + void TEST_##group##_TEAR_DOWN(void) + + +#define TEST(group, name) \ + void TEST_##group##_##name##_(void);\ + void TEST_##group##_##name##_run(void);\ + void TEST_##group##_##name##_run(void)\ + {\ + UnityTestRunner(TEST_##group##_SETUP,\ + TEST_##group##_##name##_,\ + TEST_##group##_TEAR_DOWN,\ + "TEST(" #group ", " #name ")",\ + TEST_GROUP_##group, #name,\ + __FILE__, __LINE__);\ + }\ + void TEST_##group##_##name##_(void) + +#define IGNORE_TEST(group, name) \ + void TEST_##group##_##name##_(void);\ + void TEST_##group##_##name##_run(void);\ + void TEST_##group##_##name##_run(void)\ + {\ + UnityIgnoreTest("IGNORE_TEST(" #group ", " #name ")", TEST_GROUP_##group, #name);\ + }\ + void TEST_##group##_##name##_(void) + +/* Call this for each test, insider the group runner */ +#define RUN_TEST_CASE(group, name) \ + { void TEST_##group##_##name##_run(void);\ + TEST_##group##_##name##_run(); } + +/* This goes at the bottom of each test file or in a separate c file */ +#define TEST_GROUP_RUNNER(group)\ + void TEST_##group##_GROUP_RUNNER(void);\ + void TEST_##group##_GROUP_RUNNER(void) + +/* Call this from main */ +#define RUN_TEST_GROUP(group)\ + { void TEST_##group##_GROUP_RUNNER(void);\ + TEST_##group##_GROUP_RUNNER(); } + +/* CppUTest Compatibility Macros */ +#ifndef UNITY_EXCLUDE_CPPUTEST_ASSERTS +/* Sets a pointer and automatically restores it to its old value after teardown */ +#define UT_PTR_SET(ptr, newPointerValue) UnityPointer_Set((void**)&(ptr), (void*)(newPointerValue), __LINE__) +#define TEST_ASSERT_POINTERS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_PTR((expected), (actual)) +#define TEST_ASSERT_BYTES_EQUAL(expected, actual) TEST_ASSERT_EQUAL_HEX8(0xff & (expected), 0xff & (actual)) +#define FAIL(message) TEST_FAIL_MESSAGE((message)) +#define CHECK(condition) TEST_ASSERT_TRUE((condition)) +#define LONGS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_INT((expected), (actual)) +#define STRCMP_EQUAL(expected, actual) TEST_ASSERT_EQUAL_STRING((expected), (actual)) +#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual)) +#endif + +/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */ +void UnityMalloc_MakeMallocFailAfterCount(int countdown); + +#endif /* UNITY_FIXTURE_H_ */ diff --git a/external/unity/extras/fixture/src/unity_fixture_internals.h b/external/unity/extras/fixture/src/unity_fixture_internals.h new file mode 100644 index 000000000..98d4d4430 --- /dev/null +++ b/external/unity/extras/fixture/src/unity_fixture_internals.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * Unity Project - A Test Framework for C + * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams + * [Released under MIT License. Please refer to license.txt for details] + * ========================================== */ + +#ifndef UNITY_FIXTURE_INTERNALS_H_ +#define UNITY_FIXTURE_INTERNALS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct UNITY_FIXTURE_T +{ + int Verbose; + int Silent; + unsigned int RepeatCount; + const char* NameFilter; + const char* GroupFilter; +}; +extern struct UNITY_FIXTURE_T UnityFixture; + +typedef void unityfunction(void); +void UnityTestRunner(unityfunction* setup, + unityfunction* testBody, + unityfunction* teardown, + const char* printableName, + const char* group, + const char* name, + const char* file, unsigned int line); + +void UnityIgnoreTest(const char* printableName, const char* group, const char* name); +void UnityMalloc_StartTest(void); +void UnityMalloc_EndTest(void); +int UnityGetCommandLineOptions(int argc, const char* argv[]); +void UnityConcludeFixtureTest(void); + +void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line); +void UnityPointer_UndoAllSets(void); +void UnityPointer_Init(void); +#ifndef UNITY_MAX_POINTERS +#define UNITY_MAX_POINTERS 5 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* UNITY_FIXTURE_INTERNALS_H_ */ diff --git a/external/unity/extras/fixture/src/unity_fixture_malloc_overrides.h b/external/unity/extras/fixture/src/unity_fixture_malloc_overrides.h new file mode 100644 index 000000000..7daba50aa --- /dev/null +++ b/external/unity/extras/fixture/src/unity_fixture_malloc_overrides.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * Unity Project - A Test Framework for C + * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams + * [Released under MIT License. Please refer to license.txt for details] + * ========================================== */ + +#ifndef UNITY_FIXTURE_MALLOC_OVERRIDES_H_ +#define UNITY_FIXTURE_MALLOC_OVERRIDES_H_ + +#include + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC +/* Define this macro to remove the use of stdlib.h, malloc, and free. + * Many embedded systems do not have a heap or malloc/free by default. + * This internal unity_malloc() provides allocated memory deterministically from + * the end of an array only, unity_free() only releases from end-of-array, + * blocks are not coalesced, and memory not freed in LIFO order is stranded. */ + #ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES + #define UNITY_INTERNAL_HEAP_SIZE_BYTES 256 + #endif +#endif + +/* These functions are used by the Unity Fixture to allocate and release memory + * on the heap and can be overridden with platform-specific implementations. + * For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc() + * and UNITY_FIXTURE_FREE becomes vPortFree(). */ +#if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE) + #include + #define UNITY_FIXTURE_MALLOC(size) malloc(size) + #define UNITY_FIXTURE_FREE(ptr) free(ptr) +#else + extern void* UNITY_FIXTURE_MALLOC(size_t size); + extern void UNITY_FIXTURE_FREE(void* ptr); +#endif + +#define malloc unity_malloc +#define calloc unity_calloc +#define realloc unity_realloc +#define free unity_free + +void* unity_malloc(size_t size); +void* unity_calloc(size_t num, size_t size); +void* unity_realloc(void * oldMem, size_t size); +void unity_free(void * mem); + +#endif /* UNITY_FIXTURE_MALLOC_OVERRIDES_H_ */ diff --git a/external/unity/src/unity.c b/external/unity/src/unity.c new file mode 100644 index 000000000..660bfd6cc --- /dev/null +++ b/external/unity/src/unity.c @@ -0,0 +1,2015 @@ +/* ========================================================================= + Unity Project - A Test Framework for C + Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +============================================================================ */ + +#include "unity.h" +#include + +#ifdef AVR +#include +#else +#define PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } +#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } +#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) return + +struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char PROGMEM UnityStrOk[] = "\033[42mOK\033[00m"; +const char PROGMEM UnityStrPass[] = "\033[42mPASS\033[00m"; +const char PROGMEM UnityStrFail[] = "\033[41mFAIL\033[00m"; +const char PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[00m"; +#else +const char PROGMEM UnityStrOk[] = "OK"; +const char PROGMEM UnityStrPass[] = "PASS"; +const char PROGMEM UnityStrFail[] = "FAIL"; +const char PROGMEM UnityStrIgnore[] = "IGNORE"; +#endif +static const char PROGMEM UnityStrNull[] = "NULL"; +static const char PROGMEM UnityStrSpacer[] = ". "; +static const char PROGMEM UnityStrExpected[] = " Expected "; +static const char PROGMEM UnityStrWas[] = " Was "; +static const char PROGMEM UnityStrGt[] = " to be greater than "; +static const char PROGMEM UnityStrLt[] = " to be less than "; +static const char PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char PROGMEM UnityStrElement[] = " Element "; +static const char PROGMEM UnityStrByte[] = " Byte "; +static const char PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char PROGMEM UnityStrNot[] = "Not "; +static const char PROGMEM UnityStrInf[] = "Infinity"; +static const char PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char PROGMEM UnityStrNaN[] = "NaN"; +static const char PROGMEM UnityStrDet[] = "Determinate"; +static const char PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char PROGMEM UnityStrResultsTests[] = " Tests "; +static const char PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char PROGMEM UnityStrResultsIgnored[] = " Ignored "; +static const char PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; + +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char* pch) +{ + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char* string) +{ + const char* pch = string; + UNITY_UINT count = 0; + + while (*pch && (*pch != 'm')) + { + UNITY_OUTPUT_CHAR(*pch); + pch++; + count++; + } + UNITY_OUTPUT_CHAR('m'); + count++; + + return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch) + { +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + UnityPrintChar(pch); + pch++; + } + } +} + +/*-----------------------------------------------*/ +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintFormatted(const char* format, ...) +{ + const char* pch = format; + va_list va; + va_start(va, format); + + if (pch != NULL) + { + while (*pch) + { + /* format identification character */ + if (*pch == '%') + { + pch++; + + if (pch != NULL) + { + switch (*pch) + { + case 'd': + case 'i': + { + const int number = va_arg(va, int); + UnityPrintNumber((UNITY_INT)number); + break; + } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + case 'f': + case 'g': + { + const double number = va_arg(va, double); + UnityPrintFloat((UNITY_DOUBLE)number); + break; + } +#endif + case 'u': + { + const unsigned int number = va_arg(va, unsigned int); + UnityPrintNumberUnsigned((UNITY_UINT)number); + break; + } + case 'b': + { + const unsigned int number = va_arg(va, unsigned int); + const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('b'); + UnityPrintMask(mask, (UNITY_UINT)number); + break; + } + case 'x': + case 'X': + case 'p': + { + const unsigned int number = va_arg(va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 8); + break; + } + case 'c': + { + const int ch = va_arg(va, int); + UnityPrintChar((const char *)&ch); + break; + } + case 's': + { + const char * string = va_arg(va, const char *); + UnityPrint(string); + break; + } + case '%': + { + UnityPrintChar(pch); + break; + } + default: + { + /* print the unknown format character */ + UNITY_OUTPUT_CHAR('%'); + UnityPrintChar(pch); + break; + } + } + } + } +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + else if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + else if (*pch == '\n') + { + UNITY_PRINT_EOL(); + } + else + { + UnityPrintChar(pch); + } + + pch++; + } + } + + va_end(va); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + +/*-----------------------------------------------*/ +void UnityPrintLen(const char* string, const UNITY_UINT32 length) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch && ((UNITY_UINT32)(pch - string) < length)) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + UnityPrintNumber(number); + } + else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned((UNITY_UINT)number); + } + else + { + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ + UNITY_UINT number = (UNITY_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (UNITY_UINT)-number_to_print; + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ + UNITY_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ + int nibble; + char nibbles = nibbles_to_print; + + if ((unsigned)nibbles > UNITY_MAX_NIBBLES) + { + nibbles = UNITY_MAX_NIBBLES; + } + + while (nibbles > 0) + { + nibbles--; + nibble = (int)(number >> (nibbles * 4)) & 0x0F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ + UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); + UNITY_INT32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + + UNITY_DOUBLE number = input_number; + + /* print minus sign (including for negative zero) */ + if ((number < 0.0f) || ((number == 0.0f) && ((1.0f / number) < 0.0f))) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + /* handle zero, NaN, and +/- infinity */ + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (isnan(number)) + { + UnityPrint("nan"); + } + else if (isinf(number)) + { + UnityPrint("inf"); + } + else + { + UNITY_INT32 n_int = 0, n; + int exponent = 0; + int decimals, digits; + char buf[16] = {0}; + + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if (number < 1.0f) + { + UNITY_DOUBLE factor = 1.0f; + + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; } + while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } + + number *= factor; + } + else if (number > (UNITY_DOUBLE)max_scaled) + { + UNITY_DOUBLE divisor = 1.0f; + + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; } + while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } + + number /= divisor; + } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; + + while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } + + number *= factor; + } + + /* round to nearest integer */ + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) + n--; +#endif + + n += n_int; + + if (n >= max_scaled) + { + n = min_scaled; + exponent++; + } + + /* determine where to place decimal point */ + decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); + exponent += decimals; + + /* truncate trailing zeroes after decimal point */ + while ((decimals > 0) && ((n % 10) == 0)) + { + n /= 10; + decimals--; + } + + /* build up buffer in reverse order */ + digits = 0; + while ((n != 0) || (digits < (decimals + 1))) + { + buf[digits++] = (char)('0' + n % 10); + n /= 10; + } + while (digits > 0) + { + if (digits == decimals) { UNITY_OUTPUT_CHAR('.'); } + UNITY_OUTPUT_CHAR(buf[--digits]); + } + + /* print exponent if needed */ + if (exponent != 0) + { + UNITY_OUTPUT_CHAR('e'); + + if (exponent < 0) + { + UNITY_OUTPUT_CHAR('-'); + exponent = -exponent; + } + else + { + UNITY_OUTPUT_CHAR('+'); + } + + digits = 0; + while ((exponent != 0) || (digits < 2)) + { + buf[digits++] = (char)('0' + exponent % 10); + exponent /= 10; + } + while (digits > 0) + { + UNITY_OUTPUT_CHAR(buf[--digits]); + } + } + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg) +{ + if (msg) + { + UnityPrint(UnityStrSpacer); +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, + const char* actual, + const UNITY_UINT32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_LINE_TYPE lineNumber, + const char* msg) +{ + /* Both are NULL or same pointer */ + if (expected == actual) { return 0; } + + /* print and return true if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + return 1; + } + + /* print and return true if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + return 1; + } + + return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; } + if ((threshold == actual)) { failed = 1; } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + else /* UINT or HEX */ + { + if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ +{ \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; } + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if (expect_val != actual_val) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (isinf(expected) && isinf(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \ + if (UNITY_NAN_CHECK) return 1; \ + (diff) = (actual) - (expected); \ + if ((diff) < 0) (diff) = -(diff); \ + if ((delta) < 0) (delta) = -(delta); \ + return !(isnan(diff) || isinf(diff) || ((diff) > (delta))) + /* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN + #define UNITY_NAN_CHECK isnan(expected) && isnan(actual) +#else + #define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); } +#else + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ + UNITY_FLOAT diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + if (!UnityFloatsWithin(*ptr_expected * UNITY_FLOAT_PRECISION, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + + if (!UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = isinf(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = isinf(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = isnan(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !isinf(actual) && !isnan(actual); + break; + + default: + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat((UNITY_DOUBLE)actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ + UNITY_DOUBLE diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + if (!UnityDoublesWithin(*ptr_expected * UNITY_DOUBLE_PRECISION, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = isinf(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = isinf(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = isnan(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !isinf(actual) && !isnan(actual); + break; + + default: + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat(actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual > expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + else + { + if ((UNITY_UINT)actual > (UNITY_UINT)expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual_val > expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + else + { + if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected != actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (i < length) && (expected[i] || actual[i]); i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected != actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char* expd = NULL; + const char* act = NULL; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if ((const void*)expected == (const void*)actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + expd = (const char*)expected; + } + + do + { + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expd = ((const char* const*)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (expd && act) + { + for (i = 0; expd[i] || act[i]; i++) + { + if (expd[i] != act[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expd != act) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings(expd, act); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; + UNITY_UINT32 elements = num_elements; + UNITY_UINT32 bytes; + + RETURN_IF_FAIL_OR_IGNORE; + + if ((elements == 0) || (length == 0)) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp++; + ptr_act++; + } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + } + } +} + +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch(size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + if (msg[0] != ' ') + { + UNITY_OUTPUT_CHAR(' '); + } + UnityPrint(msg); + } + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char* msg, const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + UNITY_EXEC_TIME_START(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrint(UnityStrOk); + } + else + { + UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char** argv) +{ + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + int i; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'l': /* list tests */ + return -1; + case 'n': /* include tests with name including this string */ + case 'f': /* an alias for -n */ + if (argv[i][2] == '=') + { + UnityOptionIncludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionIncludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + if (argv[i][2] == '=') + { + UnityOptionExcludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionExcludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_OUTPUT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + return 1; + } + } + } + + return 0; +} + +/*-----------------------------------------------*/ +int IsStringInBiggerString(const char* longstring, const char* shortstring) +{ + const char* lptr = longstring; + const char* sptr = shortstring; + const char* lnext = lptr; + + if (*sptr == '*') + { + return 1; + } + + while (*lptr) + { + lnext = lptr + 1; + + /* If they current bytes match, go on to the next bytes */ + while (*lptr && *sptr && (*lptr == *sptr)) + { + lptr++; + sptr++; + + /* We're done if we match the entire string or up to a wildcard */ + if (*sptr == '*') + return 1; + if (*sptr == ',') + return 1; + if (*sptr == '"') + return 1; + if (*sptr == '\'') + return 1; + if (*sptr == ':') + return 2; + if (*sptr == 0) + return 1; + } + + /* Otherwise we start in the long pointer 1 character further and try again */ + lptr = lnext; + sptr = shortstring; + } + + return 0; +} + +/*-----------------------------------------------*/ +int UnityStringArgumentMatches(const char* str) +{ + int retval; + const char* ptr1; + const char* ptr2; + const char* ptrf; + + /* Go through the options and get the substrings for matching one at a time */ + ptr1 = str; + while (ptr1[0] != 0) + { + if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { + ptr1++; + } + + /* look for the start of the next partial */ + ptr2 = ptr1; + ptrf = 0; + do + { + ptr2++; + if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { + ptrf = &ptr2[1]; + } + } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { + ptr2++; + } + + /* done if complete filename match */ + retval = IsStringInBiggerString(Unity.TestFile, ptr1); + if (retval == 1) + { + return retval; + } + + /* done if testname match after filename partial match */ + if ((retval == 2) && (ptrf != 0)) + { + if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { + return 1; + } + } + + /* done if complete testname match */ + if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { + return 1; + } + + ptr1 = ptr2; + } + + /* we couldn't find a match for any substrings */ + return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + int retval; + if (UnityOptionIncludeNamed) + { + retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); + } + else + { + retval = 1; + } + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionExcludeNamed) + { + if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { + retval = 0; + } + } + + return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ diff --git a/external/unity/src/unity.h b/external/unity/src/unity.h new file mode 100644 index 000000000..8f1fe2e5a --- /dev/null +++ b/external/unity/src/unity.h @@ -0,0 +1,581 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/* If the compiler supports it, the following block provides stub + * implementations of the above functions as weak symbols. Note that on + * some platforms (MinGW for example), weak function implementations need + * to be in the same translation unit they are called from. This can be + * achieved by defining UNITY_INCLUDE_SETUP_STUBS before including unity.h. */ +#ifdef UNITY_INCLUDE_SETUP_STUBS + #ifdef UNITY_WEAK_ATTRIBUTE + UNITY_WEAK_ATTRIBUTE void setUp(void) { } + UNITY_WEAK_ATTRIBUTE void tearDown(void) { } + UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { } + UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; } + #elif defined(UNITY_WEAK_PRAGMA) + #pragma weak setUp + void setUp(void) { } + #pragma weak tearDown + void tearDown(void) { } + #pragma weak suiteSetUp + void suiteSetUp(void) { } + #pragma weak suiteTearDown + int suiteTearDown(int num_failures) { return num_failures; } + #endif +#endif + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while(0) + +/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out + * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */ +#define TEST_FILE(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/external/unity/src/unity_internals.h b/external/unity/src/unity_internals.h new file mode 100644 index 000000000..0dd08fb54 --- /dev/null +++ b/external/unity/src/unity_internals.h @@ -0,0 +1,1003 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isinf & isnan macros should be provided by math.h */ +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define isinf(n) (isnan((n) - (n)) && !isnan(n)) +#endif + +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define isnan(n) ((n != n) ? 1 : 0) +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do{}while(0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do{}while(0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do{}while(0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Language Features Available + *-------------------------------------------------------*/ +#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA) +# if defined(__GNUC__) || defined(__ghs__) /* __GNUC__ includes clang */ +# if !(defined(__WIN32__) && defined(__clang__)) && !defined(__TMS470__) +# define UNITY_WEAK_ATTRIBUTE __attribute__((weak)) +# endif +# endif +#endif + +#ifdef UNITY_NO_WEAK +# undef UNITY_WEAK_ATTRIBUTE +# undef UNITY_WEAK_PRAGMA +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnityConcludeTest(void); +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } +#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } +#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintFormatted(const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_PROTECT() 1 +#define TEST_ABORT() return +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef __STDC_VERSION__ +#if __STDC_VERSION__ >= 199901L +#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__)) +#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway) +#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first +#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_SECOND_HELPER(first, second, ...) (second) +#endif +#endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));} +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) + + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray(UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 93b41b7b1..ff4fda03f 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,4 +1,13 @@ include(GoogleTest) -add_subdirectory(lwpa) -add_subdirectory(lwpa_timer_wraparound) +add_subdirectory(test_lwpa) +add_subdirectory(test_lwpa_timer_wraparound) + +if(WIN32 OR APPLE OR UNIX) + add_executable(test_lwpa entrypoint_non_embedded/main.c) + target_link_libraries(test_lwpa PRIVATE lib_test_lwpa) + add_test(test_lwpa test_lwpa) + + add_executable(test_lwpa_timer_wraparound entrypoint_non_embedded/main.c) + target_link_libraries(test_lwpa_timer_wraparound PRIVATE lib_test_lwpa_timer_wraparound) +endif() diff --git a/tests/unit/entrypoint_non_embedded/main.c b/tests/unit/entrypoint_non_embedded/main.c new file mode 100644 index 000000000..43c523aa7 --- /dev/null +++ b/tests/unit/entrypoint_non_embedded/main.c @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "test_main.h" + +int main(int argc, char* argv[]) +{ + return run_tests(); +} diff --git a/tests/unit/lwpa/CMakeLists.txt b/tests/unit/lwpa/CMakeLists.txt deleted file mode 100644 index b924a1124..000000000 --- a/tests/unit/lwpa/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -# test_lwpa -# Main lwpa test module, does "live" tests which use system calls of the underlying OS to ensure -# consistent behavior across platforms. - -add_executable(test_lwpa - # lwpa unit test sources - test_common.cpp - test_inet.cpp - test_log.cpp - test_mempool.cpp - test_mutex.cpp - test_netint.cpp - test_pack.cpp - test_rbtree.cpp - test_rwlock.cpp - test_signal.cpp - test_socket.cpp - test_socket_poll.cpp - test_thread.cpp - test_timer.cpp - test_uuid.cpp -) -set_target_properties(test_lwpa PROPERTIES CXX_STANDARD 14) -target_link_libraries(test_lwpa PRIVATE lwpa gmock_main) -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - target_compile_options(test_lwpa PRIVATE -Wno-format-security) -endif() -gtest_add_tests(TARGET test_lwpa TEST_LIST LWPA_TEST_LIST) - -# TODO diagnose consistent failure of these tests on the Azure Pipelines macOS hosted agent. -if(APPLE) - set(LWPA_MACOS_FAILING_TESTS SocketTest.multicast_udp SocketPollTest.udp_in) - set_tests_properties(${LWPA_MACOS_FAILING_TESTS} PROPERTIES WILL_FAIL TRUE) -endif() diff --git a/tests/unit/lwpa_timer_wraparound/CMakeLists.txt b/tests/unit/lwpa_timer_wraparound/CMakeLists.txt deleted file mode 100644 index 60d73f937..000000000 --- a/tests/unit/lwpa_timer_wraparound/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Test the lwpa_timer module against wraparound errors. -# This needs to be a separate executable because the lwpa_getms() symbol is stubbed at link time. - -add_executable(test_lwpa_timer_wraparound - test_timer_wraparound.cpp - ${LWPA_SRC}/lwpa/timer.c -) -set_target_properties(test_lwpa_timer_wraparound PROPERTIES CXX_STANDARD 14) -target_include_directories(test_lwpa_timer_wraparound PRIVATE ${LWPA_INCLUDE}) -target_link_libraries(test_lwpa_timer_wraparound PRIVATE gtest_main meekrosoft::fff) -gtest_add_tests(TARGET test_lwpa_timer_wraparound) diff --git a/tests/unit/test_lwpa/CMakeLists.txt b/tests/unit/test_lwpa/CMakeLists.txt new file mode 100644 index 000000000..b54fe4c65 --- /dev/null +++ b/tests/unit/test_lwpa/CMakeLists.txt @@ -0,0 +1,34 @@ +# test_lwpa +# Main lwpa test module, does "live" tests which use system calls of the underlying OS to ensure +# consistent behavior across platforms. + +add_library(lib_test_lwpa + # lwpa unit test sources + test_common.c +# test_inet.c +# test_log.c +# test_mempool.c +# test_mutex.c +# test_netint.c +# test_pack.c +# test_rbtree.c +# test_rwlock.c +# test_signal.c +# test_socket.c +# test_socket_poll.c +# test_thread.c +# test_timer.c +# test_uuid.c + test_main.c +) +target_include_directories(lib_test_lwpa PUBLIC ${CMAKE_CURRENT_LIST_DIR}) +target_link_libraries(lib_test_lwpa PUBLIC lwpa ThrowTheSwitch::Unity meekrosoft::fff) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_compile_options(lib_test_lwpa PRIVATE -Wno-format-security) +endif() + +# TODO diagnose consistent failure of these tests on the Azure Pipelines macOS hosted agent. +# if(APPLE) +# set(LWPA_MACOS_FAILING_TESTS SocketTest.multicast_udp SocketPollTest.udp_in) +# set_tests_properties(${LWPA_MACOS_FAILING_TESTS} PROPERTIES WILL_FAIL TRUE) +# endif() diff --git a/tests/unit/lwpa/test_common.cpp b/tests/unit/test_lwpa/test_common.c similarity index 58% rename from tests/unit/lwpa/test_common.cpp rename to tests/unit/test_lwpa/test_common.c index 169a47156..2593f0d0f 100644 --- a/tests/unit/lwpa/test_common.cpp +++ b/tests/unit/test_lwpa/test_common.c @@ -17,81 +17,81 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/common.h" -#include "gmock/gmock.h" +#include "unity.h" +#include "fff.h" #include "lwpa/netint.h" #include "lwpa/log.h" -class CommonTest : public ::testing::Test -{ -public: - MOCK_METHOD0(LogCallback, void()); -}; - // Test the LWPA_FEATURES_ALL_BUT() macro -TEST_F(CommonTest, features_all_but) +void test_lwpa_features_all_but_macro(void) { lwpa_features_t mask = LWPA_FEATURES_ALL_BUT(LWPA_FEATURE_SOCKETS); - EXPECT_TRUE(mask & LWPA_FEATURE_NETINTS); - EXPECT_TRUE(mask & LWPA_FEATURE_TIMERS); - EXPECT_TRUE(mask & LWPA_FEATURE_LOGGING); - EXPECT_FALSE(mask & LWPA_FEATURE_SOCKETS); + TEST_ASSERT(mask & LWPA_FEATURE_NETINTS); + TEST_ASSERT(mask & LWPA_FEATURE_TIMERS); + TEST_ASSERT(mask & LWPA_FEATURE_LOGGING); + TEST_ASSERT_UNLESS(mask & LWPA_FEATURE_SOCKETS); mask = LWPA_FEATURES_ALL_BUT(LWPA_FEATURE_LOGGING); - EXPECT_TRUE(mask & LWPA_FEATURE_SOCKETS); - EXPECT_TRUE(mask & LWPA_FEATURE_NETINTS); - EXPECT_TRUE(mask & LWPA_FEATURE_TIMERS); - EXPECT_FALSE(mask & LWPA_FEATURE_LOGGING); + TEST_ASSERT(mask & LWPA_FEATURE_SOCKETS); + TEST_ASSERT(mask & LWPA_FEATURE_NETINTS); + TEST_ASSERT(mask & LWPA_FEATURE_TIMERS); + TEST_ASSERT_UNLESS(mask & LWPA_FEATURE_LOGGING); } // Test multiple calls of lwpa_init() for the netint module. -TEST_F(CommonTest, netint_double_init) +void test_double_init_should_work_netint(void) { - ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_NETINTS)); - ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_NETINTS)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_NETINTS)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_NETINTS)); lwpa_deinit(LWPA_FEATURE_NETINTS); // After 2 inits and one deinit, we should still be able to make valid calls to the module. LwpaNetintInfo def_netint; - EXPECT_EQ(kLwpaErrOk, lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_netint)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_netint)); lwpa_deinit(LWPA_FEATURE_NETINTS); } // A shim from the lwpa_log module to GoogleMock. -extern "C" void log_cb(void* context, const LwpaLogStrings* strings) -{ - (void)strings; - - CommonTest* test_fixture = static_cast(context); - test_fixture->LogCallback(); -} +FAKE_VOID_FUNC(log_callback, void*, const LwpaLogStrings*); // Test multiple calls of lwpa_init() for the log module. -TEST_F(CommonTest, log_double_init) +void test_double_init_should_work_log(void) { - ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_LOGGING)); - ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_LOGGING)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_LOGGING)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_LOGGING)); LwpaLogParams params; params.action = kLwpaLogCreateHumanReadableLog; - params.log_fn = log_cb; + params.log_fn = log_callback; params.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); - params.time_fn = nullptr; - params.context = this; + params.time_fn = NULL; + params.context = NULL; - ASSERT_TRUE(lwpa_validate_log_params(¶ms)); + TEST_ASSERT_TRUE(lwpa_validate_log_params(¶ms)); - EXPECT_CALL(*this, LogCallback); lwpa_log(¶ms, LWPA_LOG_INFO, "Log message"); + TEST_ASSERT_EQUAL(log_callback_fake.call_count, 1); lwpa_deinit(LWPA_FEATURE_LOGGING); // After 2 inits and one deinit, we should still be able to use the lwpa_log() function and get // callbacks. - EXPECT_CALL(*this, LogCallback); lwpa_log(¶ms, LWPA_LOG_INFO, "Log message"); + TEST_ASSERT_EQUAL(log_callback_fake.call_count, 2); lwpa_deinit(LWPA_FEATURE_LOGGING); + + TEST_FAIL(); +} + +int run_common_tests(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_lwpa_features_all_but_macro); + RUN_TEST(test_double_init_should_work_netint); + RUN_TEST(test_double_init_should_work_log); + return UNITY_END(); } diff --git a/tests/unit/test_lwpa/test_common.h b/tests/unit/test_lwpa/test_common.h new file mode 100644 index 000000000..444ff64d5 --- /dev/null +++ b/tests/unit/test_lwpa/test_common.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _TEST_COMMON_H_ +#define _TEST_COMMON_H_ + +int run_common_tests(void); + +#endif /* _TEST_COMMON_H_ */ diff --git a/tests/unit/lwpa/test_inet.cpp b/tests/unit/test_lwpa/test_inet.cpp similarity index 100% rename from tests/unit/lwpa/test_inet.cpp rename to tests/unit/test_lwpa/test_inet.cpp diff --git a/tests/unit/lwpa/test_log.cpp b/tests/unit/test_lwpa/test_log.cpp similarity index 100% rename from tests/unit/lwpa/test_log.cpp rename to tests/unit/test_lwpa/test_log.cpp diff --git a/tests/unit/test_lwpa/test_main.c b/tests/unit/test_lwpa/test_main.c new file mode 100644 index 000000000..8a83d897f --- /dev/null +++ b/tests/unit/test_lwpa/test_main.c @@ -0,0 +1,44 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "unity.h" +#include "fff.h" +#include "test_common.h" + +DEFINE_FFF_GLOBALS; + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +int run_tests(void) +{ + int test_res; + +#define CHECK_TEST(test_func) \ + test_res = test_func(); \ + if (test_res != 0) \ + return test_res; + + CHECK_TEST(run_common_tests); +} diff --git a/tests/unit/test_lwpa/test_main.h b/tests/unit/test_lwpa/test_main.h new file mode 100644 index 000000000..da38c3503 --- /dev/null +++ b/tests/unit/test_lwpa/test_main.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _TEST_MAIN_H_ +#define _TEST_MAIN_H_ + +int run_tests(void); + +#endif /* _TEST_MAIN_H_ */ diff --git a/tests/unit/lwpa/test_mempool.cpp b/tests/unit/test_lwpa/test_mempool.cpp similarity index 100% rename from tests/unit/lwpa/test_mempool.cpp rename to tests/unit/test_lwpa/test_mempool.cpp diff --git a/tests/unit/lwpa/test_mutex.cpp b/tests/unit/test_lwpa/test_mutex.cpp similarity index 100% rename from tests/unit/lwpa/test_mutex.cpp rename to tests/unit/test_lwpa/test_mutex.cpp diff --git a/tests/unit/lwpa/test_netint.cpp b/tests/unit/test_lwpa/test_netint.cpp similarity index 100% rename from tests/unit/lwpa/test_netint.cpp rename to tests/unit/test_lwpa/test_netint.cpp diff --git a/tests/unit/lwpa/test_pack.cpp b/tests/unit/test_lwpa/test_pack.cpp similarity index 100% rename from tests/unit/lwpa/test_pack.cpp rename to tests/unit/test_lwpa/test_pack.cpp diff --git a/tests/unit/lwpa/test_rbtree.cpp b/tests/unit/test_lwpa/test_rbtree.cpp similarity index 100% rename from tests/unit/lwpa/test_rbtree.cpp rename to tests/unit/test_lwpa/test_rbtree.cpp diff --git a/tests/unit/lwpa/test_rwlock.cpp b/tests/unit/test_lwpa/test_rwlock.cpp similarity index 100% rename from tests/unit/lwpa/test_rwlock.cpp rename to tests/unit/test_lwpa/test_rwlock.cpp diff --git a/tests/unit/lwpa/test_signal.cpp b/tests/unit/test_lwpa/test_signal.cpp similarity index 100% rename from tests/unit/lwpa/test_signal.cpp rename to tests/unit/test_lwpa/test_signal.cpp diff --git a/tests/unit/lwpa/test_socket.cpp b/tests/unit/test_lwpa/test_socket.cpp similarity index 100% rename from tests/unit/lwpa/test_socket.cpp rename to tests/unit/test_lwpa/test_socket.cpp diff --git a/tests/unit/lwpa/test_socket_poll.cpp b/tests/unit/test_lwpa/test_socket_poll.cpp similarity index 100% rename from tests/unit/lwpa/test_socket_poll.cpp rename to tests/unit/test_lwpa/test_socket_poll.cpp diff --git a/tests/unit/lwpa/test_thread.cpp b/tests/unit/test_lwpa/test_thread.cpp similarity index 100% rename from tests/unit/lwpa/test_thread.cpp rename to tests/unit/test_lwpa/test_thread.cpp diff --git a/tests/unit/lwpa/test_timer.cpp b/tests/unit/test_lwpa/test_timer.cpp similarity index 100% rename from tests/unit/lwpa/test_timer.cpp rename to tests/unit/test_lwpa/test_timer.cpp diff --git a/tests/unit/lwpa/test_uuid.cpp b/tests/unit/test_lwpa/test_uuid.cpp similarity index 100% rename from tests/unit/lwpa/test_uuid.cpp rename to tests/unit/test_lwpa/test_uuid.cpp diff --git a/tests/unit/test_lwpa_timer_wraparound/CMakeLists.txt b/tests/unit/test_lwpa_timer_wraparound/CMakeLists.txt new file mode 100644 index 000000000..0e1bf0d61 --- /dev/null +++ b/tests/unit/test_lwpa_timer_wraparound/CMakeLists.txt @@ -0,0 +1,11 @@ +# Test the lwpa_timer module against wraparound errors. +# This needs to be a separate executable because the lwpa_getms() symbol is stubbed at link time. + +add_library(lib_test_lwpa_timer_wraparound + test_main.h + test_main.c + ${LWPA_SRC}/lwpa/timer.c +) +target_include_directories(lib_test_lwpa_timer_wraparound PUBLIC ${LWPA_INCLUDE} ${CMAKE_CURRENT_LIST_DIR}) +target_link_libraries(lib_test_lwpa_timer_wraparound PUBLIC ThrowTheSwitch::Unity meekrosoft::fff) +# gtest_add_tests(TARGET test_lwpa_timer_wraparound) diff --git a/tests/unit/lwpa_timer_wraparound/test_timer_wraparound.cpp b/tests/unit/test_lwpa_timer_wraparound/test_main.c similarity index 78% rename from tests/unit/lwpa_timer_wraparound/test_timer_wraparound.cpp rename to tests/unit/test_lwpa_timer_wraparound/test_main.c index 02993035d..b4810f4c5 100644 --- a/tests/unit/lwpa_timer_wraparound/test_timer_wraparound.cpp +++ b/tests/unit/test_lwpa_timer_wraparound/test_main.c @@ -18,18 +18,14 @@ ******************************************************************************/ #include "lwpa/timer.h" -#include "gtest/gtest.h" +#include "unity.h" #include "fff.h" DEFINE_FFF_GLOBALS; FAKE_VALUE_FUNC(uint32_t, lwpa_getms); -class TimerWraparoundTest : public ::testing::Test -{ -}; - -TEST_F(TimerWraparoundTest, wraparound) +void test_lwpa_timer_wraparound_works(void) { LwpaTimer t1; @@ -39,9 +35,24 @@ TEST_F(TimerWraparoundTest, wraparound) // We've wrapped around but have not exceeded the interval yet lwpa_getms_fake.return_val = 0x0f; - ASSERT_FALSE(lwpa_timer_is_expired(&t1)); - ASSERT_EQ(lwpa_timer_elapsed(&t1), 0x1fu); + TEST_ASSERT_FALSE(lwpa_timer_is_expired(&t1)); + TEST_ASSERT_EQUAL_UINT32(lwpa_timer_elapsed(&t1), 0x1fu); lwpa_getms_fake.return_val = 0x11; - ASSERT_TRUE(lwpa_timer_is_expired(&t1)); + TEST_ASSERT_TRUE(lwpa_timer_is_expired(&t1)); +} + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +int run_tests() +{ + UNITY_BEGIN(); + RUN_TEST(test_lwpa_timer_wraparound_works); + return UNITY_END(); } diff --git a/tests/unit/test_lwpa_timer_wraparound/test_main.h b/tests/unit/test_lwpa_timer_wraparound/test_main.h new file mode 100644 index 000000000..da38c3503 --- /dev/null +++ b/tests/unit/test_lwpa_timer_wraparound/test_main.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _TEST_MAIN_H_ +#define _TEST_MAIN_H_ + +int run_tests(void); + +#endif /* _TEST_MAIN_H_ */ From f05d7c0b4d10a8703f8d484fd41b0cd984c93f28 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 14 Aug 2019 17:33:10 -0500 Subject: [PATCH 096/264] Got the new test structure pretty much ironed out, now just need to finish the porting --- CMakeLists.txt | 3 + examples/netint/CMakeLists.txt | 1 + external/unity/CMakeLists.txt | 15 +- tests/CMakeLists.txt | 6 +- tests/unit/CMakeLists.txt | 60 +++- .../main.c => entrypoint/main_default.c} | 6 +- tests/unit/{test_lwpa => }/test_common.c | 37 +- tests/unit/test_inet.c | 325 ++++++++++++++++++ .../{test_lwpa/test_log.cpp => test_log.c} | 251 ++++++++------ tests/unit/test_lwpa/CMakeLists.txt | 34 -- tests/unit/test_lwpa/test_common.h | 25 -- tests/unit/test_lwpa/test_inet.cpp | 290 ---------------- tests/unit/test_lwpa/test_main.c | 44 --- tests/unit/test_lwpa/test_main.h | 25 -- .../test_lwpa_timer_wraparound/CMakeLists.txt | 11 - .../test_lwpa_timer_wraparound/test_main.h | 25 -- tests/unit/{test_lwpa => }/test_mempool.cpp | 0 tests/unit/{test_lwpa => }/test_mutex.cpp | 0 tests/unit/{test_lwpa => }/test_netint.cpp | 0 tests/unit/{test_lwpa => }/test_pack.cpp | 0 tests/unit/{test_lwpa => }/test_rbtree.cpp | 0 tests/unit/{test_lwpa => }/test_rwlock.cpp | 0 tests/unit/{test_lwpa => }/test_signal.cpp | 0 tests/unit/{test_lwpa => }/test_socket.cpp | 0 .../unit/{test_lwpa => }/test_socket_poll.cpp | 0 tests/unit/{test_lwpa => }/test_thread.cpp | 0 tests/unit/{test_lwpa => }/test_timer.cpp | 0 .../test_main.c => test_timer_wraparound.c} | 27 +- tests/unit/{test_lwpa => }/test_uuid.cpp | 0 29 files changed, 579 insertions(+), 606 deletions(-) rename tests/unit/{entrypoint_non_embedded/main.c => entrypoint/main_default.c} (89%) rename tests/unit/{test_lwpa => }/test_common.c (83%) create mode 100644 tests/unit/test_inet.c rename tests/unit/{test_lwpa/test_log.cpp => test_log.c} (61%) delete mode 100644 tests/unit/test_lwpa/CMakeLists.txt delete mode 100644 tests/unit/test_lwpa/test_common.h delete mode 100644 tests/unit/test_lwpa/test_inet.cpp delete mode 100644 tests/unit/test_lwpa/test_main.c delete mode 100644 tests/unit/test_lwpa/test_main.h delete mode 100644 tests/unit/test_lwpa_timer_wraparound/CMakeLists.txt delete mode 100644 tests/unit/test_lwpa_timer_wraparound/test_main.h rename tests/unit/{test_lwpa => }/test_mempool.cpp (100%) rename tests/unit/{test_lwpa => }/test_mutex.cpp (100%) rename tests/unit/{test_lwpa => }/test_netint.cpp (100%) rename tests/unit/{test_lwpa => }/test_pack.cpp (100%) rename tests/unit/{test_lwpa => }/test_rbtree.cpp (100%) rename tests/unit/{test_lwpa => }/test_rwlock.cpp (100%) rename tests/unit/{test_lwpa => }/test_signal.cpp (100%) rename tests/unit/{test_lwpa => }/test_socket.cpp (100%) rename tests/unit/{test_lwpa => }/test_socket_poll.cpp (100%) rename tests/unit/{test_lwpa => }/test_thread.cpp (100%) rename tests/unit/{test_lwpa => }/test_timer.cpp (100%) rename tests/unit/{test_lwpa_timer_wraparound/test_main.c => test_timer_wraparound.c} (80%) rename tests/unit/{test_lwpa => }/test_uuid.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2a26abd2..4724cd82c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,9 @@ if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) endif() endif() + # Allow folder grouping in generated IDE projects + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/tools/cmake) set(OPTION_DEFAULTS ON) else() diff --git a/examples/netint/CMakeLists.txt b/examples/netint/CMakeLists.txt index fdff24808..24581f8f3 100644 --- a/examples/netint/CMakeLists.txt +++ b/examples/netint/CMakeLists.txt @@ -4,3 +4,4 @@ add_executable(netint_example netint_example.c ) target_link_libraries(netint_example PRIVATE lwpa) +set_target_properties(netint_example PROPERTIES FOLDER examples) diff --git a/external/unity/CMakeLists.txt b/external/unity/CMakeLists.txt index 19687ba0d..3f5e2bb19 100644 --- a/external/unity/CMakeLists.txt +++ b/external/unity/CMakeLists.txt @@ -1,9 +1,16 @@ if(NOT TARGET ThrowTheSwitch::Unity) add_library(unity - unity.h - unity_internals.h - unity.c + src/unity.h + src/unity_internals.h + src/unity.c + + # The "test fixture" extension + extras/fixture/src/unity_fixture.c + ) + set_target_properties(unity PROPERTIES FOLDER tests) + target_include_directories(unity PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/src + ${CMAKE_CURRENT_LIST_DIR}/extras/fixture/src ) - target_include_directories(unity PUBLIC ${CMAKE_CURRENT_LIST_DIR}) add_library(ThrowTheSwitch::Unity ALIAS unity) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 614ae6c81..de32fa04f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,8 +3,4 @@ set(LWPA_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) set(LWPA_SRC ${CMAKE_CURRENT_LIST_DIR}/../src) -if(LWPA_TARGET_OS STREQUAL windows OR LWPA_TARGET_OS STREQUAL macos OR LWPA_TARGET_OS STREQUAL linux) - message(STATUS "Adding GoogleTest dependency...") - include(AddGoogleTest) - add_subdirectory(unit) -endif() +add_subdirectory(unit) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index ff4fda03f..008eab9d2 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,13 +1,55 @@ -include(GoogleTest) - -add_subdirectory(test_lwpa) -add_subdirectory(test_lwpa_timer_wraparound) +# lwpa unit tests. +# Most of these are "live" tests which use system calls of the underlying OS to ensure consistent +# behavior across platforms. This is intentionally contrary to normal unit testing philosophy, +# which emphasizes abstraction and separation of dependencies; in this case, what we are testing +# *is* the abstraction, so it must be done in a live-dependency environment and run on each target +# platform. if(WIN32 OR APPLE OR UNIX) - add_executable(test_lwpa entrypoint_non_embedded/main.c) - target_link_libraries(test_lwpa PRIVATE lib_test_lwpa) - add_test(test_lwpa test_lwpa) + set(LWPA_TEST_ENTRYPOINT ${CMAKE_CURRENT_LIST_DIR}/entrypoint/main_default.c) + function(lwpa_add_to_ctest target_name) + add_test(NAME ${target_name} COMMAND $ -v) + endfunction() +endif() - add_executable(test_lwpa_timer_wraparound entrypoint_non_embedded/main.c) - target_link_libraries(test_lwpa_timer_wraparound PRIVATE lib_test_lwpa_timer_wraparound) +if(WIN32) + set(LWPA_TEST_COMPILE_OPTIONS /wd4210) +elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(LWPA_TEST_COMPILE_OPTIONS -Wno-format-security) +else() + set(LWPA_TEST_COMPILE_OPTIONS "") endif() + +# Add a "live" test, which links the entire lwpa library, unmodified +function(lwpa_add_live_test target_name) + add_executable(${target_name} ${ARGN} ${LWPA_TEST_ENTRYPOINT}) + set_target_properties(${target_name} PROPERTIES FOLDER tests) + target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) + target_link_libraries(${target_name} PRIVATE lwpa ThrowTheSwitch::Unity meekrosoft::fff) + lwpa_add_to_ctest(${target_name}) +endfunction() + +# Add a "custom" test, which doesn't link the lwpa library - lwpa sources must then be selectively +# added to the target. +function(lwpa_add_custom_test target_name) + add_executable(${target_name} ${ARGN} ${LWPA_TEST_ENTRYPOINT}) + set_target_properties(${target_name} PROPERTIES FOLDER tests) + target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) + target_link_libraries(${target_name} PRIVATE ThrowTheSwitch::Unity meekrosoft::fff) + lwpa_add_to_ctest(${target_name}) +endfunction() + +# Each test builds a different executable. CTest then combines them all and runs them as one +# session. This is the way the Unity test framework nudges you to do things, and it's valuable for +# separating symbols when testing C code. + +lwpa_add_live_test(test_common test_common.c) +lwpa_add_live_test(test_inet test_inet.c) +lwpa_add_live_test(test_log test_log.c) + +lwpa_add_custom_test(test_timer_wraparound + test_timer_wraparound.c + ${LWPA_SRC}/lwpa/timer.c +) +target_include_directories(test_timer_wraparound PRIVATE ${LWPA_INCLUDE}) + diff --git a/tests/unit/entrypoint_non_embedded/main.c b/tests/unit/entrypoint/main_default.c similarity index 89% rename from tests/unit/entrypoint_non_embedded/main.c rename to tests/unit/entrypoint/main_default.c index 43c523aa7..63192dae2 100644 --- a/tests/unit/entrypoint_non_embedded/main.c +++ b/tests/unit/entrypoint/main_default.c @@ -17,9 +17,11 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "test_main.h" +#include "unity_fixture.h" + +extern void run_all_tests(void); int main(int argc, char* argv[]) { - return run_tests(); + return UnityMain(argc, argv, run_all_tests); } diff --git a/tests/unit/test_lwpa/test_common.c b/tests/unit/test_common.c similarity index 83% rename from tests/unit/test_lwpa/test_common.c rename to tests/unit/test_common.c index 2593f0d0f..3b488efae 100644 --- a/tests/unit/test_lwpa/test_common.c +++ b/tests/unit/test_common.c @@ -17,14 +17,26 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/common.h" -#include "unity.h" +#include "unity_fixture.h" #include "fff.h" #include "lwpa/netint.h" #include "lwpa/log.h" +DEFINE_FFF_GLOBALS; + +TEST_GROUP(lwpa_common); + +TEST_SETUP(lwpa_common) +{ +} + +TEST_TEAR_DOWN(lwpa_common) +{ +} + // Test the LWPA_FEATURES_ALL_BUT() macro -void test_lwpa_features_all_but_macro(void) +TEST(lwpa_common, features_all_but_macro_works) { lwpa_features_t mask = LWPA_FEATURES_ALL_BUT(LWPA_FEATURE_SOCKETS); TEST_ASSERT(mask & LWPA_FEATURE_NETINTS); @@ -40,7 +52,7 @@ void test_lwpa_features_all_but_macro(void) } // Test multiple calls of lwpa_init() for the netint module. -void test_double_init_should_work_netint(void) +TEST(lwpa_common, netint_double_init_works) { TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_NETINTS)); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_NETINTS)); @@ -54,11 +66,11 @@ void test_double_init_should_work_netint(void) lwpa_deinit(LWPA_FEATURE_NETINTS); } -// A shim from the lwpa_log module to GoogleMock. +// A shim from the lwpa_log module to fff. FAKE_VOID_FUNC(log_callback, void*, const LwpaLogStrings*); // Test multiple calls of lwpa_init() for the log module. -void test_double_init_should_work_log(void) +TEST(lwpa_common, log_double_init_works) { TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_LOGGING)); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_LOGGING)); @@ -83,15 +95,16 @@ void test_double_init_should_work_log(void) TEST_ASSERT_EQUAL(log_callback_fake.call_count, 2); lwpa_deinit(LWPA_FEATURE_LOGGING); +} - TEST_FAIL(); +TEST_GROUP_RUNNER(lwpa_common) +{ + RUN_TEST_CASE(lwpa_common, features_all_but_macro_works); + RUN_TEST_CASE(lwpa_common, netint_double_init_works); + RUN_TEST_CASE(lwpa_common, log_double_init_works); } -int run_common_tests(void) +void run_all_tests(void) { - UNITY_BEGIN(); - RUN_TEST(test_lwpa_features_all_but_macro); - RUN_TEST(test_double_init_should_work_netint); - RUN_TEST(test_double_init_should_work_log); - return UNITY_END(); + RUN_TEST_GROUP(lwpa_common); } diff --git a/tests/unit/test_inet.c b/tests/unit/test_inet.c new file mode 100644 index 000000000..ad43c012b --- /dev/null +++ b/tests/unit/test_inet.c @@ -0,0 +1,325 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/inet.h" +#include "unity_fixture.h" + +#include +#include + +TEST_GROUP(lwpa_inet); + +TEST_SETUP(lwpa_inet) +{ +} + +TEST_TEAR_DOWN(lwpa_inet) +{ +} + +// Test the LwpaIpAddr struct and macros +TEST(lwpa_inet, ipaddr_macros_work) +{ + LwpaIpAddr test_addr; + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x01020304); + TEST_ASSERT(LWPA_IP_IS_V4(&test_addr)); + TEST_ASSERT_EQUAL_UINT32(LWPA_IP_V4_ADDRESS(&test_addr), 0x01020304u); + + uint8_t v6_data[LWPA_IPV6_BYTES] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data); + TEST_ASSERT(LWPA_IP_IS_V6(&test_addr)); + TEST_ASSERT_EQUAL_UINT8_ARRAY(LWPA_IP_V6_ADDRESS(&test_addr), v6_data, LWPA_IPV6_BYTES); + + LWPA_IP_SET_INVALID(&test_addr); + TEST_ASSERT(LWPA_IP_IS_INVALID(&test_addr)); +} + +// Test the lwpa_ip_is_loopback() function +TEST(lwpa_inet, ip_is_loopback_works) +{ + LwpaIpAddr test_addr; + + // An invalid IP is not loopback + LWPA_IP_SET_INVALID(&test_addr); + TEST_ASSERT_UNLESS(lwpa_ip_is_loopback(&test_addr)); + + // Test the edges of the IPv4 loopback range + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7effffff); + TEST_ASSERT_UNLESS(lwpa_ip_is_loopback(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7f000000); + TEST_ASSERT(lwpa_ip_is_loopback(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7fffffff); + TEST_ASSERT(lwpa_ip_is_loopback(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x80000000); + TEST_ASSERT_UNLESS(lwpa_ip_is_loopback(&test_addr)); + + // Test the IPv6 loopback address + uint8_t v6_data[LWPA_IPV6_BYTES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data); + TEST_ASSERT(lwpa_ip_is_loopback(&test_addr)); + + v6_data[15] = 0; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data); + TEST_ASSERT_UNLESS(lwpa_ip_is_loopback(&test_addr)); +} + +// Test the lwpa_ip_is_multicast() function +TEST(lwpa_inet, ip_is_multicast_works) +{ + LwpaIpAddr test_addr; + + // An invalid IP is not multicast + LWPA_IP_SET_INVALID(&test_addr); + TEST_ASSERT_UNLESS(lwpa_ip_is_multicast(&test_addr)); + + // Test the edges of the IPv4 multicast range + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xdfffffff); + TEST_ASSERT_UNLESS(lwpa_ip_is_multicast(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xe0000000); + TEST_ASSERT(lwpa_ip_is_multicast(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xefffffff); + TEST_ASSERT(lwpa_ip_is_multicast(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xf0000000); + TEST_ASSERT_UNLESS(lwpa_ip_is_multicast(&test_addr)); + + LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xffffffff); + TEST_ASSERT_UNLESS(lwpa_ip_is_multicast(&test_addr)); + + // Test the edges of the IPv6 multicast range + uint8_t v6_data[LWPA_IPV6_BYTES] = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data); + TEST_ASSERT_UNLESS(lwpa_ip_is_multicast(&test_addr)); + + memcpy(v6_data, (uint8_t[]){0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, LWPA_IPV6_BYTES); + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data); + TEST_ASSERT(lwpa_ip_is_multicast(&test_addr)); + + memcpy(v6_data, + (uint8_t[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + LWPA_IPV6_BYTES); + LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data); + TEST_ASSERT(lwpa_ip_is_multicast(&test_addr)); +} + +// Just tests reflexivity of the wildcard functions, we don't rely on the wildcard address to be +// any specific value. +TEST(lwpa_inet, ip_is_wildcard_works) +{ + LwpaIpAddr test_addr; + + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &test_addr); + TEST_ASSERT(lwpa_ip_is_wildcard(&test_addr)); + + lwpa_ip_set_wildcard(kLwpaIpTypeV6, &test_addr); + TEST_ASSERT(lwpa_ip_is_wildcard(&test_addr)); +} + +// Test the lwpa_ip_equal() and lwpa_ip_cmp() functions +TEST(lwpa_inet, ip_compare_functions_work) +{ + LwpaIpAddr v4; + LWPA_IP_SET_V4_ADDRESS(&v4, 0x01020304); + + // Copied address should compare equal + LwpaIpAddr v4_copy = v4; + TEST_ASSERT(lwpa_ip_equal(&v4_copy, &v4)); + TEST_ASSERT_EQUAL_INT(0, lwpa_ip_cmp(&v4_copy, &v4)); + + LwpaIpAddr v6; + uint8_t v6_data[LWPA_IPV6_BYTES] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + LWPA_IP_SET_V6_ADDRESS(&v6, v6_data); + + // Copied address should compare equal + LwpaIpAddr v6_copy = v6; + TEST_ASSERT(lwpa_ip_equal(&v6_copy, &v6)); + TEST_ASSERT_EQUAL_INT(0, lwpa_ip_cmp(&v6_copy, &v6)); + + // The v4 and v6 should not be equal, and per the comparison algorithm the v4 should be less than + // the v6 + TEST_ASSERT_UNLESS(lwpa_ip_equal(&v4, &v6)); + TEST_ASSERT_LESS_THAN_INT(0, lwpa_ip_cmp(&v4, &v6)); + + // Further test the lwpa_ip_cmp() function, with like address types + LwpaIpAddr v4_less; + LWPA_IP_SET_V4_ADDRESS(&v4_less, 0x01020303); + + LwpaIpAddr v6_less; + uint8_t v6_data_less[LWPA_IPV6_BYTES]; + memcpy(v6_data_less, v6_data, LWPA_IPV6_BYTES); + v6_data_less[15] = 14; + LWPA_IP_SET_V6_ADDRESS(&v6_less, v6_data_less); + + TEST_ASSERT_LESS_THAN_INT(0, lwpa_ip_cmp(&v4_less, &v4)); + TEST_ASSERT_LESS_THAN_INT(0, lwpa_ip_cmp(&v6_less, &v6)); + + // Make sure there are no gotchas with 2's complement by setting high bits of addresses + LWPA_IP_SET_V4_ADDRESS(&v4, 0xffffffff); + LWPA_IP_SET_V4_ADDRESS(&v4_less, 0x0); + + TEST_ASSERT_LESS_THAN_INT(0, lwpa_ip_cmp(&v4_less, &v4)); +} + +// Test the lwpa_ip_mask_length() function +TEST(lwpa_inet, ip_mask_length_works) +{ + LwpaIpAddr test_mask; + + // Test mask: Invalid or null IP + TEST_ASSERT_EQUAL_UINT(0u, lwpa_ip_mask_length(NULL)); + LWPA_IP_SET_INVALID(&test_mask); + TEST_ASSERT_EQUAL_UINT(0u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /0, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0); + TEST_ASSERT_EQUAL_UINT(0u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /7, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xfe000000u); + TEST_ASSERT_EQUAL_UINT(7u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /25, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xffffff80u); + TEST_ASSERT_EQUAL_UINT(25u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /32, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xffffffffu); + TEST_ASSERT_EQUAL_UINT(32u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: nonzero but with leading zeroes, V4 + LWPA_IP_SET_V4_ADDRESS(&test_mask, 0x7fffffff); + TEST_ASSERT_EQUAL_UINT(0u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /0, V6 + uint8_t test_v6_val[LWPA_IPV6_BYTES] = {0}; + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val); + TEST_ASSERT_EQUAL_UINT(0u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /64, V6 + memcpy(test_v6_val, (uint8_t[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, + LWPA_IPV6_BYTES); + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val); + TEST_ASSERT_EQUAL_UINT(64u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /77, V6 + memcpy(test_v6_val, (uint8_t[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0, 0, 0, 0, 0, 0}, + LWPA_IPV6_BYTES); + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val); + TEST_ASSERT_EQUAL_UINT(77u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: /128, V6 + memcpy(test_v6_val, + (uint8_t[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + LWPA_IPV6_BYTES); + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val); + TEST_ASSERT_EQUAL_UINT(128u, lwpa_ip_mask_length(&test_mask)); + + // Test mask: nonzero but with leading zeroes, V6 + memcpy(test_v6_val, + (uint8_t[]){0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + LWPA_IPV6_BYTES); + LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val); + TEST_ASSERT_EQUAL_UINT(0u, lwpa_ip_mask_length(&test_mask)); +} + +// Test the lwpa_ip_mask_from_length() function +TEST(lwpa_inet, ip_mask_from_length_works) +{ + // Test mask: /0, V4 + LwpaIpAddr mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 0); + TEST_ASSERT(LWPA_IP_IS_V4(&mask_out)); + TEST_ASSERT_EQUAL_UINT32(LWPA_IP_V4_ADDRESS(&mask_out), 0u); + + // Test mask: /7, V4 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 7); + TEST_ASSERT(LWPA_IP_IS_V4(&mask_out)); + TEST_ASSERT_EQUAL_UINT32(LWPA_IP_V4_ADDRESS(&mask_out), 0xfe000000u); + + // Test mask: /25, V4 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 25); + TEST_ASSERT(LWPA_IP_IS_V4(&mask_out)); + TEST_ASSERT_EQUAL_UINT32(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffff80u); + + // Test mask: /32, V4 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 32); + TEST_ASSERT(LWPA_IP_IS_V4(&mask_out)); + TEST_ASSERT_EQUAL_UINT32(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffffffu); + + // Test mask: Greater than /32, V4 + // Should truncate to 32 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, UINT_MAX); + TEST_ASSERT(LWPA_IP_IS_V4(&mask_out)); + TEST_ASSERT_EQUAL_UINT32(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffffffu); + + // Test mask: /0, V6 + uint8_t v6_compare_val[LWPA_IPV6_BYTES] = {0}; + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 0); + TEST_ASSERT(LWPA_IP_IS_V6(&mask_out)); + TEST_ASSERT_EQUAL_UINT8_ARRAY(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val, LWPA_IPV6_BYTES); + + // Test mask: /64, V6 + memcpy(v6_compare_val, (uint8_t[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, + LWPA_IPV6_BYTES); + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 64); + TEST_ASSERT(LWPA_IP_IS_V6(&mask_out)); + TEST_ASSERT_EQUAL_UINT8_ARRAY(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val, LWPA_IPV6_BYTES); + + // Test mask: /77, V6 + memcpy(v6_compare_val, (uint8_t[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0, 0, 0, 0, 0, 0}, + LWPA_IPV6_BYTES); + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 77); + TEST_ASSERT(LWPA_IP_IS_V6(&mask_out)); + TEST_ASSERT_EQUAL_UINT8_ARRAY(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val, LWPA_IPV6_BYTES); + + // Test mask: /128, V6 + memcpy(v6_compare_val, + (uint8_t[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + LWPA_IPV6_BYTES); + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 128); + TEST_ASSERT(LWPA_IP_IS_V6(&mask_out)); + TEST_ASSERT_EQUAL_UINT8_ARRAY(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val, LWPA_IPV6_BYTES); + + // Test mask: Greater than /128, V6 + // Should truncate to 128 + mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, UINT_MAX); + TEST_ASSERT(LWPA_IP_IS_V6(&mask_out)); + TEST_ASSERT_EQUAL_UINT8_ARRAY(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val, LWPA_IPV6_BYTES); +} + +TEST_GROUP_RUNNER(lwpa_inet) +{ + RUN_TEST_CASE(lwpa_inet, ipaddr_macros_work); + RUN_TEST_CASE(lwpa_inet, ip_is_loopback_works); + RUN_TEST_CASE(lwpa_inet, ip_is_multicast_works); + RUN_TEST_CASE(lwpa_inet, ip_is_wildcard_works); + RUN_TEST_CASE(lwpa_inet, ip_compare_functions_work); + RUN_TEST_CASE(lwpa_inet, ip_mask_length_works); + RUN_TEST_CASE(lwpa_inet, ip_mask_from_length_works); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_inet); +} diff --git a/tests/unit/test_lwpa/test_log.cpp b/tests/unit/test_log.c similarity index 61% rename from tests/unit/test_lwpa/test_log.cpp rename to tests/unit/test_log.c index 5cffb9495..b2b5ec877 100644 --- a/tests/unit/test_lwpa/test_log.cpp +++ b/tests/unit/test_log.c @@ -17,109 +17,107 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/log.h" -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include -#include -#include -#include +#include "unity_fixture.h" +#include "fff.h" + +#include +#include +#include // Disable strcpy() warning on Windows/MSVC #ifdef _MSC_VER #pragma warning(disable : 4996) #endif -using testing::Mock; +DEFINE_FFF_GLOBALS; -class LogTest : public ::testing::Test -{ -protected: - LogTest() - { - lwpa_init(LWPA_FEATURE_LOGGING); - FillDefaultTime(cur_time); - } - ~LogTest() { lwpa_deinit(LWPA_FEATURE_LOGGING); } +// Static function prototypes +static void fill_default_time(LwpaLogTimeParams* tparams); +static void test_lwpa_vlog_helper(const char* expect_syslog_str, const char* expect_human_str, + const char* expect_raw_str, LwpaLogParams* lparams, int pri, const char* format, ...); - void TestLwpaVlogHelper(std::string expect_syslog_str, std::string expect_human_str, std::string expect_raw_str, - LwpaLogParams* lparams, int pri, const char* format, ...); +FAKE_VOID_FUNC(log_callback, void*, const LwpaLogStrings*); +FAKE_VOID_FUNC(time_callback, void*, LwpaLogTimeParams*); -public: - static void FillDefaultTime(LwpaLogTimeParams& tparams); +LwpaLogTimeParams cur_time; +LwpaLogStrings last_log_strings_received; - MOCK_METHOD3(VerifyLogCallback, void(std::string syslog_str, std::string human_str, std::string raw_str)); +static void fill_time_params(void* context, LwpaLogTimeParams* time_params) +{ + TEST_ASSERT(time_params); + *time_params = cur_time; +} - LwpaLogTimeParams cur_time; - bool time_fn_called; -}; +static void save_log_strings(void* context, const LwpaLogStrings* strings) +{ + TEST_ASSERT(strings); + last_log_strings_received = *strings; +} -extern "C" { -static void log_cb(void* context, const LwpaLogStrings* strings) +void fill_default_time(LwpaLogTimeParams* time_params) { - LogTest* lt = static_cast(context); - if (lt) - { - lt->VerifyLogCallback(strings->syslog ? strings->syslog : "", - strings->human_readable ? strings->human_readable : "", strings->raw ? strings->raw : ""); - } + time_params->year = 1970; // absolute year + time_params->month = 1; // month of the year - [1, 12] + time_params->day = 1; // day of the month - [1, 31] + time_params->hour = 0; // hours since midnight - [0, 23] + time_params->minute = 0; // minutes after the hour - [0, 59] + time_params->second = 0; // seconds after the minute - [0, 60] including leap second + time_params->msec = 0; // milliseconds after the second - [0, 999] + time_params->utc_offset = 0; // Local offset from UTC in minutes } -static void time_cb(void* context, LwpaLogTimeParams* time_params) +TEST_GROUP(lwpa_log); + +TEST_SETUP(lwpa_log) { - LogTest* lt = static_cast(context); - if (lt && time_params) - { - *time_params = lt->cur_time; - lt->time_fn_called = true; - } + lwpa_init(LWPA_FEATURE_LOGGING); + + fill_default_time(&cur_time); + + RESET_FAKE(log_callback); + RESET_FAKE(time_callback); + log_callback_fake.custom_fake = save_log_strings; + time_callback_fake.custom_fake = fill_time_params; } -} // extern "C" -void LogTest::FillDefaultTime(LwpaLogTimeParams& time_params) +TEST_TEAR_DOWN(lwpa_log) { - time_params.year = 1970; // absolute year - time_params.month = 1; // month of the year - [1, 12] - time_params.day = 1; // day of the month - [1, 31] - time_params.hour = 0; // hours since midnight - [0, 23] - time_params.minute = 0; // minutes after the hour - [0, 59] - time_params.second = 0; // seconds after the minute - [0, 60] including leap second - time_params.msec = 0; // milliseconds after the second - [0, 999] - time_params.utc_offset = 0; // Local offset from UTC in minutes + lwpa_deinit(LWPA_FEATURE_LOGGING); } // Test the LWPA_SET_LOG_MASK() and LWPA_CAN_LOG() macros -TEST_F(LogTest, log_mask) +TEST(lwpa_log, log_mask_macros_work) { // LWPA_CAN_LOG() should always return false (and not crash) on a null pointer LwpaLogParams* params_ptr = NULL; - EXPECT_FALSE(LWPA_CAN_LOG(params_ptr, LWPA_LOG_EMERG)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(params_ptr, LWPA_LOG_EMERG)); LwpaLogParams params; // Test a zero mask LWPA_SET_LOG_MASK(¶ms, 0); - EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); - EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); // Test some LOG_UPTO() values LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_UPTO(LWPA_LOG_EMERG)); - EXPECT_TRUE(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); - EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_ALERT)); - EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); + TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_ALERT)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_UPTO(LWPA_LOG_DEBUG)); - EXPECT_TRUE(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); - EXPECT_TRUE(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); + TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); + TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); // Test a weird mask with only one middle value LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_MASK(LWPA_LOG_ERR)); - EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); - EXPECT_FALSE(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); - EXPECT_TRUE(LWPA_CAN_LOG(¶ms, LWPA_LOG_ERR)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); + TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_ERR)); } // Test the lwpa_sanitize_syslog_params() function. -TEST_F(LogTest, sanitize) +TEST(lwpa_log, sanitize_syslog_params_works) { LwpaSyslogParams syslog_params; const unsigned char special_char_array[] = { @@ -134,14 +132,14 @@ TEST_F(LogTest, sanitize) syslog_params.facility = -1; lwpa_sanitize_syslog_params(&syslog_params); - ASSERT_STREQ(syslog_params.app_name, "___ABC???"); - ASSERT_STREQ(syslog_params.hostname, "___ABC???"); - ASSERT_STREQ(syslog_params.procid, "___ABC???"); - ASSERT_LT(LWPA_LOG_FAC(syslog_params.facility), LWPA_LOG_NFACILITIES); + TEST_ASSERT_EQUAL_STRING(syslog_params.app_name, "___ABC???"); + TEST_ASSERT_EQUAL_STRING(syslog_params.hostname, "___ABC???"); + TEST_ASSERT_EQUAL_STRING(syslog_params.procid, "___ABC???"); + TEST_ASSERT_LESS_THAN(LWPA_LOG_NFACILITIES, LWPA_LOG_FAC(syslog_params.facility)); } // Test the lwpa_validate_log_params() function. -TEST_F(LogTest, validate) +TEST(lwpa_log, validate_log_params_works) { LwpaLogParams lparams; const unsigned char special_char_array[] = { @@ -153,32 +151,32 @@ TEST_F(LogTest, validate) // Test some normal params lparams.action = kLwpaLogCreateSyslog; - lparams.log_fn = log_cb; - lparams.syslog_params = {0, {0}, {0}, {0}}; + lparams.log_fn = log_callback; + memset(&lparams.syslog_params, 0, sizeof(LwpaSyslogParams)); memcpy(lparams.syslog_params.app_name, special_char_array, sizeof special_char_array); lparams.log_mask = 0; - lparams.time_fn = time_cb; - lparams.context = this; + lparams.time_fn = time_callback; + lparams.context = NULL; // Make sure the validation returned true and the syslog field got sanitized - ASSERT_TRUE(lwpa_validate_log_params(&lparams)); - ASSERT_STREQ(lparams.syslog_params.app_name, "___ABC???"); + TEST_ASSERT(lwpa_validate_log_params(&lparams)); + TEST_ASSERT_EQUAL_STRING(lparams.syslog_params.app_name, "___ABC???"); // Invalid log callback - lparams.log_fn = nullptr; - ASSERT_FALSE(lwpa_validate_log_params(&lparams)); + lparams.log_fn = NULL; + TEST_ASSERT_UNLESS(lwpa_validate_log_params(&lparams)); // It's valid for time_fn to be NULL - lparams.log_fn = log_cb; - lparams.time_fn = nullptr; - ASSERT_TRUE(lwpa_validate_log_params(&lparams)); + lparams.log_fn = log_callback; + lparams.time_fn = NULL; + TEST_ASSERT(lwpa_validate_log_params(&lparams)); } // Test logging of: // - int values // - time from callback // - weird and missing value in syslog header -TEST_F(LogTest, log_intval) +TEST(lwpa_log, logging_int_values) { LwpaLogParams lparams; // A string with a non-ASCII character: "host\xC8name" @@ -188,55 +186,75 @@ TEST_F(LogTest, log_intval) char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; lparams.action = kLwpaLogCreateSyslog; - lparams.log_fn = log_cb; + lparams.log_fn = log_callback; memcpy(lparams.syslog_params.hostname, weird_hostname, sizeof weird_hostname); strcpy(lparams.syslog_params.app_name, "My_App"); lparams.syslog_params.procid[0] = '\0'; lparams.syslog_params.facility = LWPA_LOG_KERN; lparams.log_mask = 0; - lparams.time_fn = time_cb; - lparams.context = this; + lparams.time_fn = time_callback; + lparams.context = NULL; - std::string expect_syslog_str = + const char* expect_syslog_str = "<0>1 1970-01-01T00:00:00.000Z host?name My_App - - - Here are some int values: 1 42 4294967295"; - std::string expect_human_str = "1970-01-01 00:00:00.000Z Here are some int values: 1 42 4294967295"; - std::string expect_raw_str = "Here are some int values: 1 42 4294967295"; + const char* expect_human_str = "1970-01-01 00:00:00.000Z Here are some int values: 1 42 4294967295"; + const char* expect_raw_str = "Here are some int values: 1 42 4294967295"; - ASSERT_TRUE(lwpa_validate_log_params(&lparams)); + TEST_ASSERT(lwpa_validate_log_params(&lparams)); #define INTVAL_FORMAT_STR_AND_ARGS "Here are some int values: %d %d %u", 1, 42, 0xffffffffu // Try the functions that simply build the log strings - ASSERT_TRUE(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &lparams.syslog_params, + TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &lparams.syslog_params, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS)); - ASSERT_STREQ(syslog_buf, expect_syslog_str.c_str()); + TEST_ASSERT_EQUAL_STRING(syslog_buf, expect_syslog_str); - ASSERT_TRUE(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, INTVAL_FORMAT_STR_AND_ARGS)); - ASSERT_STREQ(human_buf, expect_human_str.c_str()); + TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, INTVAL_FORMAT_STR_AND_ARGS)); + TEST_ASSERT_EQUAL_STRING(human_buf, expect_human_str); // Try logging with the log mask set to 0, should not work. - ASSERT_FALSE(LWPA_CAN_LOG(&lparams, LWPA_LOG_EMERG)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, LWPA_LOG_EMERG)); lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 0); // Try logging only syslog - EXPECT_CALL(*this, VerifyLogCallback(expect_syslog_str, std::string(), expect_raw_str)); lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_EMERG); lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - Mock::VerifyAndClearExpectations(this); + // Make sure the callback was called with the syslog and raw strings, but not the human-readable + // string. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); + TEST_ASSERT(last_log_strings_received.syslog); + TEST_ASSERT_UNLESS(last_log_strings_received.human_readable); + TEST_ASSERT(last_log_strings_received.raw); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); // Try logging both lparams.action = kLwpaLogCreateBoth; - EXPECT_CALL(*this, VerifyLogCallback(expect_syslog_str, expect_human_str, expect_raw_str)); lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - Mock::VerifyAndClearExpectations(this); + // Make sure the callback was called with all three strings. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 2); + TEST_ASSERT(last_log_strings_received.syslog); + TEST_ASSERT(last_log_strings_received.human_readable); + TEST_ASSERT(last_log_strings_received.raw); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.human_readable, expect_human_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); // Try logging only human-readable lparams.action = kLwpaLogCreateHumanReadableLog; - EXPECT_CALL(*this, VerifyLogCallback(std::string(), expect_human_str, expect_raw_str)); lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - Mock::VerifyAndClearExpectations(this); + // Make sure the callback was called with the human-readable and raw strings, but not the syslog + // string. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 3); + TEST_ASSERT_UNLESS(last_log_strings_received.syslog); + TEST_ASSERT(last_log_strings_received.human_readable); + TEST_ASSERT(last_log_strings_received.raw); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.human_readable, expect_human_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); } +/* // Used by the following tests. Try using lwpa_vlog() to log various combinations of syslog and // human-readable logging. void LogTest::TestLwpaVlogHelper(std::string expect_syslog_str, std::string expect_human_str, @@ -296,20 +314,20 @@ TEST_F(LogTest, log_strval) std::string expect_human_str = "Here are some string values: hey wassup hello"; std::string expect_raw_str = expect_human_str; - ASSERT_TRUE(lwpa_validate_log_params(&lparams)); + TEST_ASSERT(lwpa_validate_log_params(&lparams)); #define STRVAL_FORMAT_STR_AND_ARGS "Here are some string values: %s %s %s", "hey", "wassup", "hello" // Try the functions that simply build the log strings - ASSERT_TRUE(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, nullptr, &lparams.syslog_params, + TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, nullptr, &lparams.syslog_params, LWPA_LOG_NOTICE, STRVAL_FORMAT_STR_AND_ARGS)); - ASSERT_STREQ(syslog_buf, expect_syslog_str.c_str()); + TEST_ASSERT_EQUAL_STRING(syslog_buf, expect_syslog_str.c_str()); - ASSERT_TRUE(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, nullptr, STRVAL_FORMAT_STR_AND_ARGS)); - ASSERT_STREQ(human_buf, expect_human_str.c_str()); + TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, nullptr, STRVAL_FORMAT_STR_AND_ARGS)); + TEST_ASSERT_EQUAL_STRING(human_buf, expect_human_str.c_str()); // Try logging with the log mask set to 0, should not work. - ASSERT_FALSE(LWPA_CAN_LOG(&lparams, LWPA_LOG_NOTICE)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, LWPA_LOG_NOTICE)); lwpa_log(&lparams, LWPA_LOG_NOTICE, STRVAL_FORMAT_STR_AND_ARGS); // Now try the actual logging using lwpa_vlog(). @@ -391,23 +409,38 @@ TEST_F(LogTest, log_maxlength) } to_log_str[i] = '\0'; - ASSERT_TRUE(lwpa_validate_log_params(&lparams)); + TEST_ASSERT(lwpa_validate_log_params(&lparams)); // We want to have a non-zero, two-digit UTC offset for the maximum length possible. cur_time.utc_offset = -720; // Try the functions that simply build the log strings - ASSERT_TRUE(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &lparams.syslog_params, + TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &lparams.syslog_params, LWPA_LOG_DEBUG, to_log_str)); - ASSERT_STREQ(syslog_buf, expect_syslog_str.c_str()); + TEST_ASSERT_EQUAL_STRING(syslog_buf, expect_syslog_str.c_str()); - ASSERT_TRUE(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, to_log_str)); - ASSERT_STREQ(human_buf, expect_human_str.c_str()); + TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, to_log_str)); + TEST_ASSERT_EQUAL_STRING(human_buf, expect_human_str.c_str()); // Try logging with the log mask set to 0, should not work. - ASSERT_FALSE(LWPA_CAN_LOG(&lparams, LWPA_LOG_DEBUG)); + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, LWPA_LOG_DEBUG)); lwpa_log(&lparams, LWPA_LOG_DEBUG, STRVAL_FORMAT_STR_AND_ARGS); // Now try the actual logging using lwpa_vlog(). lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); TestLwpaVlogHelper(expect_syslog_str, expect_human_str, expect_raw_str, &lparams, LWPA_LOG_DEBUG, to_log_str); } + +*/ + +TEST_GROUP_RUNNER(lwpa_log) +{ + RUN_TEST_CASE(lwpa_log, log_mask_macros_work); + RUN_TEST_CASE(lwpa_log, sanitize_syslog_params_works); + RUN_TEST_CASE(lwpa_log, validate_log_params_works); + RUN_TEST_CASE(lwpa_log, logging_int_values); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_log); +} diff --git a/tests/unit/test_lwpa/CMakeLists.txt b/tests/unit/test_lwpa/CMakeLists.txt deleted file mode 100644 index b54fe4c65..000000000 --- a/tests/unit/test_lwpa/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -# test_lwpa -# Main lwpa test module, does "live" tests which use system calls of the underlying OS to ensure -# consistent behavior across platforms. - -add_library(lib_test_lwpa - # lwpa unit test sources - test_common.c -# test_inet.c -# test_log.c -# test_mempool.c -# test_mutex.c -# test_netint.c -# test_pack.c -# test_rbtree.c -# test_rwlock.c -# test_signal.c -# test_socket.c -# test_socket_poll.c -# test_thread.c -# test_timer.c -# test_uuid.c - test_main.c -) -target_include_directories(lib_test_lwpa PUBLIC ${CMAKE_CURRENT_LIST_DIR}) -target_link_libraries(lib_test_lwpa PUBLIC lwpa ThrowTheSwitch::Unity meekrosoft::fff) -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - target_compile_options(lib_test_lwpa PRIVATE -Wno-format-security) -endif() - -# TODO diagnose consistent failure of these tests on the Azure Pipelines macOS hosted agent. -# if(APPLE) -# set(LWPA_MACOS_FAILING_TESTS SocketTest.multicast_udp SocketPollTest.udp_in) -# set_tests_properties(${LWPA_MACOS_FAILING_TESTS} PROPERTIES WILL_FAIL TRUE) -# endif() diff --git a/tests/unit/test_lwpa/test_common.h b/tests/unit/test_lwpa/test_common.h deleted file mode 100644 index 444ff64d5..000000000 --- a/tests/unit/test_lwpa/test_common.h +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ - -#ifndef _TEST_COMMON_H_ -#define _TEST_COMMON_H_ - -int run_common_tests(void); - -#endif /* _TEST_COMMON_H_ */ diff --git a/tests/unit/test_lwpa/test_inet.cpp b/tests/unit/test_lwpa/test_inet.cpp deleted file mode 100644 index 92866b294..000000000 --- a/tests/unit/test_lwpa/test_inet.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpa/inet.h" -#include "gtest/gtest.h" -#include -#include -#include - -class InetTest : public ::testing::Test -{ -}; - -// Test the LwpaIpAddr struct and macros -TEST_F(InetTest, addr_macros) -{ - LwpaIpAddr test_addr; - - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x01020304); - EXPECT_TRUE(LWPA_IP_IS_V4(&test_addr)); - EXPECT_EQ(LWPA_IP_V4_ADDRESS(&test_addr), 0x01020304u); - - std::array v6_data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); - EXPECT_TRUE(LWPA_IP_IS_V6(&test_addr)); - EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&test_addr), v6_data.data(), LWPA_IPV6_BYTES)); - - LWPA_IP_SET_INVALID(&test_addr); - EXPECT_TRUE(LWPA_IP_IS_INVALID(&test_addr)); -} - -// Test the lwpa_ip_is_loopback() function -TEST_F(InetTest, loopback) -{ - LwpaIpAddr test_addr; - - // An invalid IP is not loopback - LWPA_IP_SET_INVALID(&test_addr); - EXPECT_FALSE(lwpa_ip_is_loopback(&test_addr)); - - // Test the edges of the IPv4 loopback range - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7effffff); - EXPECT_FALSE(lwpa_ip_is_loopback(&test_addr)); - - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7f000000); - EXPECT_TRUE(lwpa_ip_is_loopback(&test_addr)); - - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x7fffffff); - EXPECT_TRUE(lwpa_ip_is_loopback(&test_addr)); - - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0x80000000); - EXPECT_FALSE(lwpa_ip_is_loopback(&test_addr)); - - // Test the IPv6 loopback address - std::array v6_data = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); - EXPECT_TRUE(lwpa_ip_is_loopback(&test_addr)); - - v6_data[15] = 0; - LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); - EXPECT_FALSE(lwpa_ip_is_loopback(&test_addr)); -} - -// Test the lwpa_ip_is_multicast() function -TEST_F(InetTest, multicast) -{ - LwpaIpAddr test_addr; - - // An invalid IP is not multicast - LWPA_IP_SET_INVALID(&test_addr); - EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); - - // Test the edges of the IPv4 multicast range - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xdfffffff); - EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); - - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xe0000000); - EXPECT_TRUE(lwpa_ip_is_multicast(&test_addr)); - - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xefffffff); - EXPECT_TRUE(lwpa_ip_is_multicast(&test_addr)); - - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xf0000000); - EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); - - LWPA_IP_SET_V4_ADDRESS(&test_addr, 0xffffffff); - EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); - - // Test the edges of the IPv6 multicast range - std::array v6_data = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); - EXPECT_FALSE(lwpa_ip_is_multicast(&test_addr)); - - v6_data = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); - EXPECT_TRUE(lwpa_ip_is_multicast(&test_addr)); - - v6_data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - LWPA_IP_SET_V6_ADDRESS(&test_addr, v6_data.data()); - EXPECT_TRUE(lwpa_ip_is_multicast(&test_addr)); -} - -// Just tests reflexivity of the wildcard functions, we don't rely on the wildcard address to be -// any specific value. -TEST_F(InetTest, wildcard) -{ - LwpaIpAddr test_addr; - - lwpa_ip_set_wildcard(kLwpaIpTypeV4, &test_addr); - EXPECT_TRUE(lwpa_ip_is_wildcard(&test_addr)); - - lwpa_ip_set_wildcard(kLwpaIpTypeV6, &test_addr); - EXPECT_TRUE(lwpa_ip_is_wildcard(&test_addr)); -} - -// Test the lwpa_ip_equal() and lwpa_ip_cmp() functions -TEST_F(InetTest, compare) -{ - LwpaIpAddr v4; - LWPA_IP_SET_V4_ADDRESS(&v4, 0x01020304); - - // Copied address should compare equal - LwpaIpAddr v4_copy = v4; - EXPECT_TRUE(lwpa_ip_equal(&v4_copy, &v4)); - EXPECT_EQ(0, lwpa_ip_cmp(&v4_copy, &v4)); - - LwpaIpAddr v6; - std::array v6_data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - LWPA_IP_SET_V6_ADDRESS(&v6, v6_data.data()); - - // Copied address should compare equal - LwpaIpAddr v6_copy = v6; - EXPECT_TRUE(lwpa_ip_equal(&v6_copy, &v6)); - EXPECT_EQ(0, lwpa_ip_cmp(&v6_copy, &v6)); - - // The v4 and v6 should not be equal, and per the comparison algorithm the v4 should be less than - // the v6 - EXPECT_FALSE(lwpa_ip_equal(&v4, &v6)); - EXPECT_LT(lwpa_ip_cmp(&v4, &v6), 0); - - // Further test the lwpa_ip_cmp() function, with like address types - LwpaIpAddr v4_less; - LWPA_IP_SET_V4_ADDRESS(&v4_less, 0x01020303); - - LwpaIpAddr v6_less; - auto v6_data_less = v6_data; - v6_data_less[15] = 14; - LWPA_IP_SET_V6_ADDRESS(&v6_less, v6_data_less.data()); - - EXPECT_LT(lwpa_ip_cmp(&v4_less, &v4), 0); - EXPECT_LT(lwpa_ip_cmp(&v6_less, &v6), 0); - - // Make sure there are no gotchas with 2's complement by setting high bits of addresses - LWPA_IP_SET_V4_ADDRESS(&v4, 0xffffffff); - LWPA_IP_SET_V4_ADDRESS(&v4_less, 0x0); - - EXPECT_LT(lwpa_ip_cmp(&v4_less, &v4), 0); -} - -// Test the lwpa_ip_mask_length() function -TEST_F(InetTest, mask_length) -{ - LwpaIpAddr test_mask; - - // Test mask: Invalid or null IP - EXPECT_EQ(0u, lwpa_ip_mask_length(nullptr)); - LWPA_IP_SET_INVALID(&test_mask); - EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: /0, V4 - LWPA_IP_SET_V4_ADDRESS(&test_mask, 0); - EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: /7, V4 - LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xfe000000u); - EXPECT_EQ(7u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: /25, V4 - LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xffffff80u); - EXPECT_EQ(25u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: /32, V4 - LWPA_IP_SET_V4_ADDRESS(&test_mask, 0xffffffffu); - EXPECT_EQ(32u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: nonzero but with leading zeroes, V4 - LWPA_IP_SET_V4_ADDRESS(&test_mask, 0x7fffffff); - EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: /0, V6 - std::array test_v6_val{}; - LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); - EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: /64, V6 - test_v6_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}; - LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); - EXPECT_EQ(64u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: /77, V6 - test_v6_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0, 0, 0, 0, 0, 0}; - LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); - EXPECT_EQ(77u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: /128, V6 - test_v6_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); - EXPECT_EQ(128u, lwpa_ip_mask_length(&test_mask)); - - // Test mask: nonzero but with leading zeroes, V6 - test_v6_val = {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - LWPA_IP_SET_V6_ADDRESS(&test_mask, test_v6_val.data()); - EXPECT_EQ(0u, lwpa_ip_mask_length(&test_mask)); -} - -// Test the lwpa_ip_mask_from_length() function -TEST_F(InetTest, mask_from_length) -{ - // Test mask: /0, V4 - LwpaIpAddr mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 0); - EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); - EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0u); - - // Test mask: /7, V4 - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 7); - EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); - EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0xfe000000u); - - // Test mask: /25, V4 - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 25); - EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); - EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffff80u); - - // Test mask: /32, V4 - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, 32); - EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); - EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffffffu); - - // Test mask: Greater than /32, V4 - // Should truncate to 32 - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV4, UINT_MAX); - EXPECT_TRUE(LWPA_IP_IS_V4(&mask_out)); - EXPECT_EQ(LWPA_IP_V4_ADDRESS(&mask_out), 0xffffffffu); - - // Test mask: /0, V6 - std::array v6_compare_val{}; - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 0); - EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); - EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); - - // Test mask: /64, V6 - v6_compare_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}; - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 64); - EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); - EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); - - // Test mask: /77, V6 - v6_compare_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0, 0, 0, 0, 0, 0}; - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 77); - EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); - EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); - - // Test mask: /128, V6 - v6_compare_val = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 128); - EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); - EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); - - // Test mask: Greater than /128, V6 - // Should truncate to 128 - mask_out = lwpa_ip_mask_from_length(kLwpaIpTypeV6, UINT_MAX); - EXPECT_TRUE(LWPA_IP_IS_V6(&mask_out)); - EXPECT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val.data(), LWPA_IPV6_BYTES)); -} \ No newline at end of file diff --git a/tests/unit/test_lwpa/test_main.c b/tests/unit/test_lwpa/test_main.c deleted file mode 100644 index 8a83d897f..000000000 --- a/tests/unit/test_lwpa/test_main.c +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ - -#include "unity.h" -#include "fff.h" -#include "test_common.h" - -DEFINE_FFF_GLOBALS; - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -int run_tests(void) -{ - int test_res; - -#define CHECK_TEST(test_func) \ - test_res = test_func(); \ - if (test_res != 0) \ - return test_res; - - CHECK_TEST(run_common_tests); -} diff --git a/tests/unit/test_lwpa/test_main.h b/tests/unit/test_lwpa/test_main.h deleted file mode 100644 index da38c3503..000000000 --- a/tests/unit/test_lwpa/test_main.h +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ - -#ifndef _TEST_MAIN_H_ -#define _TEST_MAIN_H_ - -int run_tests(void); - -#endif /* _TEST_MAIN_H_ */ diff --git a/tests/unit/test_lwpa_timer_wraparound/CMakeLists.txt b/tests/unit/test_lwpa_timer_wraparound/CMakeLists.txt deleted file mode 100644 index 0e1bf0d61..000000000 --- a/tests/unit/test_lwpa_timer_wraparound/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Test the lwpa_timer module against wraparound errors. -# This needs to be a separate executable because the lwpa_getms() symbol is stubbed at link time. - -add_library(lib_test_lwpa_timer_wraparound - test_main.h - test_main.c - ${LWPA_SRC}/lwpa/timer.c -) -target_include_directories(lib_test_lwpa_timer_wraparound PUBLIC ${LWPA_INCLUDE} ${CMAKE_CURRENT_LIST_DIR}) -target_link_libraries(lib_test_lwpa_timer_wraparound PUBLIC ThrowTheSwitch::Unity meekrosoft::fff) -# gtest_add_tests(TARGET test_lwpa_timer_wraparound) diff --git a/tests/unit/test_lwpa_timer_wraparound/test_main.h b/tests/unit/test_lwpa_timer_wraparound/test_main.h deleted file mode 100644 index da38c3503..000000000 --- a/tests/unit/test_lwpa_timer_wraparound/test_main.h +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ - -#ifndef _TEST_MAIN_H_ -#define _TEST_MAIN_H_ - -int run_tests(void); - -#endif /* _TEST_MAIN_H_ */ diff --git a/tests/unit/test_lwpa/test_mempool.cpp b/tests/unit/test_mempool.cpp similarity index 100% rename from tests/unit/test_lwpa/test_mempool.cpp rename to tests/unit/test_mempool.cpp diff --git a/tests/unit/test_lwpa/test_mutex.cpp b/tests/unit/test_mutex.cpp similarity index 100% rename from tests/unit/test_lwpa/test_mutex.cpp rename to tests/unit/test_mutex.cpp diff --git a/tests/unit/test_lwpa/test_netint.cpp b/tests/unit/test_netint.cpp similarity index 100% rename from tests/unit/test_lwpa/test_netint.cpp rename to tests/unit/test_netint.cpp diff --git a/tests/unit/test_lwpa/test_pack.cpp b/tests/unit/test_pack.cpp similarity index 100% rename from tests/unit/test_lwpa/test_pack.cpp rename to tests/unit/test_pack.cpp diff --git a/tests/unit/test_lwpa/test_rbtree.cpp b/tests/unit/test_rbtree.cpp similarity index 100% rename from tests/unit/test_lwpa/test_rbtree.cpp rename to tests/unit/test_rbtree.cpp diff --git a/tests/unit/test_lwpa/test_rwlock.cpp b/tests/unit/test_rwlock.cpp similarity index 100% rename from tests/unit/test_lwpa/test_rwlock.cpp rename to tests/unit/test_rwlock.cpp diff --git a/tests/unit/test_lwpa/test_signal.cpp b/tests/unit/test_signal.cpp similarity index 100% rename from tests/unit/test_lwpa/test_signal.cpp rename to tests/unit/test_signal.cpp diff --git a/tests/unit/test_lwpa/test_socket.cpp b/tests/unit/test_socket.cpp similarity index 100% rename from tests/unit/test_lwpa/test_socket.cpp rename to tests/unit/test_socket.cpp diff --git a/tests/unit/test_lwpa/test_socket_poll.cpp b/tests/unit/test_socket_poll.cpp similarity index 100% rename from tests/unit/test_lwpa/test_socket_poll.cpp rename to tests/unit/test_socket_poll.cpp diff --git a/tests/unit/test_lwpa/test_thread.cpp b/tests/unit/test_thread.cpp similarity index 100% rename from tests/unit/test_lwpa/test_thread.cpp rename to tests/unit/test_thread.cpp diff --git a/tests/unit/test_lwpa/test_timer.cpp b/tests/unit/test_timer.cpp similarity index 100% rename from tests/unit/test_lwpa/test_timer.cpp rename to tests/unit/test_timer.cpp diff --git a/tests/unit/test_lwpa_timer_wraparound/test_main.c b/tests/unit/test_timer_wraparound.c similarity index 80% rename from tests/unit/test_lwpa_timer_wraparound/test_main.c rename to tests/unit/test_timer_wraparound.c index b4810f4c5..e02eaf989 100644 --- a/tests/unit/test_lwpa_timer_wraparound/test_main.c +++ b/tests/unit/test_timer_wraparound.c @@ -18,14 +18,24 @@ ******************************************************************************/ #include "lwpa/timer.h" -#include "unity.h" +#include "unity_fixture.h" #include "fff.h" DEFINE_FFF_GLOBALS; +TEST_GROUP(lwpa_timer_wraparound); + +TEST_SETUP(lwpa_timer_wraparound) +{ +} + +TEST_TEAR_DOWN(lwpa_timer_wraparound) +{ +} + FAKE_VALUE_FUNC(uint32_t, lwpa_getms); -void test_lwpa_timer_wraparound_works(void) +TEST(lwpa_timer_wraparound, wraparound_works_as_expected) { LwpaTimer t1; @@ -42,17 +52,12 @@ void test_lwpa_timer_wraparound_works(void) TEST_ASSERT_TRUE(lwpa_timer_is_expired(&t1)); } -void setUp(void) -{ -} - -void tearDown(void) +TEST_GROUP_RUNNER(lwpa_timer_wraparound) { + RUN_TEST_CASE(lwpa_timer_wraparound, wraparound_works_as_expected); } -int run_tests() +void run_all_tests(void) { - UNITY_BEGIN(); - RUN_TEST(test_lwpa_timer_wraparound_works); - return UNITY_END(); + RUN_TEST_GROUP(lwpa_timer_wraparound); } diff --git a/tests/unit/test_lwpa/test_uuid.cpp b/tests/unit/test_uuid.cpp similarity index 100% rename from tests/unit/test_lwpa/test_uuid.cpp rename to tests/unit/test_uuid.cpp From 6c3888176fa372c63569511a3f66bb5b692791ce Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 15 Aug 2019 08:42:23 -0500 Subject: [PATCH 097/264] Making the log test better --- CMakeLists.txt | 12 ++- tests/unit/test_log.c | 212 ++++++++++++++++++++++++++++-------------- 2 files changed, 155 insertions(+), 69 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4724cd82c..be731e75e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,17 @@ cmake_minimum_required(VERSION 3.3) project(lwpa VERSION 0.3.0) -if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) +# Sometimes the seems to be some weirdness with drive letter capitalization on Windows, so do a +# case-insensitive comparision +if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) + string(TOLOWER ${PROJECT_SOURCE_DIR} PROJECT_SOURCE_DIR_LC) + string(TOLOWER ${CMAKE_SOURCE_DIR} CMAKE_SOURCE_DIR_LC) +else() + set(PROJECT_SOURCE_DIR_LC ${PROJECT_SOURCE_DIR}) + set(CMAKE_SOURCE_DIR_LC ${CMAKE_SOURCE_DIR}) +endif() + +if(PROJECT_SOURCE_DIR_LC STREQUAL CMAKE_SOURCE_DIR_LC) if (MSVC) add_compile_options(/W4) elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") diff --git a/tests/unit/test_log.c b/tests/unit/test_log.c index b2b5ec877..62fead2fe 100644 --- a/tests/unit/test_log.c +++ b/tests/unit/test_log.c @@ -172,32 +172,148 @@ TEST(lwpa_log, validate_log_params_works) TEST_ASSERT(lwpa_validate_log_params(&lparams)); } -// Test logging of: -// - int values -// - time from callback -// - weird and missing value in syslog header -TEST(lwpa_log, logging_int_values) +// Make sure the "action" member in the LwpaLogParams struct works as expected. +TEST(lwpa_log, log_action_is_honored) +{ + LwpaLogParams lparams; + lparams.action = kLwpaLogCreateSyslog; + + lparams.log_fn = log_callback; + lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); + strcpy(lparams.syslog_params.hostname, "10.101.17.38"); + strcpy(lparams.syslog_params.app_name, "My_App"); + strcpy(lparams.syslog_params.procid, "\0"); + lparams.syslog_params.facility = LWPA_LOG_KERN; + lparams.time_fn = NULL; + lparams.context = NULL; + +#define LOG_ACTION_TEST_MESSAGE "Test Message" + + const char* expect_syslog_str = "<0>1 - 10.101.17.38 My_App - - - " LOG_ACTION_TEST_MESSAGE; + const char* expect_human_str = LOG_ACTION_TEST_MESSAGE; + const char* expect_raw_str = LOG_ACTION_TEST_MESSAGE; + + // Try logging only syslog + lwpa_log(&lparams, LWPA_LOG_EMERG, "Test Message"); + // Make sure the callback was called with the syslog and raw strings, but not the human-readable + // string. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); + TEST_ASSERT(last_log_strings_received.syslog); + TEST_ASSERT_UNLESS(last_log_strings_received.human_readable); + TEST_ASSERT(last_log_strings_received.raw); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); + + // Try logging both + lparams.action = kLwpaLogCreateBoth; + lwpa_log(&lparams, LWPA_LOG_EMERG, LOG_ACTION_TEST_MESSAGE); + // Make sure the callback was called with all three strings. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 2); + TEST_ASSERT(last_log_strings_received.syslog); + TEST_ASSERT(last_log_strings_received.human_readable); + TEST_ASSERT(last_log_strings_received.raw); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.human_readable, expect_human_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); + + // Try logging only human-readable + lparams.action = kLwpaLogCreateHumanReadableLog; + lwpa_log(&lparams, LWPA_LOG_EMERG, LOG_ACTION_TEST_MESSAGE); + // Make sure the callback was called with the human-readable and raw strings, but not the syslog + // string. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 3); + TEST_ASSERT_UNLESS(last_log_strings_received.syslog); + TEST_ASSERT(last_log_strings_received.human_readable); + TEST_ASSERT(last_log_strings_received.raw); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.human_readable, expect_human_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); +} + +// Test valid, weird, and missing values in the syslog header +TEST(lwpa_log, syslog_header_is_well_formed) { LwpaLogParams lparams; + char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + // A string with a non-ASCII character: "host\xC8name" // Should be sanitized to "host?name" - const unsigned char weird_hostname[] = {0x68, 0x6f, 0x73, 0x74, 0xc8, 0x6e, 0x61, 0x6d, 0x65, 0x00}; - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; + const char weird_hostname[] = {0x68, 0x6f, 0x73, 0x74, 0xc8, 0x6e, 0x61, 0x6d, 0x65, 0x00}; + // A string with some non-printing and non-ASCII characters: "\x012\x034\xff" + const char weird_procid[] = {0x01, 0x32, 0x03, 0x34, 0xff, 0x00}; + + memcpy(lparams.syslog_params.hostname, weird_hostname, sizeof weird_hostname); + memcpy(lparams.syslog_params.procid, weird_procid, sizeof weird_procid); lparams.action = kLwpaLogCreateSyslog; lparams.log_fn = log_callback; - memcpy(lparams.syslog_params.hostname, weird_hostname, sizeof weird_hostname); strcpy(lparams.syslog_params.app_name, "My_App"); - lparams.syslog_params.procid[0] = '\0'; lparams.syslog_params.facility = LWPA_LOG_KERN; - lparams.log_mask = 0; + lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); lparams.time_fn = time_callback; lparams.context = NULL; +#define SYSLOG_HEADER_TEST_MESSAGE "Test Message" + const char* expect_syslog_str = - "<0>1 1970-01-01T00:00:00.000Z host?name My_App - - - Here are some int values: 1 42 4294967295"; - const char* expect_human_str = "1970-01-01 00:00:00.000Z Here are some int values: 1 42 4294967295"; + "<0>1 1970-01-01T00:00:00.000Z host?name My_App _2_4? - - " SYSLOG_HEADER_TEST_MESSAGE; + + TEST_ASSERT(lwpa_validate_log_params(&lparams)); + + lwpa_log(&lparams, LWPA_LOG_EMERG, LOG_ACTION_TEST_MESSAGE); + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); + + // TODO expand... +} + +TEST(lwpa_log, syslog_prival_is_correct) +{ + // TODO +} + +// Make sure the log mask member in the LwpaLogParams struct is honored properly. +TEST(lwpa_log, log_mask_is_honored) +{ + LwpaLogParams lparams; + + lparams.action = kLwpaLogCreateSyslog; + lparams.log_fn = log_callback; + memset(&lparams.syslog_params, 0, sizeof(LwpaSyslogParams)); + lparams.log_mask = 0; + lparams.time_fn = NULL; + lparams.context = NULL; + +#define LOG_MASK_TEST_MESSAGE "Test Message" + // Try logging with the log mask set to 0, should not work. + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, LWPA_LOG_EMERG)); + lwpa_log(&lparams, LWPA_LOG_EMERG, LOG_MASK_TEST_MESSAGE); + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 0); + + // Try logging with the log mask including LWPA_LOG_EMERG, should work. + lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_EMERG); + lwpa_log(&lparams, LWPA_LOG_EMERG, LOG_MASK_TEST_MESSAGE); + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); +} + +// Make sure the time header is properly present (or absent) as necessary +TEST(lwpa_log, time_header_is_well_formed) +{ +} + +/* +// Test logging of int values in the format string. +TEST(lwpa_log, formatting_int_values) +{ + LwpaLogParams lparams; + char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; + char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + + lparams.action = kLwpaLogCreateBoth; + lparams.log_fn = log_callback; + lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_EMERG); + lparams.time_fn = time_callback; + lparams.context = NULL; + const char* expect_raw_str = "Here are some int values: 1 42 4294967295"; TEST_ASSERT(lwpa_validate_log_params(&lparams)); @@ -205,20 +321,15 @@ TEST(lwpa_log, logging_int_values) #define INTVAL_FORMAT_STR_AND_ARGS "Here are some int values: %d %d %u", 1, 42, 0xffffffffu // Try the functions that simply build the log strings + // We just check to make sure the TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &lparams.syslog_params, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS)); - TEST_ASSERT_EQUAL_STRING(syslog_buf, expect_syslog_str); + TEST_ASSERT(strstr(syslog_buf, expect_raw_str)); TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, INTVAL_FORMAT_STR_AND_ARGS)); - TEST_ASSERT_EQUAL_STRING(human_buf, expect_human_str); - - // Try logging with the log mask set to 0, should not work. - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, LWPA_LOG_EMERG)); - lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 0); + TEST_ASSERT(strstr(human_buf, expect_raw_str)); // Try logging only syslog - lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_EMERG); lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); // Make sure the callback was called with the syslog and raw strings, but not the human-readable // string. @@ -254,40 +365,6 @@ TEST(lwpa_log, logging_int_values) TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); } -/* -// Used by the following tests. Try using lwpa_vlog() to log various combinations of syslog and -// human-readable logging. -void LogTest::TestLwpaVlogHelper(std::string expect_syslog_str, std::string expect_human_str, - std::string expect_raw_str, LwpaLogParams* lparams, int pri, const char* format, ...) -{ - va_list args; - va_start(args, format); - - // Try logging only syslog - lparams->action = kLwpaLogCreateSyslog; - EXPECT_CALL(*this, VerifyLogCallback(expect_syslog_str, std::string(), expect_raw_str)); - lwpa_vlog(lparams, pri, format, args); - Mock::VerifyAndClearExpectations(this); - - va_end(args); - va_start(args, format); - - // Try logging both - lparams->action = kLwpaLogCreateBoth; - EXPECT_CALL(*this, VerifyLogCallback(expect_syslog_str, expect_human_str, expect_raw_str)); - lwpa_vlog(lparams, pri, format, args); - Mock::VerifyAndClearExpectations(this); - - va_end(args); - va_start(args, format); - - // Try logging only human-readable - lparams->action = kLwpaLogCreateHumanReadableLog; - EXPECT_CALL(*this, VerifyLogCallback(std::string(), expect_human_str, expect_raw_str)); - lwpa_vlog(lparams, pri, format, args); - Mock::VerifyAndClearExpectations(this); -} - // Test logging of: // - string values // - no time @@ -295,24 +372,19 @@ void LogTest::TestLwpaVlogHelper(std::string expect_syslog_str, std::string expe TEST_F(LogTest, log_strval) { LwpaLogParams lparams; - // A string with some non-printing and non-ASCII characters: "\x012\x034\xff" - const unsigned char weird_procid[] = {0x01, 0x32, 0x03, 0x34, 0xff, 0x00}; char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; lparams.action = kLwpaLogCreateSyslog; - lparams.log_fn = log_cb; - strcpy(lparams.syslog_params.hostname, "10.101.17.38"); - memcpy(lparams.syslog_params.procid, weird_procid, sizeof weird_procid); - lparams.syslog_params.app_name[0] = '\0'; - lparams.syslog_params.facility = LWPA_LOG_LOCAL2; + lparams.log_fn = log_callback; + memset(&lparams.syslog_params, 0, sizeof(LwpaSyslogParams)); lparams.log_mask = 0; - lparams.time_fn = nullptr; - lparams.context = this; + lparams.time_fn = NULL; + lparams.context = NULL; - std::string expect_syslog_str = "<149>1 - 10.101.17.38 - _2_4? - - Here are some string values: hey wassup hello"; - std::string expect_human_str = "Here are some string values: hey wassup hello"; - std::string expect_raw_str = expect_human_str; + const char* expect_syslog_str = "<149>1 - 10.101.17.38 - _2_4? - - Here are some string values: hey wassup hello"; + const char* expect_human_str = "Here are some string values: hey wassup hello"; + const char* expect_raw_str = expect_human_str; TEST_ASSERT(lwpa_validate_log_params(&lparams)); @@ -437,7 +509,11 @@ TEST_GROUP_RUNNER(lwpa_log) RUN_TEST_CASE(lwpa_log, log_mask_macros_work); RUN_TEST_CASE(lwpa_log, sanitize_syslog_params_works); RUN_TEST_CASE(lwpa_log, validate_log_params_works); - RUN_TEST_CASE(lwpa_log, logging_int_values); + RUN_TEST_CASE(lwpa_log, log_action_is_honored); + RUN_TEST_CASE(lwpa_log, syslog_header_is_well_formed); + RUN_TEST_CASE(lwpa_log, syslog_prival_is_correct); + RUN_TEST_CASE(lwpa_log, log_mask_is_honored); + RUN_TEST_CASE(lwpa_log, time_header_is_well_formed); } void run_all_tests(void) From 8504b3eb9de6aacf6e7cc31beb9f7b01d973991f Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 15 Aug 2019 13:04:05 -0500 Subject: [PATCH 098/264] More progress on log tests --- tests/unit/test_log.c | 160 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 23 deletions(-) diff --git a/tests/unit/test_log.c b/tests/unit/test_log.c index 62fead2fe..733175955 100644 --- a/tests/unit/test_log.c +++ b/tests/unit/test_log.c @@ -20,9 +20,11 @@ #include "unity_fixture.h" #include "fff.h" +#include #include +#include +#include #include -#include // Disable strcpy() warning on Windows/MSVC #ifdef _MSC_VER @@ -31,11 +33,6 @@ DEFINE_FFF_GLOBALS; -// Static function prototypes -static void fill_default_time(LwpaLogTimeParams* tparams); -static void test_lwpa_vlog_helper(const char* expect_syslog_str, const char* expect_human_str, - const char* expect_raw_str, LwpaLogParams* lparams, int pri, const char* format, ...); - FAKE_VOID_FUNC(log_callback, void*, const LwpaLogStrings*); FAKE_VOID_FUNC(time_callback, void*, LwpaLogTimeParams*); @@ -44,17 +41,19 @@ LwpaLogStrings last_log_strings_received; static void fill_time_params(void* context, LwpaLogTimeParams* time_params) { + (void)context; TEST_ASSERT(time_params); *time_params = cur_time; } static void save_log_strings(void* context, const LwpaLogStrings* strings) { + (void)context; TEST_ASSERT(strings); last_log_strings_received = *strings; } -void fill_default_time(LwpaLogTimeParams* time_params) +static void fill_default_time(LwpaLogTimeParams* time_params) { time_params->year = 1970; // absolute year time_params->month = 1; // month of the year - [1, 12] @@ -229,6 +228,28 @@ TEST(lwpa_log, log_action_is_honored) TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); } +TEST(lwpa_log, context_pointer_is_passed_unmodified) +{ + LwpaLogParams lparams; + lparams.action = kLwpaLogCreateHumanReadableLog; + lparams.log_fn = log_callback; + memset(&lparams.syslog_params, 0, sizeof(LwpaSyslogParams)); + lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); + lparams.time_fn = NULL; + + // Test a null pointer + lparams.context = NULL; + lwpa_log(&lparams, LWPA_LOG_INFO, "Test message"); + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); + TEST_ASSERT_EQUAL_PTR(log_callback_fake.arg0_val, NULL); + + // Test a random value + lparams.context = (void*)0x01020304; + lwpa_log(&lparams, LWPA_LOG_INFO, "Test message"); + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 2); + TEST_ASSERT_EQUAL_PTR(log_callback_fake.arg0_val, 0x01020304); +} + // Test valid, weird, and missing values in the syslog header TEST(lwpa_log, syslog_header_is_well_formed) { @@ -240,13 +261,14 @@ TEST(lwpa_log, syslog_header_is_well_formed) const char weird_hostname[] = {0x68, 0x6f, 0x73, 0x74, 0xc8, 0x6e, 0x61, 0x6d, 0x65, 0x00}; // A string with some non-printing and non-ASCII characters: "\x012\x034\xff" const char weird_procid[] = {0x01, 0x32, 0x03, 0x34, 0xff, 0x00}; - - memcpy(lparams.syslog_params.hostname, weird_hostname, sizeof weird_hostname); - memcpy(lparams.syslog_params.procid, weird_procid, sizeof weird_procid); + // A string with a non-printing character: "My\x001App" + const char weird_appname[] = {0x4d, 0x79, 0x01, 0x41, 0x70, 0x70, 0x00}; lparams.action = kLwpaLogCreateSyslog; lparams.log_fn = log_callback; - strcpy(lparams.syslog_params.app_name, "My_App"); + memcpy(lparams.syslog_params.hostname, weird_hostname, sizeof weird_hostname); + memcpy(lparams.syslog_params.procid, weird_procid, sizeof weird_procid); + memcpy(lparams.syslog_params.app_name, weird_appname, sizeof weird_appname); lparams.syslog_params.facility = LWPA_LOG_KERN; lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); lparams.time_fn = time_callback; @@ -254,21 +276,75 @@ TEST(lwpa_log, syslog_header_is_well_formed) #define SYSLOG_HEADER_TEST_MESSAGE "Test Message" + // For each set of parameters, test both the lwpa_log() and lwpa_create_syslog_str() functions. +#define SYSLOG_HEADER_TEST_AND_ASSERT(time_params) \ + lwpa_log(&lparams, LWPA_LOG_EMERG, SYSLOG_HEADER_TEST_MESSAGE); \ + lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, time_params, &lparams.syslog_params, LWPA_LOG_EMERG, \ + SYSLOG_HEADER_TEST_MESSAGE); \ + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); \ + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); \ + TEST_ASSERT_EQUAL_STRING(syslog_buf, expect_syslog_str); \ + RESET_FAKE(log_callback) + + // Validate (and also sanitize) the log params + TEST_ASSERT(lwpa_validate_log_params(&lparams)); + const char* expect_syslog_str = "<0>1 1970-01-01T00:00:00.000Z host?name My_App _2_4? - - " SYSLOG_HEADER_TEST_MESSAGE; + SYSLOG_HEADER_TEST_AND_ASSERT(&cur_time); - TEST_ASSERT(lwpa_validate_log_params(&lparams)); + // Remove items from the header and make sure it still works + lparams.time_fn = NULL; + expect_syslog_str = "<0>1 - host?name My_App _2_4? - - " SYSLOG_HEADER_TEST_MESSAGE; + SYSLOG_HEADER_TEST_AND_ASSERT(NULL); - lwpa_log(&lparams, LWPA_LOG_EMERG, LOG_ACTION_TEST_MESSAGE); - TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); - TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); + lparams.time_fn = time_callback; + lparams.syslog_params.hostname[0] = '\0'; + expect_syslog_str = "<0>1 1970-01-01T00:00:00.000Z - My_App _2_4? - - " SYSLOG_HEADER_TEST_MESSAGE; + SYSLOG_HEADER_TEST_AND_ASSERT(&cur_time); + + strcpy(lparams.syslog_params.hostname, "10.101.17.38"); + lparams.syslog_params.app_name[0] = '\0'; + expect_syslog_str = "<0>1 1970-01-01T00:00:00.000Z 10.101.17.38 - _2_4? - - " SYSLOG_HEADER_TEST_MESSAGE; + SYSLOG_HEADER_TEST_AND_ASSERT(&cur_time); + + strcpy(lparams.syslog_params.app_name, "My_App"); + lparams.syslog_params.procid[0] = '\0'; + expect_syslog_str = "<0>1 1970-01-01T00:00:00.000Z 10.101.17.38 My_App - - - " SYSLOG_HEADER_TEST_MESSAGE; + SYSLOG_HEADER_TEST_AND_ASSERT(&cur_time); - // TODO expand... + // Test no values in the header + lparams.time_fn = NULL; + lparams.syslog_params.hostname[0] = '\0'; + lparams.syslog_params.app_name[0] = '\0'; + lparams.syslog_params.procid[0] = '\0'; + expect_syslog_str = "<0>1 - - - - - - " SYSLOG_HEADER_TEST_MESSAGE; + SYSLOG_HEADER_TEST_AND_ASSERT(NULL); } TEST(lwpa_log, syslog_prival_is_correct) { - // TODO + char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + LwpaSyslogParams syslog_params; + memset(&syslog_params, 0, sizeof(LwpaSyslogParams)); + +#define SYSLOG_PRIVAL_TEST_MESSAGE "Test Message" + + for (int facility = 0; facility < LWPA_LOG_NFACILITIES; ++facility) + { + syslog_params.facility = facility << 3; + for (int priority = 0; priority < 8; ++priority) + { + const char error_format[] = "Testing facility %d, priority %d"; + char error_msg[sizeof error_format + 20]; + sprintf(error_msg, error_format, facility, priority); + + TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, NULL, &syslog_params, priority, + SYSLOG_PRIVAL_TEST_MESSAGE)); + TEST_ASSERT_EQUAL(syslog_buf[0], '<'); + TEST_ASSERT_EQUAL_MESSAGE(atoi(&syslog_buf[1]), ((facility << 3) + priority), error_msg); + } + } } // Make sure the log mask member in the LwpaLogParams struct is honored properly. @@ -284,20 +360,57 @@ TEST(lwpa_log, log_mask_is_honored) lparams.context = NULL; #define LOG_MASK_TEST_MESSAGE "Test Message" + // Try logging with the log mask set to 0, should not work. - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, LWPA_LOG_EMERG)); - lwpa_log(&lparams, LWPA_LOG_EMERG, LOG_MASK_TEST_MESSAGE); + for (int pri = 0; pri < 8; ++pri) + { + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, pri)); + lwpa_log(&lparams, pri, LOG_MASK_TEST_MESSAGE); + } TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 0); - // Try logging with the log mask including LWPA_LOG_EMERG, should work. - lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_EMERG); - lwpa_log(&lparams, LWPA_LOG_EMERG, LOG_MASK_TEST_MESSAGE); - TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); + // Use the LWPA_LOG_UPTO macro to test logging below and above a given priority + for (int mask_pri = 0; mask_pri < 8; ++mask_pri) + { + lparams.log_mask = LWPA_LOG_UPTO(mask_pri); + for (int test_pri = 0; test_pri < 8; ++test_pri) + { + if (test_pri <= mask_pri) + { + TEST_ASSERT(LWPA_CAN_LOG(&lparams, test_pri)); + } + else + { + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, test_pri)); + } + lwpa_log(&lparams, test_pri, LOG_MASK_TEST_MESSAGE); + } + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, mask_pri + 1); + RESET_FAKE(log_callback); + } + + // Test some other, random log masks + lparams.log_mask = LWPA_LOG_MASK(LWPA_LOG_ALERT) | LWPA_LOG_MASK(LWPA_LOG_WARNING); + for (int test_pri = 0; test_pri < 8; ++test_pri) + { + if (test_pri == LWPA_LOG_ALERT || test_pri == LWPA_LOG_WARNING) + { + TEST_ASSERT(LWPA_CAN_LOG(&lparams, test_pri)); + } + else + { + TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, test_pri)); + } + lwpa_log(&lparams, test_pri, LOG_MASK_TEST_MESSAGE); + } + // The callback should only have been called for our two masked priorities. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 2); } // Make sure the time header is properly present (or absent) as necessary TEST(lwpa_log, time_header_is_well_formed) { + // TODO } /* @@ -510,6 +623,7 @@ TEST_GROUP_RUNNER(lwpa_log) RUN_TEST_CASE(lwpa_log, sanitize_syslog_params_works); RUN_TEST_CASE(lwpa_log, validate_log_params_works); RUN_TEST_CASE(lwpa_log, log_action_is_honored); + RUN_TEST_CASE(lwpa_log, context_pointer_is_passed_unmodified); RUN_TEST_CASE(lwpa_log, syslog_header_is_well_formed); RUN_TEST_CASE(lwpa_log, syslog_prival_is_correct); RUN_TEST_CASE(lwpa_log, log_mask_is_honored); From a7ecc8822578d3ea2afe1104e457fec3b2999906 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Thu, 15 Aug 2019 18:26:49 -0500 Subject: [PATCH 099/264] Continue test work, move some tests to integration where they belong --- include/lwpa/thread.h | 2 +- tests/CMakeLists.txt | 16 ++ tests/integration/CMakeLists.txt | 16 ++ tests/integration/entrypoint/main_default.c | 27 +++ .../mutex_integration_test.c} | 49 +--- .../rwlock_integration_test.c} | 77 +------ tests/integration/signal_integration_test.c | 61 +++++ tests/integration/test_main.c | 41 ++++ tests/integration/test_main.h | 29 +++ tests/unit/CMakeLists.txt | 21 +- .../entrypoint/main_freertos_lwip_kinetis.c | 90 ++++++++ tests/unit/test_lock.c | 117 ++++++++++ tests/unit/test_log.c | 214 ++++++++++-------- tests/unit/test_mempool.c | 160 +++++++++++++ tests/unit/test_mempool.cpp | 139 ------------ tests/unit/test_signal.cpp | 35 --- 16 files changed, 696 insertions(+), 398 deletions(-) create mode 100644 tests/integration/CMakeLists.txt create mode 100644 tests/integration/entrypoint/main_default.c rename tests/{unit/test_mutex.cpp => integration/mutex_integration_test.c} (71%) rename tests/{unit/test_rwlock.cpp => integration/rwlock_integration_test.c} (62%) create mode 100644 tests/integration/signal_integration_test.c create mode 100644 tests/integration/test_main.c create mode 100644 tests/integration/test_main.h create mode 100644 tests/unit/entrypoint/main_freertos_lwip_kinetis.c create mode 100644 tests/unit/test_lock.c create mode 100644 tests/unit/test_mempool.c delete mode 100644 tests/unit/test_mempool.cpp diff --git a/include/lwpa/thread.h b/include/lwpa/thread.h index fc3aa14ad..c3527ade7 100644 --- a/include/lwpa/thread.h +++ b/include/lwpa/thread.h @@ -38,7 +38,7 @@ typedef struct LwpaThreadParams do \ { \ (threadparamsptr)->thread_priority = LWPA_THREAD_DEFAULT_PRIORITY; \ - (threadparamsptr)->thread_stack = LWPA_THREAD_DEFAULT_STACK; \ + (threadparamsptr)->stack_size = LWPA_THREAD_DEFAULT_STACK; \ (threadparamsptr)->thread_name = LWPA_THREAD_DEFAULT_NAME; \ (threadparamsptr)->platform_data = NULL; \ } while (0) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index de32fa04f..ec8058166 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,4 +3,20 @@ set(LWPA_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) set(LWPA_SRC ${CMAKE_CURRENT_LIST_DIR}/../src) +if(WIN32 OR APPLE OR UNIX) + set(LWPA_TEST_ENTRYPOINT main_default.c) + function(lwpa_add_to_ctest target_name) + add_test(NAME ${target_name} COMMAND $ -v) + endfunction() +endif() + +if(WIN32) + set(LWPA_TEST_COMPILE_OPTIONS /wd4210) +elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(LWPA_TEST_COMPILE_OPTIONS -Wno-format-security) +else() + set(LWPA_TEST_COMPILE_OPTIONS "") +endif() + add_subdirectory(unit) +add_subdirectory(integration) diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt new file mode 100644 index 000000000..ce5c64721 --- /dev/null +++ b/tests/integration/CMakeLists.txt @@ -0,0 +1,16 @@ +# lwpa integration tests +# These are "live" tests which use multiple parts of the lwpa library. Most of what is tested here +# are the locking, threading and synchronization functions. + +add_executable(lwpa_integration_tests + signal_integration_test.c + + test_main.h + test_main.c + + entrypoint/${LWPA_TEST_ENTRYPOINT} +) +set_target_properties(lwpa_integration_tests PROPERTIES FOLDER tests) +target_compile_options(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) +target_link_libraries(lwpa_integration_tests PRIVATE lwpa ThrowTheSwitch::Unity) +lwpa_add_to_ctest(lwpa_integration_tests) diff --git a/tests/integration/entrypoint/main_default.c b/tests/integration/entrypoint/main_default.c new file mode 100644 index 000000000..63192dae2 --- /dev/null +++ b/tests/integration/entrypoint/main_default.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "unity_fixture.h" + +extern void run_all_tests(void); + +int main(int argc, char* argv[]) +{ + return UnityMain(argc, argv, run_all_tests); +} diff --git a/tests/unit/test_mutex.cpp b/tests/integration/mutex_integration_test.c similarity index 71% rename from tests/unit/test_mutex.cpp rename to tests/integration/mutex_integration_test.c index 81192702b..43061885e 100644 --- a/tests/unit/test_mutex.cpp +++ b/tests/integration/mutex_integration_test.c @@ -17,51 +17,16 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/lock.h" -#include "gtest/gtest.h" -#include -#include -#include -#include +#include "unity_fixture.h" -class MutexTest : public ::testing::Test -{ -public: - // Constants - static constexpr int kNumThreads = 10; - static constexpr int kNumIterations = 10000; - - // For thread test - int shared_var{0}; - - // For general usage - lwpa_mutex_t mutex{}; -}; - -TEST_F(MutexTest, create_destroy) -{ - // Basic creation and taking ownership. - ASSERT_TRUE(lwpa_mutex_create(&mutex)); - ASSERT_TRUE(lwpa_mutex_take(&mutex)); +#include "lwpa/thread.h" - // On Windows, take succeeds when taking a mutex again from the same thread. -#ifdef WIN32 - ASSERT_TRUE(lwpa_mutex_take(&mutex)); -#else - ASSERT_FALSE(lwpa_mutex_try_take(&mutex)); -#endif +// Constants +#define NUM_THREADS 10 +#define NUM_ITERATIONS 10000 - lwpa_mutex_give(&mutex); - - // Test the guard class - { // Mutex lock scope - lwpa::MutexGuard lock(mutex); - // Just make sure it doesn't throw - } - - // Take should fail on a destroyed mutex. - lwpa_mutex_destroy(&mutex); - ASSERT_FALSE(lwpa_mutex_take(&mutex)); -} +// The shared variable +int shared_var{0}; static void mutex_test_thread(MutexTest* fixture) { diff --git a/tests/unit/test_rwlock.cpp b/tests/integration/rwlock_integration_test.c similarity index 62% rename from tests/unit/test_rwlock.cpp rename to tests/integration/rwlock_integration_test.c index 85991318a..27f0dbac4 100644 --- a/tests/unit/test_rwlock.cpp +++ b/tests/integration/rwlock_integration_test.c @@ -17,79 +17,16 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/lock.h" -#include "gtest/gtest.h" -#include -#include -#include -#include -#include +#include "unity_fixture.h" -class RwlockTest : public ::testing::Test -{ -public: - // Constants - static const int RWLOCK_TEST_NUM_WRITE_THREADS = 10; - static const int RWLOCK_TEST_NUM_ITERATIONS = 10000; - - // For general usage - lwpa_rwlock_t rwlock; - - // For thread test - int shared_var{0}; - bool read_thread_pass{false}; -}; - -TEST_F(RwlockTest, create_destroy) -{ - // Basic creation and taking ownership. - ASSERT_TRUE(lwpa_rwlock_create(&rwlock)); - for (size_t i = 0; i < 100; ++i) - ASSERT_TRUE(lwpa_rwlock_readlock(&rwlock)); - - // Time-based functionality not implemented for now. - // auto start_time = std::chrono::high_resolution_clock::now(); - - // Write lock should fail if there are readers - ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); - - // It should wait for at least the timeout specified, minus up to one ms - // auto time_taken = - // std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); - // ASSERT_GE(time_taken.count(), 99); +#include "lwpa/thread.h" - // When there are no more readers, write lock should succeed - for (size_t i = 0; i < 100; ++i) - lwpa_rwlock_readunlock(&rwlock); - ASSERT_TRUE(lwpa_rwlock_writelock(&rwlock)); +#define NUM_WRITE_THREADS 10 +#define NUM_ITERATIONS 10000 - // On Windows, take succeeds when taking a mutex again from the same thread. -#ifdef WIN32 - ASSERT_TRUE(lwpa_rwlock_writelock(&rwlock)); -#else - ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); - ASSERT_FALSE(lwpa_rwlock_try_readlock(&rwlock)); -#endif - - lwpa_rwlock_writeunlock(&rwlock); - - // Test the guard classes - { // Read lock scope - lwpa::ReadGuard read(rwlock); - - ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); - } - { // Write lock scope - lwpa::WriteGuard write(rwlock); - -#if !WIN32 - ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); -#endif - } - - // Take should fail on a destroyed rwlock. - lwpa_rwlock_destroy(&rwlock); - ASSERT_FALSE(lwpa_rwlock_writelock(&rwlock)); -} +lwpa_rwlock_t rwlock; +int shared_var; +bool read_thread_pass; static void write_test_thread(RwlockTest* fixture) { diff --git a/tests/integration/signal_integration_test.c b/tests/integration/signal_integration_test.c new file mode 100644 index 000000000..ef3d65192 --- /dev/null +++ b/tests/integration/signal_integration_test.c @@ -0,0 +1,61 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/lock.h" +#include "unity_fixture.h" +#include "test_main.h" +#include "lwpa/thread.h" + +// For general usage +lwpa_signal_t signal; + +static void signal_test_thread(void* arg) +{ + (void)arg; + + for (size_t i = 0; i < 3; ++i) + lwpa_signal_wait(&signal); +} + +// Two threads are created. They wait on the same signal 3 times. Each post of the signal should +// wake up only one of the threads, so 6 posts should end both threads. +TEST(lwpa_integration, signal_thread_test) +{ + TEST_ASSERT_TRUE(lwpa_signal_create(&signal)); + + lwpa_thread_t threads[2]; + + LwpaThreadParams params; + LWPA_THREAD_SET_DEFAULT_PARAMS(¶ms); + + for (size_t i = 0; i < 2; ++i) + { + TEST_ASSERT_TRUE(lwpa_thread_create(&threads[i], ¶ms, signal_test_thread, NULL)); + } + + for (size_t i = 0; i < 6; ++i) + { + lwpa_thread_sleep(10); + lwpa_signal_post(&signal); + } + + for (size_t i = 0; i < 2; ++i) + TEST_ASSERT_TRUE(lwpa_thread_join(&threads[i])); + + lwpa_signal_destroy(&signal); +} diff --git a/tests/integration/test_main.c b/tests/integration/test_main.c new file mode 100644 index 000000000..46c68a208 --- /dev/null +++ b/tests/integration/test_main.c @@ -0,0 +1,41 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "unity_fixture.h" + +// HACK to get the Unity Fixture add-on to work in multiple files +const char* TEST_GROUP_lwpa_integration = "lwpa_integration"; +// TEST_GROUP(lwpa_integration); + +TEST_SETUP(lwpa_integration) +{ +} + +TEST_TEAR_DOWN(lwpa_integration) +{ +} + +TEST_GROUP_RUNNER(lwpa_integration) +{ + RUN_TEST_CASE(lwpa_integration, signal_thread_test); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_integration); +} diff --git a/tests/integration/test_main.h b/tests/integration/test_main.h new file mode 100644 index 000000000..d490bdd05 --- /dev/null +++ b/tests/integration/test_main.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#ifndef _TEST_MAIN_H_ +#define _TEST_MAIN_H_ + +/* This is a little bit of a hack around the limitations of the Unity Fixture add-on. Add some + * extern declarations for the test fixture so it can be seen in multiple files. */ + +extern const char* TEST_GROUP_lwpa_integration; +void TEST_lwpa_integration_SETUP(void); +void TEST_lwpa_integration_TEAR_DOWN(void); + +#endif /* _TEST_MAIN_H_ */ diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 008eab9d2..f6bc810a7 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -5,24 +5,9 @@ # *is* the abstraction, so it must be done in a live-dependency environment and run on each target # platform. -if(WIN32 OR APPLE OR UNIX) - set(LWPA_TEST_ENTRYPOINT ${CMAKE_CURRENT_LIST_DIR}/entrypoint/main_default.c) - function(lwpa_add_to_ctest target_name) - add_test(NAME ${target_name} COMMAND $ -v) - endfunction() -endif() - -if(WIN32) - set(LWPA_TEST_COMPILE_OPTIONS /wd4210) -elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(LWPA_TEST_COMPILE_OPTIONS -Wno-format-security) -else() - set(LWPA_TEST_COMPILE_OPTIONS "") -endif() - # Add a "live" test, which links the entire lwpa library, unmodified function(lwpa_add_live_test target_name) - add_executable(${target_name} ${ARGN} ${LWPA_TEST_ENTRYPOINT}) + add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) set_target_properties(${target_name} PROPERTIES FOLDER tests) target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) target_link_libraries(${target_name} PRIVATE lwpa ThrowTheSwitch::Unity meekrosoft::fff) @@ -32,7 +17,7 @@ endfunction() # Add a "custom" test, which doesn't link the lwpa library - lwpa sources must then be selectively # added to the target. function(lwpa_add_custom_test target_name) - add_executable(${target_name} ${ARGN} ${LWPA_TEST_ENTRYPOINT}) + add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) set_target_properties(${target_name} PROPERTIES FOLDER tests) target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) target_link_libraries(${target_name} PRIVATE ThrowTheSwitch::Unity meekrosoft::fff) @@ -45,7 +30,9 @@ endfunction() lwpa_add_live_test(test_common test_common.c) lwpa_add_live_test(test_inet test_inet.c) +lwpa_add_live_test(test_lock test_lock.c) lwpa_add_live_test(test_log test_log.c) +lwpa_add_live_test(test_mempool test_mempool.c) lwpa_add_custom_test(test_timer_wraparound test_timer_wraparound.c diff --git a/tests/unit/entrypoint/main_freertos_lwip_kinetis.c b/tests/unit/entrypoint/main_freertos_lwip_kinetis.c new file mode 100644 index 000000000..0751eeb15 --- /dev/null +++ b/tests/unit/entrypoint/main_freertos_lwip_kinetis.c @@ -0,0 +1,90 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include +#include + +#include +#include "ethernetif.h" +#include "lwip/tcpip.h" + +#include "fsl_debug_console.h" +#include "board.h" +#include "fsl_phy.h" +#include "pin_mux.h" +#include "clock_config.h" + +#include "unity_fixture.h" + +extern void run_all_tests(void); + +void main_task(void* pvParameters) +{ + const char* fake_argv[] = {"freertos_test_runner", "-v"}; + + UnityMain(2, fake_argv, run_all_tests); +} + +void main(void) +{ + ip4_addr_t fsl_netif0_ipaddr, fsl_netif0_netmask, fsl_netif0_gw; + SYSMPU_Type* base = SYSMPU; + ethernetif_config_t enet_config0; + + /* Init board hardware. */ + BOARD_InitPins(); + BOARD_BootClockRUN(); + BOARD_InitDebugConsole(); + + /* Disable MPU. */ + base->CESR &= ~SYSMPU_CESR_VLD_MASK; + + PRINTF("TCP/IP initializing...\n"); + tcpip_init(NULL, NULL); + PRINTF("TCP/IP initialized.\n"); + + IP4_ADDR(&fsl_netif0_ipaddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3); + IP4_ADDR(&fsl_netif0_netmask, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3); + IP4_ADDR(&fsl_netif0_gw, configGW_ADDR0, configGW_ADDR1, configGW_ADDR2, configGW_ADDR3); + + enet_config0.phyAddress = ENET_PHY_ADDRESS; + enet_config0.clockName = kCLOCK_CoreSysClk; + memcpy(enet_config0.macAddress, g_EnetMacAddr, sizeof g_EnetMacAddr); + + netif_add(&fsl_netif0, &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, &enet_config0, ethernetif0_init, + tcpip_input); + netif_set_default(&fsl_netif0); + netif_set_up(&fsl_netif0); + + phy_speed_t speed; + phy_duplex_t duplex; + if (kStatus_Success == PHY_GetLinkSpeedDuplex(ENET, ENET_PHY_ADDRESS, &speed, &duplex)) + { + PRINTF("Ethernet link: %s %s\n", speed == kPHY_Speed10M ? "10M" : "100M", + duplex == kPHY_HalfDuplex ? "half duplex" : "full duplex"); + } + + /* Create RTOS tasks */ + xTaskCreate(main_task, "test", 2000, NULL, 4, NULL); + vTaskStartScheduler(); + + for (;;) + { /* Infinite loop to avoid leaving the main function */ + __asm("NOP"); /* something to use as a breakpoint stop while looping */ + } +} diff --git a/tests/unit/test_lock.c b/tests/unit/test_lock.c new file mode 100644 index 000000000..9ed01c686 --- /dev/null +++ b/tests/unit/test_lock.c @@ -0,0 +1,117 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/lock.h" +#include "unity_fixture.h" + +#include + +TEST_GROUP(lwpa_lock); + +TEST_SETUP(lwpa_lock) +{ +} + +TEST_TEAR_DOWN(lwpa_lock) +{ +} + +TEST(lwpa_lock, mutex_create_and_destroy_works) +{ + lwpa_mutex_t mutex; + + // Basic creation and taking ownership. + TEST_ASSERT_TRUE(lwpa_mutex_create(&mutex)); + TEST_ASSERT_TRUE(lwpa_mutex_take(&mutex)); + + // On Windows, take succeeds when taking a mutex again from the same thread. +#ifdef WIN32 + TEST_ASSERT_TRUE(lwpa_mutex_take(&mutex)); +#else + TEST_ASSERT_FALSE(lwpa_mutex_try_take(&mutex)); +#endif + + lwpa_mutex_give(&mutex); + + // Take should fail on a destroyed mutex. + lwpa_mutex_destroy(&mutex); + TEST_ASSERT_FALSE(lwpa_mutex_take(&mutex)); +} + +TEST(lwpa_lock, rwlock_create_and_destroy_works) +{ + lwpa_rwlock_t rwlock; + + // Basic creation and taking ownership. + TEST_ASSERT_TRUE(lwpa_rwlock_create(&rwlock)); + for (size_t i = 0; i < 100; ++i) + TEST_ASSERT_TRUE(lwpa_rwlock_readlock(&rwlock)); + + // Write lock should fail if there are readers + TEST_ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); + + // When there are no more readers, write lock should succeed + for (size_t i = 0; i < 100; ++i) + lwpa_rwlock_readunlock(&rwlock); + TEST_ASSERT_TRUE(lwpa_rwlock_writelock(&rwlock)); + + // On Windows, take succeeds when taking a mutex again from the same thread. +#ifdef WIN32 + TEST_ASSERT_TRUE(lwpa_rwlock_writelock(&rwlock)); +#else + TEST_ASSERT_FALSE(lwpa_rwlock_try_writelock(&rwlock)); + TEST_ASSERT_FALSE(lwpa_rwlock_try_readlock(&rwlock)); +#endif + + lwpa_rwlock_writeunlock(&rwlock); + + // Take should fail on a destroyed rwlock. + lwpa_rwlock_destroy(&rwlock); + TEST_ASSERT_FALSE(lwpa_rwlock_writelock(&rwlock)); +} + +TEST(lwpa_lock, signal_create_and_destroy_works) +{ + lwpa_signal_t signal; + + // Basic creation. + TEST_ASSERT_TRUE(lwpa_signal_create(&signal)); + + // Signals shouldn't be created in the signaled state. + TEST_ASSERT_FALSE(lwpa_signal_poll(&signal)); + + lwpa_signal_post(&signal); + TEST_ASSERT_TRUE(lwpa_signal_wait(&signal)); + + // Take should fail on a destroyed signal. + lwpa_signal_post(&signal); + lwpa_signal_destroy(&signal); + TEST_ASSERT_FALSE(lwpa_signal_wait(&signal)); +} + +TEST_GROUP_RUNNER(lwpa_lock) +{ + RUN_TEST_CASE(lwpa_lock, mutex_create_and_destroy_works); + RUN_TEST_CASE(lwpa_lock, rwlock_create_and_destroy_works); + RUN_TEST_CASE(lwpa_lock, signal_create_and_destroy_works); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_lock); +} diff --git a/tests/unit/test_log.c b/tests/unit/test_log.c index 733175955..6e05266d2 100644 --- a/tests/unit/test_log.c +++ b/tests/unit/test_log.c @@ -108,7 +108,7 @@ TEST(lwpa_log, log_mask_macros_work) TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); - // Test a weird mask with only one middle value + // Test a weird mask with some middle values LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_MASK(LWPA_LOG_ERR)); TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); @@ -254,7 +254,7 @@ TEST(lwpa_log, context_pointer_is_passed_unmodified) TEST(lwpa_log, syslog_header_is_well_formed) { LwpaLogParams lparams; - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; // A string with a non-ASCII character: "host\xC8name" // Should be sanitized to "host?name" @@ -324,7 +324,7 @@ TEST(lwpa_log, syslog_header_is_well_formed) TEST(lwpa_log, syslog_prival_is_correct) { - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; LwpaSyslogParams syslog_params; memset(&syslog_params, 0, sizeof(LwpaSyslogParams)); @@ -410,21 +410,51 @@ TEST(lwpa_log, log_mask_is_honored) // Make sure the time header is properly present (or absent) as necessary TEST(lwpa_log, time_header_is_well_formed) { - // TODO + LwpaSyslogParams syslog_params; + static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; + + memset(&syslog_params, 0, sizeof syslog_params); + TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &syslog_params, LWPA_LOG_EMERG, + "Test Message")); + TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, "Test Message")); + + TEST_ASSERT(strstr(syslog_buf, "1970-01-01T00:00:00.000Z")); + TEST_ASSERT(strstr(human_buf, "1970-01-01 00:00:00.000Z")); + + // We test absence of the time in the syslog header in a different test, but here we test absence + // in the human-readable log string + TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, NULL, "Test Message")); + TEST_ASSERT_EQUAL_STRING(human_buf, "Test Message"); + + // Test the addition of UTC offsets + cur_time.utc_offset = 30; + TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &syslog_params, LWPA_LOG_EMERG, + "Test Message")); + TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, "Test Message")); + TEST_ASSERT(strstr(syslog_buf, "1970-01-01T00:00:00.000+00:30")); + TEST_ASSERT(strstr(human_buf, "1970-01-01 00:00:00.000+00:30")); + + cur_time.utc_offset = -120; + TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &syslog_params, LWPA_LOG_EMERG, + "Test Message")); + TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, "Test Message")); + TEST_ASSERT(strstr(syslog_buf, "1970-01-01T00:00:00.000-02:00")); + TEST_ASSERT(strstr(human_buf, "1970-01-01 00:00:00.000-02:00")); } -/* // Test logging of int values in the format string. -TEST(lwpa_log, formatting_int_values) +TEST(lwpa_log, formatting_int_values_works) { LwpaLogParams lparams; - char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; + static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; lparams.action = kLwpaLogCreateBoth; lparams.log_fn = log_callback; - lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_EMERG); - lparams.time_fn = time_callback; + memset(&lparams.syslog_params, 0, sizeof(LwpaSyslogParams)); + lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); + lparams.time_fn = NULL; lparams.context = NULL; const char* expect_raw_str = "Here are some int values: 1 42 4294967295"; @@ -442,83 +472,56 @@ TEST(lwpa_log, formatting_int_values) TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, INTVAL_FORMAT_STR_AND_ARGS)); TEST_ASSERT(strstr(human_buf, expect_raw_str)); - // Try logging only syslog + // Now test the lwpa_log function lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - // Make sure the callback was called with the syslog and raw strings, but not the human-readable - // string. + // Make sure the callback was called with all three strings, with the correct format. TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); TEST_ASSERT(last_log_strings_received.syslog); - TEST_ASSERT_UNLESS(last_log_strings_received.human_readable); - TEST_ASSERT(last_log_strings_received.raw); - TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); - TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); - - // Try logging both - lparams.action = kLwpaLogCreateBoth; - lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - // Make sure the callback was called with all three strings. - TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 2); - TEST_ASSERT(last_log_strings_received.syslog); TEST_ASSERT(last_log_strings_received.human_readable); TEST_ASSERT(last_log_strings_received.raw); - TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); - TEST_ASSERT_EQUAL_STRING(last_log_strings_received.human_readable, expect_human_str); - TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); - - // Try logging only human-readable - lparams.action = kLwpaLogCreateHumanReadableLog; - lwpa_log(&lparams, LWPA_LOG_EMERG, INTVAL_FORMAT_STR_AND_ARGS); - // Make sure the callback was called with the human-readable and raw strings, but not the syslog - // string. - TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 3); - TEST_ASSERT_UNLESS(last_log_strings_received.syslog); - TEST_ASSERT(last_log_strings_received.human_readable); - TEST_ASSERT(last_log_strings_received.raw); - TEST_ASSERT_EQUAL_STRING(last_log_strings_received.human_readable, expect_human_str); + TEST_ASSERT(strstr(last_log_strings_received.syslog, expect_raw_str)); + TEST_ASSERT(strstr(last_log_strings_received.human_readable, expect_raw_str)); TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); } -// Test logging of: -// - string values -// - no time -// - weird and missing value in syslog header -TEST_F(LogTest, log_strval) +// Test logging of string values in the format string. +TEST(lwpa_log, formatting_string_values_works) { LwpaLogParams lparams; - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; + static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; - lparams.action = kLwpaLogCreateSyslog; + lparams.action = kLwpaLogCreateBoth; lparams.log_fn = log_callback; memset(&lparams.syslog_params, 0, sizeof(LwpaSyslogParams)); - lparams.log_mask = 0; + lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); lparams.time_fn = NULL; lparams.context = NULL; - const char* expect_syslog_str = "<149>1 - 10.101.17.38 - _2_4? - - Here are some string values: hey wassup hello"; - const char* expect_human_str = "Here are some string values: hey wassup hello"; - const char* expect_raw_str = expect_human_str; + const char* expect_raw_str = "Here are some string values: hey wassup hello"; TEST_ASSERT(lwpa_validate_log_params(&lparams)); #define STRVAL_FORMAT_STR_AND_ARGS "Here are some string values: %s %s %s", "hey", "wassup", "hello" // Try the functions that simply build the log strings - TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, nullptr, &lparams.syslog_params, - LWPA_LOG_NOTICE, STRVAL_FORMAT_STR_AND_ARGS)); - TEST_ASSERT_EQUAL_STRING(syslog_buf, expect_syslog_str.c_str()); - - TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, nullptr, STRVAL_FORMAT_STR_AND_ARGS)); - TEST_ASSERT_EQUAL_STRING(human_buf, expect_human_str.c_str()); + TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, NULL, &lparams.syslog_params, LWPA_LOG_EMERG, + STRVAL_FORMAT_STR_AND_ARGS)); + TEST_ASSERT(strstr(syslog_buf, expect_raw_str)); - // Try logging with the log mask set to 0, should not work. - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, LWPA_LOG_NOTICE)); - lwpa_log(&lparams, LWPA_LOG_NOTICE, STRVAL_FORMAT_STR_AND_ARGS); + TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, NULL, STRVAL_FORMAT_STR_AND_ARGS)); + TEST_ASSERT(strstr(human_buf, expect_raw_str)); - // Now try the actual logging using lwpa_vlog(). - lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_NOTICE); - TestLwpaVlogHelper(expect_syslog_str, expect_human_str, expect_raw_str, &lparams, LWPA_LOG_NOTICE, - STRVAL_FORMAT_STR_AND_ARGS); + // Now test the lwpa_log function + lwpa_log(&lparams, LWPA_LOG_EMERG, STRVAL_FORMAT_STR_AND_ARGS); + // Make sure the callback was called with all three strings, with the correct format. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); + TEST_ASSERT(last_log_strings_received.syslog); + TEST_ASSERT(last_log_strings_received.human_readable); + TEST_ASSERT(last_log_strings_received.raw); + TEST_ASSERT(strstr(last_log_strings_received.syslog, expect_raw_str)); + TEST_ASSERT(strstr(last_log_strings_received.human_readable, expect_raw_str)); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); } // Helper to get the proper sanitized character from a loop counter for the @@ -536,22 +539,28 @@ static unsigned char get_sanitized_char(size_t i) } // Test logging a maximum length string. -TEST_F(LogTest, log_maxlength) +TEST(lwpa_log, logging_maximum_length_string_works) { LwpaLogParams lparams; - char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; + static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; + static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; - lparams.action = kLwpaLogCreateSyslog; - lparams.log_fn = log_cb; + lparams.action = kLwpaLogCreateBoth; + lparams.log_fn = log_callback; lparams.syslog_params.facility = LWPA_LOG_LOCAL7; - lparams.log_mask = 0; - lparams.time_fn = time_cb; - lparams.context = this; + lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); + lparams.time_fn = time_callback; + lparams.context = NULL; + + static char expect_syslog_str[LWPA_SYSLOG_STR_MAX_LEN]; + static char expect_human_str[LWPA_HUMAN_LOG_STR_MAX_LEN]; + static char expect_raw_str[LWPA_HUMAN_LOG_STR_MAX_LEN]; + strcpy(expect_syslog_str, "<191>1 1970-01-01T00:00:00.000-12:00 "); + strcpy(expect_human_str, "1970-01-01 00:00:00.000-12:00 "); - std::string expect_syslog_str = "<191>1 1970-01-01T00:00:00.000-12:00 "; - std::string expect_human_str = "1970-01-01 00:00:00.000-12:00 "; - std::string expect_raw_str; + size_t expect_syslog_str_pos = strlen(expect_syslog_str); + size_t expect_human_str_pos = strlen(expect_human_str); + size_t expect_raw_str_pos = 0; // Create our very long syslog header components size_t i; @@ -559,41 +568,54 @@ TEST_F(LogTest, log_maxlength) { char to_add = get_sanitized_char(i); lparams.syslog_params.hostname[i] = to_add; - expect_syslog_str.append(1, to_add); + expect_syslog_str[expect_syslog_str_pos++] = to_add; } lparams.syslog_params.hostname[i] = '\0'; - expect_syslog_str.append(" "); + expect_syslog_str[expect_syslog_str_pos++] = ' '; + + TEST_ASSERT_LESS_THAN(LWPA_SYSLOG_STR_MAX_LEN, expect_syslog_str_pos); for (i = 0; i < LWPA_LOG_APP_NAME_MAX_LEN - 1; ++i) { char to_add = get_sanitized_char(i); lparams.syslog_params.app_name[i] = to_add; - expect_syslog_str.append(1, to_add); + expect_syslog_str[expect_syslog_str_pos++] = to_add; } lparams.syslog_params.app_name[i] = '\0'; - expect_syslog_str.append(" "); + expect_syslog_str[expect_syslog_str_pos++] = ' '; + + TEST_ASSERT_LESS_THAN(LWPA_SYSLOG_STR_MAX_LEN, expect_syslog_str_pos); for (i = 0; i < LWPA_LOG_PROCID_MAX_LEN - 1; ++i) { char to_add = get_sanitized_char(i); lparams.syslog_params.procid[i] = to_add; - expect_syslog_str.append(1, to_add); + expect_syslog_str[expect_syslog_str_pos++] = to_add; } lparams.syslog_params.procid[i] = '\0'; - expect_syslog_str.append(" - - "); + strcat(expect_syslog_str, " - - "); + expect_syslog_str_pos += 5; + + TEST_ASSERT_LESS_THAN(LWPA_SYSLOG_STR_MAX_LEN, expect_syslog_str_pos); // Now build our actual log message char to_log_str[LWPA_LOG_MSG_MAX_LEN]; for (i = 0; i < LWPA_LOG_MSG_MAX_LEN - 1; ++i) { char to_add = get_sanitized_char(i); - expect_syslog_str.append(1, to_add); - expect_human_str.append(1, to_add); - expect_raw_str.append(1, to_add); + expect_syslog_str[expect_syslog_str_pos++] = to_add; + expect_human_str[expect_human_str_pos++] = to_add; + expect_raw_str[expect_raw_str_pos++] = to_add; to_log_str[i] = to_add; } + expect_syslog_str[expect_syslog_str_pos++] = '\0'; + expect_human_str[expect_human_str_pos++] = '\0'; + expect_raw_str[expect_raw_str_pos++] = '\0'; to_log_str[i] = '\0'; + TEST_ASSERT_LESS_OR_EQUAL(LWPA_SYSLOG_STR_MAX_LEN, expect_syslog_str_pos); + TEST_ASSERT_LESS_OR_EQUAL(LWPA_HUMAN_LOG_STR_MAX_LEN, expect_human_str_pos); + TEST_ASSERT(lwpa_validate_log_params(&lparams)); // We want to have a non-zero, two-digit UTC offset for the maximum length possible. cur_time.utc_offset = -720; @@ -601,22 +623,23 @@ TEST_F(LogTest, log_maxlength) // Try the functions that simply build the log strings TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &lparams.syslog_params, LWPA_LOG_DEBUG, to_log_str)); - TEST_ASSERT_EQUAL_STRING(syslog_buf, expect_syslog_str.c_str()); + TEST_ASSERT_EQUAL_STRING(syslog_buf, expect_syslog_str); TEST_ASSERT(lwpa_create_human_log_str(human_buf, LWPA_HUMAN_LOG_STR_MAX_LEN, &cur_time, to_log_str)); - TEST_ASSERT_EQUAL_STRING(human_buf, expect_human_str.c_str()); - - // Try logging with the log mask set to 0, should not work. - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, LWPA_LOG_DEBUG)); - lwpa_log(&lparams, LWPA_LOG_DEBUG, STRVAL_FORMAT_STR_AND_ARGS); + TEST_ASSERT_EQUAL_STRING(human_buf, expect_human_str); - // Now try the actual logging using lwpa_vlog(). - lparams.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); - TestLwpaVlogHelper(expect_syslog_str, expect_human_str, expect_raw_str, &lparams, LWPA_LOG_DEBUG, to_log_str); + // Now test the lwpa_log function + lwpa_log(&lparams, LWPA_LOG_DEBUG, to_log_str); + // Make sure the callback was called with all three strings, with the correct format. + TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 1); + TEST_ASSERT(last_log_strings_received.syslog); + TEST_ASSERT(last_log_strings_received.human_readable); + TEST_ASSERT(last_log_strings_received.raw); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.syslog, expect_syslog_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.human_readable, expect_human_str); + TEST_ASSERT_EQUAL_STRING(last_log_strings_received.raw, expect_raw_str); } -*/ - TEST_GROUP_RUNNER(lwpa_log) { RUN_TEST_CASE(lwpa_log, log_mask_macros_work); @@ -628,6 +651,9 @@ TEST_GROUP_RUNNER(lwpa_log) RUN_TEST_CASE(lwpa_log, syslog_prival_is_correct); RUN_TEST_CASE(lwpa_log, log_mask_is_honored); RUN_TEST_CASE(lwpa_log, time_header_is_well_formed); + RUN_TEST_CASE(lwpa_log, formatting_int_values_works); + RUN_TEST_CASE(lwpa_log, formatting_string_values_works); + RUN_TEST_CASE(lwpa_log, logging_maximum_length_string_works); } void run_all_tests(void) diff --git a/tests/unit/test_mempool.c b/tests/unit/test_mempool.c new file mode 100644 index 000000000..56fb57217 --- /dev/null +++ b/tests/unit/test_mempool.c @@ -0,0 +1,160 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/mempool.h" +#include "unity_fixture.h" + +#include +#include +#include + +#define ALLOC_TEST_MEMP_SIZE 500 +#define ALLOC_TEST_MEMP_ARR_SIZE 30 + +typedef struct TestElem +{ + int val1; + char val2; +} TestElem; + +LWPA_MEMPOOL_DEFINE(alloc_test, TestElem, ALLOC_TEST_MEMP_SIZE); +LWPA_MEMPOOL_DEFINE_ARRAY(alloc_array_test, TestElem, ALLOC_TEST_MEMP_ARR_SIZE, ALLOC_TEST_MEMP_SIZE); + +TestElem* test_arr[ALLOC_TEST_MEMP_SIZE]; +size_t index_arr[ALLOC_TEST_MEMP_SIZE]; + +static void create_shuffled_index_array(size_t* array, size_t size) +{ + for (size_t i = 0; i < size; ++i) + array[i] = i; + + for (size_t i = 0; i < size - 1; ++i) + { + size_t j = i + rand() / (RAND_MAX / (size - i) + 1); + size_t swap_val = array[j]; + array[j] = array[i]; + array[i] = swap_val; + } +} + +TEST_GROUP(lwpa_mempool); + +TEST_SETUP(lwpa_mempool) +{ + // We don't srand() for now since an entropy source is not available on all platforms. + // This results in the shuffled arrays being deterministic every test run, but that's not really + // that big of a deal. + + memset(test_arr, 0, sizeof test_arr); + memset(index_arr, 0, sizeof index_arr); +} + +TEST_TEAR_DOWN(lwpa_mempool) +{ +} + +TEST(lwpa_mempool, alloc_and_free_works) +{ + // Initialize the pool. + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_mempool_init(alloc_test)); + TEST_ASSERT_EQUAL_UINT(ALLOC_TEST_MEMP_SIZE, lwpa_mempool_size(alloc_test)); + + // Allocate the entire pool. + for (size_t i = 0; i < ALLOC_TEST_MEMP_SIZE; ++i) + { + TestElem* elem = (TestElem*)lwpa_mempool_alloc(alloc_test); + TEST_ASSERT(elem); + test_arr[i] = elem; + } + TEST_ASSERT_EQUAL_UINT(ALLOC_TEST_MEMP_SIZE, lwpa_mempool_used(alloc_test)); + + // Free the elements back in random order. + // Generate and shuffle the index array. + create_shuffled_index_array(index_arr, ALLOC_TEST_MEMP_SIZE); + for (size_t i = 0; i < ALLOC_TEST_MEMP_SIZE; ++i) + { + lwpa_mempool_free(alloc_test, test_arr[index_arr[i]]); + } + TEST_ASSERT_EQUAL_UINT(0u, lwpa_mempool_used(alloc_test)); + + // Make sure we can allocate the entire pool again. + for (size_t i = 0; i < ALLOC_TEST_MEMP_SIZE; ++i) + { + test_arr[i] = (TestElem*)lwpa_mempool_alloc(alloc_test); + TEST_ASSERT(test_arr[i]); + } +} + +TEST(lwpa_mempool, alloc_and_free_array_works) +{ + // Initialize the pool. + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_mempool_init(alloc_array_test)); + TEST_ASSERT_EQUAL_UINT(ALLOC_TEST_MEMP_SIZE, lwpa_mempool_size(alloc_array_test)); + + // Allocate the entire pool. + for (size_t i = 0; i < ALLOC_TEST_MEMP_SIZE; ++i) + { + TestElem* elem_arr = (TestElem*)lwpa_mempool_alloc(alloc_array_test); + TEST_ASSERT(elem_arr); + + // Write to each spot in the array - failure could be caught by a segfault or similar + for (size_t j = 0; j < ALLOC_TEST_MEMP_ARR_SIZE; ++j) + { + elem_arr[j].val1 = 1; + elem_arr[j].val2 = 2; + } + + test_arr[i] = elem_arr; + } + TEST_ASSERT_EQUAL_UINT(ALLOC_TEST_MEMP_SIZE, lwpa_mempool_used(alloc_array_test)); + + // Free the elements back in random order. + // Generate and shuffle the index array. + create_shuffled_index_array(index_arr, ALLOC_TEST_MEMP_SIZE); + for (size_t i = 0; i < ALLOC_TEST_MEMP_SIZE; ++i) + { + lwpa_mempool_free(alloc_array_test, test_arr[index_arr[i]]); + } + TEST_ASSERT_EQUAL_UINT(0u, lwpa_mempool_used(alloc_array_test)); + + // Make sure we can allocate the entire pool again. + for (size_t i = 0; i < ALLOC_TEST_MEMP_SIZE; ++i) + { + test_arr[i] = (TestElem*)lwpa_mempool_alloc(alloc_array_test); + + TEST_ASSERT(test_arr[i]); + + // Make sure the sentinel values we set before are still there. + for (size_t j = 0; j < ALLOC_TEST_MEMP_ARR_SIZE; ++j) + { + TEST_ASSERT_EQUAL(test_arr[i][j].val1, 1); + TEST_ASSERT_EQUAL(test_arr[i][j].val2, 2); + } + } +} + +TEST_GROUP_RUNNER(lwpa_mempool) +{ + RUN_TEST_CASE(lwpa_mempool, alloc_and_free_works); + RUN_TEST_CASE(lwpa_mempool, alloc_and_free_array_works); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_mempool); +} diff --git a/tests/unit/test_mempool.cpp b/tests/unit/test_mempool.cpp deleted file mode 100644 index b20032e48..000000000 --- a/tests/unit/test_mempool.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpa/mempool.h" -#include "gtest/gtest.h" -#include -#include -#include -#include -#include - -class MempoolTest : public ::testing::Test -{ -protected: - static constexpr size_t kAllocTestMempSize = 500; - static constexpr size_t kAllocTestMempArraySize = 30; - - struct TestElem - { - int val1; - char val2; - }; - LWPA_MEMPOOL_DEFINE(alloc_test, TestElem, kAllocTestMempSize); - LWPA_MEMPOOL_DEFINE_ARRAY(alloc_array_test, TestElem, kAllocTestMempArraySize, kAllocTestMempSize); - - std::vector test_vec; -}; - -constexpr size_t MempoolTest::kAllocTestMempSize; -constexpr size_t MempoolTest::kAllocTestMempArraySize; - -TEST_F(MempoolTest, alloc_free) -{ - // Initialize the pool. - ASSERT_EQ(kLwpaErrOk, lwpa_mempool_init(alloc_test)); - ASSERT_EQ(kAllocTestMempSize, lwpa_mempool_size(alloc_test)); - - // Allocate the entire pool. - test_vec.reserve(kAllocTestMempSize); - for (size_t i = 0; i < kAllocTestMempSize; ++i) - { - auto elem = static_cast(lwpa_mempool_alloc(alloc_test)); - ASSERT_TRUE(elem != NULL); - test_vec.push_back(elem); - } - ASSERT_EQ(kAllocTestMempSize, lwpa_mempool_used(alloc_test)); - - // Free the elements back in random order. - // Generate and shuffle the index array. - std::array free_indices; - for (size_t i = 0; i < kAllocTestMempSize; ++i) - free_indices[i] = i; - std::random_device seed; - std::default_random_engine rand(seed()); - std::shuffle(free_indices.begin(), free_indices.end(), rand); - - for (size_t i = 0; i < kAllocTestMempSize; ++i) - { - lwpa_mempool_free(alloc_test, test_vec[free_indices[i]]); - } - ASSERT_EQ(0u, lwpa_mempool_used(alloc_test)); - - // Make sure we can allocate the entire pool again. - for (size_t i = 0; i < kAllocTestMempSize; ++i) - { - test_vec[i] = static_cast(lwpa_mempool_alloc(alloc_test)); - ASSERT_TRUE(test_vec[i] != NULL); - } -} - -TEST_F(MempoolTest, alloc_free_array) -{ - // Initialize the pool. - ASSERT_EQ(kLwpaErrOk, lwpa_mempool_init(alloc_array_test)); - ASSERT_EQ(kAllocTestMempSize, lwpa_mempool_size(alloc_array_test)); - - // Allocate the entire pool. - test_vec.reserve(kAllocTestMempSize); - for (size_t i = 0; i < kAllocTestMempSize; ++i) - { - auto elem_arr = static_cast(lwpa_mempool_alloc(alloc_array_test)); - ASSERT_TRUE(elem_arr != NULL); - - // Write to each spot in the array - failure could be caught by a segfault or similar - for (size_t j = 0; j < kAllocTestMempArraySize; ++j) - { - elem_arr[j].val1 = 1; - elem_arr[j].val2 = 2; - } - - test_vec.push_back(elem_arr); - } - ASSERT_EQ(kAllocTestMempSize, lwpa_mempool_used(alloc_array_test)); - - // Free the elements back in random order. - // Generate and shuffle the index array. - std::array free_indices; - for (size_t i = 0; i < kAllocTestMempSize; ++i) - free_indices[i] = i; - std::random_device seed; - std::default_random_engine rand(seed()); - std::shuffle(free_indices.begin(), free_indices.end(), rand); - - for (size_t i = 0; i < kAllocTestMempSize; ++i) - { - lwpa_mempool_free(alloc_array_test, test_vec[free_indices[i]]); - } - ASSERT_EQ(0u, lwpa_mempool_used(alloc_array_test)); - - // Make sure we can allocate the entire pool again. - for (size_t i = 0; i < kAllocTestMempSize; ++i) - { - test_vec[i] = static_cast(lwpa_mempool_alloc(alloc_array_test)); - - // Make sure the sentinel values we set before are still there. - for (size_t j = 0; j < kAllocTestMempArraySize; ++j) - { - ASSERT_EQ(test_vec[i][j].val1, 1); - ASSERT_EQ(test_vec[i][j].val2, 2); - } - - ASSERT_TRUE(test_vec[i] != NULL); - } -} diff --git a/tests/unit/test_signal.cpp b/tests/unit/test_signal.cpp index 0a93ad9f6..c8aabbd63 100644 --- a/tests/unit/test_signal.cpp +++ b/tests/unit/test_signal.cpp @@ -24,41 +24,6 @@ #include #include -static_assert(std::ratio_less_equal::value, - "This platform does not have access to a millisecond-resolution clock. This test cannot be run."); - -class SignalTest : public ::testing::Test -{ -public: - // For general usage - lwpa_signal_t signal{}; -}; - -TEST_F(SignalTest, create_destroy) -{ - // Basic creation. - ASSERT_TRUE(lwpa_signal_create(&signal)); - - // Signals shouldn't be created in the signaled state. - ASSERT_FALSE(lwpa_signal_poll(&signal)); - - lwpa_signal_post(&signal); - ASSERT_TRUE(lwpa_signal_wait(&signal)); - - // auto start_time = std::chrono::high_resolution_clock::now(); - // // Signal wait should fail if not signaled - // ASSERT_FALSE(lwpa_signal_timed_wait(&signal, 100)); - // // It should wait for at least the timeout specified, minus up to one ms - // auto time_taken = - // std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); - // ASSERT_GE(time_taken.count(), 99); - - // Take should fail on a destroyed signal. - lwpa_signal_post(&signal); - lwpa_signal_destroy(&signal); - ASSERT_FALSE(lwpa_signal_wait(&signal)); -} - static void signal_test_thread(SignalTest* fixture) { if (fixture) From 1e7355ad7e7aea9cb06713aa0f56ff4c47a6ce0d Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 16 Aug 2019 09:43:58 -0500 Subject: [PATCH 100/264] Checking in WIP --- tests/unit/CMakeLists.txt | 1 + tests/unit/{test_netint.cpp => test_netint.c} | 59 +++++++++++-------- 2 files changed, 37 insertions(+), 23 deletions(-) rename tests/unit/{test_netint.cpp => test_netint.c} (81%) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index f6bc810a7..96d4fcb21 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -33,6 +33,7 @@ lwpa_add_live_test(test_inet test_inet.c) lwpa_add_live_test(test_lock test_lock.c) lwpa_add_live_test(test_log test_log.c) lwpa_add_live_test(test_mempool test_mempool.c) +lwpa_add_live_test(test_netint test_netint.c) lwpa_add_custom_test(test_timer_wraparound test_timer_wraparound.c diff --git a/tests/unit/test_netint.cpp b/tests/unit/test_netint.c similarity index 81% rename from tests/unit/test_netint.cpp rename to tests/unit/test_netint.c index c82eb04d1..bb6fdcb39 100644 --- a/tests/unit/test_netint.cpp +++ b/tests/unit/test_netint.c @@ -17,44 +17,46 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/netint.h" -#include "gtest/gtest.h" -#include -#include -#include -#include +#include "unity_fixture.h" -class NetintTest : public ::testing::Test +#include +#include + +static size_t num_netints; + +TEST_GROUP(lwpa_netint); + +TEST_SETUP(lwpa_netint) { -protected: - NetintTest() - { - lwpa_init(LWPA_FEATURE_NETINTS); - num_netints = lwpa_netint_get_num_interfaces(); - } - ~NetintTest() { lwpa_deinit(LWPA_FEATURE_NETINTS); } + lwpa_init(LWPA_FEATURE_NETINTS); + num_netints = lwpa_netint_get_num_interfaces(); +} - size_t num_netints{0}; -}; +TEST_TEAR_DOWN(lwpa_netint) +{ + lwpa_deinit(LWPA_FEATURE_NETINTS); +} -TEST_F(NetintTest, enumerate) +TEST(lwpa_netint, netint_enumeration_works) { - ASSERT_GT(num_netints, 0u); + TEST_ASSERT_GREATER_THAN_UINT(0u, num_netints); size_t num_defaults = 0; const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); - ASSERT_NE(netint_list, nullptr); - for (auto netint = netint_list; netint < netint_list + num_netints; ++netint) + TEST_ASSERT_NOT_NULL(netint_list); + for (const LwpaNetintInfo* netint = netint_list; netint < netint_list + num_netints; ++netint) { if (netint->is_default) ++num_defaults; - EXPECT_GT(strlen(netint->name), 0u); - EXPECT_GT(strlen(netint->friendly_name), 0u); + TEST_ASSERT_GREATER_THAN_UINT(0u, strlen(netint->name)); + TEST_ASSERT_GREATER_THAN_UINT(0u, strlen(netint->friendly_name)); } // There can be a maximum of two default interfaces: one each for IPv4 and IPv6. - EXPECT_LE(num_defaults, 2u); + TEST_ASSERT_LESS_OR_EQUAL_UINT(2u, num_defaults); } -TEST_F(NetintTest, copy) +/* +TEST(lwpa_netint, copy_interfaces_works) { // Test copying the full array auto netint_arr = std::make_unique(num_netints); @@ -139,3 +141,14 @@ TEST_F(NetintTest, ipv4_routing) EXPECT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&ext_addr, &def)); EXPECT_TRUE(def.is_default); } +*/ + +TEST_GROUP_RUNNER(lwpa_netint) +{ + RUN_TEST_CASE(lwpa_netint, netint_enumeration_works); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_netint); +} \ No newline at end of file From ea72618a5a9b0259016f9a72c3c6a83db67c656b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 16 Aug 2019 10:26:27 -0500 Subject: [PATCH 101/264] Netint and pack tests --- tests/integration/signal_integration_test.c | 2 +- tests/unit/CMakeLists.txt | 1 + tests/unit/test_netint.c | 44 ++-- tests/unit/test_pack.c | 249 ++++++++++++++++++++ tests/unit/test_pack.cpp | 225 ------------------ 5 files changed, 275 insertions(+), 246 deletions(-) create mode 100644 tests/unit/test_pack.c delete mode 100644 tests/unit/test_pack.cpp diff --git a/tests/integration/signal_integration_test.c b/tests/integration/signal_integration_test.c index ef3d65192..69f480bc1 100644 --- a/tests/integration/signal_integration_test.c +++ b/tests/integration/signal_integration_test.c @@ -22,7 +22,7 @@ #include "lwpa/thread.h" // For general usage -lwpa_signal_t signal; +static lwpa_signal_t signal; static void signal_test_thread(void* arg) { diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 96d4fcb21..505a322e6 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -34,6 +34,7 @@ lwpa_add_live_test(test_lock test_lock.c) lwpa_add_live_test(test_log test_log.c) lwpa_add_live_test(test_mempool test_mempool.c) lwpa_add_live_test(test_netint test_netint.c) +lwpa_add_live_test(test_pack test_pack.c) lwpa_add_custom_test(test_timer_wraparound test_timer_wraparound.c diff --git a/tests/unit/test_netint.c b/tests/unit/test_netint.c index bb6fdcb39..9c34b8a56 100644 --- a/tests/unit/test_netint.c +++ b/tests/unit/test_netint.c @@ -21,6 +21,7 @@ #include #include +#include static size_t num_netints; @@ -55,7 +56,7 @@ TEST(lwpa_netint, netint_enumeration_works) TEST_ASSERT_LESS_OR_EQUAL_UINT(2u, num_defaults); } -/* +/* TODO Figure out how we're gonna handle mallocing TEST(lwpa_netint, copy_interfaces_works) { // Test copying the full array @@ -66,10 +67,11 @@ TEST(lwpa_netint, copy_interfaces_works) // Make sure the array is equal to the list obtained from lwpa_netint_get_interfaces() EXPECT_EQ(0, memcmp(netint_arr.get(), lwpa_netint_get_interfaces(), num_netints)); } +*/ -TEST_F(NetintTest, default) +TEST(lwpa_netint, default_netint_is_consistent) { - ASSERT_GT(num_netints, 0u); + TEST_ASSERT_GREATER_THAN_UINT(0u, num_netints); LwpaNetintInfo def_v4; LwpaNetintInfo def_v6; @@ -81,74 +83,76 @@ TEST_F(NetintTest, default) if (have_default_v4) { - EXPECT_TRUE(def_v4.is_default); + TEST_ASSERT(def_v4.is_default); } if (have_default_v6) { - EXPECT_TRUE(def_v6.is_default); + TEST_ASSERT(def_v6.is_default); } const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); - ASSERT_NE(netint_list, nullptr); - for (auto netint = netint_list; netint < netint_list + num_netints; ++netint) + TEST_ASSERT_NOT_NULL(netint_list); + for (const LwpaNetintInfo* netint = netint_list; netint < netint_list + num_netints; ++netint) { if (netint->is_default) { if (netint->addr.type == kLwpaIpTypeV4) { - EXPECT_EQ(0, memcmp(netint, &def_v4, sizeof def_v4)); + TEST_ASSERT_EQUAL_MEMORY(netint, &def_v4, sizeof def_v4); } else if (netint->addr.type == kLwpaIpTypeV6) { - EXPECT_EQ(0, memcmp(netint, &def_v6, sizeof def_v6)); + TEST_ASSERT_EQUAL_MEMORY(netint, &def_v6, sizeof def_v6); } } } } -TEST_F(NetintTest, ipv4_routing) +TEST(lwpa_netint, get_interface_for_dest_works_ipv4) { - ASSERT_GT(num_netints, 0u); + TEST_ASSERT_GREATER_THAN_UINT(0u, num_netints); const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); - ASSERT_NE(netint_list, nullptr); + TEST_ASSERT_NOT_NULL(netint_list); // For each normally routable (non-loopback, non-link-local) network interface, check to make sure // that lwpa_netint_get_interface_for_dest() resolves to that interface when asked for a route to // the interface address itself. - for (auto netint = netint_list; netint < netint_list + num_netints; ++netint) + for (const LwpaNetintInfo* netint = netint_list; netint < netint_list + num_netints; ++netint) { if (!LWPA_IP_IS_V4(&netint->addr) || lwpa_ip_is_loopback(&netint->addr) || lwpa_ip_is_link_local(&netint->addr)) continue; LwpaIpAddr test_addr = netint->addr; LwpaNetintInfo netint_res; - ASSERT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&test_addr, &netint_res)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&test_addr, &netint_res)); // Put addresses in print form to test meaningful information in case of test failure char test_addr_str[LWPA_INET6_ADDRSTRLEN]; char result_str[LWPA_INET6_ADDRSTRLEN]; lwpa_inet_ntop(&test_addr, test_addr_str, LWPA_INET6_ADDRSTRLEN); lwpa_inet_ntop(&netint_res.addr, result_str, LWPA_INET6_ADDRSTRLEN); + char test_msg[150]; + snprintf(test_msg, 150, "Address tried: %s, interface returned: %s", test_addr_str, result_str); - EXPECT_TRUE(lwpa_ip_equal(&netint_res.addr, &netint->addr)) - << "Address tried: " << test_addr_str << ", interface returned: " << result_str; + TEST_ASSERT_TRUE_MESSAGE(lwpa_ip_equal(&netint_res.addr, &netint->addr), test_msg); } LwpaIpAddr ext_addr; LWPA_IP_SET_V4_ADDRESS(&ext_addr, 0xc8dc0302); // 200.220.3.2 LwpaNetintInfo def; - EXPECT_EQ(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&ext_addr, &def)); - EXPECT_TRUE(def.is_default); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&ext_addr, &def)); + TEST_ASSERT(def.is_default); } -*/ TEST_GROUP_RUNNER(lwpa_netint) { RUN_TEST_CASE(lwpa_netint, netint_enumeration_works); + RUN_TEST_CASE(lwpa_netint, default_netint_is_consistent); + RUN_TEST_CASE(lwpa_netint, get_interface_for_dest_works_ipv4); } void run_all_tests(void) { RUN_TEST_GROUP(lwpa_netint); -} \ No newline at end of file +} diff --git a/tests/unit/test_pack.c b/tests/unit/test_pack.c new file mode 100644 index 000000000..b6fe16c5c --- /dev/null +++ b/tests/unit/test_pack.c @@ -0,0 +1,249 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/pack.h" +#include "unity_fixture.h" + +#include +#include +#include "lwpa/bool.h" + +// What we pack and unpack from +uint8_t test_buf[100]; + +// Test utility functions that are used by the actual tests + +static bool test_pack16b(uint8_t* buffer) +{ + const uint16_t tst = 0x1234; + const uint8_t* ptst = (const uint8_t*)(&tst); + memset(buffer, 0, sizeof(uint16_t)); + + lwpa_pack_16b(buffer, tst); + if ((ptst[0] == buffer[1]) && (ptst[1] == buffer[0])) + return true; + return false; +} + +static bool test_pack16l(uint8_t* buffer) +{ + const uint16_t tst = 0x1234; + const uint8_t* ptst = (const uint8_t*)(&tst); + memset(buffer, 0, sizeof(uint16_t)); + + lwpa_pack_16l(buffer, tst); + if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1])) + return true; + return false; +} + +static bool test_upack16b(uint8_t* buffer) +{ + const uint16_t tst = 0x1234; + uint16_t var; + memset(buffer, 0, sizeof(uint16_t)); + + lwpa_pack_16b(buffer, tst); + var = lwpa_upack_16b(buffer); + if (tst == var) + return true; + return false; +} + +static bool test_upack16l(uint8_t* buffer) +{ + const uint16_t tst = 0x1234; + uint16_t var; + memset(buffer, 0, sizeof(uint16_t)); + + lwpa_pack_16l(buffer, tst); + var = lwpa_upack_16l(buffer); + if (tst == var) + return true; + return false; +} + +static bool test_pack32b(uint8_t* buffer) +{ + const uint32_t tst = 0x12345678; + const uint8_t* ptst = (const uint8_t*)(&tst); + memset(buffer, 0, sizeof(uint32_t)); + + lwpa_pack_32b(buffer, tst); + if ((ptst[0] == buffer[3]) && (ptst[1] == buffer[2]) && (ptst[2] == buffer[1]) && (ptst[3] == buffer[0])) + { + return true; + } + return false; +} + +static bool test_pack32l(uint8_t* buffer) +{ + const uint32_t tst = 0x12345678; + const uint8_t* ptst = (const uint8_t*)(&tst); + memset(buffer, 0, sizeof(uint32_t)); + + lwpa_pack_32l(buffer, tst); + if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1]) && (ptst[2] == buffer[2]) && (ptst[3] == buffer[3])) + { + return true; + } + return false; +} + +static bool test_upack32b(uint8_t* buffer) +{ + const uint32_t tst = 0x12345678; + uint32_t var; + memset(buffer, 0, sizeof(uint32_t)); + + lwpa_pack_32b(buffer, tst); + var = lwpa_upack_32b(buffer); + if (tst == var) + return true; + return false; +} + +static bool test_upack32l(uint8_t* buffer) +{ + const uint32_t tst = 0x12345678; + uint32_t var; + memset(buffer, 0, sizeof(uint32_t)); + + lwpa_pack_32l(buffer, tst); + var = lwpa_upack_32l(buffer); + if (tst == var) + return true; + return false; +} + +static bool test_pack64b(uint8_t* buffer) +{ + const uint64_t tst = 0x1234567890abcdef; + const uint8_t* ptst = (const uint8_t*)(&tst); + memset(buffer, 0, sizeof(uint64_t)); + + lwpa_pack_64b(buffer, tst); + if ((ptst[0] == buffer[7]) && (ptst[1] == buffer[6]) && (ptst[2] == buffer[5]) && (ptst[3] == buffer[4]) && + (ptst[4] == buffer[3]) && (ptst[5] == buffer[2]) && (ptst[6] == buffer[1]) && (ptst[7] == buffer[0])) + { + return true; + } + return false; +} + +static bool test_pack64l(uint8_t* buffer) +{ + const uint64_t tst = 0x1234567890abcdef; + const uint8_t* ptst = (const uint8_t*)(&tst); + memset(buffer, 0, sizeof(uint64_t)); + + lwpa_pack_64l(buffer, tst); + if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1]) && (ptst[2] == buffer[2]) && (ptst[3] == buffer[3]) && + (ptst[4] == buffer[4]) && (ptst[5] == buffer[5]) && (ptst[6] == buffer[6]) && (ptst[7] == buffer[7])) + { + return true; + } + return false; +} + +static bool test_upack64b(uint8_t* buffer) +{ + const uint64_t tst = 0x1234567890abcdef; + uint64_t var; + memset(buffer, 0, sizeof(uint64_t)); + + lwpa_pack_64b(buffer, tst); + var = lwpa_upack_64b(buffer); + if (tst == var) + return true; + return false; +} + +static bool test_upack64l(uint8_t* buffer) +{ + const uint64_t tst = 0x1234567890abcdef; + uint64_t var; + memset(buffer, 0, sizeof(uint64_t)); + + lwpa_pack_64l(buffer, tst); + var = lwpa_upack_64l(buffer); + if (tst == var) + return true; + return false; +} + +// The tests themselves + +TEST_GROUP(lwpa_pack); + +TEST_SETUP(lwpa_pack) +{ +} + +TEST_TEAR_DOWN(lwpa_pack) +{ +} + +TEST(lwpa_pack, pack_16_functions_work) +{ + // Test packing and unpacking values at varying memory offsets. + for (size_t offset = 0; offset <= 60; ++offset) + { + TEST_ASSERT(test_pack16b(test_buf + offset)); + TEST_ASSERT(test_pack16l(test_buf + offset)); + TEST_ASSERT(test_upack16b(test_buf + offset)); + TEST_ASSERT(test_upack16l(test_buf + offset)); + } +} + +TEST(lwpa_pack, pack_32_functions_work) +{ + // Test packing and unpacking values at varying memory offsets. + for (size_t offset = 0; offset <= 60; ++offset) + { + TEST_ASSERT(test_pack32b(test_buf + offset)); + TEST_ASSERT(test_pack32l(test_buf + offset)); + TEST_ASSERT(test_upack32b(test_buf + offset)); + TEST_ASSERT(test_upack32l(test_buf + offset)); + } +} + +TEST(lwpa_pack, pack_64_functions_work) +{ + // Test packing and unpacking values at varying memory offsets. + for (size_t offset = 0; offset <= 60; ++offset) + { + TEST_ASSERT(test_pack64b(test_buf + offset)); + TEST_ASSERT(test_pack64l(test_buf + offset)); + TEST_ASSERT(test_upack64b(test_buf + offset)); + TEST_ASSERT(test_upack64l(test_buf + offset)); + } +} + +TEST_GROUP_RUNNER(lwpa_pack) +{ + RUN_TEST_CASE(lwpa_pack, pack_16_functions_work); + RUN_TEST_CASE(lwpa_pack, pack_32_functions_work); + RUN_TEST_CASE(lwpa_pack, pack_64_functions_work); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_pack); +} \ No newline at end of file diff --git a/tests/unit/test_pack.cpp b/tests/unit/test_pack.cpp deleted file mode 100644 index 65077c4cf..000000000 --- a/tests/unit/test_pack.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpa/pack.h" -#include "gtest/gtest.h" -#include -#include - -class PackTest : public ::testing::Test -{ -protected: - bool test_pack16b(uint8_t* buffer) - { - const uint16_t tst = 0x1234; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint16_t)); - - lwpa_pack_16b(buffer, tst); - if ((ptst[0] == buffer[1]) && (ptst[1] == buffer[0])) - return true; - return false; - } - - bool test_pack16l(uint8_t* buffer) - { - const uint16_t tst = 0x1234; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint16_t)); - - lwpa_pack_16l(buffer, tst); - if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1])) - return true; - return false; - } - - bool test_upack16b(uint8_t* buffer) - { - const uint16_t tst = 0x1234; - uint16_t var; - memset(buffer, 0, sizeof(uint16_t)); - - lwpa_pack_16b(buffer, tst); - var = lwpa_upack_16b(buffer); - if (tst == var) - return true; - return false; - } - - bool test_upack16l(uint8_t* buffer) - { - const uint16_t tst = 0x1234; - uint16_t var; - memset(buffer, 0, sizeof(uint16_t)); - - lwpa_pack_16l(buffer, tst); - var = lwpa_upack_16l(buffer); - if (tst == var) - return true; - return false; - } - - bool test_pack32b(uint8_t* buffer) - { - const uint32_t tst = 0x12345678; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint32_t)); - - lwpa_pack_32b(buffer, tst); - if ((ptst[0] == buffer[3]) && (ptst[1] == buffer[2]) && (ptst[2] == buffer[1]) && (ptst[3] == buffer[0])) - { - return true; - } - return false; - } - - bool test_pack32l(uint8_t* buffer) - { - const uint32_t tst = 0x12345678; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint32_t)); - - lwpa_pack_32l(buffer, tst); - if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1]) && (ptst[2] == buffer[2]) && (ptst[3] == buffer[3])) - { - return true; - } - return false; - } - - bool test_upack32b(uint8_t* buffer) - { - const uint32_t tst = 0x12345678; - uint32_t var; - memset(buffer, 0, sizeof(uint32_t)); - - lwpa_pack_32b(buffer, tst); - var = lwpa_upack_32b(buffer); - if (tst == var) - return true; - return false; - } - - bool test_upack32l(uint8_t* buffer) - { - const uint32_t tst = 0x12345678; - uint32_t var; - memset(buffer, 0, sizeof(uint32_t)); - - lwpa_pack_32l(buffer, tst); - var = lwpa_upack_32l(buffer); - if (tst == var) - return true; - return false; - } - - bool test_pack64b(uint8_t* buffer) - { - const uint64_t tst = 0x1234567890abcdef; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint64_t)); - - lwpa_pack_64b(buffer, tst); - if ((ptst[0] == buffer[7]) && (ptst[1] == buffer[6]) && (ptst[2] == buffer[5]) && (ptst[3] == buffer[4]) && - (ptst[4] == buffer[3]) && (ptst[5] == buffer[2]) && (ptst[6] == buffer[1]) && (ptst[7] == buffer[0])) - { - return true; - } - return false; - } - - bool test_pack64l(uint8_t* buffer) - { - const uint64_t tst = 0x1234567890abcdef; - const uint8_t* ptst = (const uint8_t*)(&tst); - memset(buffer, 0, sizeof(uint64_t)); - - lwpa_pack_64l(buffer, tst); - if ((ptst[0] == buffer[0]) && (ptst[1] == buffer[1]) && (ptst[2] == buffer[2]) && (ptst[3] == buffer[3]) && - (ptst[4] == buffer[4]) && (ptst[5] == buffer[5]) && (ptst[6] == buffer[6]) && (ptst[7] == buffer[7])) - { - return true; - } - return false; - } - - bool test_upack64b(uint8_t* buffer) - { - const uint64_t tst = 0x1234567890abcdef; - uint64_t var; - memset(buffer, 0, sizeof(uint64_t)); - - lwpa_pack_64b(buffer, tst); - var = lwpa_upack_64b(buffer); - if (tst == var) - return true; - return false; - } - - bool test_upack64l(uint8_t* buffer) - { - const uint64_t tst = 0x1234567890abcdef; - uint64_t var; - memset(buffer, 0, sizeof(uint64_t)); - - lwpa_pack_64l(buffer, tst); - var = lwpa_upack_64l(buffer); - if (tst == var) - return true; - return false; - } - - // What we pack and unpack from - uint8_t test_buf[100]; -}; - -TEST_F(PackTest, pack16) -{ - // Test packing and unpacking values at varying memory offsets. - for (size_t offset = 0; offset <= 60; ++offset) - { - ASSERT_TRUE(test_pack16b(test_buf + offset)); - ASSERT_TRUE(test_pack16l(test_buf + offset)); - ASSERT_TRUE(test_upack16b(test_buf + offset)); - ASSERT_TRUE(test_upack16l(test_buf + offset)); - } -} - -TEST_F(PackTest, pack32) -{ - // Test packing and unpacking values at varying memory offsets. - for (size_t offset = 0; offset <= 60; ++offset) - { - ASSERT_TRUE(test_pack32b(test_buf + offset)); - ASSERT_TRUE(test_pack32l(test_buf + offset)); - ASSERT_TRUE(test_upack32b(test_buf + offset)); - ASSERT_TRUE(test_upack32l(test_buf + offset)); - } -} - -TEST_F(PackTest, pack64) -{ - // Test packing and unpacking values at varying memory offsets. - for (size_t offset = 0; offset <= 60; ++offset) - { - ASSERT_TRUE(test_pack64b(test_buf + offset)); - ASSERT_TRUE(test_pack64l(test_buf + offset)); - ASSERT_TRUE(test_upack64b(test_buf + offset)); - ASSERT_TRUE(test_upack64l(test_buf + offset)); - } -} From 747006775a130f2f9fc537d2d25edbe547e31a78 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 16 Aug 2019 14:08:54 -0500 Subject: [PATCH 102/264] Fix compile on mac, start on rbtree, fix small issues --- include/lwpa/log.h | 13 +++--- src/lwpa/log.c | 18 ++++++++ tests/integration/signal_integration_test.c | 10 ++--- tests/unit/CMakeLists.txt | 1 + tests/unit/test_log.c | 42 +++---------------- tests/unit/{test_rbtree.cpp => test_rbtree.c} | 17 +++++--- 6 files changed, 45 insertions(+), 56 deletions(-) rename tests/unit/{test_rbtree.cpp => test_rbtree.c} (97%) diff --git a/include/lwpa/log.h b/include/lwpa/log.h index 7ee072ed8..1e1fb488c 100644 --- a/include/lwpa/log.h +++ b/include/lwpa/log.h @@ -210,7 +210,7 @@ typedef struct LwpaSyslogParams /*! A set of parameters used for the lwpa_*log() functions. */ typedef struct LwpaLogParams { - /*! What should be done when lwpa_*log() is called. */ + /*! What should be done when lwpa_log() or lwpa_vlog() is called. */ lwpa_log_action_t action; /*! A callback function for the finished log string(s). */ lwpa_log_callback log_fn; @@ -218,18 +218,13 @@ typedef struct LwpaLogParams LwpaSyslogParams syslog_params; /*! A mask value that determines which priority messages can be logged. */ int log_mask; - /*! A callback function for lwpa_*log() functions to obtain the time from the application. If - * NULL, no timestamp will be added to log messages. */ + /*! A callback function for the lwpa_log() and lwpa_vlog() functions to obtain the time from the + * application. If NULL, no timestamp will be added to log messages. */ lwpa_log_time_fn time_fn; /*! Application context that will be passed back with the log callback function. */ void* context; } LwpaLogParams; -#define LWPA_SET_LOG_MASK(logparamsptr, newlogmask) ((logparamsptr)->log_mask = newlogmask) - -#define LWPA_CAN_LOG(logparamsptr, pri) \ - ((logparamsptr) ? ((LWPA_LOG_MASK(pri) & (logparamsptr)->log_mask) != 0) : false) - #ifdef __cplusplus extern "C" { #endif @@ -259,6 +254,8 @@ bool lwpa_create_human_log_str(char* buf, size_t buflen, const LwpaLogTimeParams void lwpa_sanitize_syslog_params(LwpaSyslogParams* params); bool lwpa_validate_log_params(LwpaLogParams* params); +bool lwpa_can_log(const LwpaLogParams* params, int pri); + #ifdef __ICCARM__ #pragma __printf_args #endif diff --git a/src/lwpa/log.c b/src/lwpa/log.c index 60a1ab7f2..20a3081c6 100644 --- a/src/lwpa/log.c +++ b/src/lwpa/log.c @@ -317,6 +317,24 @@ bool lwpa_create_human_log_str(char* buf, size_t buflen, const LwpaLogTimeParams return res; } +/*! \brief Determine whether a priority level can be logged given the mask present in the log + * params. + * + * This is useful to use as a guard around doing any conversions that are only for logging, e.g. + * converting addresses to strings -- if the priority of the message can't be logged, then those + * conversions are just wasted work. + * + * \param[in] params The log parameters to be checked. + * \param[in] pri Priority to check. + * \return Whether this priority will be logged with the current mask setting. + */ +bool lwpa_can_log(const LwpaLogParams* params, int pri) +{ + if (params) + return ((LWPA_LOG_MASK(pri) & params->log_mask) != 0); + return false; +} + /*! \brief Log a message from a library module. * * Takes a printf-style format string which is formatted and passed to the application callback. diff --git a/tests/integration/signal_integration_test.c b/tests/integration/signal_integration_test.c index 69f480bc1..b8b51f3b3 100644 --- a/tests/integration/signal_integration_test.c +++ b/tests/integration/signal_integration_test.c @@ -22,21 +22,21 @@ #include "lwpa/thread.h" // For general usage -static lwpa_signal_t signal; +static lwpa_signal_t sig; static void signal_test_thread(void* arg) { (void)arg; for (size_t i = 0; i < 3; ++i) - lwpa_signal_wait(&signal); + lwpa_signal_wait(&sig); } // Two threads are created. They wait on the same signal 3 times. Each post of the signal should // wake up only one of the threads, so 6 posts should end both threads. TEST(lwpa_integration, signal_thread_test) { - TEST_ASSERT_TRUE(lwpa_signal_create(&signal)); + TEST_ASSERT_TRUE(lwpa_signal_create(&sig)); lwpa_thread_t threads[2]; @@ -51,11 +51,11 @@ TEST(lwpa_integration, signal_thread_test) for (size_t i = 0; i < 6; ++i) { lwpa_thread_sleep(10); - lwpa_signal_post(&signal); + lwpa_signal_post(&sig); } for (size_t i = 0; i < 2; ++i) TEST_ASSERT_TRUE(lwpa_thread_join(&threads[i])); - lwpa_signal_destroy(&signal); + lwpa_signal_destroy(&sig); } diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 505a322e6..44a761b8c 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -35,6 +35,7 @@ lwpa_add_live_test(test_log test_log.c) lwpa_add_live_test(test_mempool test_mempool.c) lwpa_add_live_test(test_netint test_netint.c) lwpa_add_live_test(test_pack test_pack.c) +# lwpa_add_live_test(test_rbtree test_rbtree.c) lwpa_add_custom_test(test_timer_wraparound test_timer_wraparound.c diff --git a/tests/unit/test_log.c b/tests/unit/test_log.c index 6e05266d2..8b0c6a23d 100644 --- a/tests/unit/test_log.c +++ b/tests/unit/test_log.c @@ -84,37 +84,6 @@ TEST_TEAR_DOWN(lwpa_log) lwpa_deinit(LWPA_FEATURE_LOGGING); } -// Test the LWPA_SET_LOG_MASK() and LWPA_CAN_LOG() macros -TEST(lwpa_log, log_mask_macros_work) -{ - // LWPA_CAN_LOG() should always return false (and not crash) on a null pointer - LwpaLogParams* params_ptr = NULL; - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(params_ptr, LWPA_LOG_EMERG)); - - LwpaLogParams params; - - // Test a zero mask - LWPA_SET_LOG_MASK(¶ms, 0); - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); - - // Test some LOG_UPTO() values - LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_UPTO(LWPA_LOG_EMERG)); - TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_ALERT)); - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); - - LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_UPTO(LWPA_LOG_DEBUG)); - TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); - TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); - - // Test a weird mask with some middle values - LWPA_SET_LOG_MASK(¶ms, LWPA_LOG_MASK(LWPA_LOG_ERR)); - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_EMERG)); - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(¶ms, LWPA_LOG_DEBUG)); - TEST_ASSERT(LWPA_CAN_LOG(¶ms, LWPA_LOG_ERR)); -} - // Test the lwpa_sanitize_syslog_params() function. TEST(lwpa_log, sanitize_syslog_params_works) { @@ -364,7 +333,7 @@ TEST(lwpa_log, log_mask_is_honored) // Try logging with the log mask set to 0, should not work. for (int pri = 0; pri < 8; ++pri) { - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, pri)); + TEST_ASSERT_UNLESS(lwpa_can_log(&lparams, pri)); lwpa_log(&lparams, pri, LOG_MASK_TEST_MESSAGE); } TEST_ASSERT_EQUAL_UINT(log_callback_fake.call_count, 0); @@ -377,11 +346,11 @@ TEST(lwpa_log, log_mask_is_honored) { if (test_pri <= mask_pri) { - TEST_ASSERT(LWPA_CAN_LOG(&lparams, test_pri)); + TEST_ASSERT(lwpa_can_log(&lparams, test_pri)); } else { - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, test_pri)); + TEST_ASSERT_UNLESS(lwpa_can_log(&lparams, test_pri)); } lwpa_log(&lparams, test_pri, LOG_MASK_TEST_MESSAGE); } @@ -395,11 +364,11 @@ TEST(lwpa_log, log_mask_is_honored) { if (test_pri == LWPA_LOG_ALERT || test_pri == LWPA_LOG_WARNING) { - TEST_ASSERT(LWPA_CAN_LOG(&lparams, test_pri)); + TEST_ASSERT(lwpa_can_log(&lparams, test_pri)); } else { - TEST_ASSERT_UNLESS(LWPA_CAN_LOG(&lparams, test_pri)); + TEST_ASSERT_UNLESS(lwpa_can_log(&lparams, test_pri)); } lwpa_log(&lparams, test_pri, LOG_MASK_TEST_MESSAGE); } @@ -642,7 +611,6 @@ TEST(lwpa_log, logging_maximum_length_string_works) TEST_GROUP_RUNNER(lwpa_log) { - RUN_TEST_CASE(lwpa_log, log_mask_macros_work); RUN_TEST_CASE(lwpa_log, sanitize_syslog_params_works); RUN_TEST_CASE(lwpa_log, validate_log_params_works); RUN_TEST_CASE(lwpa_log, log_action_is_honored); diff --git a/tests/unit/test_rbtree.cpp b/tests/unit/test_rbtree.c similarity index 97% rename from tests/unit/test_rbtree.cpp rename to tests/unit/test_rbtree.c index 6cde41d85..9ad7b8fb9 100644 --- a/tests/unit/test_rbtree.cpp +++ b/tests/unit/test_rbtree.c @@ -17,12 +17,17 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/rbtree.h" -#include "gtest/gtest.h" -#include -#include -#include -#include -#include +#include "unity_fixture.h" +#include "fff.h" + +#include +#include + +#define INT_ARRAY_SIZE 100 + +static int incrementing_int_array[INT_ARRAY_SIZE]; +static int random_int_array[INT_ARRAY_SIZE]; +LwpaRbNode node_pool[INT_ARRAY_SIZE]; class RbTreeTest : public ::testing::Test { From 76d6f2aa98e5c61d4e5c69d9065e96edbf53e205 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sat, 17 Aug 2019 21:40:39 -0500 Subject: [PATCH 103/264] Socket tests --- tests/CMakeLists.txt | 8 + tests/integration/CMakeLists.txt | 6 +- tests/integration/mutex_integration_test.c | 65 ++-- tests/integration/rwlock_integration_test.c | 112 +++--- tests/integration/signal_integration_test.c | 25 +- tests/integration/socket_integration_test.c | 408 ++++++++++++++++++++ tests/integration/test_main.c | 22 +- tests/integration/test_main.h | 29 -- tests/unit/CMakeLists.txt | 5 +- tests/unit/entrypoint/main_default.c | 3 + tests/unit/test_inet.c | 52 +++ tests/unit/test_mempool.c | 5 +- tests/unit/test_rbtree.c | 292 +++++++------- tests/unit/test_signal.cpp | 64 --- tests/unit/test_socket.c | 97 +++++ tests/unit/test_socket.cpp | 318 --------------- 16 files changed, 848 insertions(+), 663 deletions(-) create mode 100644 tests/integration/socket_integration_test.c delete mode 100644 tests/integration/test_main.h delete mode 100644 tests/unit/test_signal.cpp create mode 100644 tests/unit/test_socket.c delete mode 100644 tests/unit/test_socket.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ec8058166..12acd1a5f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,13 +3,17 @@ set(LWPA_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) set(LWPA_SRC ${CMAKE_CURRENT_LIST_DIR}/../src) +option(LWPA_TEST_IPV6 "Test IPv6 socket functions in the lwpa unit and integration tests" ON) + if(WIN32 OR APPLE OR UNIX) set(LWPA_TEST_ENTRYPOINT main_default.c) function(lwpa_add_to_ctest target_name) add_test(NAME ${target_name} COMMAND $ -v) + set_tests_properties(${target_name} PROPERTIES TIMEOUT 30) endfunction() endif() + if(WIN32) set(LWPA_TEST_COMPILE_OPTIONS /wd4210) elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -18,5 +22,9 @@ else() set(LWPA_TEST_COMPILE_OPTIONS "") endif() +if(LWPA_TEST_IPV6) + set(LWPA_TEST_COMPILE_DEFINITIONS LWPA_TEST_IPV6) +endif() + add_subdirectory(unit) add_subdirectory(integration) diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index ce5c64721..afeecd483 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -3,14 +3,16 @@ # are the locking, threading and synchronization functions. add_executable(lwpa_integration_tests + mutex_integration_test.c + rwlock_integration_test.c signal_integration_test.c - - test_main.h + socket_integration_test.c test_main.c entrypoint/${LWPA_TEST_ENTRYPOINT} ) set_target_properties(lwpa_integration_tests PROPERTIES FOLDER tests) target_compile_options(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) +target_compile_definitions(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) target_link_libraries(lwpa_integration_tests PRIVATE lwpa ThrowTheSwitch::Unity) lwpa_add_to_ctest(lwpa_integration_tests) diff --git a/tests/integration/mutex_integration_test.c b/tests/integration/mutex_integration_test.c index 43061885e..25b8c5f13 100644 --- a/tests/integration/mutex_integration_test.c +++ b/tests/integration/mutex_integration_test.c @@ -25,50 +25,63 @@ #define NUM_THREADS 10 #define NUM_ITERATIONS 10000 -// The shared variable -int shared_var{0}; +static int shared_var; +static lwpa_mutex_t mutex; -static void mutex_test_thread(MutexTest* fixture) +static void mutex_test_thread(void* arg) { - if (fixture) + (void)arg; + + for (int i = 0; i < NUM_ITERATIONS; ++i) { - for (int i = 0; i < MutexTest::kNumIterations; ++i) - { - lwpa_mutex_take(&fixture->mutex); - ++fixture->shared_var; - lwpa_mutex_give(&fixture->mutex); - // Had to insert an artificial delay to get it to fail reliably when the mutexes don't work. - // This ensures that each thread runs for long enough to get time-sliced multiple times. - for (volatile size_t j = 0; j < 100; ++j) - ; - } + lwpa_mutex_take(&mutex); + ++shared_var; + lwpa_mutex_give(&mutex); + // Had to insert an artificial delay to get it to fail reliably when the mutexes don't work. + // This ensures that each thread runs for long enough to get time-sliced multiple times. + for (volatile size_t j = 0; j < 100; ++j) + ; } } +TEST_GROUP(mutex_integration); + +TEST_SETUP(mutex_integration) +{ + shared_var = 0; + TEST_ASSERT(lwpa_mutex_create(&mutex)); +} + +TEST_TEAR_DOWN(mutex_integration) +{ + lwpa_mutex_destroy(&mutex); +} + // Test the actual mutex functionality. Start a number of threads and have them all increment the // same variable inside a mutex. At the end of the test, the value of the variable should be exactly // the number of threads times the number of times each thread incremented the variable. // Yes, this test isn't guaranteed to fail if the mutexes don't work. But it's still a good test to // run. Tests on several platforms where the mutex lines were commented showed failure very reliably. -TEST_F(MutexTest, threads) +TEST(mutex_integration, mutex_thread_test) { - ASSERT_TRUE(lwpa_mutex_create(&mutex)); + lwpa_thread_t threads[NUM_THREADS]; - std::vector threads; - threads.reserve(kNumThreads); + LwpaThreadParams params; + LWPA_THREAD_SET_DEFAULT_PARAMS(¶ms); - for (size_t i = 0; i < kNumThreads; ++i) + for (size_t i = 0; i < NUM_THREADS; ++i) { - std::thread thread(mutex_test_thread, this); - ASSERT_TRUE(thread.joinable()); - threads.push_back(std::move(thread)); + TEST_ASSERT_TRUE(lwpa_thread_create(&threads[i], ¶ms, mutex_test_thread, NULL)); } - for (auto& thread : threads) - thread.join(); + for (size_t i = 0; i < NUM_THREADS; ++i) + TEST_ASSERT_TRUE(lwpa_thread_join(&threads[i])); - ASSERT_EQ(shared_var, (kNumThreads * kNumIterations)); + TEST_ASSERT_EQUAL(shared_var, (NUM_THREADS * NUM_ITERATIONS)); +} - lwpa_mutex_destroy(&mutex); +TEST_GROUP_RUNNER(mutex_integration) +{ + RUN_TEST_CASE(mutex_integration, mutex_thread_test); } diff --git a/tests/integration/rwlock_integration_test.c b/tests/integration/rwlock_integration_test.c index 27f0dbac4..5688723af 100644 --- a/tests/integration/rwlock_integration_test.c +++ b/tests/integration/rwlock_integration_test.c @@ -24,53 +24,62 @@ #define NUM_WRITE_THREADS 10 #define NUM_ITERATIONS 10000 -lwpa_rwlock_t rwlock; -int shared_var; -bool read_thread_pass; +static lwpa_rwlock_t rwlock; +static int shared_var; +static bool read_thread_pass; -static void write_test_thread(RwlockTest* fixture) +static void write_test_thread(void* arg) { - if (fixture) + (void)arg; + + for (size_t i = 0; i < NUM_ITERATIONS; ++i) { - for (size_t i = 0; i < RwlockTest::RWLOCK_TEST_NUM_ITERATIONS; ++i) - { - lwpa_rwlock_writelock(&fixture->rwlock); - ++fixture->shared_var; - lwpa_rwlock_writeunlock(&fixture->rwlock); - // Had to insert an artificial delay to get it to fail reliably when the mutexes don't work. - // This ensures that each thread runs for long enough to get time-sliced multiple times. - for (volatile size_t j = 0; j < 100; ++j) - ; - } + lwpa_rwlock_writelock(&rwlock); + ++shared_var; + lwpa_rwlock_writeunlock(&rwlock); + // Had to insert an artificial delay to get it to fail reliably when the mutexes don't work. + // This ensures that each thread runs for long enough to get time-sliced multiple times. + for (volatile size_t j = 0; j < 100; ++j) + ; } } -using namespace std::chrono_literals; - -static void read_test_thread(RwlockTest* fixture) +static void read_test_thread(void* arg) { - if (fixture) + (void)arg; + + read_thread_pass = true; + for (int i = 0; i < 10; ++i) { - fixture->read_thread_pass = true; - for (int i = 0; i < 10; ++i) + lwpa_rwlock_readlock(&rwlock); + int val = shared_var; + + lwpa_thread_sleep(5); + + // Make sure the value hasn't changed. + if (val != shared_var) { - lwpa_rwlock_readlock(&fixture->rwlock); - int val = fixture->shared_var; - - std::this_thread::sleep_for(5ms); - - // Make sure the value hasn't changed. - if (val != fixture->shared_var) - { - fixture->read_thread_pass = false; - break; - } - lwpa_rwlock_readunlock(&fixture->rwlock); - std::this_thread::sleep_for(5ms); + read_thread_pass = false; + break; } + lwpa_rwlock_readunlock(&rwlock); + lwpa_thread_sleep(5); } } +TEST_GROUP(rwlock_integration); + +TEST_SETUP(rwlock_integration) +{ + shared_var = 0; + TEST_ASSERT(lwpa_rwlock_create(&rwlock)); +} + +TEST_TEAR_DOWN(rwlock_integration) +{ + lwpa_rwlock_destroy(&rwlock); +} + // Test the actual read-write lock functionality. Start a number of threads and have them all // increment the same variable inside a write lock. Meanwhile, another thread periodically reads the // variable. At the end of the test, the value of the variable should be exactly the number of @@ -79,29 +88,30 @@ static void read_test_thread(RwlockTest* fixture) // Yes, this test isn't guaranteed to fail if the read-write locks don't work. But it's still a good // test to run. Tests on several platform where the lock lines were commented showed failure very // reliably. -TEST_F(RwlockTest, threads) +TEST(rwlock_integration, rwlock_thread_test) { - ASSERT_TRUE(lwpa_rwlock_create(&rwlock)); + lwpa_thread_t write_threads[NUM_WRITE_THREADS]; + lwpa_thread_t read_thread; - std::vector threads; - threads.reserve(RWLOCK_TEST_NUM_WRITE_THREADS + 1); + LwpaThreadParams params; + LWPA_THREAD_SET_DEFAULT_PARAMS(¶ms); - std::thread read_thread(read_test_thread, this); - ASSERT_TRUE(read_thread.joinable()); - threads.push_back(std::move(read_thread)); + TEST_ASSERT_TRUE(lwpa_thread_create(&read_thread, ¶ms, read_test_thread, NULL)); - for (size_t i = 0; i < RWLOCK_TEST_NUM_WRITE_THREADS; ++i) + for (size_t i = 0; i < NUM_WRITE_THREADS; ++i) { - std::thread write_thread(write_test_thread, this); - ASSERT_TRUE(write_thread.joinable()); - threads.push_back(std::move(write_thread)); + TEST_ASSERT_TRUE(lwpa_thread_create(&write_threads[i], ¶ms, write_test_thread, NULL)); } - for (auto& thread : threads) - thread.join(); + for (size_t i = 0; i < NUM_WRITE_THREADS; ++i) + TEST_ASSERT_TRUE(lwpa_thread_join(&write_threads[i])); + TEST_ASSERT_TRUE(lwpa_thread_join(&read_thread)); - EXPECT_TRUE(read_thread_pass); - EXPECT_EQ(shared_var, (RWLOCK_TEST_NUM_WRITE_THREADS * RWLOCK_TEST_NUM_ITERATIONS)); - - lwpa_rwlock_destroy(&rwlock); + TEST_ASSERT(read_thread_pass); + TEST_ASSERT_EQUAL(shared_var, (NUM_WRITE_THREADS * NUM_ITERATIONS)); } + +TEST_GROUP_RUNNER(rwlock_integration) +{ + RUN_TEST_CASE(rwlock_integration, rwlock_thread_test); +} \ No newline at end of file diff --git a/tests/integration/signal_integration_test.c b/tests/integration/signal_integration_test.c index b8b51f3b3..413cb08f6 100644 --- a/tests/integration/signal_integration_test.c +++ b/tests/integration/signal_integration_test.c @@ -18,7 +18,7 @@ ******************************************************************************/ #include "lwpa/lock.h" #include "unity_fixture.h" -#include "test_main.h" + #include "lwpa/thread.h" // For general usage @@ -32,12 +32,22 @@ static void signal_test_thread(void* arg) lwpa_signal_wait(&sig); } +TEST_GROUP(signal_integration); + +TEST_SETUP(signal_integration) +{ + TEST_ASSERT(lwpa_signal_create(&sig)); +} + +TEST_TEAR_DOWN(signal_integration) +{ + lwpa_signal_destroy(&sig); +} + // Two threads are created. They wait on the same signal 3 times. Each post of the signal should // wake up only one of the threads, so 6 posts should end both threads. -TEST(lwpa_integration, signal_thread_test) +TEST(signal_integration, signal_thread_test) { - TEST_ASSERT_TRUE(lwpa_signal_create(&sig)); - lwpa_thread_t threads[2]; LwpaThreadParams params; @@ -56,6 +66,9 @@ TEST(lwpa_integration, signal_thread_test) for (size_t i = 0; i < 2; ++i) TEST_ASSERT_TRUE(lwpa_thread_join(&threads[i])); - - lwpa_signal_destroy(&sig); } + +TEST_GROUP_RUNNER(signal_integration) +{ + RUN_TEST_CASE(signal_integration, signal_thread_test); +} \ No newline at end of file diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c new file mode 100644 index 000000000..f900f5134 --- /dev/null +++ b/tests/integration/socket_integration_test.c @@ -0,0 +1,408 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/socket.h" +#include "unity_fixture.h" + +#include "lwpa/netint.h" +#include "lwpa/thread.h" + +#define NUM_TEST_PACKETS 1000 + +static LwpaNetintInfo v4_netint; +bool run_ipv4_mcast_test; +#if LWPA_TEST_IPV6 +static LwpaNetintInfo v6_netint; +bool run_ipv6_mcast_test; +#endif + +static const char kSocketTestMessage[] = "testtesttest"; +#define SOCKET_TEST_MESSAGE_LENGTH (sizeof(kSocketTestMessage)) +static const uint32_t kTestMcastAddrIPv4 = 0xec02054d; // 236.2.5.77 +// ff02::7465:7374:7465:7374 +static const uint8_t kTestMcastAddrIPv6[LWPA_IPV6_BYTES] = {0xff, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74}; + +static lwpa_socket_t send_sock; +static LwpaSockaddr send_addr; + +// Select the default interface if available, the very first non-loopback, non-link-local interface +// if not. +static void select_network_interface_v4() +{ + run_ipv4_mcast_test = true; + if (kLwpaErrOk != lwpa_netint_get_default_interface(kLwpaIpTypeV6, &v4_netint)) + { + const LwpaNetintInfo* arr = lwpa_netint_get_interfaces(); + if (arr) + { + for (const LwpaNetintInfo* netint = arr; netint < arr + lwpa_netint_get_num_interfaces(); ++netint) + { + if (LWPA_IP_IS_V4(&netint->addr) && !lwpa_ip_is_link_local(&netint->addr) && + !lwpa_ip_is_loopback(&netint->addr)) + { + v4_netint = *netint; + return; + } + } + // We haven't found a network interface... + UnityPrint( + "WARNING: No IPv4 non-loopback, non-link-local network interfaces found. Disabling multicast IPv4 " + "test...\n"); + run_ipv4_mcast_test = false; + } + } +} + +#if LWPA_TEST_IPV6 +// Select the default interface if available, the very first non-loopback interface if not. +static void select_network_interface_v6() +{ + run_ipv6_mcast_test = true; + if (kLwpaErrOk != lwpa_netint_get_default_interface(kLwpaIpTypeV6, &v6_netint)) + { + const LwpaNetintInfo* arr = lwpa_netint_get_interfaces(); + if (arr) + { + for (const LwpaNetintInfo* netint = arr; netint < arr + lwpa_netint_get_num_interfaces(); ++netint) + { + if (LWPA_IP_IS_V6(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr)) + { + v6_netint = *netint; + return; + } + } + // We haven't found a network interface... + UnityPrint("WARNING: No IPv6 non-loopback network interfaces found. Disabling multicast IPv6 test...\n"); + run_ipv6_mcast_test = false; + } + } +} +#endif + +TEST_GROUP(socket_integration); + +TEST_SETUP(socket_integration) +{ +} + +TEST_TEAR_DOWN(socket_integration) +{ +} + +// For UDP testing we apply strength in numbers to get around the inherent unreliability of UDP. +// Packets are sent in bulk from another thread, and pass if we receive some of them. + +static void send_thread(void* arg) +{ + (void)arg; + + for (size_t i = 0; i < NUM_TEST_PACKETS; ++i) + lwpa_sendto(send_sock, (const uint8_t*)kSocketTestMessage, SOCKET_TEST_MESSAGE_LENGTH, 0, &send_addr); +} + +#define UNICAST_UDP_PORT_BASE 6000 + +void unicast_udp_test(lwpa_iptype_t ip_type, lwpa_socket_t rcvsock1, lwpa_socket_t rcvsock2) +{ + int intval = 500; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + intval = 1; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + + LwpaSockaddr bind_addr; + lwpa_ip_set_wildcard(ip_type, &bind_addr.ip); + bind_addr.port = UNICAST_UDP_PORT_BASE; + // Bind socket 1 to the wildcard address and a specific port. + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); + // Bind socket 2 to the wildcard address and a different port. + bind_addr.port = UNICAST_UDP_PORT_BASE + 1; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); + + send_addr.port = UNICAST_UDP_PORT_BASE; + + // Start the send thread + LwpaThreadParams thread_params; + LWPA_THREAD_SET_DEFAULT_PARAMS(&thread_params); + lwpa_thread_t send_thr_handle; + TEST_ASSERT(lwpa_thread_create(&send_thr_handle, &thread_params, send_thread, NULL)); + + size_t num_packets_received = 0; + for (size_t i = 0; i < NUM_TEST_PACKETS; ++i) + { + LwpaSockaddr from_addr; + uint8_t buf[SOCKET_TEST_MESSAGE_LENGTH + 1]; + + int res = lwpa_recvfrom(rcvsock1, buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr); + if (res == SOCKET_TEST_MESSAGE_LENGTH) + { + ++num_packets_received; + } + else + { + TEST_ASSERT_EQUAL(res, kLwpaErrTimedOut); + break; + } + + TEST_ASSERT(lwpa_ip_equal(&send_addr.ip, &from_addr.ip)); + TEST_ASSERT_NOT_EQUAL(from_addr.port, UNICAST_UDP_PORT_BASE); + + buf[SOCKET_TEST_MESSAGE_LENGTH] = '\0'; + TEST_ASSERT_EQUAL_STRING((char*)buf, kSocketTestMessage); + } + + TEST_ASSERT_GREATER_THAN_UINT(0u, num_packets_received); + + // recvfrom should time out because this socket is bound to a different port and we set the + // timeout option on this socket. + LwpaSockaddr from_addr; + uint8_t buf[SOCKET_TEST_MESSAGE_LENGTH + 1]; + TEST_ASSERT_LESS_OR_EQUAL_INT(0, lwpa_recvfrom(rcvsock2, buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr)); + + // Let the send thread end + TEST_ASSERT_TRUE(lwpa_thread_join(&send_thr_handle)); +} + +TEST(socket_integration, unicast_udp_ipv4) +{ + lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; + lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); + TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); + TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); + TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); + + LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, 0x7f000001u); + + unicast_udp_test(kLwpaIpTypeV4, rcvsock1, rcvsock2); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); +} + +TEST(socket_integration, unicast_udp_ipv6) +{ + lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; + lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &rcvsock1)); + TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &rcvsock2)); + TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &send_sock)); + TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); + + uint8_t v6_loopback[LWPA_IPV6_BYTES]; + memset(&v6_loopback, 0, LWPA_IPV6_BYTES); + v6_loopback[15] = 1; + LWPA_IP_SET_V6_ADDRESS(&send_addr.ip, &v6_loopback); + + unicast_udp_test(kLwpaIpTypeV6, rcvsock1, rcvsock2); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); +} + +#define MULTICAST_UDP_PORT_BASE 7000 + +void multicast_udp_test(lwpa_socket_t rcvsock1, lwpa_socket_t rcvsock2) +{ + int intval = 500; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + intval = 1; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + + // Start the send thread + LwpaThreadParams thread_params; + LWPA_THREAD_SET_DEFAULT_PARAMS(&thread_params); + lwpa_thread_t send_thr_handle; + TEST_ASSERT(lwpa_thread_create(&send_thr_handle, &thread_params, send_thread, NULL)); + + size_t num_packets_received = 0; + for (size_t i = 0; i < NUM_TEST_PACKETS; ++i) + { + LwpaSockaddr from_addr; + uint8_t buf[SOCKET_TEST_MESSAGE_LENGTH + 1]; + + int res = lwpa_recvfrom(rcvsock1, buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr); + if (res == SOCKET_TEST_MESSAGE_LENGTH) + { + ++num_packets_received; + } + else + { + TEST_ASSERT_EQUAL(res, kLwpaErrWouldBlock); + break; + } + + TEST_ASSERT_NOT_EQUAL(from_addr.port, MULTICAST_UDP_PORT_BASE); + + buf[SOCKET_TEST_MESSAGE_LENGTH] = '\0'; + TEST_ASSERT_EQUAL_STRING((char*)buf, kSocketTestMessage); + } + TEST_ASSERT_GREATER_THAN(0u, num_packets_received); + + LwpaSockaddr from_addr; + uint8_t buf[SOCKET_TEST_MESSAGE_LENGTH + 1]; + // recvfrom should time out because this socket is bound to a different port and we set the + // timeout option on this socket. + TEST_ASSERT_LESS_OR_EQUAL_INT(0, lwpa_recvfrom(rcvsock2, buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr)); + + // Let the send thread end + TEST_ASSERT(lwpa_thread_join(&send_thr_handle)); +} + +TEST(socket_integration, multicast_udp_ipv4) +{ + LwpaSockaddr bind_addr; + + lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; + lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); + TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); + TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + + int intval = 1; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); + TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &v4_netint.index, + sizeof v4_netint.index)); + + // Bind socket 1 to the wildcard address and a specific port. + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); + bind_addr.port = MULTICAST_UDP_PORT_BASE; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); + + // Bind socket 2 to the wildcard address and a different port. + bind_addr.port = MULTICAST_UDP_PORT_BASE + 1; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); + + // Subscribe socket 1 to the multicast address. + LwpaGroupReq greq; + greq.ifindex = v4_netint.index; + LWPA_IP_SET_V4_ADDRESS(&greq.group, kTestMcastAddrIPv4); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); + + // Subscribe socket 2 to the multicast address + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); + + LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, kTestMcastAddrIPv4); + send_addr.port = MULTICAST_UDP_PORT_BASE; + + multicast_udp_test(rcvsock1, rcvsock2); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); +} + +#if LWPA_TEST_IPV6 +TEST(socket_integration, multicast_udp_ipv6) +{ + LwpaSockaddr bind_addr; + + lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; + lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &rcvsock1)); + TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &rcvsock2)); + TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + + int intval = 1; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &send_sock)); + TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_IF, &v6_netint.index, + sizeof v6_netint.index)); + + // Bind socket 1 to the wildcard address and a specific port. + lwpa_ip_set_wildcard(kLwpaIpTypeV6, &bind_addr.ip); + bind_addr.port = MULTICAST_UDP_PORT_BASE; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); + + // Bind socket 2 to the wildcard address and a different port. + bind_addr.port = MULTICAST_UDP_PORT_BASE + 1; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); + + // Subscribe socket 1 to the multicast address. + LwpaGroupReq greq; + greq.ifindex = v6_netint.index; + LWPA_IP_SET_V6_ADDRESS(&greq.group, kTestMcastAddrIPv6); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); + + // Subscribe socket 2 to the multicast address + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); + + LWPA_IP_SET_V6_ADDRESS(&send_addr.ip, kTestMcastAddrIPv6); + send_addr.port = MULTICAST_UDP_PORT_BASE; + + multicast_udp_test(rcvsock1, rcvsock2); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); +} +#endif + +TEST_GROUP_RUNNER(socket_integration) +{ + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS)); + + select_network_interface_v4(); +#if LWPA_TEST_IPV6 + select_network_interface_v6(); +#endif + + RUN_TEST_CASE(socket_integration, unicast_udp_ipv4); + if (run_ipv4_mcast_test) + RUN_TEST_CASE(socket_integration, multicast_udp_ipv4); +#if LWPA_TEST_IPV6 + RUN_TEST_CASE(socket_integration, unicast_udp_ipv6); + if (run_ipv6_mcast_test) + RUN_TEST_CASE(socket_integration, multicast_udp_ipv6); +#endif + + lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); +} diff --git a/tests/integration/test_main.c b/tests/integration/test_main.c index 46c68a208..0fe19b2fd 100644 --- a/tests/integration/test_main.c +++ b/tests/integration/test_main.c @@ -18,24 +18,10 @@ ******************************************************************************/ #include "unity_fixture.h" -// HACK to get the Unity Fixture add-on to work in multiple files -const char* TEST_GROUP_lwpa_integration = "lwpa_integration"; -// TEST_GROUP(lwpa_integration); - -TEST_SETUP(lwpa_integration) -{ -} - -TEST_TEAR_DOWN(lwpa_integration) -{ -} - -TEST_GROUP_RUNNER(lwpa_integration) -{ - RUN_TEST_CASE(lwpa_integration, signal_thread_test); -} - void run_all_tests(void) { - RUN_TEST_GROUP(lwpa_integration); + RUN_TEST_GROUP(mutex_integration); + RUN_TEST_GROUP(rwlock_integration); + RUN_TEST_GROUP(signal_integration); + RUN_TEST_GROUP(socket_integration); } diff --git a/tests/integration/test_main.h b/tests/integration/test_main.h deleted file mode 100644 index d490bdd05..000000000 --- a/tests/integration/test_main.h +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#ifndef _TEST_MAIN_H_ -#define _TEST_MAIN_H_ - -/* This is a little bit of a hack around the limitations of the Unity Fixture add-on. Add some - * extern declarations for the test fixture so it can be seen in multiple files. */ - -extern const char* TEST_GROUP_lwpa_integration; -void TEST_lwpa_integration_SETUP(void); -void TEST_lwpa_integration_TEAR_DOWN(void); - -#endif /* _TEST_MAIN_H_ */ diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 44a761b8c..cdbbba6f7 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -10,6 +10,7 @@ function(lwpa_add_live_test target_name) add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) set_target_properties(${target_name} PROPERTIES FOLDER tests) target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) + target_compile_definitions(${target_name} PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) target_link_libraries(${target_name} PRIVATE lwpa ThrowTheSwitch::Unity meekrosoft::fff) lwpa_add_to_ctest(${target_name}) endfunction() @@ -20,6 +21,7 @@ function(lwpa_add_custom_test target_name) add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) set_target_properties(${target_name} PROPERTIES FOLDER tests) target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) + target_compile_definitions(${target_name} PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) target_link_libraries(${target_name} PRIVATE ThrowTheSwitch::Unity meekrosoft::fff) lwpa_add_to_ctest(${target_name}) endfunction() @@ -35,7 +37,8 @@ lwpa_add_live_test(test_log test_log.c) lwpa_add_live_test(test_mempool test_mempool.c) lwpa_add_live_test(test_netint test_netint.c) lwpa_add_live_test(test_pack test_pack.c) -# lwpa_add_live_test(test_rbtree test_rbtree.c) +lwpa_add_live_test(test_rbtree test_rbtree.c) +lwpa_add_live_test(test_socket test_socket.c) lwpa_add_custom_test(test_timer_wraparound test_timer_wraparound.c diff --git a/tests/unit/entrypoint/main_default.c b/tests/unit/entrypoint/main_default.c index 63192dae2..2ecbab09a 100644 --- a/tests/unit/entrypoint/main_default.c +++ b/tests/unit/entrypoint/main_default.c @@ -17,11 +17,14 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ +#include +#include #include "unity_fixture.h" extern void run_all_tests(void); int main(int argc, char* argv[]) { + srand((unsigned int)time(NULL)); return UnityMain(argc, argv, run_all_tests); } diff --git a/tests/unit/test_inet.c b/tests/unit/test_inet.c index ad43c012b..1ecc4969c 100644 --- a/tests/unit/test_inet.c +++ b/tests/unit/test_inet.c @@ -308,6 +308,57 @@ TEST(lwpa_inet, ip_mask_from_length_works) TEST_ASSERT_EQUAL_UINT8_ARRAY(LWPA_IP_V6_ADDRESS(&mask_out), v6_compare_val, LWPA_IPV6_BYTES); } +// For inet_xtox +char str[LWPA_INET6_ADDRSTRLEN]; +const char* test_ip4_1 = "0.0.0.0"; +const char* test_ip4_2 = "255.255.255.255"; +const char* test_ip4_fail = "256.256.256.256"; +const char* test_ip6_1 = "::"; +const uint8_t test_ip6_1_bin[LWPA_IPV6_BYTES] = {0}; +const char* test_ip6_2 = "::1"; +const uint8_t test_ip6_2_bin[LWPA_IPV6_BYTES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; +const char* test_ip6_3 = "ffff:FFFF:ffff:FFFF:ffff:FFFF:ffff:FFFF"; +const uint8_t test_ip6_3_bin[LWPA_IPV6_BYTES] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +const char* test_ip6_fail = "abcd::ef01::2345"; + +TEST(lwpa_inet, inet_string_functions_work) +{ + LwpaIpAddr addr; + + // Test lwpa_inet_pton() + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_1, &addr)); + TEST_ASSERT_EQUAL(LWPA_IP_V4_ADDRESS(&addr), 0u); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_2, &addr)); + TEST_ASSERT_EQUAL(LWPA_IP_V4_ADDRESS(&addr), 0xffffffffu); + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_fail, &addr)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_1, &addr)); + TEST_ASSERT_EQUAL(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_1_bin, LWPA_IPV6_BYTES)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_2, &addr)); + TEST_ASSERT_EQUAL(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_2_bin, LWPA_IPV6_BYTES)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_3, &addr)); + TEST_ASSERT_EQUAL(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_3_bin, LWPA_IPV6_BYTES)); + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_fail, &addr)); + + // Test lwpa_inet_ntop() + LWPA_IP_SET_V4_ADDRESS(&addr, 0); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); + TEST_ASSERT_EQUAL(0, strcmp(str, test_ip4_1)); + LWPA_IP_SET_V4_ADDRESS(&addr, 0xffffffff); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); + TEST_ASSERT_EQUAL(0, strcmp(str, test_ip4_2)); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_1_bin); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); + TEST_ASSERT_EQUAL(0, strcmp(str, test_ip6_1)); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_2_bin); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); + TEST_ASSERT_EQUAL(0, strcmp(str, test_ip6_2)); + LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_3_bin); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); + TEST_ASSERT((0 == strcmp(str, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) || + (0 == strcmp(str, "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"))); +} + TEST_GROUP_RUNNER(lwpa_inet) { RUN_TEST_CASE(lwpa_inet, ipaddr_macros_work); @@ -317,6 +368,7 @@ TEST_GROUP_RUNNER(lwpa_inet) RUN_TEST_CASE(lwpa_inet, ip_compare_functions_work); RUN_TEST_CASE(lwpa_inet, ip_mask_length_works); RUN_TEST_CASE(lwpa_inet, ip_mask_from_length_works); + RUN_TEST_CASE(lwpa_inet, inet_string_functions_work); } void run_all_tests(void) diff --git a/tests/unit/test_mempool.c b/tests/unit/test_mempool.c index 56fb57217..d3cae357a 100644 --- a/tests/unit/test_mempool.c +++ b/tests/unit/test_mempool.c @@ -45,6 +45,7 @@ static void create_shuffled_index_array(size_t* array, size_t size) for (size_t i = 0; i < size - 1; ++i) { + // srand() is taken care of at the entry point. size_t j = i + rand() / (RAND_MAX / (size - i) + 1); size_t swap_val = array[j]; array[j] = array[i]; @@ -56,10 +57,6 @@ TEST_GROUP(lwpa_mempool); TEST_SETUP(lwpa_mempool) { - // We don't srand() for now since an entropy source is not available on all platforms. - // This results in the shuffled arrays being deterministic every test run, but that's not really - // that big of a deal. - memset(test_arr, 0, sizeof test_arr); memset(index_arr, 0, sizeof index_arr); } diff --git a/tests/unit/test_rbtree.c b/tests/unit/test_rbtree.c index 9ad7b8fb9..d0e85591d 100644 --- a/tests/unit/test_rbtree.c +++ b/tests/unit/test_rbtree.c @@ -23,67 +23,40 @@ #include #include +// Disable sprintf() warning on Windows/MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + +DEFINE_FFF_GLOBALS; + #define INT_ARRAY_SIZE 100 +#define RANDOM_INT_IN_ARRAY() (int)(rand() / ((RAND_MAX + 1.0) / INT_ARRAY_SIZE)) static int incrementing_int_array[INT_ARRAY_SIZE]; static int random_int_array[INT_ARRAY_SIZE]; -LwpaRbNode node_pool[INT_ARRAY_SIZE]; - -class RbTreeTest : public ::testing::Test -{ -protected: - RbTreeTest() - { - // Initialize the static variables. They need to be static because they are accessed from the - // non-member functions (which need to be non-member functions because they are passed as - // function pointers to the C library) - alloc_call_count = 0; - dealloc_call_count = 0; - - // Initialize an array of monotonically increasing ints - for (int i = 0; i < kIntArraySize; ++i) - incrementing_int_array_[i] = i; - - // Copy and shuffle the integer array - random_int_array_ = incrementing_int_array_; - std::shuffle(random_int_array_.begin(), random_int_array_.end(), rand_); - } - - static constexpr int kIntArraySize = 100; - std::array incrementing_int_array_; - std::array random_int_array_; - std::array node_pool_; - std::random_device seed_; - std::default_random_engine rand_{seed_()}; +LwpaRbNode node_pool[INT_ARRAY_SIZE]; +size_t next_node_index; -public: - static int alloc_call_count; - static int dealloc_call_count; +// Private function prototypes - int clearfunc_call_count{0}; - bool remove_one_flag{false}; - static const int kMagicRemoveValue = kIntArraySize / 2; -}; +static LwpaRbNode* get_node(); +static int int_compare(const LwpaRbTree* self, const LwpaRbNode* node_a, const LwpaRbNode* node_b); +static void populate_int_arrays(); -int RbTreeTest::alloc_call_count; -int RbTreeTest::dealloc_call_count; -constexpr int RbTreeTest::kIntArraySize; +FAKE_VALUE_FUNC(LwpaRbNode*, node_alloc); +FAKE_VOID_FUNC(node_dealloc, LwpaRbNode*); +FAKE_VOID_FUNC(clear_func, const LwpaRbTree*, LwpaRbNode*); -extern "C" { -LwpaRbNode* node_alloc() +// Very very dumb "allocation" of nodes but all we need for these tests - each call returns the +// next one from the array, freeing does nothing. +LwpaRbNode* get_node(void) { - ++RbTreeTest::alloc_call_count; - return new LwpaRbNode; + return &node_pool[next_node_index++]; } -void node_dealloc(LwpaRbNode* node) -{ - ++RbTreeTest::dealloc_call_count; - delete node; -} - -static int int_cmp(const LwpaRbTree* self, const LwpaRbNode* node_a, const LwpaRbNode* node_b) +int int_compare(const LwpaRbTree* self, const LwpaRbNode* node_a, const LwpaRbNode* node_b) { (void)self; int a = *(int*)node_a->value; @@ -91,193 +64,224 @@ static int int_cmp(const LwpaRbTree* self, const LwpaRbNode* node_a, const LwpaR return a - b; } -static void clear_func(const LwpaRbTree* self, LwpaRbNode* node) +void populate_int_arrays() { - RbTreeTest* rbtt = static_cast(self->info); - if (rbtt) + // Initialize two arrays of monotonically increasing ints + for (int i = 0; i < INT_ARRAY_SIZE; ++i) + { + incrementing_int_array[i] = i; + random_int_array[i] = i; + } + + // Shuffle the random array + for (int i = 0; i < INT_ARRAY_SIZE - 1; ++i) { - if (rbtt->remove_one_flag && *(int*)node->value == RbTreeTest::kMagicRemoveValue) - { - rbtt->remove_one_flag = false; - } - ++rbtt->clearfunc_call_count; + // srand() is taken care of at the entry point. + int j = i + rand() / (RAND_MAX / (INT_ARRAY_SIZE - i) + 1); + int swap_val = random_int_array[j]; + random_int_array[j] = random_int_array[i]; + random_int_array[i] = swap_val; } } + +// The tests themselves + +TEST_GROUP(lwpa_rbtree); + +TEST_SETUP(lwpa_rbtree) +{ + RESET_FAKE(node_alloc); + RESET_FAKE(node_dealloc); + RESET_FAKE(clear_func); + + node_alloc_fake.custom_fake = get_node; + + populate_int_arrays(); + next_node_index = 0; +} + +TEST_TEAR_DOWN(lwpa_rbtree) +{ } -TEST_F(RbTreeTest, insert_static) +TEST(lwpa_rbtree, insert_node_functions_work) { LwpaRbTree tree; - ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, nullptr, nullptr)); - tree.info = this; + TEST_ASSERT_NOT_NULL(lwpa_rbtree_init(&tree, int_compare, NULL, NULL)); // Point each node at its respective value and insert it into the tree - for (int i = 0; i < kIntArraySize; ++i) + for (int i = 0; i < INT_ARRAY_SIZE; ++i) { - LwpaRbNode* node = &node_pool_[i]; - ASSERT_TRUE(nullptr != lwpa_rbnode_init(node, &random_int_array_[i])); - ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert_node(&tree, node)); + LwpaRbNode* node = &node_pool[i]; + TEST_ASSERT_NOT_NULL(lwpa_rbnode_init(node, &random_int_array[i])); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_insert_node(&tree, node)); } - ASSERT_EQ(static_cast(kIntArraySize), lwpa_rbtree_size(&tree)); - EXPECT_GT(lwpa_rbtree_test(&tree, tree.root), 0); + TEST_ASSERT_EQUAL_UINT(INT_ARRAY_SIZE, lwpa_rbtree_size(&tree)); + TEST_ASSERT_GREATER_THAN(0, lwpa_rbtree_test(&tree, tree.root)); // Find a random number - std::uniform_int_distribution<> dist(0, kIntArraySize - 1); - int to_find = dist(rand_); + int to_find = RANDOM_INT_IN_ARRAY(); + + char test_error_msg[100]; + sprintf(test_error_msg, "Couldn't find value %d in the tree.", to_find); + int* found = (int*)lwpa_rbtree_find(&tree, &to_find); - ASSERT_TRUE(found != nullptr); - EXPECT_EQ(*found, to_find); + TEST_ASSERT_NOT_NULL_MESSAGE(found, test_error_msg); + TEST_ASSERT_EQUAL(*found, to_find); // Try removing one item - remove_one_flag = true; - int to_remove = kMagicRemoveValue; - ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_remove_with_cb(&tree, &to_remove, clear_func)); - ASSERT_FALSE(remove_one_flag); + int to_remove = RANDOM_INT_IN_ARRAY(); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_remove_with_cb(&tree, &to_remove, clear_func)); + TEST_ASSERT_EQUAL(to_remove, *((int*)(clear_func_fake.arg1_val->value))); // Clear the tree - EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear_with_cb(&tree, clear_func)); - EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); - EXPECT_EQ(clearfunc_call_count, kIntArraySize); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_clear_with_cb(&tree, clear_func)); + TEST_ASSERT_EQUAL_UINT(0u, lwpa_rbtree_size(&tree)); + TEST_ASSERT_EQUAL_UINT(clear_func_fake.call_count, INT_ARRAY_SIZE); } -TEST_F(RbTreeTest, insert_dynamic) +TEST(lwpa_rbtree, insert_functions_work) { LwpaRbTree tree; - ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); + TEST_ASSERT_NOT_NULL(lwpa_rbtree_init(&tree, int_compare, node_alloc, node_dealloc)); // Insert each value into the tree; dynamic alloc functions should be called. - for (int i = 0; i < kIntArraySize; ++i) - ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &random_int_array_[i])); - ASSERT_EQ(static_cast(kIntArraySize), lwpa_rbtree_size(&tree)); - ASSERT_EQ(kIntArraySize, alloc_call_count); - ASSERT_GT(lwpa_rbtree_test(&tree, tree.root), 0); + for (int i = 0; i < INT_ARRAY_SIZE; ++i) + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_insert(&tree, &random_int_array[i])); + TEST_ASSERT_EQUAL_UINT(INT_ARRAY_SIZE, lwpa_rbtree_size(&tree)); + TEST_ASSERT_EQUAL_UINT(INT_ARRAY_SIZE, node_alloc_fake.call_count); + TEST_ASSERT_GREATER_THAN(0, lwpa_rbtree_test(&tree, tree.root)); // Find a random number - int to_find = rand() / (int)(RAND_MAX / kIntArraySize + 1); + int to_find = RANDOM_INT_IN_ARRAY(); + + char test_error_msg[100]; + sprintf(test_error_msg, "Couldn't find value %d in the tree.", to_find); + int* found = (int*)lwpa_rbtree_find(&tree, &to_find); - ASSERT_TRUE(found != nullptr); - ASSERT_EQ(*found, to_find); + TEST_ASSERT_NOT_NULL_MESSAGE(found, test_error_msg); + TEST_ASSERT_EQUAL(*found, to_find); // Make sure removing something that wasn't in the tree fails. - int not_in_tree = kIntArraySize + 1; - ASSERT_EQ(kLwpaErrNotFound, lwpa_rbtree_remove(&tree, ¬_in_tree)); + int not_in_tree = INT_ARRAY_SIZE; + TEST_ASSERT_EQUAL(kLwpaErrNotFound, lwpa_rbtree_remove(&tree, ¬_in_tree)); + TEST_ASSERT_EQUAL_UINT(node_dealloc_fake.call_count, 0u); // Clear the tree - EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear(&tree)); - EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); - EXPECT_EQ(dealloc_call_count, kIntArraySize); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_clear(&tree)); + TEST_ASSERT_EQUAL_UINT(0u, lwpa_rbtree_size(&tree)); + TEST_ASSERT_EQUAL_UINT(node_dealloc_fake.call_count, INT_ARRAY_SIZE); } -TEST_F(RbTreeTest, element_already_exists) +TEST(lwpa_rbtree, insert_should_fail_if_element_already_exists) { LwpaRbTree tree; - ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); + TEST_ASSERT_NOT_NULL(lwpa_rbtree_init(&tree, int_compare, node_alloc, node_dealloc)); // Insert a few values into the tree. Enough so we have some branches to traverse for (int i = 0; i < 10; ++i) - ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &incrementing_int_array_[i])); - ASSERT_EQ(10u, lwpa_rbtree_size(&tree)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_insert(&tree, &incrementing_int_array[i])); + TEST_ASSERT_EQUAL_UINT(10u, lwpa_rbtree_size(&tree)); // Try inserting a duplicate value - should fail with error 'already exists' int duplicate = 5; - ASSERT_EQ(kLwpaErrExists, lwpa_rbtree_insert(&tree, &duplicate)); + TEST_ASSERT_EQUAL(kLwpaErrExists, lwpa_rbtree_insert(&tree, &duplicate)); // Remove the offending value and try inserting it again, should succeed - ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_remove(&tree, &duplicate)); - ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &duplicate)); - - // Clear the tree - EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear(&tree)); - EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_remove(&tree, &duplicate)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_insert(&tree, &duplicate)); } -TEST_F(RbTreeTest, iter) +TEST(lwpa_rbtree, iterators_work_as_expected) { LwpaRbTree tree; - ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); + TEST_ASSERT_NOT_NULL(lwpa_rbtree_init(&tree, int_compare, node_alloc, node_dealloc)); // Insert each value into the tree; dynamic alloc functions should be called. - for (int i = 0; i < kIntArraySize; ++i) - ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &random_int_array_[i])); - ASSERT_EQ(static_cast(kIntArraySize), lwpa_rbtree_size(&tree)); + for (int i = 0; i < INT_ARRAY_SIZE; ++i) + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_insert(&tree, &random_int_array[i])); + TEST_ASSERT_EQUAL_UINT(INT_ARRAY_SIZE, lwpa_rbtree_size(&tree)); // Initialize an iterator LwpaRbIter iter; - ASSERT_TRUE(nullptr != lwpa_rbiter_init(&iter)); + TEST_ASSERT_EQUAL_PTR(&iter, lwpa_rbiter_init(&iter)); // Get the first value. int* val = (int*)lwpa_rbiter_first(&iter, &tree); // Although the elements were inserted in random order, the tree should be sorted so 0 should be // the first value. - ASSERT_TRUE(val != nullptr); - ASSERT_EQ(*val, 0); + TEST_ASSERT_NOT_NULL(val); + TEST_ASSERT_EQUAL(*val, 0); // Test iterating through the tree in forward order. int num_iterations = 1; int last_val = *val; - while ((val = (int*)lwpa_rbiter_next(&iter)) != nullptr) + while ((val = (int*)lwpa_rbiter_next(&iter)) != NULL) { ++num_iterations; - // Each value given by the iterator should be numerically higher than the one that came before - // it. - ASSERT_GT(*val, last_val); + // Each value given by the iterator should be the next one in order in the tree. + TEST_ASSERT_EQUAL(*val, last_val + 1); last_val = *val; } - ASSERT_EQ(num_iterations, kIntArraySize); + TEST_ASSERT_EQUAL(num_iterations, INT_ARRAY_SIZE); // Get the last value. val = (int*)lwpa_rbiter_last(&iter, &tree); - ASSERT_TRUE(val != nullptr); - ASSERT_EQ(*val, static_cast(kIntArraySize - 1)); + TEST_ASSERT_NOT_NULL(val); + TEST_ASSERT_EQUAL(*val, INT_ARRAY_SIZE - 1); // Test iterating through the tree in reverse order. num_iterations = 1; last_val = *val; - while ((val = (int*)lwpa_rbiter_prev(&iter)) != nullptr) + while ((val = (int*)lwpa_rbiter_prev(&iter)) != NULL) { ++num_iterations; - // Each value given by the iterator should be numerically lower than the one that came before - // it. - ASSERT_LT(*val, last_val); + // Each value given by the iterator should be the previous one in order in the tree. + TEST_ASSERT_EQUAL(*val, last_val - 1); last_val = *val; } - ASSERT_EQ(num_iterations, kIntArraySize); - - // Clear the tree. - EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear(&tree)); - EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); - EXPECT_EQ(kIntArraySize, dealloc_call_count); + TEST_ASSERT_EQUAL(num_iterations, INT_ARRAY_SIZE); } -TEST_F(RbTreeTest, max_height) +TEST(lwpa_rbtree, max_height_is_within_bounds) { LwpaRbTree tree; - ASSERT_TRUE(nullptr != lwpa_rbtree_init(&tree, int_cmp, node_alloc, node_dealloc)); + TEST_ASSERT_NOT_NULL(lwpa_rbtree_init(&tree, int_compare, node_alloc, node_dealloc)); + // Insert monotonically incrementing values into the tree. In a traditional binary tree, this - // would result in a worst-case unbalanced tree of height kIntArraySize. In the red-black tree, - // the maximum height should be determined by the formula 2 * log2(kIntArraySize + 1). - for (int i = 0; i < kIntArraySize; ++i) - ASSERT_EQ(kLwpaErrOk, lwpa_rbtree_insert(&tree, &incrementing_int_array_[i])); - ASSERT_EQ(static_cast(kIntArraySize), lwpa_rbtree_size(&tree)); + // would result in a worst-case unbalanced tree of height INT_ARRAY_SIZE. In the red-black tree, + // the maximum height should be determined by the formula 2 * log2(INT_ARRAY_SIZE + 1). + for (int i = 0; i < INT_ARRAY_SIZE; ++i) + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_insert(&tree, &incrementing_int_array[i])); + TEST_ASSERT_EQUAL_UINT(INT_ARRAY_SIZE, lwpa_rbtree_size(&tree)); // Get the height of the tree and compare it against the theoretical maximum. LwpaRbIter iter; size_t max_height = 0; size_t theoretical_max_height; - ASSERT_TRUE(nullptr != lwpa_rbiter_init(&iter)); - ASSERT_TRUE(nullptr != lwpa_rbiter_first(&iter, &tree)); + TEST_ASSERT_NOT_NULL(lwpa_rbiter_init(&iter)); + TEST_ASSERT_NOT_NULL(lwpa_rbiter_first(&iter, &tree)); do { if (iter.top > max_height) max_height = iter.top; - } while (nullptr != lwpa_rbiter_next(&iter)); + } while (NULL != lwpa_rbiter_next(&iter)); max_height += 1; // http://www.doctrina.org/maximum-height-of-red-black-tree.html - theoretical_max_height = 2 * (size_t)(log(kIntArraySize + 1) / log(2)); - ASSERT_LE(max_height, theoretical_max_height); + theoretical_max_height = 2 * (size_t)(log(INT_ARRAY_SIZE + 1) / log(2)); + TEST_ASSERT_LESS_OR_EQUAL_UINT(theoretical_max_height, max_height); +} - // Clear the tree - EXPECT_EQ(kLwpaErrOk, lwpa_rbtree_clear(&tree)); - EXPECT_EQ(0u, lwpa_rbtree_size(&tree)); - EXPECT_EQ(kIntArraySize, dealloc_call_count); +TEST_GROUP_RUNNER(lwpa_rbtree) +{ + RUN_TEST_CASE(lwpa_rbtree, insert_node_functions_work); + RUN_TEST_CASE(lwpa_rbtree, insert_functions_work); + RUN_TEST_CASE(lwpa_rbtree, insert_should_fail_if_element_already_exists); + RUN_TEST_CASE(lwpa_rbtree, iterators_work_as_expected); + RUN_TEST_CASE(lwpa_rbtree, max_height_is_within_bounds); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_rbtree); } diff --git a/tests/unit/test_signal.cpp b/tests/unit/test_signal.cpp deleted file mode 100644 index c8aabbd63..000000000 --- a/tests/unit/test_signal.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpa/lock.h" -#include "gtest/gtest.h" -#include -#include -#include -#include -#include - -static void signal_test_thread(SignalTest* fixture) -{ - if (fixture) - { - for (size_t i = 0; i < 3; ++i) - lwpa_signal_wait(&fixture->signal); - } -} - -using namespace std::chrono_literals; - -// Two threads are created. They wait on the same signal 3 times. Each post of the signal should -// wake up only one of the threads, so 6 posts should end both threads. -TEST_F(SignalTest, threads) -{ - ASSERT_TRUE(lwpa_signal_create(&signal)); - - std::vector threads; - threads.reserve(2); - - for (size_t i = 0; i < 2; ++i) - { - std::thread thread(signal_test_thread, this); - ASSERT_TRUE(thread.joinable()); - threads.push_back(std::move(thread)); - } - - for (size_t i = 0; i < 6; ++i) - { - std::this_thread::sleep_for(10ms); - lwpa_signal_post(&signal); - } - - for (auto& thread : threads) - thread.join(); - - lwpa_signal_destroy(&signal); -} diff --git a/tests/unit/test_socket.c b/tests/unit/test_socket.c new file mode 100644 index 000000000..d422fd2b6 --- /dev/null +++ b/tests/unit/test_socket.c @@ -0,0 +1,97 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/socket.h" +#include "unity_fixture.h" + +#include "lwpa/netint.h" +#include + +// For getaddrinfo +static const char* test_hostname = "www.google.com"; +static const char* test_service = "http"; + +static const char* test_gai_ip_str = "10.101.1.1"; +static const uint32_t test_gai_ip = 0x0a650101; +static const char* test_gai_port_str = "8080"; +static const uint16_t test_gai_port = 8080; + +TEST_GROUP(lwpa_socket); + +TEST_SETUP(lwpa_socket) +{ + lwpa_init(LWPA_FEATURE_SOCKETS); +} + +TEST_TEAR_DOWN(lwpa_socket) +{ + lwpa_deinit(LWPA_FEATURE_SOCKETS); +} + +TEST(lwpa_socket, bind_works_as_expected) +{ + lwpa_socket_t sock = LWPA_SOCKET_INVALID; + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock)); + TEST_ASSERT_NOT_EQUAL(sock, LWPA_SOCKET_INVALID); + + // Make sure we can bind to the wildcard address and port + LwpaSockaddr bind_addr; + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); + bind_addr.port = 0; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(sock, &bind_addr)); + + // Shouldn't be able to bind to a closed socket. + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(sock)); + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_bind(sock, &bind_addr)); +} + +TEST(lwpa_socket, sockopts) +{ + // TODO, need getsockopt() implemented for this +} + +TEST(lwpa_socket, getaddrinfo_works_as_expected) +{ + LwpaAddrinfo ai_hints; + LwpaAddrinfo ai; + + memset(&ai_hints, 0, sizeof ai_hints); + ai_hints.ai_family = LWPA_AF_INET; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_getaddrinfo(test_hostname, test_service, &ai_hints, &ai)); + TEST_ASSERT(LWPA_IP_IS_V4(&ai.ai_addr.ip)); + lwpa_freeaddrinfo(&ai); + + ai_hints.ai_flags = LWPA_AI_NUMERICHOST; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_getaddrinfo(test_gai_ip_str, test_gai_port_str, &ai_hints, &ai)); + TEST_ASSERT(LWPA_IP_IS_V4(&ai.ai_addr.ip)); + TEST_ASSERT_EQUAL_UINT32(LWPA_IP_V4_ADDRESS(&ai.ai_addr.ip), test_gai_ip); + TEST_ASSERT_EQUAL_UINT16(ai.ai_addr.port, test_gai_port); +} + +TEST_GROUP_RUNNER(lwpa_socket) +{ + RUN_TEST_CASE(lwpa_socket, bind_works_as_expected); + RUN_TEST_CASE(lwpa_socket, sockopts); + RUN_TEST_CASE(lwpa_socket, getaddrinfo_works_as_expected); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_socket); +} \ No newline at end of file diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp deleted file mode 100644 index b591ba5c4..000000000 --- a/tests/unit/test_socket.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpa/socket.h" -#include "lwpa/netint.h" -#include "gtest/gtest.h" -#include -#include - -class SocketTest : public ::testing::Test -{ -public: - static const size_t NUM_TEST_PACKETS = 1000; - static const char* SEND_MSG; - static const size_t SEND_MSG_LEN; - static const uint32_t TEST_MCAST_ADDR = 0xec02054d; // 236.2.5.77 - lwpa_socket_t send_sock = LWPA_SOCKET_INVALID; - LwpaSockaddr send_addr_1; - -protected: - SocketTest() - { - lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); - lwpa_netint_get_default_interface(kLwpaIpTypeV4, &default_netint_); - } - ~SocketTest() { lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); } - - LwpaNetintInfo default_netint_; - - // For inet_xtox - char str[LWPA_INET6_ADDRSTRLEN]; - const char* test_ip4_1 = "0.0.0.0"; - const char* test_ip4_2 = "255.255.255.255"; - const char* test_ip4_fail = "256.256.256.256"; - const char* test_ip6_1 = "::"; - const uint8_t test_ip6_1_bin[LWPA_IPV6_BYTES] = {0}; - const char* test_ip6_2 = "::1"; - const uint8_t test_ip6_2_bin[LWPA_IPV6_BYTES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - const char* test_ip6_3 = "ffff:FFFF:ffff:FFFF:ffff:FFFF:ffff:FFFF"; - const uint8_t test_ip6_3_bin[LWPA_IPV6_BYTES] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const char* test_ip6_fail = "abcd::ef01::2345"; - - // For getaddrinfo - const char* test_hostname = "www.google.com"; - const char* test_service = "http"; - - const char* test_gai_ip_str = "10.101.1.1"; - const uint32_t test_gai_ip = 0x0a650101; - const char* test_gai_port_str = "8080"; - const uint16_t test_gai_port = 8080; -}; - -const char* SocketTest::SEND_MSG = "testtesttest"; -const size_t SocketTest::SEND_MSG_LEN = 12; - -TEST_F(SocketTest, inet_xtox) -{ - LwpaIpAddr addr; - - // Test lwpa_inet_pton() - ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_1, &addr)); - ASSERT_EQ(LWPA_IP_V4_ADDRESS(&addr), 0u); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_2, &addr)); - ASSERT_EQ(LWPA_IP_V4_ADDRESS(&addr), 0xffffffffu); - ASSERT_NE(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV4, test_ip4_fail, &addr)); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_1, &addr)); - ASSERT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_1_bin, LWPA_IPV6_BYTES)); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_2, &addr)); - ASSERT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_2_bin, LWPA_IPV6_BYTES)); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_3, &addr)); - ASSERT_EQ(0, memcmp(LWPA_IP_V6_ADDRESS(&addr), test_ip6_3_bin, LWPA_IPV6_BYTES)); - ASSERT_NE(kLwpaErrOk, lwpa_inet_pton(kLwpaIpTypeV6, test_ip6_fail, &addr)); - - // Test lwpa_inet_ntop() - LWPA_IP_SET_V4_ADDRESS(&addr, 0); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); - ASSERT_EQ(0, strcmp(str, test_ip4_1)); - LWPA_IP_SET_V4_ADDRESS(&addr, 0xffffffff); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET_ADDRSTRLEN)); - ASSERT_EQ(0, strcmp(str, test_ip4_2)); - LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_1_bin); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); - ASSERT_EQ(0, strcmp(str, test_ip6_1)); - LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_2_bin); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); - ASSERT_EQ(0, strcmp(str, test_ip6_2)); - LWPA_IP_SET_V6_ADDRESS(&addr, test_ip6_3_bin); - ASSERT_EQ(kLwpaErrOk, lwpa_inet_ntop(&addr, str, LWPA_INET6_ADDRSTRLEN)); - ASSERT_TRUE((0 == strcmp(str, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) || - (0 == strcmp(str, "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"))); -} - -TEST_F(SocketTest, sockopts) -{ - // TODO, need getsockopt() implemented for this -} - -static void send_thread(SocketTest* fixture) -{ - if (fixture) - { - const uint8_t* send_buf = (const uint8_t*)(SocketTest::SEND_MSG); - for (size_t i = 0; i < SocketTest::NUM_TEST_PACKETS; ++i) - lwpa_sendto(fixture->send_sock, send_buf, SocketTest::SEND_MSG_LEN, 0, &fixture->send_addr_1); - } -} - -#define UNICAST_UDP_PORT_BASE 6000 - -TEST_F(SocketTest, unicast_udp) -{ - lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock3 = LWPA_SOCKET_INVALID; - LwpaSockaddr bind_addr; - - // We'll just use the default interface for this test. - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); - ASSERT_NE(rcvsock1, LWPA_SOCKET_INVALID); - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); - ASSERT_NE(rcvsock2, LWPA_SOCKET_INVALID); - - int intval = 500; - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); - intval = 1; - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock3)); - ASSERT_NE(rcvsock3, LWPA_SOCKET_INVALID); - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); - ASSERT_NE(send_sock, LWPA_SOCKET_INVALID); - - ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock3)); - - lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = UNICAST_UDP_PORT_BASE; - // Shouldn't be able to bind to a closed socket. - ASSERT_NE(kLwpaErrOk, lwpa_bind(rcvsock3, &bind_addr)); - // Bind socket 1 to the wildcard address and a specific port. - ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); - // Bind socket 2 to the wildcard address and a different port. - bind_addr.port = UNICAST_UDP_PORT_BASE + 1; - ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); - - LWPA_IP_SET_V4_ADDRESS(&send_addr_1.ip, 0x7f000001u); - send_addr_1.port = UNICAST_UDP_PORT_BASE; - - std::thread send_thr(send_thread, this); - ASSERT_TRUE(send_thr.joinable()); - - size_t num_packets_received = 0; - for (size_t i = 0; i < NUM_TEST_PACKETS; ++i) - { - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - - int res = lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr); - if (res == SEND_MSG_LEN) - { - ++num_packets_received; - } - else - { - EXPECT_EQ(res, kLwpaErrTimedOut); - break; - } - - EXPECT_TRUE(lwpa_ip_equal(&send_addr_1.ip, &from_addr.ip)); - EXPECT_NE(from_addr.port, UNICAST_UDP_PORT_BASE); - - buf[SEND_MSG_LEN] = '\0'; - EXPECT_EQ(0, strcmp((char*)buf, SEND_MSG)); - } - - EXPECT_GT(num_packets_received, 0u); - - // recvfrom should time out because this socket is bound to a different port and we set the - // timeout option on this socket. - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - EXPECT_GE(0, lwpa_recvfrom(rcvsock2, buf, SEND_MSG_LEN, 0, &from_addr)); - - // Let the send thread end - send_thr.join(); - - ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock1)); - ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock2)); - ASSERT_EQ(kLwpaErrOk, lwpa_close(send_sock)); -} - -#define MULTICAST_UDP_PORT_BASE 7000 - -TEST_F(SocketTest, multicast_udp) -{ - lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; - LwpaSockaddr bind_addr; - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); - ASSERT_NE(rcvsock1, LWPA_SOCKET_INVALID); - - int intval = 500; - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); - intval = 1; - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); - ASSERT_NE(rcvsock2, LWPA_SOCKET_INVALID); - - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); - ASSERT_NE(send_sock, LWPA_SOCKET_INVALID); - - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &default_netint_.index, - sizeof default_netint_.index)); - - // Bind socket 1 to the wildcard address and a specific port. - lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = MULTICAST_UDP_PORT_BASE; - ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); - - // Bind socket 2 to the wildcard address and a different port. - bind_addr.port = MULTICAST_UDP_PORT_BASE + 1; - ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); - - // Subscribe socket 1 to the multicast address. - LwpaGroupReq greq; - greq.ifindex = default_netint_.index; - LWPA_IP_SET_V4_ADDRESS(&greq.group, TEST_MCAST_ADDR); - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); - - // Subscribe socket 2 to the multicast address - ASSERT_EQ(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); - - LWPA_IP_SET_V4_ADDRESS(&send_addr_1.ip, TEST_MCAST_ADDR); - send_addr_1.port = MULTICAST_UDP_PORT_BASE; - - // Start the send thread. - std::thread send_thr(send_thread, this); - ASSERT_TRUE(send_thr.joinable()); - - size_t num_packets_received = 0; - for (size_t i = 0; i < NUM_TEST_PACKETS; ++i) - { - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - - int res = lwpa_recvfrom(rcvsock1, buf, SEND_MSG_LEN, 0, &from_addr); - if (res == SEND_MSG_LEN) - { - ++num_packets_received; - } - else - { - EXPECT_EQ(res, kLwpaErrWouldBlock); - break; - } - - EXPECT_NE(from_addr.port, MULTICAST_UDP_PORT_BASE); - - buf[SEND_MSG_LEN] = '\0'; - EXPECT_EQ(0, strcmp((char*)buf, SEND_MSG)); - } - EXPECT_GT(num_packets_received, 0u); - - LwpaSockaddr from_addr; - uint8_t buf[SEND_MSG_LEN + 1]; - // recvfrom should time out because this socket is bound to a different port and we set the - // timeout option on this socket. - ASSERT_GE(0, lwpa_recvfrom(rcvsock2, buf, SEND_MSG_LEN, 0, &from_addr)); - - // Let the send thread end - send_thr.join(); - - ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock1)); - ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock2)); - ASSERT_EQ(kLwpaErrOk, lwpa_close(send_sock)); -} - -TEST_F(SocketTest, getaddrinfo) -{ - LwpaAddrinfo ai_hints; - LwpaAddrinfo ai; - - memset(&ai_hints, 0, sizeof ai_hints); - ai_hints.ai_family = LWPA_AF_INET; - ASSERT_EQ(kLwpaErrOk, lwpa_getaddrinfo(test_hostname, test_service, &ai_hints, &ai)); - ASSERT_TRUE(LWPA_IP_IS_V4(&ai.ai_addr.ip)); - lwpa_freeaddrinfo(&ai); - - ai_hints.ai_flags = LWPA_AI_NUMERICHOST; - ASSERT_EQ(kLwpaErrOk, lwpa_getaddrinfo(test_gai_ip_str, test_gai_port_str, &ai_hints, &ai)); - ASSERT_TRUE(LWPA_IP_IS_V4(&ai.ai_addr.ip)); - ASSERT_EQ(LWPA_IP_V4_ADDRESS(&ai.ai_addr.ip), test_gai_ip); - ASSERT_EQ(ai.ai_addr.port, test_gai_port); -} From 75cf574cf97be2455773f1436c4f934aeaf00ecc Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sat, 17 Aug 2019 23:11:21 -0500 Subject: [PATCH 104/264] Finish porting the rest of the tests. --- tests/integration/socket_integration_test.c | 77 ++++ tests/unit/CMakeLists.txt | 3 + tests/unit/test_socket.c | 254 +++++++++++++ tests/unit/test_socket_poll.cpp | 343 ------------------ tests/unit/{test_thread.cpp => test_thread.c} | 112 +++--- tests/unit/{test_timer.cpp => test_timer.c} | 62 ++-- tests/unit/test_uuid.c | 195 ++++++++++ tests/unit/test_uuid.cpp | 159 -------- 8 files changed, 620 insertions(+), 585 deletions(-) delete mode 100644 tests/unit/test_socket_poll.cpp rename tests/unit/{test_thread.cpp => test_thread.c} (51%) rename tests/unit/{test_timer.cpp => test_timer.c} (52%) create mode 100644 tests/unit/test_uuid.c delete mode 100644 tests/unit/test_uuid.cpp diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index f900f5134..d06b8f03f 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -22,6 +22,20 @@ #include "lwpa/netint.h" #include "lwpa/thread.h" +// Disable sprintf() warning on Windows/MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + +#ifndef LWPA_BULK_POLL_TEST_NUM_SOCKETS +#if LWPA_SOCKET_MAX_POLL_SIZE <= 0 || LWPA_SOCKET_MAX_POLL_SIZE > 1024 +// Limit the bulk socket test to a reasonable number +#define LWPA_BULK_POLL_TEST_NUM_SOCKETS 512 +#else +#define LWPA_BULK_POLL_TEST_NUM_SOCKETS LWPA_SOCKET_MAX_POLL_SIZE +#endif +#endif + #define NUM_TEST_PACKETS 1000 static LwpaNetintInfo v4_netint; @@ -386,6 +400,67 @@ TEST(socket_integration, multicast_udp_ipv6) } #endif +// Test to make sure lwpa_poll_* functions work properly with a large number of sockets. +// (Tests the maximum number defined by LWPA_SOCKET_MAX_POLL_SIZE if that number is well-defined and +// reasonable). +TEST(socket_integration, bulk_poll) +{ + LwpaPollContext context; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_context_init(&context)); + + static lwpa_socket_t socket_arr[LWPA_BULK_POLL_TEST_NUM_SOCKETS]; + static uint16_t bind_ports[LWPA_BULK_POLL_TEST_NUM_SOCKETS]; + for (size_t i = 0; i < LWPA_BULK_POLL_TEST_NUM_SOCKETS; ++i) + { + char error_msg[50]; + sprintf(error_msg, "Failed on iteration %zu", i); + + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &socket_arr[i]), error_msg); + TEST_ASSERT_NOT_EQUAL_MESSAGE(socket_arr[i], LWPA_SOCKET_INVALID, error_msg); + + LwpaSockaddr bind_addr; + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); + bind_addr.port = 0; + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_bind(socket_arr[i], &bind_addr), error_msg); + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_getsockname(socket_arr[i], &bind_addr), error_msg); + bind_ports[i] = bind_addr.port; + + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_poll_add_socket(&context, socket_arr[i], LWPA_POLL_IN, NULL), error_msg); + } + + lwpa_socket_t poll_send_sock; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &poll_send_sock)); + + LwpaSockaddr poll_send_addr; + LWPA_IP_SET_V4_ADDRESS(&poll_send_addr.ip, 0x7f000001); + for (size_t i = 0; i < LWPA_BULK_POLL_TEST_NUM_SOCKETS; ++i) + { + char error_msg[50]; + sprintf(error_msg, "Failed on iteration %zu", i); + + // Send to each socket in turn and make sure poll works for it + poll_send_addr.port = bind_ports[i]; + lwpa_sendto(poll_send_sock, kSocketTestMessage, SOCKET_TEST_MESSAGE_LENGTH, 0, &poll_send_addr); + + LwpaPollEvent event; + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100), error_msg); + TEST_ASSERT_EQUAL_MESSAGE(event.socket, socket_arr[i], error_msg); + TEST_ASSERT_EQUAL_MESSAGE(event.events, LWPA_POLL_IN, error_msg); + TEST_ASSERT_EQUAL_MESSAGE(event.err, kLwpaErrOk, error_msg); + + uint8_t recv_buf[SOCKET_TEST_MESSAGE_LENGTH]; + TEST_ASSERT_GREATER_THAN(0, lwpa_recvfrom(socket_arr[i], recv_buf, SOCKET_TEST_MESSAGE_LENGTH, 0, NULL)); + } + + for (size_t i = 0; i < LWPA_BULK_POLL_TEST_NUM_SOCKETS; ++i) + { + char error_msg[50]; + sprintf(error_msg, "Failed on iteration %zu", i); + + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_close(socket_arr[i]), error_msg); + } +} + TEST_GROUP_RUNNER(socket_integration) { TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS)); @@ -404,5 +479,7 @@ TEST_GROUP_RUNNER(socket_integration) RUN_TEST_CASE(socket_integration, multicast_udp_ipv6); #endif + RUN_TEST_CASE(socket_integration, bulk_poll); + lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); } diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index cdbbba6f7..7dfee65ef 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -39,6 +39,9 @@ lwpa_add_live_test(test_netint test_netint.c) lwpa_add_live_test(test_pack test_pack.c) lwpa_add_live_test(test_rbtree test_rbtree.c) lwpa_add_live_test(test_socket test_socket.c) +lwpa_add_live_test(test_thread test_thread.c) +lwpa_add_live_test(test_timer test_timer.c) +lwpa_add_live_test(test_uuid test_uuid.c) lwpa_add_custom_test(test_timer_wraparound test_timer_wraparound.c diff --git a/tests/unit/test_socket.c b/tests/unit/test_socket.c index d422fd2b6..02bee870d 100644 --- a/tests/unit/test_socket.c +++ b/tests/unit/test_socket.c @@ -66,6 +66,255 @@ TEST(lwpa_socket, sockopts) // TODO, need getsockopt() implemented for this } +// Test to make sure various invalid calls to lwpa_poll_* functions fail properly. +TEST(lwpa_socket, poll_invalid_calls_fail) +{ + LwpaPollContext context; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_context_init(&context)); + + // Wait should fail with a meaningful error code when no sockets have been added + LwpaPollEvent event; + TEST_ASSERT_EQUAL(kLwpaErrNoSockets, lwpa_poll_wait(&context, &event, 100)); + + lwpa_socket_t sock; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock)); + TEST_ASSERT_NOT_EQUAL(sock, LWPA_SOCKET_INVALID); + + // Deinit and make sure add of a valid socket fails + lwpa_poll_context_deinit(&context); + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock, LWPA_POLL_IN, NULL)); + + // Initialize the context and add invalid sockets or invalid events + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_context_init(&context)); + + // Add invalid socket + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, LWPA_SOCKET_INVALID, LWPA_POLL_IN, NULL)); + + // Add socket with invalid events + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock, 0, NULL)); + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock, LWPA_POLL_ERR, NULL)); + + // Try to modify a socket that has not been added + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_modify_socket(&context, sock, LWPA_POLL_IN, NULL)); + + // Add the socket and try to modify it with invalid calls + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock, LWPA_POLL_IN, NULL)); + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_modify_socket(&context, sock, 0, NULL)); // Invalid events + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_modify_socket(&context, sock, LWPA_POLL_ERR, NULL)); // Invalid events + + // Deinit and make sure we cannot modify + lwpa_poll_context_deinit(&context); + TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_modify_socket(&context, sock, LWPA_POLL_OUT, NULL)); +} + +TEST(lwpa_socket, poll_user_data_works) +{ + lwpa_socket_t sock_1, sock_2; + void* user_data_1 = (void*)1; + void* user_data_2 = (void*)2; + + LwpaPollContext context; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_context_init(&context)); + + // Create two UDP sockets and poll for writability, make sure our user data gets passed back to us + // intact. + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock_1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock_2)); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock_1, LWPA_POLL_OUT, user_data_1)); + + LwpaPollEvent event; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100)); + TEST_ASSERT_EQUAL(event.socket, sock_1); + TEST_ASSERT_EQUAL(event.user_data, user_data_1); + + lwpa_poll_remove_socket(&context, sock_1); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock_2, LWPA_POLL_OUT, user_data_2)); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100)); + TEST_ASSERT_EQUAL(event.socket, sock_2); + TEST_ASSERT_EQUAL(event.user_data, user_data_2); + + // Modify and make sure we get the updated user data + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_modify_socket(&context, sock_2, LWPA_POLL_OUT, user_data_1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100)); + TEST_ASSERT_EQUAL(event.socket, sock_2); + TEST_ASSERT_EQUAL(event.user_data, user_data_1); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(sock_1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(sock_2)); + lwpa_poll_context_deinit(&context); +} + +#define POLL_MODIFY_TEST_PORT_BASE 8000 + +// Test the lwpa_poll_modify_socket() functionality, using UDP sockets for simplicity +TEST(lwpa_socket, poll_modify_socket_works) +{ + lwpa_socket_t sock = LWPA_SOCKET_INVALID; + + LwpaPollContext context; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_context_init(&context)); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock)); + TEST_ASSERT_NOT_EQUAL(sock, LWPA_SOCKET_INVALID); + + // Bind the socket to the wildcard address and a specific port. + LwpaSockaddr bind_addr; + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); + bind_addr.port = POLL_MODIFY_TEST_PORT_BASE; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(sock, &bind_addr)); + + // Add it for output polling first + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock, LWPA_POLL_OUT, NULL)); + + // Socket should be ready right away + LwpaPollEvent event; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100)); + TEST_ASSERT_EQUAL(event.socket, sock); + TEST_ASSERT_EQUAL(event.events, LWPA_POLL_OUT); + TEST_ASSERT_EQUAL(event.err, kLwpaErrOk); + + // Modify it to do input polling + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_modify_socket(&context, sock, LWPA_POLL_IN, NULL)); + + // Should time out now + TEST_ASSERT_EQUAL(kLwpaErrTimedOut, lwpa_poll_wait(&context, &event, 100)); + + // Send data to socket + LwpaSockaddr send_addr; + LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, 0x7f000001); + send_addr.port = POLL_MODIFY_TEST_PORT_BASE; + lwpa_sendto(sock, (const uint8_t*)"test message", sizeof("test message"), 0, &send_addr); + + // Should get the poll in event + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100)); + TEST_ASSERT_EQUAL(event.socket, sock); + TEST_ASSERT_EQUAL(event.events, LWPA_POLL_IN); + TEST_ASSERT_EQUAL(event.err, kLwpaErrOk); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(sock)); + lwpa_poll_context_deinit(&context); +} + +#define POLL_UDP_IN_TEST_PORT_BASE 9000 + +// Test the lwpa_poll_* API, polling for readability on UDP sockets. +TEST(lwpa_socket, poll_for_readability_on_udp_sockets_works) +{ + lwpa_socket_t send_sock = LWPA_SOCKET_INVALID; + lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; + lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; + + LwpaPollContext context; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_context_init(&context)); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); + TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); + TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); + TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); + + // Bind socket 1 to the wildcard address and a specific port. + LwpaSockaddr bind_addr; + lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); + bind_addr.port = POLL_UDP_IN_TEST_PORT_BASE; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); + + // Bind socket 2 to the wildcard address and a different port. + bind_addr.port = POLL_UDP_IN_TEST_PORT_BASE + 1; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); + + // Get the poll context set up + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, rcvsock1, LWPA_POLL_IN, NULL)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, rcvsock2, LWPA_POLL_IN, NULL)); + + // Test poll with nothing sending - should time out. + LwpaPollEvent event; + TEST_ASSERT_EQUAL(kLwpaErrTimedOut, lwpa_poll_wait(&context, &event, 100)); + + LwpaSockaddr send_addr; + LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, 0x7f000001); + send_addr.port = POLL_UDP_IN_TEST_PORT_BASE; + +#define POLL_UDP_IN_TEST_MESSAGE (const uint8_t*)"test message" +#define POLL_UDP_IN_TEST_MESSAGE_LENGTH sizeof("test message") + + lwpa_sendto(send_sock, POLL_UDP_IN_TEST_MESSAGE, POLL_UDP_IN_TEST_MESSAGE_LENGTH, 0, &send_addr); + send_addr.port = POLL_UDP_IN_TEST_PORT_BASE + 1; + lwpa_sendto(send_sock, POLL_UDP_IN_TEST_MESSAGE, POLL_UDP_IN_TEST_MESSAGE_LENGTH, 0, &send_addr); + + // Poll once, make sure we get one of the sockets. + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 1000)); + TEST_ASSERT(event.socket == rcvsock1 || event.socket == rcvsock2); + TEST_ASSERT_EQUAL(event.events, LWPA_POLL_IN); + TEST_ASSERT_EQUAL(event.err, kLwpaErrOk); + + // Receive data on the socket. + uint8_t recv_buf[POLL_UDP_IN_TEST_MESSAGE_LENGTH]; + LwpaSockaddr from_addr; + TEST_ASSERT_EQUAL(POLL_UDP_IN_TEST_MESSAGE_LENGTH, + (size_t)lwpa_recvfrom(event.socket, recv_buf, POLL_UDP_IN_TEST_MESSAGE_LENGTH, 0, &from_addr)); + TEST_ASSERT(lwpa_ip_equal(&send_addr.ip, &from_addr.ip)); + TEST_ASSERT_NOT_EQUAL(from_addr.port, POLL_UDP_IN_TEST_PORT_BASE); + TEST_ASSERT_NOT_EQUAL(from_addr.port, POLL_UDP_IN_TEST_PORT_BASE + 1); + TEST_ASSERT_EQUAL_MEMORY(recv_buf, POLL_UDP_IN_TEST_MESSAGE, POLL_UDP_IN_TEST_MESSAGE_LENGTH); + + lwpa_socket_t first_socket = event.socket; + + // Poll a second time for the other socket. + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 1000)); + if (first_socket == rcvsock1) + TEST_ASSERT_EQUAL(event.socket, rcvsock2); + else + TEST_ASSERT_EQUAL(event.socket, rcvsock1); + TEST_ASSERT_EQUAL(event.events, LWPA_POLL_IN); + TEST_ASSERT_EQUAL(event.err, kLwpaErrOk); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); + lwpa_poll_context_deinit(&context); +} + +// Test the lwpa_poll_* API, polling for writeablility on UDP sockets. +TEST(lwpa_socket, poll_for_writability_on_udp_sockets_works) +{ + lwpa_socket_t sock_1, sock_2; + + LwpaPollContext context; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_context_init(&context)); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock_1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock_2)); + + // The sockets should poll as ready for output right away. Not sure what else there is to test + // here. + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock_1, LWPA_POLL_OUT, NULL)); + + LwpaPollEvent event; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100)); + TEST_ASSERT_EQUAL(event.socket, sock_1); + TEST_ASSERT_EQUAL(event.events, LWPA_POLL_OUT); + TEST_ASSERT_EQUAL(event.err, kLwpaErrOk); + + lwpa_poll_remove_socket(&context, sock_1); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_add_socket(&context, sock_2, LWPA_POLL_OUT, NULL)); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100)); + TEST_ASSERT_EQUAL(event.socket, sock_2); + TEST_ASSERT_EQUAL(event.events, LWPA_POLL_OUT); + TEST_ASSERT_EQUAL(event.err, kLwpaErrOk); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(sock_1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(sock_2)); + lwpa_poll_context_deinit(&context); +} + TEST(lwpa_socket, getaddrinfo_works_as_expected) { LwpaAddrinfo ai_hints; @@ -88,6 +337,11 @@ TEST_GROUP_RUNNER(lwpa_socket) { RUN_TEST_CASE(lwpa_socket, bind_works_as_expected); RUN_TEST_CASE(lwpa_socket, sockopts); + RUN_TEST_CASE(lwpa_socket, poll_invalid_calls_fail); + RUN_TEST_CASE(lwpa_socket, poll_user_data_works); + RUN_TEST_CASE(lwpa_socket, poll_modify_socket_works); + RUN_TEST_CASE(lwpa_socket, poll_for_readability_on_udp_sockets_works); + RUN_TEST_CASE(lwpa_socket, poll_for_writability_on_udp_sockets_works); RUN_TEST_CASE(lwpa_socket, getaddrinfo_works_as_expected); } diff --git a/tests/unit/test_socket_poll.cpp b/tests/unit/test_socket_poll.cpp deleted file mode 100644 index 0383d0197..000000000 --- a/tests/unit/test_socket_poll.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ - -// This file tests the lwpa_poll_* functions in lwpa_socket. - -#include -#include "lwpa/socket.h" -#include "lwpa/netint.h" -#include "gtest/gtest.h" - -#if LWPA_SOCKET_MAX_POLL_SIZE <= 0 || LWPA_SOCKET_MAX_POLL_SIZE > 1024 -// Limit the bulk socket test to a reasonable number -#define BULK_POLL_TEST_NUM_SOCKETS 512 -#else -#define BULK_POLL_TEST_NUM_SOCKETS LWPA_SOCKET_MAX_POLL_SIZE -#endif - -class SocketPollTest : public ::testing::Test -{ -protected: - SocketPollTest() - { - lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); - lwpa_netint_get_default_interface(kLwpaIpTypeV4, &default_netint_); - } - ~SocketPollTest() { lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); } - - LwpaNetintInfo default_netint_; - - static const char* SEND_MSG; - static const size_t SEND_MSG_LEN; - - void SetUp() override { ASSERT_EQ(kLwpaErrOk, lwpa_poll_context_init(&context_)); } - void TearDown() override { lwpa_poll_context_deinit(&context_); } - - LwpaPollContext context_{}; -}; - -const char* SocketPollTest::SEND_MSG = "testtesttest"; -const size_t SocketPollTest::SEND_MSG_LEN = 12; - -// Test to make sure various invalid calls to lwpa_poll_* functions fail properly. -TEST_F(SocketPollTest, invalid_calls) -{ - // Wait should fail with a meaningful error code when no sockets have been added - LwpaPollEvent event; - ASSERT_EQ(kLwpaErrNoSockets, lwpa_poll_wait(&context_, &event, 100)); - - lwpa_socket_t sock; - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock)); - ASSERT_NE(sock, LWPA_SOCKET_INVALID); - - // Deinit and make sure add of a valid socket fails - lwpa_poll_context_deinit(&context_); - EXPECT_NE(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock, LWPA_POLL_IN, nullptr)); - - // Initialize the context and add invalid sockets or invalid events - ASSERT_EQ(kLwpaErrOk, lwpa_poll_context_init(&context_)); - - // Add invalid socket - EXPECT_NE(kLwpaErrOk, lwpa_poll_add_socket(&context_, LWPA_SOCKET_INVALID, LWPA_POLL_IN, nullptr)); - - // Add socket with invalid events - EXPECT_NE(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock, 0, nullptr)); - EXPECT_NE(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock, LWPA_POLL_ERR, nullptr)); - - // Try to modify a socket that has not been added - EXPECT_NE(kLwpaErrOk, lwpa_poll_modify_socket(&context_, sock, LWPA_POLL_IN, nullptr)); - - // Add the socket and try to modify it with invalid calls - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock, LWPA_POLL_IN, nullptr)); - EXPECT_NE(kLwpaErrOk, lwpa_poll_modify_socket(&context_, sock, 0, nullptr)); // Invalid events - EXPECT_NE(kLwpaErrOk, lwpa_poll_modify_socket(&context_, sock, LWPA_POLL_ERR, nullptr)); // Invalid events - - // Deinit and make sure we cannot modify - lwpa_poll_context_deinit(&context_); - EXPECT_NE(kLwpaErrOk, lwpa_poll_modify_socket(&context_, sock, LWPA_POLL_OUT, nullptr)); -} - -// Test the user_data passing functionality. -TEST_F(SocketPollTest, user_data) -{ - lwpa_socket_t sock_1, sock_2; - void* user_data_1 = reinterpret_cast(1); - void* user_data_2 = reinterpret_cast(2); - - // Create two UDP sockets and poll for writability, make sure our user data gets passed back to us - // intact. - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock_1)); - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock_2)); - - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock_1, LWPA_POLL_OUT, user_data_1)); - - LwpaPollEvent event; - ASSERT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 100)); - ASSERT_EQ(event.socket, sock_1); - ASSERT_EQ(event.user_data, user_data_1); - - lwpa_poll_remove_socket(&context_, sock_1); - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock_2, LWPA_POLL_OUT, user_data_2)); - - ASSERT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 100)); - ASSERT_EQ(event.socket, sock_2); - ASSERT_EQ(event.user_data, user_data_2); - - // Modify and make sure we get the updated user data - ASSERT_EQ(kLwpaErrOk, lwpa_poll_modify_socket(&context_, sock_2, LWPA_POLL_OUT, user_data_1)); - ASSERT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 100)); - ASSERT_EQ(event.socket, sock_2); - ASSERT_EQ(event.user_data, user_data_1); - - ASSERT_EQ(kLwpaErrOk, lwpa_close(sock_1)); - ASSERT_EQ(kLwpaErrOk, lwpa_close(sock_2)); -} - -#define POLL_MODIFY_TEST_PORT_BASE 8000 - -// Test the lwpa_poll_modify_socket() functionality, using UDP sockets for simplicity -TEST_F(SocketPollTest, modify) -{ - lwpa_socket_t sock = LWPA_SOCKET_INVALID; - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock)); - ASSERT_NE(sock, LWPA_SOCKET_INVALID); - - // Bind the socket to the wildcard address and a specific port. - LwpaSockaddr bind_addr; - lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = POLL_MODIFY_TEST_PORT_BASE; - ASSERT_EQ(kLwpaErrOk, lwpa_bind(sock, &bind_addr)); - - // Add it for output polling first - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock, LWPA_POLL_OUT, nullptr)); - - // Socket should be ready right away - LwpaPollEvent event; - EXPECT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 100)); - EXPECT_EQ(event.socket, sock); - EXPECT_EQ(event.events, LWPA_POLL_OUT); - EXPECT_EQ(event.err, kLwpaErrOk); - - // Modify it to do input polling - ASSERT_EQ(kLwpaErrOk, lwpa_poll_modify_socket(&context_, sock, LWPA_POLL_IN, nullptr)); - - // Should time out now - EXPECT_EQ(kLwpaErrTimedOut, lwpa_poll_wait(&context_, &event, 100)); - - // Send data to socket - LwpaSockaddr send_addr; - send_addr.ip = default_netint_.addr; - send_addr.port = POLL_MODIFY_TEST_PORT_BASE; - lwpa_sendto(sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); - - // Should get the poll in event - EXPECT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 100)); - EXPECT_EQ(event.socket, sock); - EXPECT_EQ(event.events, LWPA_POLL_IN); - EXPECT_EQ(event.err, kLwpaErrOk); - - ASSERT_EQ(kLwpaErrOk, lwpa_close(sock)); -} - -// Test to make sure lwpa_poll_* functions work properly with a large number of sockets. -// (Tests the maximum number defined by LWPA_SOCKET_MAX_POLL_SIZE if that number is well-defined and -// reasonable). -TEST_F(SocketPollTest, bulk_poll) -{ - ASSERT_EQ(kLwpaErrOk, lwpa_poll_context_init(&context_)); - - std::array socket_arr; - std::array bind_ports; - for (size_t i = 0; i < BULK_POLL_TEST_NUM_SOCKETS + 1; ++i) - { - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &socket_arr[i])) << "Failed on iteration " << i; - ASSERT_NE(socket_arr[i], LWPA_SOCKET_INVALID) << "Failed on iteration " << i; - - if (i < BULK_POLL_TEST_NUM_SOCKETS) - { - LwpaSockaddr bind_addr; - lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = 0; - ASSERT_EQ(kLwpaErrOk, lwpa_bind(socket_arr[i], &bind_addr)) << "Failed on iteration " << i; - ASSERT_EQ(kLwpaErrOk, lwpa_getsockname(socket_arr[i], &bind_addr)) << "Failed on iteration " << i; - bind_ports[i] = bind_addr.port; - - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, socket_arr[i], LWPA_POLL_IN, nullptr)) - << "Failed on iteration " << i; - } - } - - // The first socket over BULK_POLL_TEST_NUM_SOCKETS should fail - // ASSERT_NE(kLwpaErrOk, lwpa_poll_add_socket(&context_, socket_arr[BULK_POLL_TEST_NUM_SOCKETS], LWPA_POLL_IN, - // nullptr)); - - lwpa_socket_t send_sock; - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); - - LwpaSockaddr send_addr; - LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, 0x7f000001); - for (size_t i = 0; i < BULK_POLL_TEST_NUM_SOCKETS; ++i) - { - // Send to each socket in turn and make sure poll works for it - send_addr.port = bind_ports[i]; - lwpa_sendto(send_sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); - - LwpaPollEvent event; - ASSERT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 100)) << "Failed on iteration " << i; - ASSERT_EQ(event.socket, socket_arr[i]) << "Failed on iteration " << i; - ASSERT_EQ(event.events, LWPA_POLL_IN) << "Failed on iteration " << i; - ASSERT_EQ(event.err, kLwpaErrOk) << "Failed on iteration " << i; - - std::array recv_buf; - ASSERT_GT(lwpa_recvfrom(socket_arr[i], recv_buf.data(), SEND_MSG_LEN, 0, nullptr), 0); - } - - for (size_t i = 0; i < BULK_POLL_TEST_NUM_SOCKETS + 1; ++i) - { - EXPECT_EQ(kLwpaErrOk, lwpa_close(socket_arr[i])) << "Failed on iteration " << i; - } -} - -#define POLL_UDP_IN_TEST_PORT_BASE 9000 - -// Test the lwpa_poll_* API, polling for readability on UDP sockets. -TEST_F(SocketPollTest, udp_in) -{ - lwpa_socket_t send_sock = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); - ASSERT_NE(rcvsock1, LWPA_SOCKET_INVALID); - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); - ASSERT_NE(rcvsock2, LWPA_SOCKET_INVALID); - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); - ASSERT_NE(send_sock, LWPA_SOCKET_INVALID); - - // Bind socket 1 to the wildcard address and a specific port. - LwpaSockaddr bind_addr; - lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); - bind_addr.port = POLL_UDP_IN_TEST_PORT_BASE; - ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); - - // Bind socket 2 to the wildcard address and a different port. - bind_addr.port = POLL_UDP_IN_TEST_PORT_BASE + 1; - ASSERT_EQ(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); - - // Get the poll context set up - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, rcvsock1, LWPA_POLL_IN, nullptr)); - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, rcvsock2, LWPA_POLL_IN, nullptr)); - - // Test poll with nothing sending - should time out. - LwpaPollEvent event; - ASSERT_EQ(kLwpaErrTimedOut, lwpa_poll_wait(&context_, &event, 100)); - - LwpaSockaddr send_addr; - send_addr.ip = default_netint_.addr; - send_addr.port = POLL_UDP_IN_TEST_PORT_BASE; - - lwpa_sendto(send_sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); - send_addr.port = POLL_UDP_IN_TEST_PORT_BASE + 1; - lwpa_sendto(send_sock, SEND_MSG, SEND_MSG_LEN, 0, &send_addr); - - // Poll once, make sure we get one of the sockets. - ASSERT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 1000)); - ASSERT_TRUE(event.socket == rcvsock1 || event.socket == rcvsock2); - ASSERT_EQ(event.events, LWPA_POLL_IN); - ASSERT_EQ(event.err, kLwpaErrOk); - - // Receive data on the socket. - std::array recv_buf; - LwpaSockaddr from_addr; - ASSERT_EQ(SEND_MSG_LEN, (size_t)lwpa_recvfrom(event.socket, recv_buf.data(), SEND_MSG_LEN, 0, &from_addr)); - ASSERT_TRUE(lwpa_ip_equal(&send_addr.ip, &from_addr.ip)); - ASSERT_NE(from_addr.port, POLL_UDP_IN_TEST_PORT_BASE); - ASSERT_NE(from_addr.port, POLL_UDP_IN_TEST_PORT_BASE + 1); - recv_buf[SEND_MSG_LEN] = '\0'; - ASSERT_EQ(0, strcmp((char*)recv_buf.data(), SEND_MSG)); - - lwpa_socket_t first_socket = event.socket; - - // Poll a second time for the other socket. - ASSERT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 1000)); - if (first_socket == rcvsock1) - ASSERT_EQ(event.socket, rcvsock2); - else - ASSERT_EQ(event.socket, rcvsock1); - ASSERT_EQ(event.events, LWPA_POLL_IN); - ASSERT_EQ(event.err, kLwpaErrOk); - - ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock1)); - ASSERT_EQ(kLwpaErrOk, lwpa_close(rcvsock2)); - ASSERT_EQ(kLwpaErrOk, lwpa_close(send_sock)); -} - -// Test the lwpa_poll_* API, polling for writeablility on UDP sockets. -TEST_F(SocketPollTest, udp_out) -{ - lwpa_socket_t sock_1, sock_2; - - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock_1)); - ASSERT_EQ(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &sock_2)); - - // The sockets should poll as ready for output right away. Not sure what else there is to test - // here. - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock_1, LWPA_POLL_OUT, nullptr)); - - LwpaPollEvent event; - ASSERT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 100)); - ASSERT_EQ(event.socket, sock_1); - ASSERT_EQ(event.events, LWPA_POLL_OUT); - ASSERT_EQ(event.err, kLwpaErrOk); - - lwpa_poll_remove_socket(&context_, sock_1); - ASSERT_EQ(kLwpaErrOk, lwpa_poll_add_socket(&context_, sock_2, LWPA_POLL_OUT, nullptr)); - - ASSERT_EQ(kLwpaErrOk, lwpa_poll_wait(&context_, &event, 100)); - ASSERT_EQ(event.socket, sock_2); - ASSERT_EQ(event.events, LWPA_POLL_OUT); - ASSERT_EQ(event.err, kLwpaErrOk); - - ASSERT_EQ(kLwpaErrOk, lwpa_close(sock_1)); - ASSERT_EQ(kLwpaErrOk, lwpa_close(sock_2)); -} diff --git a/tests/unit/test_thread.cpp b/tests/unit/test_thread.c similarity index 51% rename from tests/unit/test_thread.cpp rename to tests/unit/test_thread.c index 5332ae06b..6747804f5 100644 --- a/tests/unit/test_thread.cpp +++ b/tests/unit/test_thread.c @@ -17,35 +17,32 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/thread.h" -#include "gtest/gtest.h" -#include -#include +#include "unity_fixture.h" -class ThreadTest : public ::testing::Test +#include "lwpa/bool.h" + +TEST_GROUP(lwpa_thread); + +TEST_SETUP(lwpa_thread) +{ +} + +TEST_TEAR_DOWN(lwpa_thread) { -public: - // For create_destroy - volatile bool waitthread_run{false}; +} - // for time_slice - volatile bool spin_task_run{false}; - volatile bool spin_task_ran{false}; - volatile bool oneshot_task_run{false}; - volatile bool oneshot_task_ran{false}; -}; +volatile bool waitthread_run; void wait_and_exit(void* param) { - ThreadTest* tt = static_cast(param); - if (tt) - { - while (tt->waitthread_run) - lwpa_thread_sleep(5); - } + (void)param; + + while (waitthread_run) + lwpa_thread_sleep(5); } // Basic test of the three thread functions. -TEST_F(ThreadTest, create_destroy) +TEST(lwpa_thread, create_and_destroy_functions_work) { LwpaThreadParams params = { LWPA_THREAD_DEFAULT_PRIORITY, // thread_priority @@ -56,53 +53,39 @@ TEST_F(ThreadTest, create_destroy) lwpa_thread_t wait_thread; waitthread_run = true; - ASSERT_TRUE(lwpa_thread_create(&wait_thread, ¶ms, wait_and_exit, this)); - - ////////////////////////////////////////////////////////////////////////////// - // Time-based functionality not implemented for now. - ////////////////////////////////////////////////////////////////////////////// - - // Stop should time out if the thread is still looping. - // auto start_time = std::chrono::high_resolution_clock::now(); - - // ASSERT_FALSE(lwpa_thread_join(&wait_thread, 100)); - // It should wait for at least the timeout specified, minus a fudge factor to account for - // differing time resolutions on platforms. - // auto time_taken = - // std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time); - // ASSERT_GE(time_taken.count(), 80); + TEST_ASSERT(lwpa_thread_create(&wait_thread, ¶ms, wait_and_exit, NULL)); // Stop should work if the thread has exited. waitthread_run = false; - ASSERT_TRUE(lwpa_thread_join(&wait_thread)); + TEST_ASSERT(lwpa_thread_join(&wait_thread)); } +volatile bool spin_task_run; +volatile bool spin_task_ran; + void increment_and_spin(void* param) { - ThreadTest* tt = static_cast(param); - if (tt) - { - tt->spin_task_ran = true; - while (tt->spin_task_run) - ; - } + (void)param; + + spin_task_ran = true; + while (spin_task_run) + ; } +volatile bool oneshot_task_run; +volatile bool oneshot_task_ran; + void oneshot(void* param) { - ThreadTest* tt = static_cast(param); - if (tt) - { - if (tt->oneshot_task_run) - tt->oneshot_task_ran = true; - } -} + (void)param; -using namespace std::chrono_literals; + if (oneshot_task_run) + oneshot_task_ran = true; +} // Test time slicing. One thread spins constantly; if time slicing works, the second thread should // get a chance to set its flag. Failure mode could be the flag not being set or a full test timeout. -TEST_F(ThreadTest, time_slice) +TEST(lwpa_thread, threads_are_time_sliced) { LwpaThreadParams params = { LWPA_THREAD_DEFAULT_PRIORITY, // thread_priority @@ -115,16 +98,27 @@ TEST_F(ThreadTest, time_slice) oneshot_task_run = true; // Create the spin task. - ASSERT_TRUE(lwpa_thread_create(&spin_task, ¶ms, increment_and_spin, this)); + TEST_ASSERT_TRUE(lwpa_thread_create(&spin_task, ¶ms, increment_and_spin, NULL)); // Create the oneshot task. - ASSERT_TRUE(lwpa_thread_create(&oneshot_task, ¶ms, oneshot, this)); + TEST_ASSERT_TRUE(lwpa_thread_create(&oneshot_task, ¶ms, oneshot, NULL)); // Give both tasks time to run. - std::this_thread::sleep_for(100ms); + lwpa_thread_sleep(100); // Stop the tasks oneshot_task_run = false; - ASSERT_TRUE(lwpa_thread_join(&oneshot_task)); + TEST_ASSERT_TRUE(lwpa_thread_join(&oneshot_task)); spin_task_run = false; - ASSERT_TRUE(lwpa_thread_join(&spin_task)); - ASSERT_TRUE(spin_task_ran); - ASSERT_TRUE(oneshot_task_ran); + TEST_ASSERT_TRUE(lwpa_thread_join(&spin_task)); + TEST_ASSERT_TRUE(spin_task_ran); + TEST_ASSERT_TRUE(oneshot_task_ran); } + +TEST_GROUP_RUNNER(lwpa_thread) +{ + RUN_TEST_CASE(lwpa_thread, create_and_destroy_functions_work); + RUN_TEST_CASE(lwpa_thread, threads_are_time_sliced); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_thread); +} \ No newline at end of file diff --git a/tests/unit/test_timer.cpp b/tests/unit/test_timer.c similarity index 52% rename from tests/unit/test_timer.cpp rename to tests/unit/test_timer.c index 2d494fdb6..5166bccd5 100644 --- a/tests/unit/test_timer.cpp +++ b/tests/unit/test_timer.c @@ -16,34 +16,37 @@ * This file is a part of lwpa. For more information, go to: * https://github.com/ETCLabs/lwpa ******************************************************************************/ - -#include "lwpa/common.h" #include "lwpa/timer.h" +#include "unity_fixture.h" + +// Interdependency is unavoidable here, we need a platform-neutral sleep +#include "lwpa/thread.h" -#include "gtest/gtest.h" -#include +TEST_GROUP(lwpa_timer); -class TimerTest : public ::testing::Test +TEST_SETUP(lwpa_timer) { - void SetUp() override { ASSERT_EQ(kLwpaErrOk, lwpa_init(LWPA_FEATURE_TIMERS)); } - void TearDown() override { lwpa_deinit(LWPA_FEATURE_TIMERS); } -}; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_TIMERS)); +} -using namespace std::chrono_literals; +TEST_TEAR_DOWN(lwpa_timer) +{ + lwpa_deinit(LWPA_FEATURE_TIMERS); +} -TEST_F(TimerTest, getms) +TEST(lwpa_timer, getms_gets_increasing_values) { uint32_t t1, t2; t1 = lwpa_getms(); - std::this_thread::sleep_for(10ms); + lwpa_thread_sleep(10); t2 = lwpa_getms(); - ASSERT_NE(t1, 0u); - ASSERT_NE(t2, 0u); - ASSERT_GE((int32_t)t2 - (int32_t)t1, 0); + TEST_ASSERT_NOT_EQUAL(t1, 0u); + TEST_ASSERT_NOT_EQUAL(t2, 0u); + TEST_ASSERT_GREATER_OR_EQUAL_INT32(0, (int32_t)t2 - (int32_t)t1); } -TEST_F(TimerTest, timeouts) +TEST(lwpa_timer, timers_report_expired_properly) { LwpaTimer t1, t2; @@ -51,23 +54,34 @@ TEST_F(TimerTest, timeouts) lwpa_timer_start(&t2, 100); // A timer with a timeout of 0 should start expired. - ASSERT_TRUE(lwpa_timer_is_expired(&t1)); + TEST_ASSERT(lwpa_timer_is_expired(&t1)); // The nonzero timeout should not be expired yet. - ASSERT_FALSE(lwpa_timer_is_expired(&t2)); + TEST_ASSERT_UNLESS(lwpa_timer_is_expired(&t2)); - std::this_thread::sleep_for(110ms); + lwpa_thread_sleep(110); // Now it should. - ASSERT_TRUE(lwpa_timer_is_expired(&t2)); - ASSERT_GE(lwpa_timer_elapsed(&t2), 100u); + TEST_ASSERT(lwpa_timer_is_expired(&t2)); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(100u, lwpa_timer_elapsed(&t2)); // Test resetting the timer. lwpa_timer_reset(&t2); - ASSERT_FALSE(lwpa_timer_is_expired(&t2)); + TEST_ASSERT_UNLESS(lwpa_timer_is_expired(&t2)); // And test the timeout one more time. - std::this_thread::sleep_for(110ms); - ASSERT_TRUE(lwpa_timer_is_expired(&t2)); - ASSERT_GE(lwpa_timer_elapsed(&t2), 100u); + lwpa_thread_sleep(110); + TEST_ASSERT(lwpa_timer_is_expired(&t2)); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(100u, lwpa_timer_elapsed(&t2)); +} + +TEST_GROUP_RUNNER(lwpa_timer) +{ + RUN_TEST_CASE(lwpa_timer, getms_gets_increasing_values); + RUN_TEST_CASE(lwpa_timer, timers_report_expired_properly); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_timer); } diff --git a/tests/unit/test_uuid.c b/tests/unit/test_uuid.c new file mode 100644 index 000000000..01fab3275 --- /dev/null +++ b/tests/unit/test_uuid.c @@ -0,0 +1,195 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "lwpa/uuid.h" +#include "unity_fixture.h" + +#include + +// Disable sprintf() warning on Windows/MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + +#define NUM_V1_UUID_GENERATIONS 10000 +#define NUM_V4_UUID_GENERATIONS 10000 + +TEST_GROUP(lwpa_uuid); + +TEST_SETUP(lwpa_uuid) +{ +} + +TEST_TEAR_DOWN(lwpa_uuid) +{ +} + +TEST(lwpa_uuid, uuid_is_null_works) +{ + LwpaUuid uuid = {{0}}; + TEST_ASSERT(LWPA_UUID_IS_NULL(&uuid)); + uuid = kLwpaNullUuid; + TEST_ASSERT(LWPA_UUID_IS_NULL(&uuid)); + for (uint8_t i = 0; i < LWPA_UUID_BYTES; ++i) + uuid.data[i] = i; + TEST_ASSERT_UNLESS(LWPA_UUID_IS_NULL(&uuid)); +} + +TEST(lwpa_uuid, uuid_compare_works) +{ + LwpaUuid uuid1 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; + LwpaUuid uuid1_dup = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; + LwpaUuid uuid2 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17}}; + + TEST_ASSERT_EQUAL(0, LWPA_UUID_CMP(&uuid1, &uuid1_dup)); + TEST_ASSERT_GREATER_THAN(0, LWPA_UUID_CMP(&uuid2, &uuid1)); + TEST_ASSERT_LESS_THAN(0, LWPA_UUID_CMP(&uuid1, &uuid2)); +} + +TEST(lwpa_uuid, uuid_to_string_conversion_works) +{ + char str_buf[LWPA_UUID_STRING_BYTES]; + LwpaUuid uuid = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; + + lwpa_uuid_to_string(str_buf, &uuid); + TEST_ASSERT_EQUAL_STRING(str_buf, "01020304-0506-0708-090a-0b0c0d0e0f10"); + + uuid = kLwpaNullUuid; + lwpa_uuid_to_string(str_buf, &uuid); + TEST_ASSERT_EQUAL_STRING(str_buf, "00000000-0000-0000-0000-000000000000"); +} + +TEST(lwpa_uuid, string_to_uuid_conversion_works) +{ + LwpaUuid uuid; + const char good_str[] = "08090a0b-0C0D-0e0f-1011-121314151617"; + const char short_str[] = "08090a0b-0c0d-0e0f-1011-1213141516"; + const char bad_str[] = "This isn't a UUID"; + + TEST_ASSERT(lwpa_string_to_uuid(&uuid, good_str, strlen(good_str))); + LwpaUuid uuid_cmp = {{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}}; + TEST_ASSERT_EQUAL(0, LWPA_UUID_CMP(&uuid, &uuid_cmp)); + + uuid = kLwpaNullUuid; + TEST_ASSERT_UNLESS(lwpa_string_to_uuid(&uuid, short_str, strlen(short_str))); + TEST_ASSERT_UNLESS(lwpa_string_to_uuid(&uuid, bad_str, strlen(bad_str))); +} + +TEST(lwpa_uuid, generates_correct_v1_uuids) +{ + // Generate a bunch of V1 UUIDs. They should all be unique from each other and have the proper + // version and variant information. We will cheat a little and just make sure that each one is + // unique from the last one generated. + LwpaUuid last_uuid = kLwpaNullUuid; + + for (int i = 0; i < NUM_V1_UUID_GENERATIONS; ++i) + { + LwpaUuid uuid; + char error_msg[100]; + sprintf(error_msg, "This failure occurred on UUID attempt %d of %d", i + 1, NUM_V1_UUID_GENERATIONS); + + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_generate_v1_uuid(&uuid), error_msg); + + // We should always have Variant 1, Version 1. + TEST_ASSERT_EQUAL_UINT8_MESSAGE((uuid.data[6] & 0xf0u), 0x10u, error_msg); + TEST_ASSERT_EQUAL_UINT8_MESSAGE((uuid.data[8] & 0xc0u), 0x80u, error_msg); + + // Should be unique from the last one generated. + TEST_ASSERT_NOT_EQUAL_MESSAGE(0, LWPA_UUID_CMP(&uuid, &last_uuid), error_msg); + + last_uuid = uuid; + } +} + +TEST(lwpa_uuid, generates_correct_v3_uuids) +{ + uint8_t mac1[6] = {0x00, 0xc0, 0x16, 0xff, 0xef, 0x12}; + uint8_t mac2[6] = {0x00, 0xc0, 0x16, 0xff, 0xef, 0x13}; + LwpaUuid uuid1, uuid2, uuid3, uuid4, uuid1_dup; + + // Version 3 UUIDs should be deterministic for the same combination of the three possible input + // arguments. If any of the arguments is different, a different UUID should result. + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_generate_v3_uuid(&uuid1, "Test Device", mac1, 0)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_generate_v3_uuid(&uuid2, "Test Device", mac1, 1)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_generate_v3_uuid(&uuid3, "Tst Device", mac1, 0)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_generate_v3_uuid(&uuid4, "Test Device", mac2, 0)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_generate_v3_uuid(&uuid1_dup, "Test Device", mac1, 0)); + + TEST_ASSERT_NOT_EQUAL(0, LWPA_UUID_CMP(&uuid1, &uuid2)); + TEST_ASSERT_NOT_EQUAL(0, LWPA_UUID_CMP(&uuid1, &uuid3)); + TEST_ASSERT_NOT_EQUAL(0, LWPA_UUID_CMP(&uuid1, &uuid4)); + TEST_ASSERT_NOT_EQUAL(0, LWPA_UUID_CMP(&uuid2, &uuid3)); + TEST_ASSERT_NOT_EQUAL(0, LWPA_UUID_CMP(&uuid2, &uuid4)); + TEST_ASSERT_NOT_EQUAL(0, LWPA_UUID_CMP(&uuid3, &uuid4)); + TEST_ASSERT_EQUAL(0, LWPA_UUID_CMP(&uuid1, &uuid1_dup)); + + // Make sure the Variant Version bits are correct. + // We should always have Variant 1, Version 3. + TEST_ASSERT_EQUAL_UINT8((uuid1.data[6] & 0xf0u), 0x30u); + TEST_ASSERT_EQUAL_UINT8((uuid1.data[8] & 0xc0u), 0x80u); + TEST_ASSERT_EQUAL_UINT8((uuid2.data[6] & 0xf0u), 0x30u); + TEST_ASSERT_EQUAL_UINT8((uuid2.data[8] & 0xc0u), 0x80u); + TEST_ASSERT_EQUAL_UINT8((uuid3.data[6] & 0xf0u), 0x30u); + TEST_ASSERT_EQUAL_UINT8((uuid3.data[8] & 0xc0u), 0x80u); + TEST_ASSERT_EQUAL_UINT8((uuid4.data[6] & 0xf0u), 0x30u); + TEST_ASSERT_EQUAL_UINT8((uuid4.data[8] & 0xc0u), 0x80u); + TEST_ASSERT_EQUAL_UINT8((uuid1_dup.data[6] & 0xf0u), 0x30u); + TEST_ASSERT_EQUAL_UINT8((uuid1_dup.data[8] & 0xc0u), 0x80u); +} + +TEST(lwpa_uuid, generates_correct_v4_uuids) +{ + // Generate a bunch of V4 UUIDs. They should all be unique from each other and have the proper + // version and variant information. We will cheat a little and just make sure that each one is + // unique from the last one generated. + LwpaUuid last_uuid = kLwpaNullUuid; + + for (int i = 0; i < NUM_V4_UUID_GENERATIONS; ++i) + { + LwpaUuid uuid; + char error_msg[100]; + sprintf(error_msg, "This failure occurred on UUID attempt %d of %d", i + 1, NUM_V4_UUID_GENERATIONS); + + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_generate_v4_uuid(&uuid), error_msg); + + // We should always have Variant 1, Version 4. + TEST_ASSERT_EQUAL_MESSAGE((uuid.data[6] & 0xf0u), 0x40u, error_msg); + TEST_ASSERT_EQUAL_MESSAGE((uuid.data[8] & 0xc0u), 0x80u, error_msg); + + // Should be unique from the last one generated. + TEST_ASSERT_NOT_EQUAL_MESSAGE(0, LWPA_UUID_CMP(&uuid, &last_uuid), error_msg); + + last_uuid = uuid; + } +} + +TEST_GROUP_RUNNER(lwpa_uuid) +{ + RUN_TEST_CASE(lwpa_uuid, uuid_is_null_works); + RUN_TEST_CASE(lwpa_uuid, uuid_compare_works); + RUN_TEST_CASE(lwpa_uuid, uuid_to_string_conversion_works); + RUN_TEST_CASE(lwpa_uuid, string_to_uuid_conversion_works); + RUN_TEST_CASE(lwpa_uuid, generates_correct_v1_uuids); + RUN_TEST_CASE(lwpa_uuid, generates_correct_v3_uuids); + RUN_TEST_CASE(lwpa_uuid, generates_correct_v4_uuids); +} + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_uuid); +} diff --git a/tests/unit/test_uuid.cpp b/tests/unit/test_uuid.cpp deleted file mode 100644 index 9df0c636f..000000000 --- a/tests/unit/test_uuid.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include "lwpa/uuid.h" -#include "gtest/gtest.h" -#include -#include - -class UuidTest : public ::testing::Test -{ -public: - static constexpr int kNumV1UuidGenerations = 10000; - static constexpr int kNumV4UuidGenerations = 10000; -}; - -TEST_F(UuidTest, null) -{ - LwpaUuid uuid = {{0}}; - ASSERT_TRUE(LWPA_UUID_IS_NULL(&uuid)); - uuid = kLwpaNullUuid; - ASSERT_TRUE(LWPA_UUID_IS_NULL(&uuid)); - for (size_t i = 0; i < LWPA_UUID_BYTES; ++i) - uuid.data[i] = static_cast(i); - ASSERT_FALSE(LWPA_UUID_IS_NULL(&uuid)); -} - -TEST_F(UuidTest, compare) -{ - LwpaUuid uuid1 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; - LwpaUuid uuid1_dup = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; - LwpaUuid uuid2 = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17}}; - - ASSERT_EQ(0, LWPA_UUID_CMP(&uuid1, &uuid1_dup)); - ASSERT_LT(0, LWPA_UUID_CMP(&uuid2, &uuid1)); - ASSERT_GT(0, LWPA_UUID_CMP(&uuid1, &uuid2)); - - // Test the C++ operators - ASSERT_LT(uuid1, uuid2); - ASSERT_EQ(uuid1, uuid1_dup); -} - -TEST_F(UuidTest, string) -{ - const char good_str[] = "08090a0b-0C0D-0e0f-1011-121314151617"; - const char short_str[] = "08090a0b-0c0d-0e0f-1011-1213141516"; - const char bad_str[] = "This isn't a UUID"; - char str_buf[LWPA_UUID_STRING_BYTES]; - LwpaUuid uuid = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}; - - lwpa_uuid_to_string(str_buf, &uuid); - ASSERT_EQ(0, strcmp(str_buf, "01020304-0506-0708-090a-0b0c0d0e0f10")); - uuid = kLwpaNullUuid; - lwpa_uuid_to_string(str_buf, &uuid); - ASSERT_EQ(0, strcmp(str_buf, "00000000-0000-0000-0000-000000000000")); - ASSERT_TRUE(lwpa_string_to_uuid(&uuid, good_str, strlen(good_str))); - LwpaUuid uuid_cmp = {{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}}; - ASSERT_EQ(0, LWPA_UUID_CMP(&uuid, &uuid_cmp)); - uuid = kLwpaNullUuid; - ASSERT_FALSE(lwpa_string_to_uuid(&uuid, short_str, strlen(short_str))); - ASSERT_FALSE(lwpa_string_to_uuid(&uuid, bad_str, strlen(bad_str))); -} - -TEST_F(UuidTest, generate_v1) -{ - // Generate a bunch of V1 UUIDs. They should all be unique from each other and have the proper - // version and variant information. We will cheat a little and just make sure that each one is - // unique from the last one generated. - LwpaUuid last_uuid = kLwpaNullUuid; - - for (int i = 0; i < kNumV1UuidGenerations; ++i) - { - LwpaUuid uuid; - std::string failure_msg = "This failure occurred on UUID attempt " + std::to_string(i + 1) + " of " + - std::to_string(kNumV1UuidGenerations); - - ASSERT_EQ(kLwpaErrOk, lwpa_generate_v1_uuid(&uuid)) << failure_msg; - - // We should always have Variant 1, Version 1. - ASSERT_EQ((uuid.data[6] & 0xf0u), 0x10u) << failure_msg; - ASSERT_EQ((uuid.data[8] & 0xc0u), 0x80u) << failure_msg; - - // Should be unique from the last one generated. - ASSERT_NE(0, LWPA_UUID_CMP(&uuid, &last_uuid)) << failure_msg; - - last_uuid = uuid; - } -} - -TEST_F(UuidTest, generate_v3) -{ - uint8_t mac1[6] = {0x00, 0xc0, 0x16, 0xff, 0xef, 0x12}; - uint8_t mac2[6] = {0x00, 0xc0, 0x16, 0xff, 0xef, 0x13}; - LwpaUuid uuid1, uuid2, uuid3, uuid4, uuid1_dup; - - // Version 3 UUIDs should be deterministic for the same combination of the three possible input - // arguments. If any of the arguments is different, a different UUID should result. - lwpa_generate_v3_uuid(&uuid1, "Test Device", mac1, 0); - lwpa_generate_v3_uuid(&uuid2, "Test Device", mac1, 1); - lwpa_generate_v3_uuid(&uuid3, "Tst Device", mac1, 0); - lwpa_generate_v3_uuid(&uuid4, "Test Device", mac2, 0); - lwpa_generate_v3_uuid(&uuid1_dup, "Test Device", mac1, 0); - - ASSERT_NE(0, LWPA_UUID_CMP(&uuid1, &uuid2)); - ASSERT_NE(0, LWPA_UUID_CMP(&uuid1, &uuid3)); - ASSERT_NE(0, LWPA_UUID_CMP(&uuid1, &uuid4)); - ASSERT_NE(0, LWPA_UUID_CMP(&uuid2, &uuid3)); - ASSERT_NE(0, LWPA_UUID_CMP(&uuid2, &uuid4)); - ASSERT_NE(0, LWPA_UUID_CMP(&uuid3, &uuid4)); - ASSERT_EQ(0, LWPA_UUID_CMP(&uuid1, &uuid1_dup)); - - // Make sure the Variant Version bits are correct. - // We should always have Variant 1, Version 3. - std::vector uuid_vect{uuid1, uuid2, uuid3, uuid4, uuid1_dup}; - std::for_each(uuid_vect.begin(), uuid_vect.end(), [](const LwpaUuid& uuid) { - ASSERT_EQ((uuid.data[6] & 0xf0u), 0x30u); - ASSERT_EQ((uuid.data[8] & 0xc0u), 0x80u); - }); -} - -TEST_F(UuidTest, generate_v4) -{ - // Generate a bunch of V4 UUIDs. They should all be unique from each other and have the proper - // version and variant information. We will cheat a little and just make sure that each one is - // unique from the last one generated. - LwpaUuid last_uuid = kLwpaNullUuid; - - for (int i = 0; i < kNumV4UuidGenerations; ++i) - { - LwpaUuid uuid; - std::string failure_msg = "This failure occurred on UUID attempt " + std::to_string(i + 1) + " of " + - std::to_string(kNumV4UuidGenerations); - - ASSERT_EQ(kLwpaErrOk, lwpa_generate_v4_uuid(&uuid)) << failure_msg; - - // We should always have Variant 1, Version 4. - ASSERT_EQ((uuid.data[6] & 0xf0u), 0x40u) << failure_msg; - ASSERT_EQ((uuid.data[8] & 0xc0u), 0x80u) << failure_msg; - - // Should be unique from the last one generated. - ASSERT_NE(0, LWPA_UUID_CMP(&uuid, &last_uuid)) << failure_msg; - - last_uuid = uuid; - } -} From a6a566818fad368493bfbe43b08a0ab8026e4e06 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sat, 17 Aug 2019 23:13:28 -0500 Subject: [PATCH 105/264] Fix build - some tests will likely still be failing --- tests/unit/test_timer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test_timer.c b/tests/unit/test_timer.c index 5166bccd5..c806f7274 100644 --- a/tests/unit/test_timer.c +++ b/tests/unit/test_timer.c @@ -20,6 +20,7 @@ #include "unity_fixture.h" // Interdependency is unavoidable here, we need a platform-neutral sleep +#include "lwpa/common.h" #include "lwpa/thread.h" TEST_GROUP(lwpa_timer); From a74b5ca95dcb22d32e440f046e4894c42b979941 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 18 Aug 2019 10:21:25 -0500 Subject: [PATCH 106/264] Fix some warnings and test failures on mac --- tests/CMakeLists.txt | 8 ++++++-- tests/integration/entrypoint/main_default.c | 2 +- tests/integration/socket_integration_test.c | 2 +- tests/unit/entrypoint/main_default.c | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 12acd1a5f..a575caaca 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,7 +13,6 @@ if(WIN32 OR APPLE OR UNIX) endfunction() endif() - if(WIN32) set(LWPA_TEST_COMPILE_OPTIONS /wd4210) elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -22,8 +21,13 @@ else() set(LWPA_TEST_COMPILE_OPTIONS "") endif() +# Set the platform-dependent compile definitions for the tests if(LWPA_TEST_IPV6) - set(LWPA_TEST_COMPILE_DEFINITIONS LWPA_TEST_IPV6) + list(APPEND LWPA_TEST_COMPILE_DEFINITIONS LWPA_TEST_IPV6) +endif() + +if(APPLE) + list(APPEND LWPA_TEST_COMPILE_DEFINITIONS LWPA_BULK_POLL_TEST_NUM_SOCKETS=200) endif() add_subdirectory(unit) diff --git a/tests/integration/entrypoint/main_default.c b/tests/integration/entrypoint/main_default.c index 63192dae2..20f73bc63 100644 --- a/tests/integration/entrypoint/main_default.c +++ b/tests/integration/entrypoint/main_default.c @@ -23,5 +23,5 @@ extern void run_all_tests(void); int main(int argc, char* argv[]) { - return UnityMain(argc, argv, run_all_tests); + return UnityMain(argc, (const char**)argv, run_all_tests); } diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index d06b8f03f..553b95df1 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -60,7 +60,7 @@ static LwpaSockaddr send_addr; static void select_network_interface_v4() { run_ipv4_mcast_test = true; - if (kLwpaErrOk != lwpa_netint_get_default_interface(kLwpaIpTypeV6, &v4_netint)) + if (kLwpaErrOk != lwpa_netint_get_default_interface(kLwpaIpTypeV4, &v4_netint)) { const LwpaNetintInfo* arr = lwpa_netint_get_interfaces(); if (arr) diff --git a/tests/unit/entrypoint/main_default.c b/tests/unit/entrypoint/main_default.c index 2ecbab09a..66fd50600 100644 --- a/tests/unit/entrypoint/main_default.c +++ b/tests/unit/entrypoint/main_default.c @@ -26,5 +26,5 @@ extern void run_all_tests(void); int main(int argc, char* argv[]) { srand((unsigned int)time(NULL)); - return UnityMain(argc, argv, run_all_tests); + return UnityMain(argc, (const char**)argv, run_all_tests); } From 6f6a5e5ec5a6c36549c3c4e49d7b656fb46dc504 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 18 Aug 2019 10:27:30 -0500 Subject: [PATCH 107/264] Add some temporary debug statements for the Azure hosted mac agent --- azure-pipelines.yml | 2 ++ tests/integration/socket_integration_test.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ee8aad5de..54d1bd220 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -46,6 +46,8 @@ jobs: cmake --build . displayName: 'lwpa macOS build' - script: | + ifconfig + netstat -rn cd build ctest --output-on-failure displayName: 'lwpa macOS test' diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index 553b95df1..23992c637 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -22,6 +22,10 @@ #include "lwpa/netint.h" #include "lwpa/thread.h" +// DEBUG REMOVEME +#include +// END DEBUG + // Disable sprintf() warning on Windows/MSVC #ifdef _MSC_VER #pragma warning(disable : 4996) @@ -468,6 +472,12 @@ TEST_GROUP_RUNNER(socket_integration) select_network_interface_v4(); #if LWPA_TEST_IPV6 select_network_interface_v6(); + + // DEBUG REMOVEME + char addr_str[LWPA_INET6_ADDRSTRLEN]; + lwpa_inet_ntop(&v6_netint.addr, addr_str, LWPA_INET6_ADDRSTRLEN); + printf("IPv6 netint address %d, index %u\n", addr_str, v6_netint.index); + // END DEBUG #endif RUN_TEST_CASE(socket_integration, unicast_udp_ipv4); From 2fa4b92ea8ed8d07ec4da387924af6b232942c9d Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 18 Aug 2019 10:28:08 -0500 Subject: [PATCH 108/264] Fix bug in debug code --- tests/integration/socket_integration_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index 23992c637..cc8ba4f14 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -476,7 +476,7 @@ TEST_GROUP_RUNNER(socket_integration) // DEBUG REMOVEME char addr_str[LWPA_INET6_ADDRSTRLEN]; lwpa_inet_ntop(&v6_netint.addr, addr_str, LWPA_INET6_ADDRSTRLEN); - printf("IPv6 netint address %d, index %u\n", addr_str, v6_netint.index); + printf("IPv6 netint address %s, index %u\n", addr_str, v6_netint.index); // END DEBUG #endif From 1ddf56c7b6029ef58670ba2e7ebeaa211cd9b5d9 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 18 Aug 2019 10:34:33 -0500 Subject: [PATCH 109/264] Mystery solved - the mac hosted agent has no IPv6 NICs. Improve test skip detection --- azure-pipelines.yml | 8 +++----- tests/integration/socket_integration_test.c | 15 +++------------ 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 54d1bd220..0d5c92aa5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -30,7 +30,7 @@ jobs: displayName: 'lwpa Windows build' - script: | cd build - ctest --output-on-failure -C %LWPA_BUILD_CONFIG% + ctest --verbose -C %LWPA_BUILD_CONFIG% displayName: 'lwpa Windows test' - job: macos_build @@ -46,10 +46,8 @@ jobs: cmake --build . displayName: 'lwpa macOS build' - script: | - ifconfig - netstat -rn cd build - ctest --output-on-failure + ctest --verbose displayName: 'lwpa macOS test' - job: linux_build @@ -68,7 +66,7 @@ jobs: displayName: 'lwpa Linux build' - script: | cd build - ctest --output-on-failure + ctest --verbose displayName: 'lwpa Linux test' # Generate documentation with doxygen. Documentation is generated from the diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index cc8ba4f14..1ed3939b4 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -19,13 +19,10 @@ #include "lwpa/socket.h" #include "unity_fixture.h" +#include #include "lwpa/netint.h" #include "lwpa/thread.h" -// DEBUG REMOVEME -#include -// END DEBUG - // Disable sprintf() warning on Windows/MSVC #ifdef _MSC_VER #pragma warning(disable : 4996) @@ -72,7 +69,7 @@ static void select_network_interface_v4() for (const LwpaNetintInfo* netint = arr; netint < arr + lwpa_netint_get_num_interfaces(); ++netint) { if (LWPA_IP_IS_V4(&netint->addr) && !lwpa_ip_is_link_local(&netint->addr) && - !lwpa_ip_is_loopback(&netint->addr)) + !lwpa_ip_is_loopback(&netint->addr) && NULL == strstr(netint->name, "utun")) { v4_netint = *netint; return; @@ -99,7 +96,7 @@ static void select_network_interface_v6() { for (const LwpaNetintInfo* netint = arr; netint < arr + lwpa_netint_get_num_interfaces(); ++netint) { - if (LWPA_IP_IS_V6(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr)) + if (LWPA_IP_IS_V6(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr) && NULL == strstr(netint->name, "utun")) { v6_netint = *netint; return; @@ -472,12 +469,6 @@ TEST_GROUP_RUNNER(socket_integration) select_network_interface_v4(); #if LWPA_TEST_IPV6 select_network_interface_v6(); - - // DEBUG REMOVEME - char addr_str[LWPA_INET6_ADDRSTRLEN]; - lwpa_inet_ntop(&v6_netint.addr, addr_str, LWPA_INET6_ADDRSTRLEN); - printf("IPv6 netint address %s, index %u\n", addr_str, v6_netint.index); - // END DEBUG #endif RUN_TEST_CASE(socket_integration, unicast_udp_ipv4); From f7045aab5b35db1195235d3da56669483b5cb465 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 18 Aug 2019 10:42:10 -0500 Subject: [PATCH 110/264] *sigh* more debug code --- tests/integration/socket_integration_test.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index 1ed3939b4..f71a6a69a 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -23,6 +23,8 @@ #include "lwpa/netint.h" #include "lwpa/thread.h" +#include + // Disable sprintf() warning on Windows/MSVC #ifdef _MSC_VER #pragma warning(disable : 4996) @@ -71,6 +73,9 @@ static void select_network_interface_v4() if (LWPA_IP_IS_V4(&netint->addr) && !lwpa_ip_is_link_local(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr) && NULL == strstr(netint->name, "utun")) { + char addr_str[LWPA_INET6_ADDRSTRLEN]; + lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); + printf("IPv4 selecting netint %s, addr %s, index %u\n", netint->friendly_name, addr_str, netint->index); v4_netint = *netint; return; } @@ -82,6 +87,10 @@ static void select_network_interface_v4() run_ipv4_mcast_test = false; } } + else + { + printf("IPv4 selecting default interface index %u\n", v4_netint.index); + } } #if LWPA_TEST_IPV6 @@ -98,6 +107,9 @@ static void select_network_interface_v6() { if (LWPA_IP_IS_V6(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr) && NULL == strstr(netint->name, "utun")) { + char addr_str[LWPA_INET6_ADDRSTRLEN]; + lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); + printf("IPv6 selecting netint %s, addr %s, index %u\n", netint->friendly_name, addr_str, netint->index); v6_netint = *netint; return; } @@ -107,6 +119,10 @@ static void select_network_interface_v6() run_ipv6_mcast_test = false; } } + else + { + printf("IPv6 selecting default interface index %u\n", v6_netint.index); + } } #endif From bbd5166b351eb4b172b825a84a72f6eb0a94c061 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 18 Aug 2019 10:48:57 -0500 Subject: [PATCH 111/264] Try netint selection code again... --- tests/integration/socket_integration_test.c | 28 ++++++++++++--------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index f71a6a69a..033fa3531 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -62,8 +62,13 @@ static LwpaSockaddr send_addr; // if not. static void select_network_interface_v4() { - run_ipv4_mcast_test = true; - if (kLwpaErrOk != lwpa_netint_get_default_interface(kLwpaIpTypeV4, &v4_netint)) + if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV4, &v4_netint) && + NULL == strstr(v4_netint.name, "utun")) + { + run_ipv4_mcast_test = true; + printf("IPv4 selecting default interface index %u\n", v4_netint.index); + } + else { const LwpaNetintInfo* arr = lwpa_netint_get_interfaces(); if (arr) @@ -77,6 +82,7 @@ static void select_network_interface_v4() lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); printf("IPv4 selecting netint %s, addr %s, index %u\n", netint->friendly_name, addr_str, netint->index); v4_netint = *netint; + run_ipv4_mcast_test = true; return; } } @@ -87,18 +93,19 @@ static void select_network_interface_v4() run_ipv4_mcast_test = false; } } - else - { - printf("IPv4 selecting default interface index %u\n", v4_netint.index); - } } #if LWPA_TEST_IPV6 // Select the default interface if available, the very first non-loopback interface if not. static void select_network_interface_v6() { - run_ipv6_mcast_test = true; - if (kLwpaErrOk != lwpa_netint_get_default_interface(kLwpaIpTypeV6, &v6_netint)) + if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV6, &v6_netint) && + NULL == strstr(v6_netint.name, "utun")) + { + run_ipv6_mcast_test = true; + printf("IPv6 selecting default interface index %u\n", v6_netint.index); + } + else { const LwpaNetintInfo* arr = lwpa_netint_get_interfaces(); if (arr) @@ -111,6 +118,7 @@ static void select_network_interface_v6() lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); printf("IPv6 selecting netint %s, addr %s, index %u\n", netint->friendly_name, addr_str, netint->index); v6_netint = *netint; + run_ipv6_mcast_test = true; return; } } @@ -119,10 +127,6 @@ static void select_network_interface_v6() run_ipv6_mcast_test = false; } } - else - { - printf("IPv6 selecting default interface index %u\n", v6_netint.index); - } } #endif From 9de370d84042f44c68c97c21acdc9f5109889f7e Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 18 Aug 2019 11:10:33 -0500 Subject: [PATCH 112/264] Disable multicast tests on mac hosted agents. --- azure-pipelines.yml | 9 ++++++--- tests/integration/CMakeLists.txt | 6 ++++++ tests/integration/socket_integration_test.c | 11 ++--------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0d5c92aa5..2b3090315 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -8,6 +8,9 @@ trigger: pr: - develop +variables: + cmake_definitions: -DLWPA_BUILD_MOCK_LIB=ON -DLWPA_BUILDING_FOR_AZURE_PIPELINES_CI=1 + jobs: # Build and test lwpa on Windows using CMake and Visual Studio 2017. - job: windows_build @@ -25,7 +28,7 @@ jobs: mkdir build cd build cmake --version - cmake -G "Visual Studio 15 2017 Win64" -DLWPA_BUILD_MOCK_LIB=ON .. + cmake -G "Visual Studio 15 2017 Win64" $(cmake_definitions) .. cmake --build . --config %LWPA_BUILD_CONFIG% displayName: 'lwpa Windows build' - script: | @@ -42,7 +45,7 @@ jobs: mkdir build cd build cmake --version - cmake -DLWPA_BUILD_MOCK_LIB=ON .. + cmake $(cmake_definitions) .. cmake --build . displayName: 'lwpa macOS build' - script: | @@ -61,7 +64,7 @@ jobs: mkdir build cd build cmake --version - cmake -G "Unix Makefiles" -DLWPA_BUILD_MOCK_LIB=ON .. + cmake -G "Unix Makefiles" $(cmake_definitions) .. cmake --build . displayName: 'lwpa Linux build' - script: | diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index afeecd483..213b525de 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -16,3 +16,9 @@ target_compile_options(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_OPTION target_compile_definitions(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) target_link_libraries(lwpa_integration_tests PRIVATE lwpa ThrowTheSwitch::Unity) lwpa_add_to_ctest(lwpa_integration_tests) + +# The macOS hosted agents have some unknown restriction on multicast traffic which causes the +# multicast tests to fail. +if(APPLE AND LWPA_BUILDING_FOR_AZURE_PIPELINES_CI) + target_compile_definitions(lwpa_integration_tests PRIVATE LWPA_TEST_DISABLE_MCAST_INTEGRATION_TESTS) +endif() \ No newline at end of file diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index 033fa3531..7b8db868d 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -23,8 +23,6 @@ #include "lwpa/netint.h" #include "lwpa/thread.h" -#include - // Disable sprintf() warning on Windows/MSVC #ifdef _MSC_VER #pragma warning(disable : 4996) @@ -66,7 +64,6 @@ static void select_network_interface_v4() NULL == strstr(v4_netint.name, "utun")) { run_ipv4_mcast_test = true; - printf("IPv4 selecting default interface index %u\n", v4_netint.index); } else { @@ -78,9 +75,6 @@ static void select_network_interface_v4() if (LWPA_IP_IS_V4(&netint->addr) && !lwpa_ip_is_link_local(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr) && NULL == strstr(netint->name, "utun")) { - char addr_str[LWPA_INET6_ADDRSTRLEN]; - lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); - printf("IPv4 selecting netint %s, addr %s, index %u\n", netint->friendly_name, addr_str, netint->index); v4_netint = *netint; run_ipv4_mcast_test = true; return; @@ -114,9 +108,6 @@ static void select_network_interface_v6() { if (LWPA_IP_IS_V6(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr) && NULL == strstr(netint->name, "utun")) { - char addr_str[LWPA_INET6_ADDRSTRLEN]; - lwpa_inet_ntop(&netint->addr, addr_str, LWPA_INET6_ADDRSTRLEN); - printf("IPv6 selecting netint %s, addr %s, index %u\n", netint->friendly_name, addr_str, netint->index); v6_netint = *netint; run_ipv6_mcast_test = true; return; @@ -486,9 +477,11 @@ TEST_GROUP_RUNNER(socket_integration) { TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS)); +#if !LWPA_TEST_DISABLE_MCAST_INTEGRATION_TESTS select_network_interface_v4(); #if LWPA_TEST_IPV6 select_network_interface_v6(); +#endif #endif RUN_TEST_CASE(socket_integration, unicast_udp_ipv4); From f27f5e856a91021905822da32d6d1939b7d2456b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Sun, 18 Aug 2019 11:40:57 -0500 Subject: [PATCH 113/264] Remove GoogleTest cruft --- tools/cmake/AddGoogleTest.cmake | 97 ----------- .../cmake/DownloadProject.CMakeLists.cmake.in | 17 -- tools/cmake/DownloadProject.cmake | 164 ------------------ 3 files changed, 278 deletions(-) delete mode 100644 tools/cmake/AddGoogleTest.cmake delete mode 100644 tools/cmake/DownloadProject.CMakeLists.cmake.in delete mode 100644 tools/cmake/DownloadProject.cmake diff --git a/tools/cmake/AddGoogleTest.cmake b/tools/cmake/AddGoogleTest.cmake deleted file mode 100644 index 299de0592..000000000 --- a/tools/cmake/AddGoogleTest.cmake +++ /dev/null @@ -1,97 +0,0 @@ -# -# -# Downloads GTest and provides a helper macro to add tests. Add make check, as well, which -# gives output on failed tests without having to set an environment variable. -# -# -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - -if(CMAKE_VERSION VERSION_LESS 3.11) - set(UPDATE_DISCONNECTED_IF_AVAILABLE "UPDATE_DISCONNECTED 1") - - include(DownloadProject) - download_project(PROJ googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG origin/master - UPDATE_DISCONNECTED 1 - QUIET - ) - - # CMake warning suppression will not be needed in version 1.9 - set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE BOOL "") - add_subdirectory(${googletest_SOURCE_DIR} ${googletest_SOURCE_DIR} EXCLUDE_FROM_ALL) - unset(CMAKE_SUPPRESS_DEVELOPER_WARNINGS) -else() - include(FetchContent) - FetchContent_Declare(googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG origin/master) - FetchContent_GetProperties(googletest) - if(NOT googletest_POPULATED) - FetchContent_Populate(googletest) - set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE BOOL "") - add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) - unset(CMAKE_SUPPRESS_DEVELOPER_WARNINGS) - endif() -endif() - - -# if(CMAKE_CONFIGURATION_TYPES) -# add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -# --force-new-ctest-process --output-on-failure -# --build-config "$") -# else() -# add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -# --force-new-ctest-process --output-on-failure) -# endif() -# set_target_properties(check PROPERTIES FOLDER "Scripts") - -#include_directories(${gtest_SOURCE_DIR}/include) - -# More modern way to do the last line, less messy but needs newish CMake: -# target_include_directories(gtest INTERFACE ${gtest_SOURCE_DIR}/include) - - -if(GOOGLE_TEST_INDIVIDUAL) - if(NOT CMAKE_VERSION VERSION_LESS 3.9) - include(GoogleTest) - else() - set(GOOGLE_TEST_INDIVIDUAL OFF) - endif() -endif() - -# Target must already exist -macro(add_gtest TESTNAME) - target_link_libraries(${TESTNAME} PUBLIC gtest gmock gtest_main) - - if(GOOGLE_TEST_INDIVIDUAL) - if(CMAKE_VERSION VERSION_LESS 3.10) - gtest_add_tests(TARGET ${TESTNAME} - TEST_PREFIX "${TESTNAME}." - TEST_LIST TmpTestList) - set_tests_properties(${TmpTestList} PROPERTIES FOLDER "Tests") - else() - gtest_discover_tests(${TESTNAME} - TEST_PREFIX "${TESTNAME}." - PROPERTIES FOLDER "Tests") - endif() - else() - add_test(${TESTNAME} ${TESTNAME}) - set_target_properties(${TESTNAME} PROPERTIES FOLDER "Tests") - endif() - -endmacro() - -mark_as_advanced( -gmock_build_tests -gtest_build_samples -gtest_build_tests -gtest_disable_pthreads -gtest_force_shared_crt -gtest_hide_internal_symbols -BUILD_GMOCK -BUILD_GTEST -) - -set_target_properties(gtest gtest_main gmock gmock_main - PROPERTIES FOLDER "Extern") \ No newline at end of file diff --git a/tools/cmake/DownloadProject.CMakeLists.cmake.in b/tools/cmake/DownloadProject.CMakeLists.cmake.in deleted file mode 100644 index 89be4fdd4..000000000 --- a/tools/cmake/DownloadProject.CMakeLists.cmake.in +++ /dev/null @@ -1,17 +0,0 @@ -# Distributed under the OSI-approved MIT License. See accompanying -# file LICENSE or https://github.com/Crascit/DownloadProject for details. - -cmake_minimum_required(VERSION 2.8.2) - -project(${DL_ARGS_PROJ}-download NONE) - -include(ExternalProject) -ExternalProject_Add(${DL_ARGS_PROJ}-download - ${DL_ARGS_UNPARSED_ARGUMENTS} - SOURCE_DIR "${DL_ARGS_SOURCE_DIR}" - BINARY_DIR "${DL_ARGS_BINARY_DIR}" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" -) diff --git a/tools/cmake/DownloadProject.cmake b/tools/cmake/DownloadProject.cmake deleted file mode 100644 index 798c74b63..000000000 --- a/tools/cmake/DownloadProject.cmake +++ /dev/null @@ -1,164 +0,0 @@ -# Distributed under the OSI-approved MIT License. See accompanying -# file LICENSE or https://github.com/Crascit/DownloadProject for details. -# -# MODULE: DownloadProject -# -# PROVIDES: -# download_project( PROJ projectName -# [PREFIX prefixDir] -# [DOWNLOAD_DIR downloadDir] -# [SOURCE_DIR srcDir] -# [BINARY_DIR binDir] -# [QUIET] -# ... -# ) -# -# Provides the ability to download and unpack a tarball, zip file, git repository, -# etc. at configure time (i.e. when the cmake command is run). How the downloaded -# and unpacked contents are used is up to the caller, but the motivating case is -# to download source code which can then be included directly in the build with -# add_subdirectory() after the call to download_project(). Source and build -# directories are set up with this in mind. -# -# The PROJ argument is required. The projectName value will be used to construct -# the following variables upon exit (obviously replace projectName with its actual -# value): -# -# projectName_SOURCE_DIR -# projectName_BINARY_DIR -# -# The SOURCE_DIR and BINARY_DIR arguments are optional and would not typically -# need to be provided. They can be specified if you want the downloaded source -# and build directories to be located in a specific place. The contents of -# projectName_SOURCE_DIR and projectName_BINARY_DIR will be populated with the -# locations used whether you provide SOURCE_DIR/BINARY_DIR or not. -# -# The DOWNLOAD_DIR argument does not normally need to be set. It controls the -# location of the temporary CMake build used to perform the download. -# -# The PREFIX argument can be provided to change the base location of the default -# values of DOWNLOAD_DIR, SOURCE_DIR and BINARY_DIR. If all of those three arguments -# are provided, then PREFIX will have no effect. The default value for PREFIX is -# CMAKE_BINARY_DIR. -# -# The QUIET option can be given if you do not want to show the output associated -# with downloading the specified project. -# -# In addition to the above, any other options are passed through unmodified to -# ExternalProject_Add() to perform the actual download, patch and update steps. -# The following ExternalProject_Add() options are explicitly prohibited (they -# are reserved for use by the download_project() command): -# -# CONFIGURE_COMMAND -# BUILD_COMMAND -# INSTALL_COMMAND -# TEST_COMMAND -# -# Only those ExternalProject_Add() arguments which relate to downloading, patching -# and updating of the project sources are intended to be used. Also note that at -# least one set of download-related arguments are required. -# -# If using CMake 3.2 or later, the UPDATE_DISCONNECTED option can be used to -# prevent a check at the remote end for changes every time CMake is run -# after the first successful download. See the documentation of the ExternalProject -# module for more information. It is likely you will want to use this option if it -# is available to you. Note, however, that the ExternalProject implementation contains -# bugs which result in incorrect handling of the UPDATE_DISCONNECTED option when -# using the URL download method or when specifying a SOURCE_DIR with no download -# method. Fixes for these have been created, the last of which is scheduled for -# inclusion in CMake 3.8.0. Details can be found here: -# -# https://gitlab.kitware.com/cmake/cmake/commit/bdca68388bd57f8302d3c1d83d691034b7ffa70c -# https://gitlab.kitware.com/cmake/cmake/issues/16428 -# -# If you experience build errors related to the update step, consider avoiding -# the use of UPDATE_DISCONNECTED. -# -# EXAMPLE USAGE: -# -# include(DownloadProject) -# download_project(PROJ googletest -# GIT_REPOSITORY https://github.com/google/googletest.git -# GIT_TAG master -# UPDATE_DISCONNECTED 1 -# QUIET -# ) -# -# add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) -# -#======================================================================================== - - -set(_DownloadProjectDir "${CMAKE_CURRENT_LIST_DIR}") - -include(CMakeParseArguments) - -function(download_project) - - set(options QUIET) - set(oneValueArgs - PROJ - PREFIX - DOWNLOAD_DIR - SOURCE_DIR - BINARY_DIR - # Prevent the following from being passed through - CONFIGURE_COMMAND - BUILD_COMMAND - INSTALL_COMMAND - TEST_COMMAND - ) - set(multiValueArgs "") - - cmake_parse_arguments(DL_ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - # Hide output if requested - if (DL_ARGS_QUIET) - set(OUTPUT_QUIET "OUTPUT_QUIET") - else() - unset(OUTPUT_QUIET) - message(STATUS "Downloading/updating ${DL_ARGS_PROJ}") - endif() - - # Set up where we will put our temporary CMakeLists.txt file and also - # the base point below which the default source and binary dirs will be - if (NOT DL_ARGS_PREFIX) - set(DL_ARGS_PREFIX "${CMAKE_BINARY_DIR}") - endif() - if (NOT DL_ARGS_DOWNLOAD_DIR) - set(DL_ARGS_DOWNLOAD_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-download") - endif() - - # Ensure the caller can know where to find the source and build directories - if (NOT DL_ARGS_SOURCE_DIR) - set(DL_ARGS_SOURCE_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-src") - endif() - if (NOT DL_ARGS_BINARY_DIR) - set(DL_ARGS_BINARY_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-build") - endif() - set(${DL_ARGS_PROJ}_SOURCE_DIR "${DL_ARGS_SOURCE_DIR}" PARENT_SCOPE) - set(${DL_ARGS_PROJ}_BINARY_DIR "${DL_ARGS_BINARY_DIR}" PARENT_SCOPE) - - # Create and build a separate CMake project to carry out the download. - # If we've already previously done these steps, they will not cause - # anything to be updated, so extra rebuilds of the project won't occur. - configure_file("${_DownloadProjectDir}/DownloadProject.CMakeLists.cmake.in" - "${DL_ARGS_DOWNLOAD_DIR}/CMakeLists.txt") - execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . - RESULT_VARIABLE result - ${OUTPUT_QUIET} - WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}" - ) - if(result) - message(FATAL_ERROR "CMake step for ${DL_ARGS_PROJ} failed: ${result}") - endif() - execute_process(COMMAND ${CMAKE_COMMAND} --build . - RESULT_VARIABLE result - ${OUTPUT_QUIET} - WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}" - ) - if(result) - message(FATAL_ERROR "Build step for ${DL_ARGS_PROJ} failed: ${result}") - endif() - -endfunction() From 2d3f4cfabaaf73a9164cde5249ce6d88429fe403 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 19 Aug 2019 17:31:09 -0500 Subject: [PATCH 114/264] Beginning work on FreeRTOS/lwIP port and making the CMake target OS support better --- CMakeLists.txt | 4 +- include/os/freertos/lwpa/os_lock.h | 17 +- include/os/lwip/lwpa/os_inet.h | 29 ++++ include/os/lwip/lwpa/os_socket.h | 53 ++++++ src/CMakeLists.txt | 146 +++++------------ src/os/freertos/lwpa/os_lock.c | 72 +++++--- src/os/freertos/lwpa/os_thread.c | 8 +- src/os/freertos/lwpa/os_timer.c | 19 ++- src/os/freertos/lwpa/os_uuid.c | 31 ++++ src/os/lwip/lwpa/os_inet.c | 0 src/os/lwip/lwpa/os_socket.c | 254 +++++++++++++++++++++++------ tools/cmake/lwpa-os.cmake | 56 +++++++ tools/cmake/net/lwip.cmake | 11 ++ tools/cmake/os/freertos.cmake | 11 ++ tools/cmake/os/linux.cmake | 6 + tools/cmake/os/macos.cmake | 5 + tools/cmake/os/mqx.cmake | 29 ++++ tools/cmake/os/windows.cmake | 6 + 18 files changed, 562 insertions(+), 195 deletions(-) create mode 100644 include/os/lwip/lwpa/os_inet.h create mode 100644 include/os/lwip/lwpa/os_socket.h create mode 100644 src/os/freertos/lwpa/os_uuid.c create mode 100644 src/os/lwip/lwpa/os_inet.c create mode 100644 tools/cmake/lwpa-os.cmake create mode 100644 tools/cmake/net/lwip.cmake create mode 100644 tools/cmake/os/freertos.cmake create mode 100644 tools/cmake/os/linux.cmake create mode 100644 tools/cmake/os/macos.cmake create mode 100644 tools/cmake/os/mqx.cmake create mode 100644 tools/cmake/os/windows.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index be731e75e..8402cb5be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,6 @@ if(PROJECT_SOURCE_DIR_LC STREQUAL CMAKE_SOURCE_DIR_LC) # Allow folder grouping in generated IDE projects set_property(GLOBAL PROPERTY USE_FOLDERS ON) - list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/tools/cmake) set(OPTION_DEFAULTS ON) else() set(OPTION_DEFAULTS OFF) @@ -39,6 +38,9 @@ option(LWPA_BUILD_MOCK_LIB "Build the lwpa_mock library" OFF) option(LWPA_BUILD_TESTS "Build the lwpa unit tests" ${OPTION_DEFAULTS}) option(LWPA_BUILD_EXAMPLES "Build the lwpa example apps" ${OPTION_DEFAULTS}) +# Platform support +include(${PROJECT_SOURCE_DIR}/tools/cmake/lwpa-os.cmake) + if(LWPA_BUILD_MOCK_LIB OR LWPA_BUILD_TESTS) add_subdirectory(external/fff) endif() diff --git a/include/os/freertos/lwpa/os_lock.h b/include/os/freertos/lwpa/os_lock.h index eea128200..fd2c1db8d 100644 --- a/include/os/freertos/lwpa/os_lock.h +++ b/include/os/freertos/lwpa/os_lock.h @@ -20,8 +20,8 @@ #ifndef _LWPA_OS_LOCK_H_ #define _LWPA_OS_LOCK_H_ -#include "FreeRTOS.h" -#include "semphr.h" +#include +#include #include "lwpa/common.h" #include "lwpa/bool.h" @@ -32,27 +32,32 @@ extern "C" { typedef SemaphoreHandle_t lwpa_mutex_t; bool lwpa_mutex_create(lwpa_mutex_t* id); -bool lwpa_mutex_take(lwpa_mutex_t* id, int wait_ms); +bool lwpa_mutex_take(lwpa_mutex_t* id); +bool lwpa_mutex_try_take(lwpa_mutex_t* id); void lwpa_mutex_give(lwpa_mutex_t* id); void lwpa_mutex_destroy(lwpa_mutex_t* id); typedef SemaphoreHandle_t lwpa_signal_t; bool lwpa_signal_create(lwpa_signal_t* id); -bool lwpa_signal_wait(lwpa_signal_t* id, int wait_ms); +bool lwpa_signal_wait(lwpa_signal_t* id); +bool lwpa_signal_poll(lwpa_signal_t* id); void lwpa_signal_post(lwpa_signal_t* id); void lwpa_signal_destroy(lwpa_signal_t* id); typedef struct { + bool valid; SemaphoreHandle_t sem; unsigned int reader_count; } lwpa_rwlock_t; bool lwpa_rwlock_create(lwpa_rwlock_t* id); -bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms); +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id); void lwpa_rwlock_readunlock(lwpa_rwlock_t* id); -bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms); +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id); +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id); void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id); void lwpa_rwlock_destroy(lwpa_rwlock_t* id); diff --git a/include/os/lwip/lwpa/os_inet.h b/include/os/lwip/lwpa/os_inet.h new file mode 100644 index 000000000..6d47c643d --- /dev/null +++ b/include/os/lwip/lwpa/os_inet.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_INET_H_ +#define _LWPA_OS_INET_H_ + +#include + +typedef struct sockaddr lwpa_os_sockaddr_t; +typedef struct sockaddr lwpa_os_ipaddr_t; + +#endif /* _LWPA_OS_INET_H_ */ + diff --git a/include/os/lwip/lwpa/os_socket.h b/include/os/lwip/lwpa/os_socket.h new file mode 100644 index 000000000..2a23121c2 --- /dev/null +++ b/include/os/lwip/lwpa/os_socket.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_OS_SOCKET_H_ +#define _LWPA_OS_SOCKET_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Definitions for the lwpa socket type */ + +typedef int lwpa_socket_t; + +#define PRIlwpasockt "d" + +#define LWPA_SOCKET_INVALID -1 + +#define LWPA_SOCKET_MAX_POLL_SIZE FD_SETSIZE + +/* Definitions for lwpa_poll API */ + +typedef struct LwpaPollContext +{ + bool valid; + int epoll_fd; + LwpaRbTree sockets; +} LwpaPollContext; + +#ifdef __cplusplus +} +#endif + +#endif /* _LWPA_OS_SOCKET_H_ */ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6d2331503..edf79c1c1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,45 +1,8 @@ -############################### Platform support ############################## -if(DEFINED LWPA_CONFIG) - get_filename_component(LWPA_CONFIG_LOC LWPA_CONFIG DIRECTORY) - set(${LWPA_HAVE_CONFIG_H} LWPA_HAVE_CONFIG_H) -endif() - -# The set of supported target OS -set(VALID_LWPA_TARGETS - linux - macos - mqx - windows -) - -if(NOT DEFINED LWPA_TARGET_OS) - message(STATUS "LWPA_TARGET_OS not supplied, assuming native compile by default...") - if(WIN32) - set(LWPA_TARGET_OS windows) - elseif(APPLE) - set(LWPA_TARGET_OS macos) - elseif(UNIX) - set(LWPA_TARGET_OS linux) - else() - # The error check below will catch this and print the fatal error. - set(LWPA_TARGET_OS ${CMAKE_HOST_SYSTEM_NAME}) - endif() -endif() - -if(NOT ${LWPA_TARGET_OS} IN_LIST VALID_LWPA_TARGETS) - message(FATAL_ERROR "${LWPA_TARGET_OS} is not a valid target OS. " - "Specify LWPA_TARGET_OS from these options: ${VALID_LWPA_TARGETS}") -endif() - -# MQX compilation support -if(LWPA_TARGET_OS STREQUAL mqx) - if(NOT DEFINED MQX_BOARD_DIR) - message(FATAL_ERROR "You must provide a variable MQX_BOARD_DIR to indicate the location of your MQX libraries.") - endif() -endif() - -set(LWPA_TARGET_OS ${LWPA_TARGET_OS} PARENT_SCOPE) +# if(DEFINED LWPA_CONFIG) +# get_filename_component(LWPA_CONFIG_LOC LWPA_CONFIG DIRECTORY) +# set(${LWPA_HAVE_CONFIG_H} LWPA_HAVE_CONFIG_H) +# endif() ############################################################################### # Core lwpa library @@ -66,10 +29,13 @@ add_library(lwpa ${LWPA_ROOT}/include/lwpa/root_layer_pdu.h ${LWPA_ROOT}/include/lwpa/socket.h ${LWPA_ROOT}/include/lwpa/timer.h - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_inet.h - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_lock.h - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_thread.h - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_socket.h + + ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_lock.h + ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_thread.h + + ${LWPA_ROOT}/include/os/${LWPA_NETWORK_TARGET}/lwpa/os_socket.h + ${LWPA_ROOT}/include/os/${LWPA_NETWORK_TARGET}/lwpa/os_inet.h + # lwpa sources ${LWPA_ROOT}/src/lwpa/common.c ${LWPA_ROOT}/src/lwpa/error.c @@ -85,72 +51,42 @@ add_library(lwpa ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/timer.c ${LWPA_ROOT}/src/lwpa/uuid.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_inet.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_uuid.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_socket.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_thread.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_timer.c + + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_lock.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_uuid.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_thread.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_timer.c + + ${LWPA_ROOT}/src/os/${LWPA_NETWORK_TARGET}/lwpa/os_inet.c + ${LWPA_ROOT}/src/os/${LWPA_NETWORK_TARGET}/lwpa/os_netint.c + ${LWPA_ROOT}/src/os/${LWPA_NETWORK_TARGET}/lwpa/os_socket.c + + ${LWPA_OS_ADDITIONAL_SOURCES} + ${LWPA_NETWORK_ADDITIONAL_SOURCES} ) # lwpa public include directories and library dependencies target_include_directories(lwpa PUBLIC ${LWPA_ROOT}/include - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS} - ${LWPA_CONFIG_LOC} + ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET} + ${LWPA_ROOT}/include/os/${LWPA_NETWORK_TARGET} + ${LWPA_OS_ADDITIONAL_INCLUDE_DIRS} + ${LWPA_NETWORK_ADDITIONAL_INCLUDE_DIRS} + # ${LWPA_CONFIG_LOC} ) target_include_directories(lwpa PRIVATE ${LWPA_ROOT}/src) target_compile_definitions(lwpa PUBLIC ${LWPA_HAVE_CONFIG_H}) if(LWPA_NETINT_DEBUG_OUTPUT) target_compile_definitions(lwpa PRIVATE LWPA_NETINT_DEBUG_OUTPUT) endif() - -# Add include paths and library dependencies based on OS for which we are being compiled -if(LWPA_TARGET_OS STREQUAL windows) - target_sources(lwpa PRIVATE - ${LWPA_ROOT}/src/os/windows/lwpa/os_error.h - ${LWPA_ROOT}/src/os/windows/lwpa/os_error.c - ) - target_link_libraries(lwpa PUBLIC winmm ws2_32 Iphlpapi Rpcrt4) -elseif(LWPA_TARGET_OS STREQUAL macos) - target_sources(lwpa PRIVATE - ${LWPA_ROOT}/src/os/macos/lwpa/os_error.h - ${LWPA_ROOT}/src/os/macos/lwpa/os_error.c - ) -elseif(LWPA_TARGET_OS STREQUAL linux) - target_link_libraries(lwpa PUBLIC uuid pthread) - target_sources(lwpa PRIVATE - ${LWPA_ROOT}/src/os/linux/lwpa/os_error.h - ${LWPA_ROOT}/src/os/linux/lwpa/os_error.c - ) -elseif(LWPA_TARGET_OS STREQUAL mqx) - # Include the debug versions of the MQX libs if a Debug configuration is specified. - # I think there's probably a better way of doing this and I'm missing something here. - if(CMAKE_BUILD_TYPE STREQUAL Debug) - set(MQX_BOARD_INT_DIR debug) - else() - set(MQX_BOARD_INT_DIR release) - endif() - - # Depend on the MQX libs. - target_include_directories(lwpa PUBLIC ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR} - ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/bsp - ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/bsp/Generated_Code - ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/bsp/Sources - ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/psp - ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/rtcs) - target_link_libraries(lwpa PUBLIC ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/bsp/bsp.a - ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/psp/psp.a - ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/rtcs/rtcs.a) -endif() +target_link_libraries(lwpa PUBLIC ${LWPA_OS_ADDITIONAL_LIBS} ${LWPA_NETWORK_ADDITIONAL_LIBS}) set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) # Installation install(TARGETS lwpa ARCHIVE DESTINATION lib) install(DIRECTORY ${LWPA_ROOT}/include/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") -install(DIRECTORY ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") +install(DIRECTORY ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") ############################################################################### # Mock lwpa library @@ -176,9 +112,9 @@ if(LWPA_BUILD_MOCK_LIB) ${LWPA_ROOT}/include/lwpa/root_layer_pdu.h ${LWPA_ROOT}/include/lwpa/socket.h ${LWPA_ROOT}/include/lwpa/timer.h - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_lock.h - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_socket.h - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS}/lwpa/os_thread.h + ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_lock.h + ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_socket.h + ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_thread.h ${LWPA_ROOT}/include/lwpa_mock/socket.h @@ -193,23 +129,23 @@ if(LWPA_BUILD_MOCK_LIB) ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c ${LWPA_ROOT}/src/lwpa/md5.h ${LWPA_ROOT}/src/lwpa/md5.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_lock.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_netint.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_uuid.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_socket.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_thread.c - ${LWPA_ROOT}/src/os/${LWPA_TARGET_OS}/lwpa/os_timer.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_lock.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_netint.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_uuid.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_socket.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_thread.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_timer.c ${LWPA_ROOT}/src/lwpa_mock/socket.c ) target_include_directories(lwpa_mock PUBLIC ${LWPA_ROOT}/include - ${LWPA_ROOT}/include/os/${LWPA_TARGET_OS} + ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET} ) target_include_directories(lwpa_mock PRIVATE ${LWPA_ROOT}/src) target_compile_definitions(lwpa_mock PRIVATE LWPA_BUILDING_MOCK_LIB) target_link_libraries(lwpa_mock PUBLIC meekrosoft::fff) - if(LWPA_TARGET_OS STREQUAL windows) + if(LWPA_OS_TARGET STREQUAL windows) target_link_libraries(lwpa_mock PUBLIC winmm ws2_32 Iphlpapi Rpcrt4) endif() set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) diff --git a/src/os/freertos/lwpa/os_lock.c b/src/os/freertos/lwpa/os_lock.c index 00c4101b7..3e3b1f507 100644 --- a/src/os/freertos/lwpa/os_lock.c +++ b/src/os/freertos/lwpa/os_lock.c @@ -17,36 +17,49 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_lock.h" -#include "lwpa_int.h" -#include "task.h" +#include "lwpa/lock.h" +#include -#define convert_ms_to_ticks(ms) ((ms == LWPA_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(ms)) + +/*********************** Private function prototypes *************************/ + +static void reader_atomic_increment(lwpa_rwlock_t* id); +static void reader_atomic_decrement(lwpa_rwlock_t* id); + +/*************************** Function definitions ****************************/ bool lwpa_mutex_create(lwpa_mutex_t* id) { - return id ? ((*id = (lwpa_mutex_t)xSemaphoreCreateMutex()) != NULL) : false; + id ? ((*id = (lwpa_mutex_t)xSemaphoreCreateMutex()) != NULL) : false; +} + +bool lwpa_mutex_take(lwpa_mutex_t* id) +{ + if (id) + { + return (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, portMAX_DELAY)); + } + return false; } -bool lwpa_mutex_take(lwpa_mutex_t* id, int wait_ms) +bool lwpa_mutex_try_take(lwpa_mutex_t* id) { if (id) { - SemaphoreHandle_t sem = *id; - return sem ? (pdTRUE == xSemaphoreTake(sem, convert_ms_to_ticks(wait_ms))) : false; + return (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, 0)); } return false; } void lwpa_mutex_give(lwpa_mutex_t* id) { - if (id && *id) + if (id) xSemaphoreGive((SemaphoreHandle_t)*id); } void lwpa_mutex_destroy(lwpa_mutex_t* id) { - if (id && *id) + if (id) { vSemaphoreDelete((SemaphoreHandle_t)*id); *id = (lwpa_mutex_t)NULL; @@ -58,14 +71,19 @@ bool lwpa_signal_create(lwpa_signal_t* id) return id ? ((*id = (lwpa_signal_t)xSemaphoreCreateBinary()) != NULL) : false; } -bool lwpa_signal_wait(lwpa_signal_t* id, int wait_ms) +bool lwpa_signal_wait(lwpa_signal_t* id) +{ + return id ? (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, portMAX_DELAY)) : false; +} + +bool lwpa_signal_poll(lwpa_signal_t* id) { - return (id && *id) ? (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, convert_ms_to_ticks(wait_ms))) : false; + return id ? (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, 0)) : false; } void lwpa_signal_post(lwpa_signal_t* id) { - if (id && *id) + if (id) xSemaphoreGive((SemaphoreHandle_t)*id); } @@ -78,20 +96,6 @@ void lwpa_signal_destroy(lwpa_signal_t* id) } } -static void atomic_inc(unsigned int* count) -{ - portENTER_CRITICAL(); - (*count)++; - portEXIT_CRITICAL(); -} - -static void atomic_dec(unsigned int* count) -{ - portENTER_CRITICAL(); - (*count)--; - portEXIT_CRITICAL(); -} - bool lwpa_rwlock_create(lwpa_rwlock_t* id) { if (id && (NULL != (id->sem = xSemaphoreCreateMutex()))) @@ -176,3 +180,17 @@ void lwpa_rwlock_destroy(lwpa_rwlock_t* id) id->sem = NULL; } } + +void reader_atomic_increment(lwpa_rwlock_t* id) +{ + portENTER_CRITICAL(); + ++id->reader_count; + portEXIT_CRITICAL(); +} + +void reader_atomic_decrement(lwpa_rwlock_t* id) +{ + portENTER_CRITICAL(); + --id->reader_count; + portEXIT_CRITICAL(); +} diff --git a/src/os/freertos/lwpa/os_thread.c b/src/os/freertos/lwpa/os_thread.c index 6f354f663..c8bc0aedd 100644 --- a/src/os/freertos/lwpa/os_thread.c +++ b/src/os/freertos/lwpa/os_thread.c @@ -17,9 +17,7 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_thread.h" - -#define convert_ms_to_ticks(ms) ((ms == LWPA_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(ms)) +#include "lwpa/thread.h" static void thread_func_internal(void* pvParameters) { @@ -51,14 +49,14 @@ bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void return false; } -bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms) +bool lwpa_thread_join(lwpa_thread_t* id) { bool res; if (!id) return false; - res = (pdTRUE == xSemaphoreTake(id->sig, convert_ms_to_ticks(wait_ms))); + res = (pdTRUE == xSemaphoreTake(id->sig, portMAX_DELAY)); if (res) { vSemaphoreDelete(id->sig); diff --git a/src/os/freertos/lwpa/os_timer.c b/src/os/freertos/lwpa/os_timer.c index fcb9c4222..8ff78e339 100644 --- a/src/os/freertos/lwpa/os_timer.c +++ b/src/os/freertos/lwpa/os_timer.c @@ -17,9 +17,22 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_timer.h" -#include "FreeRTOS.h" -#include "task.h" +#include "lwpa/timer.h" +#include "lwpa/private/timer.h" + +#include +#include + +lwpa_error_t lwpa_timer_init() +{ + // No initialization necessary on this platform + return kLwpaErrOk; +} + +void lwpa_timer_deinit() +{ + // No deinitialization necessary on this platform +} uint32_t lwpa_getms() { diff --git a/src/os/freertos/lwpa/os_uuid.c b/src/os/freertos/lwpa/os_uuid.c new file mode 100644 index 000000000..f48e4e73a --- /dev/null +++ b/src/os/freertos/lwpa/os_uuid.c @@ -0,0 +1,31 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/uuid.h" + +/* We don't have the capability to generate V1 or V4 UUIDs on FreeRTOS. */ +lwpa_error_t lwpa_generate_v1_uuid(LwpaUuid* uuid) +{ + return kLwpaErrNotImpl; +} + +lwpa_error_t lwpa_generate_v4_uuid(LwpaUuid* uuid) +{ + return kLwpaErrNotImpl; +} diff --git a/src/os/lwip/lwpa/os_inet.c b/src/os/lwip/lwpa/os_inet.c new file mode 100644 index 000000000..e69de29bb diff --git a/src/os/lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c index ee1e63722..a563aecdd 100644 --- a/src/os/lwip/lwpa/os_socket.c +++ b/src/os/lwip/lwpa/os_socket.c @@ -17,10 +17,10 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_socket.h" +#include "lwpa/socket.h" #include -#include "lwip/sockets.h" -#include "lwip/netdb.h" +#include +#include /* clang-format off */ @@ -460,71 +460,229 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* return kLwpaErrInvalid; } -int lwpa_poll(LwpaPollfd* fds, size_t nfds, int timeout_ms) +lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { - fd_set readfds; - fd_set writefds; - LwpaPollfd* fd; - int nosfds; - int sel_res; - int nreadfds = 0, nwritefds = 0; - struct timeval os_timeout; + if (!context) + return kLwpaErrInvalid; - if (fds && nfds > 0) - { - FD_ZERO(&readfds); - FD_ZERO(&writefds); + init_context_socket_array(context); + LWPA_FD_ZERO(&context->readfds); + LWPA_FD_ZERO(&context->writefds); + context->valid = true; + return kLwpaErrOk; +} + +void lwpa_poll_context_deinit(LwpaPollContext* context) +{ + if (!context || !context->valid) + return; + + context->valid = false; +} + +lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, + void* user_data) +{ + if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + return kLwpaErrInvalid; - for (fd = fds; fd < fds + nfds; ++fd) + if (context->num_valid_sockets >= LWPA_SOCKET_MAX_POLL_SIZE) + { + return kLwpaErrNoMem; + } + else + { + LwpaPollCtxSocket* new_sock = find_hole(context); + if (new_sock) { - if (fd->events & LWPA_POLLIN) - { - FD_SET((int)fd->fd, &readfds); - nreadfds++; - } - if (fd->events & LWPA_POLLOUT) - { - FD_SET((int)fd->fd, &writefds); - nwritefds++; - } - /* LWPA_POLLPRI/exceptfds is not handled properly on this os */ + new_sock->socket = socket; + new_sock->events = events; + new_sock->user_data = user_data; + set_in_fd_sets(context, new_sock); + context->num_valid_sockets++; + return kLwpaErrOk; } + return kLwpaErrNoMem; } +} - if (timeout_ms == 0) +lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, + void* new_user_data) +{ + if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) + return kLwpaErrInvalid; + + LwpaPollCtxSocket* sock_desc = find_socket(context, socket); + if (sock_desc) { - os_timeout.tv_sec = 0; - os_timeout.tv_usec = 0; + clear_in_fd_sets(context, sock_desc); + sock_desc->events = new_events; + sock_desc->user_data = new_user_data; + set_in_fd_sets(context, sock_desc); + return kLwpaErrOk; } - else if (timeout_ms != LWPA_WAIT_FOREVER) + else { - os_timeout.tv_sec = timeout_ms / 1000; - os_timeout.tv_usec = (timeout_ms % 1000) * 1000; + return kLwpaErrNotFound; } - nosfds = (nreadfds > nwritefds) ? nreadfds : nwritefds; - sel_res = select(nosfds, nreadfds ? &readfds : NULL, nwritefds ? &writefds : NULL, NULL, - timeout_ms == LWPA_WAIT_FOREVER ? NULL : &os_timeout); +} - if (sel_res < 0) - return -1; - else if (sel_res > 0 && fds && nfds > 0) +void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) +{ + if (!context || !context->valid || socket == LWPA_SOCKET_INVALID) + return; + + LwpaPollCtxSocket* sock_desc = find_socket(context, socket); + if (sock_desc) { - for (fd = fds; fd < fds + nfds; ++fd) + clear_in_fd_sets(context, sock_desc); + sock_desc->socket = LWPA_SOCKET_INVALID; + context->num_valid_sockets--; + } +} + +lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int timeout_ms) +{ + if (!context || !context->valid || !event) + return kLwpaErrInvalid; + + if (context->readfds.count == 0 && context->writefds.count == 0) + { + // No valid sockets are currently added to the context. + return kLwpaErrNoSockets; + } + + uint32_t os_timeout; + if (timeout_ms == LWPA_WAIT_FOREVER) + os_timeout = 0; + else if (timeout_ms == 0) + os_timeout = 0xffffffff; + else + os_timeout = (uint32_t)timeout_ms; + + int32_t nfds = + (int32_t)((context->readfds.count > context->writefds.count) ? context->readfds.count : context->writefds.count); + int32_t sel_res = select(nfds, context->readfds.count ? &context->readfds.set : NULL, + context->writefds.count ? &context->writefds.set : NULL, NULL, os_timeout); + + if (sel_res == RTCS_ERROR) + { + // RTCS handles some socket errors by returning them from select(). + uint32_t rtcs_err = RTCS_get_errno(); + if (rtcs_err == RTCSERR_SOCK_ESHUTDOWN) + return handle_select_result(context, event, kLwpaErrConnClosed); + else if (rtcs_err == RTCSERR_SOCK_CLOSED) + return handle_select_result(context, event, kLwpaErrNotFound); + else + return err_os_to_lwpa(rtcs_err); + } + else if (sel_res == 0) + { + return kLwpaErrTimedOut; + } + else + { + return handle_select_result(context, event, kLwpaErrOk); + } +} + +lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, lwpa_error_t socket_error) +{ + // Init the event data. + event->socket = LWPA_SOCKET_INVALID; + event->events = 0; + event->err = kLwpaErrOk; + + // The default return; if we don't find any sockets set that we passed to select(), something has + // gone wrong. + lwpa_error_t res = kLwpaErrSys; + + for (LwpaPollCtxSocket* sock_desc = context->sockets; sock_desc < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; + ++sock_desc) + { + if (sock_desc->socket == LWPA_SOCKET_INVALID) + continue; + + if (LWPA_FD_ISSET(sock_desc->socket, &context->readfds) || LWPA_FD_ISSET(sock_desc->socket, &context->writefds)) { - fd->revents = 0; - if (nreadfds && (fd->events & LWPA_POLLIN) && FD_ISSET((int)fd->fd, &readfds)) + res = kLwpaErrOk; + event->socket = sock_desc->socket; + event->user_data = sock_desc->user_data; + + /* Check for errors */ + if (socket_error != kLwpaErrOk) { - fd->revents |= LWPA_POLLIN; + event->events |= LWPA_POLL_ERR; + event->err = socket_error; } - if (nwritefds && (fd->events & LWPA_POLLOUT) && FD_ISSET((int)fd->fd, &writefds)) + + if (LWPA_FD_ISSET(sock_desc->socket, &context->readfds)) { - fd->revents |= LWPA_POLLOUT; + if (sock_desc->events & LWPA_POLL_IN) + event->events |= LWPA_POLL_IN; } - /* LWPA_POLLPRI/exceptfds is not handled properly on this - * os */ + if (LWPA_FD_ISSET(sock_desc->socket, &context->writefds)) + { + if (sock_desc->events & LWPA_POLL_CONNECT) + event->events |= LWPA_POLL_CONNECT; + else if (sock_desc->events & LWPA_POLL_OUT) + event->events |= LWPA_POLL_OUT; + } + // LWPA_POLL_OOB/exceptfds is not handled properly on this OS + + break; // We handle one event at a time. } } - return sel_res; + return res; +} + +void init_context_socket_array(LwpaPollContext* context) +{ + context->num_valid_sockets = 0; + for (LwpaPollCtxSocket* ctx_socket = context->sockets; ctx_socket < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; + ++ctx_socket) + { + ctx_socket->socket = LWPA_SOCKET_INVALID; + } +} + +LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket) +{ + for (LwpaPollCtxSocket* cur = context->sockets; cur < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; ++cur) + { + if (cur->socket == socket) + return cur; + } + return NULL; +} + +LwpaPollCtxSocket* find_hole(LwpaPollContext* context) +{ + return find_socket(context, LWPA_SOCKET_INVALID); +} + +void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) +{ + if (sock->events & LWPA_POLL_IN) + { + LWPA_FD_SET(sock->socket, &context->readfds); + } + if (sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + { + LWPA_FD_SET(sock->socket, &context->writefds); + } +} + +void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) +{ + if (sock->events & LWPA_POLL_IN) + { + LWPA_FD_CLEAR(sock->socket, &context->readfds); + } + if (sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + { + LWPA_FD_CLEAR(sock->socket, &context->writefds); + } } int lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, LwpaAddrinfo* result) diff --git a/tools/cmake/lwpa-os.cmake b/tools/cmake/lwpa-os.cmake new file mode 100644 index 000000000..38f827233 --- /dev/null +++ b/tools/cmake/lwpa-os.cmake @@ -0,0 +1,56 @@ + +# The set of supported target OS +set(VALID_LWPA_OS_TARGETS + freertos + linux + macos + mqx + windows +) +set(VALID_LWPA_NETWORK_TARGETS + linux + lwip + macos + mqx + windows +) + +set(LWPA_OS_TARGET "" CACHE STRING "OS provider for lwpa. See /CMakeLists.txt for valid values.") +set(LWPA_NETWORK_TARGET "" CACHE STRING "Network stack provider for lwpa. Often (but not always) the same as LWPA_OS_TARGET. See src/CMakeLists.txt for valid values.") + +if(NOT LWPA_OS_TARGET) + message(STATUS "LWPA_OS_TARGET not supplied, assuming native compile by default...") + if(WIN32) + set(LWPA_OS_TARGET windows) + elseif(APPLE) + set(LWPA_OS_TARGET macos) + elseif(UNIX) + set(LWPA_OS_TARGET linux) + else() + # The error check below will catch this and print the fatal error. + set(LWPA_OS_TARGET ${CMAKE_HOST_SYSTEM_NAME}) + endif() +endif() + +if(NOT LWPA_NETWORK_TARGET) + if(${LWPA_OS_TARGET} IN_LIST VALID_LWPA_NETWORK_TARGETS) + set(LWPA_NETWORK_TARGET ${LWPA_OS_TARGET}) + endif() +endif() + +if(NOT ${LWPA_OS_TARGET} IN_LIST VALID_LWPA_OS_TARGETS) + message(FATAL_ERROR "${LWPA_OS_TARGET} is not a valid target OS. " + "Specify LWPA_OS_TARGET from these options: ${VALID_LWPA_OS_TARGETS}") +endif() + +if(NOT ${LWPA_NETWORK_TARGET} IN_LIST VALID_LWPA_NETWORK_TARGETS) + message(FATAL_ERROR "${LWPA_NETWORK_TARGET} is not a valid target network stack. " + "Specify LWPA_NETWORK_TARGET from these options: ${VALID_LWPA_NETWORK_TARGETS}") +endif() + +if(EXISTS ${PROJECT_SOURCE_DIR}/tools/cmake/os/${LWPA_OS_TARGET}.cmake) + include(${PROJECT_SOURCE_DIR}/tools/cmake/os/${LWPA_OS_TARGET}.cmake) +endif() +if(EXISTS ${PROJECT_SOURCE_DIR}/tools/cmake/net/${LWPA_NETWORK_TARGET}.cmake) + include(${PROJECT_SOURCE_DIR}/tools/cmake/net/${LWPA_NETWORK_TARGET}.cmake) +endif() diff --git a/tools/cmake/net/lwip.cmake b/tools/cmake/net/lwip.cmake new file mode 100644 index 000000000..d524726a2 --- /dev/null +++ b/tools/cmake/net/lwip.cmake @@ -0,0 +1,11 @@ + +# lwIP compilation support for lwpa +set(LWPA_LWIP_INCLUDE_DIR "" CACHE STRING "The include directory for the lwIP headers") +set(LWPA_LWIPOPTS_DIR "" CACHE STRING "The directory of the project's lwipopts.h file") +if(NOT LWPA_LWIP_INCLUDE_DIR OR NOT LWPA_LWIPOPTS_DIR) + message(FATAL_ERROR "You must provide the options LWPA_LWIP_INCLUDE_DIR to specify the lwIP include directory " + "and LWPA_LWIPOPTS_DIR to specify the location of the lwipopts.h file." + ) +endif() + +set(LWPA_NETWORK_ADDITIONAL_INCLUDE_DIRS ${LWPA_LWIP_INCLUDE_DIR} ${LWPA_LWIPOPTS_DIR}) diff --git a/tools/cmake/os/freertos.cmake b/tools/cmake/os/freertos.cmake new file mode 100644 index 000000000..4fa52a5d6 --- /dev/null +++ b/tools/cmake/os/freertos.cmake @@ -0,0 +1,11 @@ + +# FreeRTOS compilation support for lwpa +set(LWPA_FREERTOS_INCLUDE_DIR "" CACHE STRING "The include directory for the FreeRTOS headers") +set(LWPA_FREERTOSCONFIG_DIR "" CACHE STRING "The directory of the project's FreeRTOSConfig.h file") +if(NOT LWPA_FREERTOS_INCLUDE_DIR OR NOT LWPA_FREERTOSCONFIG_DIR) + message(FATAL_ERROR "You must provide the options LWPA_FREERTOS_INCLUDE_DIR to specify the FreeRTOS include directory " + "and LWPA_FREERTOSCONFIG_DIR to specify the location of the FreeRTOSConfig.h." + ) +endif() + +set(LWPA_OS_ADDITIONAL_INCLUDE_DIRS ${LWPA_FREERTOS_INCLUDE_DIR} ${LWPA_FREERTOSCONFIG_DIR}) diff --git a/tools/cmake/os/linux.cmake b/tools/cmake/os/linux.cmake new file mode 100644 index 000000000..b9ea0da7f --- /dev/null +++ b/tools/cmake/os/linux.cmake @@ -0,0 +1,6 @@ + +set(LWPA_OS_ADDITIONAL_SOURCES + ${LWPA_ROOT}/src/os/linux/lwpa/os_error.h + ${LWPA_ROOT}/src/os/linux/lwpa/os_error.c +) +set(LWPA_OS_ADDITIONAL_LIBS uuid pthread) diff --git a/tools/cmake/os/macos.cmake b/tools/cmake/os/macos.cmake new file mode 100644 index 000000000..2cc249fd2 --- /dev/null +++ b/tools/cmake/os/macos.cmake @@ -0,0 +1,5 @@ + +set(LWPA_OS_ADDITIONAL_SOURCES + ${LWPA_ROOT}/src/os/macos/lwpa/os_error.h + ${LWPA_ROOT}/src/os/macos/lwpa/os_error.c +) diff --git a/tools/cmake/os/mqx.cmake b/tools/cmake/os/mqx.cmake new file mode 100644 index 000000000..92e890076 --- /dev/null +++ b/tools/cmake/os/mqx.cmake @@ -0,0 +1,29 @@ + +# MQX compilation support for lwpa +set(MQX_BOARD_DIR "" CACHE STRING "Location of the MQX compiled libraries, e.g. \"MQX/v4.2.0/lib/[your board name]\"") +if(NOT MQX_BOARD_DIR) + message(FATAL_ERROR "You must provide the option MQX_BOARD_DIR to indicate the location of your MQX libraries.") +endif() + +# Include the debug versions of the MQX libs if a Debug configuration is specified. +# I think there's probably a better way of doing this and I'm missing something here. +if(CMAKE_BUILD_TYPE STREQUAL Debug) + set(MQX_BOARD_INT_DIR debug) +else() + set(MQX_BOARD_INT_DIR release) +endif() + +# Depend on the MQX libs. +set(LWPA_OS_ADDITIONAL_INCLUDE_DIRS + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR} + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/bsp + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/bsp/Generated_Code + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/bsp/Sources + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/psp + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/rtcs +) +set(LWPA_OS_ADDITIONAL_LIBS + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/bsp/bsp.a + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/psp/psp.a + ${MQX_BOARD_DIR}/${MQX_BOARD_INT_DIR}/rtcs/rtcs.a +) diff --git a/tools/cmake/os/windows.cmake b/tools/cmake/os/windows.cmake new file mode 100644 index 000000000..39b65b0d5 --- /dev/null +++ b/tools/cmake/os/windows.cmake @@ -0,0 +1,6 @@ + +set(LWPA_OS_ADDITIONAL_SOURCES + ${LWPA_ROOT}/src/os/windows/lwpa/os_error.h + ${LWPA_ROOT}/src/os/windows/lwpa/os_error.c +) +set(LWPA_OS_ADDITIONAL_LIBS winmm ws2_32 Iphlpapi Rpcrt4) From 00e47ee89bd704ce6672a7bd286c05eefde72ce4 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 20 Aug 2019 16:48:54 -0500 Subject: [PATCH 115/264] Still portin' --- include/os/freertos/lwpa/os_thread.h | 16 +---- src/CMakeLists.txt | 1 + src/os/freertos/lwpa/os_lock.c | 89 +++++++++++++++++----------- src/os/freertos/lwpa/os_thread.c | 2 +- src/os/lwip/lwpa/os_netint.c | 4 +- src/os/mqx/lwpa/os_lock.c | 6 +- tools/cmake/lwpa-os.cmake | 2 +- tools/cmake/net/lwip.cmake | 8 +-- tools/cmake/os/freertos.cmake | 8 +-- 9 files changed, 74 insertions(+), 62 deletions(-) diff --git a/include/os/freertos/lwpa/os_thread.h b/include/os/freertos/lwpa/os_thread.h index 8143cb56a..e369bc972 100644 --- a/include/os/freertos/lwpa/os_thread.h +++ b/include/os/freertos/lwpa/os_thread.h @@ -20,9 +20,9 @@ #ifndef _LWPA_OS_THREAD_H_ #define _LWPA_OS_THREAD_H_ -#include "FreeRTOS.h" -#include "task.h" -#include "semphr.h" +#include +#include +#include #include "lwpa/common.h" #include "lwpa/bool.h" @@ -30,14 +30,6 @@ extern "C" { #endif -typedef struct LwpaThreadParams -{ - unsigned int thread_priority; - unsigned int stack_size; - char* thread_name; - void* platform_data; -} LwpaThreadParams; - #define LWPA_THREAD_DEFAULT_PRIORITY (configMAX_PRIORITIES / 2) #define LWPA_THREAD_DEFAULT_STACK 2000 #define LWPA_THREAD_DEFAULT_NAME "lwpa_thread" @@ -50,8 +42,6 @@ typedef struct TaskHandle_t tid; } lwpa_thread_t; -bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void (*thread_fn)(void*), void* thread_arg); -bool lwpa_thread_stop(lwpa_thread_t* id, int wait_ms); #define lwpa_thread_sleep(sleep_ms) vTaskDelay(pdMS_TO_TICKS(sleep_ms)) #ifdef __cplusplus diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index edf79c1c1..bac017f46 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,6 +72,7 @@ target_include_directories(lwpa PUBLIC ${LWPA_ROOT}/include/os/${LWPA_NETWORK_TARGET} ${LWPA_OS_ADDITIONAL_INCLUDE_DIRS} ${LWPA_NETWORK_ADDITIONAL_INCLUDE_DIRS} + ${LWPA_TOOLCHAIN_ADDITIONAL_INCLUDE_DIRS} # ${LWPA_CONFIG_LOC} ) target_include_directories(lwpa PRIVATE ${LWPA_ROOT}/src) diff --git a/src/os/freertos/lwpa/os_lock.c b/src/os/freertos/lwpa/os_lock.c index 3e3b1f507..b79baa6a8 100644 --- a/src/os/freertos/lwpa/os_lock.c +++ b/src/os/freertos/lwpa/os_lock.c @@ -30,7 +30,7 @@ static void reader_atomic_decrement(lwpa_rwlock_t* id); bool lwpa_mutex_create(lwpa_mutex_t* id) { - id ? ((*id = (lwpa_mutex_t)xSemaphoreCreateMutex()) != NULL) : false; + return id ? ((*id = (lwpa_mutex_t)xSemaphoreCreateMutex()) != NULL) : false; } bool lwpa_mutex_take(lwpa_mutex_t* id) @@ -101,83 +101,104 @@ bool lwpa_rwlock_create(lwpa_rwlock_t* id) if (id && (NULL != (id->sem = xSemaphoreCreateMutex()))) { id->reader_count = 0; + id->valid = true; return true; } return false; } -bool lwpa_rwlock_readlock(lwpa_rwlock_t* id, int wait_ms) +bool lwpa_rwlock_readlock(lwpa_rwlock_t* id) { - if (!id || !id->sem) + if (!id || !id->valid) return false; - if (pdTRUE == xSemaphoreTake(id->sem, convert_ms_to_ticks(wait_ms))) + if (pdTRUE == xSemaphoreTake(id->sem, portMAX_DELAY)) { - /* Add one to the reader count. */ - atomic_inc(&id->reader_count); - /* Allow other readers to access. */ + // Add one to the reader count. + reader_atomic_increment(id); + // Allow other readers to access. xSemaphoreGive(id->sem); return true; } return false; } -void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) +bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id) { - if (id && id->sem) - atomic_dec(&id->reader_count); + if (!id || !id->valid) + return false; + + // Poll the semaphore + if (pdTRUE == xSemaphoreTake(id->sem, 0)) + { + // Add one to the reader count + reader_atomic_increment(id); + // Allow other readers to access + xSemaphoreGive(id->sem); + return true; + } + return false; } -bool lwpa_rwlock_writelock(lwpa_rwlock_t* id, int wait_ms) +void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) { - TickType_t initial_time; + if (id && id->valid) + reader_atomic_decrement(id); +} - if (!id || !id->sem) +bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) +{ + if (!id || !id->valid) return false; - /* Start our timer here */ - initial_time = xTaskGetTickCount(); - - if (pdTRUE == xSemaphoreTake(id->sem, convert_ms_to_ticks(wait_ms))) + if (pdTRUE == xSemaphoreTake(id->sem, portMAX_DELAY)) { - /* Wait until there are no readers, keeping the lock so that no new readers - * can get in. */ + // Wait until there are no readers, keeping the lock so that no new readers can get in. while (id->reader_count > 0) { - vTaskDelay(pdMS_TO_TICKS(1)); - if (wait_ms != LWPA_WAIT_FOREVER) - { - TickType_t current_time = xTaskGetTickCount(); - if (current_time - initial_time > convert_ms_to_ticks(wait_ms)) - { - break; - } - } + vTaskDelay(1); // Wait one tick at a time } + // Hold on to the lock until writeunlock() is called + return true; + } + return false; +} + +bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id) +{ + if (!id || !id->valid) + return false; + + if (pdTRUE == xSemaphoreTake(id->sem, 0)) + { + // Just check once if there are still readers if (id->reader_count > 0) { - /* Timed out waiting for readers to leave. Bail. */ + // Readers are present, give up the lock and return false below. xSemaphoreGive(id->sem); - return false; } - /* Hold on to the lock until writeunlock() is called */ - return true; + else + { + // Return, holding the lock + return true; + } } return false; } void lwpa_rwlock_writeunlock(lwpa_rwlock_t* id) { - if (id && id->sem) + if (id && id->valid) xSemaphoreGive(id->sem); } void lwpa_rwlock_destroy(lwpa_rwlock_t* id) { - if (id && id->sem) + if (id && id->valid) { vSemaphoreDelete(id->sem); id->sem = NULL; + id->valid = false; } } diff --git a/src/os/freertos/lwpa/os_thread.c b/src/os/freertos/lwpa/os_thread.c index c8bc0aedd..038b6dde0 100644 --- a/src/os/freertos/lwpa/os_thread.c +++ b/src/os/freertos/lwpa/os_thread.c @@ -42,7 +42,7 @@ bool lwpa_thread_create(lwpa_thread_t* id, const LwpaThreadParams* params, void id->fn = thread_fn; id->arg = thread_arg; if (pdPASS == xTaskCreate(thread_func_internal, params->thread_name ? params->thread_name : "lwpa_thread", - params->stack_size, id, params->thread_priority, &id->tid)) + (uint16_t)params->stack_size, id, params->thread_priority, &id->tid)) { return true; } diff --git a/src/os/lwip/lwpa/os_netint.c b/src/os/lwip/lwpa/os_netint.c index 48ceaf881..318a68e4b 100644 --- a/src/os/lwip/lwpa/os_netint.c +++ b/src/os/lwip/lwpa/os_netint.c @@ -17,9 +17,9 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#include "lwpa_netint.h" +#include "lwpa/netint.h" #include -#include "lwip/netif.h" +#include static bool mask_is_empty(const LwpaIpAddr* mask); static bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask); diff --git a/src/os/mqx/lwpa/os_lock.c b/src/os/mqx/lwpa/os_lock.c index 8018c2754..69a5f8042 100644 --- a/src/os/mqx/lwpa/os_lock.c +++ b/src/os/mqx/lwpa/os_lock.c @@ -82,7 +82,7 @@ bool lwpa_rwlock_try_readlock(lwpa_rwlock_t* id) void lwpa_rwlock_readunlock(lwpa_rwlock_t* id) { - if (id) + if (id && id->valid) reader_atomic_decrement(id); } @@ -90,7 +90,7 @@ bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) { if (id && id->valid) { - if (_lwsem_wait(&id->sem)) + if (MQX_OK == _lwsem_wait(&id->sem)) { // Wait until there are no readers, keeping the lock so that no new readers can get in. while (id->reader_count > 0) @@ -108,7 +108,7 @@ bool lwpa_rwlock_try_writelock(lwpa_rwlock_t* id) { if (id && id->valid) { - if (_lwsem_wait(&id->sem)) + if (MQX_OK == _lwsem_wait_ticks(&id->sem, 1u)) { // Just check once to see if there are still readers if (id->reader_count > 0) diff --git a/tools/cmake/lwpa-os.cmake b/tools/cmake/lwpa-os.cmake index 38f827233..2ee57d0a0 100644 --- a/tools/cmake/lwpa-os.cmake +++ b/tools/cmake/lwpa-os.cmake @@ -15,7 +15,7 @@ set(VALID_LWPA_NETWORK_TARGETS windows ) -set(LWPA_OS_TARGET "" CACHE STRING "OS provider for lwpa. See /CMakeLists.txt for valid values.") +set(LWPA_OS_TARGET "" CACHE STRING "OS provider for lwpa. See tools/cmake/lwpa-os.cmake for valid values.") set(LWPA_NETWORK_TARGET "" CACHE STRING "Network stack provider for lwpa. Often (but not always) the same as LWPA_OS_TARGET. See src/CMakeLists.txt for valid values.") if(NOT LWPA_OS_TARGET) diff --git a/tools/cmake/net/lwip.cmake b/tools/cmake/net/lwip.cmake index d524726a2..df36936f5 100644 --- a/tools/cmake/net/lwip.cmake +++ b/tools/cmake/net/lwip.cmake @@ -1,11 +1,11 @@ # lwIP compilation support for lwpa -set(LWPA_LWIP_INCLUDE_DIR "" CACHE STRING "The include directory for the lwIP headers") +set(LWPA_LWIP_INCLUDE_DIRS "" CACHE STRING "The include directories for the lwIP headers") set(LWPA_LWIPOPTS_DIR "" CACHE STRING "The directory of the project's lwipopts.h file") -if(NOT LWPA_LWIP_INCLUDE_DIR OR NOT LWPA_LWIPOPTS_DIR) - message(FATAL_ERROR "You must provide the options LWPA_LWIP_INCLUDE_DIR to specify the lwIP include directory " +if(NOT LWPA_LWIP_INCLUDE_DIRS OR NOT LWPA_LWIPOPTS_DIR) + message(FATAL_ERROR "You must provide the options LWPA_LWIP_INCLUDE_DIRS to specify the lwIP include directories " "and LWPA_LWIPOPTS_DIR to specify the location of the lwipopts.h file." ) endif() -set(LWPA_NETWORK_ADDITIONAL_INCLUDE_DIRS ${LWPA_LWIP_INCLUDE_DIR} ${LWPA_LWIPOPTS_DIR}) +set(LWPA_NETWORK_ADDITIONAL_INCLUDE_DIRS ${LWPA_LWIP_INCLUDE_DIRS} ${LWPA_LWIPOPTS_DIR}) diff --git a/tools/cmake/os/freertos.cmake b/tools/cmake/os/freertos.cmake index 4fa52a5d6..96a59a1aa 100644 --- a/tools/cmake/os/freertos.cmake +++ b/tools/cmake/os/freertos.cmake @@ -1,11 +1,11 @@ # FreeRTOS compilation support for lwpa -set(LWPA_FREERTOS_INCLUDE_DIR "" CACHE STRING "The include directory for the FreeRTOS headers") +set(LWPA_FREERTOS_INCLUDE_DIRS "" CACHE STRING "The include directory for the FreeRTOS headers") set(LWPA_FREERTOSCONFIG_DIR "" CACHE STRING "The directory of the project's FreeRTOSConfig.h file") -if(NOT LWPA_FREERTOS_INCLUDE_DIR OR NOT LWPA_FREERTOSCONFIG_DIR) - message(FATAL_ERROR "You must provide the options LWPA_FREERTOS_INCLUDE_DIR to specify the FreeRTOS include directory " +if(NOT LWPA_FREERTOS_INCLUDE_DIRS OR NOT LWPA_FREERTOSCONFIG_DIR) + message(FATAL_ERROR "You must provide the options LWPA_FREERTOS_INCLUDE_DIRS to specify the FreeRTOS include directories " "and LWPA_FREERTOSCONFIG_DIR to specify the location of the FreeRTOSConfig.h." ) endif() -set(LWPA_OS_ADDITIONAL_INCLUDE_DIRS ${LWPA_FREERTOS_INCLUDE_DIR} ${LWPA_FREERTOSCONFIG_DIR}) +set(LWPA_OS_ADDITIONAL_INCLUDE_DIRS ${LWPA_FREERTOS_INCLUDE_DIRS} ${LWPA_FREERTOSCONFIG_DIR}) From 0629e4416061344dce2bac08634d6bf1c64da4a9 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 21 Aug 2019 18:01:41 -0500 Subject: [PATCH 116/264] Still portin' --- src/CMakeLists.txt | 12 +- src/lwpa/private/opts.h | 62 +++++++++ src/os/lwip/lwpa/os_netint.c | 239 ++++++++++++++++++----------------- 3 files changed, 191 insertions(+), 122 deletions(-) create mode 100644 src/lwpa/private/opts.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bac017f46..da2bf5eab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,8 @@ -# if(DEFINED LWPA_CONFIG) -# get_filename_component(LWPA_CONFIG_LOC LWPA_CONFIG DIRECTORY) -# set(${LWPA_HAVE_CONFIG_H} LWPA_HAVE_CONFIG_H) -# endif() +set(LWPA_CONFIG_FILE_LOC "" CACHE STRING "The directory path of the lwpa_config.h file, if provided") +if(LWPA_CONFIG_FILE_LOC) + set(${LWPA_HAVE_CONFIG_H} LWPA_HAVE_CONFIG_H) +endif() ############################################################################### # Core lwpa library @@ -73,10 +73,10 @@ target_include_directories(lwpa PUBLIC ${LWPA_OS_ADDITIONAL_INCLUDE_DIRS} ${LWPA_NETWORK_ADDITIONAL_INCLUDE_DIRS} ${LWPA_TOOLCHAIN_ADDITIONAL_INCLUDE_DIRS} - # ${LWPA_CONFIG_LOC} + ${LWPA_CONFIG_FILE_LOC} ) target_include_directories(lwpa PRIVATE ${LWPA_ROOT}/src) -target_compile_definitions(lwpa PUBLIC ${LWPA_HAVE_CONFIG_H}) +target_compile_definitions(lwpa PRIVATE ${LWPA_HAVE_CONFIG_H}) if(LWPA_NETINT_DEBUG_OUTPUT) target_compile_definitions(lwpa PRIVATE LWPA_NETINT_DEBUG_OUTPUT) endif() diff --git a/src/lwpa/private/opts.h b/src/lwpa/private/opts.h new file mode 100644 index 000000000..681a8ac16 --- /dev/null +++ b/src/lwpa/private/opts.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#ifndef _LWPA_PRIVATE_OPTS_H_ +#define _LWPA_PRIVATE_OPTS_H_ + +#if LWPA_HAVE_CONFIG_H +#include "lwpa_config.h" +#endif + +/*! \defgroup lwpa_opts lwpa config options + * \ingroup lwpa + * \brief Compile-time configuration options for lwpa + * + * Options starting with "LWPA_EMBOS_" (currently all of them) are ignored on Windows, macOS and + * Linux. + * + * To override any of these options, provide a file called lwpa_config.h and: + * * If not building lwpa with CMake: add LWPA_HAVE_CONFIG_H to your preprocessor definitions, + * and add the path to lwpa_config.h as an include path + * * If building with CMake: use the CMake option LWPA_CONFIG_FILE_LOC + * + * In the lwpa_config.h file, simply #define any overridden options to the desired value. + * + * @{ + */ + +/*! \brief Whether a malloc() implementation is available. + * + * Currently this only affects network interface enumeration using lwIP. + */ +#ifndef LWPA_EMBOS_USE_MALLOC +#define LWPA_EMBOS_USE_MALLOC 0 +#endif + +/*! \brief The maximum number of network interfaces that can be tracked by the \ref lwpa_netint module. + * + * Currently this limit is not necessary and therefore ignored on all targets except lwIP. + */ +#ifndef LWPA_EMBOS_MAX_NETINTS +#define LWPA_EMBOS_MAX_NETINTS 5 +#endif + +/*! @} */ + +#endif /* _LWPA_PRIVATE_OPTS_H_ */ diff --git a/src/os/lwip/lwpa/os_netint.c b/src/os/lwip/lwpa/os_netint.c index 318a68e4b..4a23dcdae 100644 --- a/src/os/lwip/lwpa/os_netint.c +++ b/src/os/lwip/lwpa/os_netint.c @@ -20,173 +20,180 @@ #include "lwpa/netint.h" #include #include +#include "lwpa/private/opts.h" -static bool mask_is_empty(const LwpaIpAddr* mask); -static bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask); +#if LWPA_EMBOS_USE_MALLOC +#include +static LwpaNetintInfo* static_netints; +#else +static LwpaNetintInfo static_netints[LWPA_EMBOS_MAX_NETINTS]; +#endif +size_t num_static_netints; +size_t default_index; -static void copy_interface_info(struct netif* lwip_netint, LwpaNetintInfo* netint) +static void copy_common_interface_info(const struct netif* lwip_netif, LwpaNetintInfo* netint) { - netint->index = (int)lwip_netint->num; - if (lwip_netint->hwaddr_len == NETINTINFO_MAC_LEN) - memcpy(netint->mac, lwip_netint->hwaddr, NETINTINFO_MAC_LEN); - else - memset(netint->mac, 0, NETINTINFO_MAC_LEN); - if (lwip_netint->name[0] != '\0') + netint->index = netif_get_index(lwip_netif); + memset(netint->mac, 0, LWPA_NETINTINFO_MAC_LEN); + memcpy(netint->mac, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + + char lwip_name[NETIF_NAMESIZE]; + if (NULL != netif_index_to_name(netint->index, lwip_name)) { - netint->name[0] = lwip_netint->name[0]; - netint->name[1] = lwip_netint->name[1]; - netint->name[2] = (char)(lwip_netint->num + '0'); - netint->name[3] = '\0'; + strncpy(netint->name, lwip_name, LWPA_NETINTINFO_NAME_LEN); + strncpy(netint->friendly_name, lwip_name, LWPA_NETINTINFO_FRIENDLY_NAME_LEN); } - if (lwip_netint == netif_default) - netint->is_default = true; - else - netint->is_default = false; +} + +static void copy_interface_info_v4(const struct netif* lwip_netif, LwpaNetintInfo* netint) +{ + copy_common_interface_info(lwip_netif, netint); -#if LWIP_IPV4 if (!ip_addr_isany(netif_ip_addr4(lwip_netint))) { LWPA_IP_SET_V4_ADDRESS(&netint->addr, ntohl(netif_ip4_addr(lwip_netint)->addr)); LWPA_IP_SET_V4_ADDRESS(&netint->mask, ntohl(netif_ip4_netmask(lwip_netint)->addr)); - LWPA_IP_SET_V4_ADDRESS(&netint->gate, ntohl(netif_ip4_gw(lwip_netint)->addr)); } -#endif -#if 0 + + if (lwip_netif == netif_default) + netint->is_default = true; + else + netint->is_default = false; +} + +static void copy_interface_info_v6(const struct netif* lwip_netif, size_t v6_addr_index, LwpaNetintInfo* netint) +{ + copy_common_interface_info(lwip_netif, netint); + /* TODO port this IPv6 code copied from AsyncSocket */ /* Add all of the IPv6 addresses that are valid, each gets its own - * netintinfo */ + * netintinfo */ /* NOTE: We are not currently supporting IPv6 in any lwIP products, and - * this implementation will probably need to be revisited before we do, - * especially the default interface code. */ + * this implementation will probably need to be revisited before we do, + * especially the default interface code. */ for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { if (ip6_addr_isvalid(iface->ip6_addr_mca_state[i])) { - IAsyncSocketServ::netintinfo v6info = info; - v6info.addr.SetV6Address(reinterpret_cast( - ip_2_ip6(&iface->ip6_addr[i])->addr)); - v6info.id = m_ifaces.size(); - m_ifaces.push_back(v6info); - /* This will result in the last valid IPv6 address on the - * default interface being made the 'default'. Or if there are - * no IPv6 addresses, the IPv4 address will get it. Good enough - * for now. */ - if (iface == netif_default) - m_defaultiface = v6info.id; - } - } +#if LWIP_IPV6_SCOPES + LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&netint->addr, &(ip_2_ip6(lwip_netif->ip6_addr[i])->addr), + ip_2_ip6(lwip_netif->ip6_addr[i])->zone); +#else + LWPA_IP_SET_V6_ADDRESS(&netint->addr, &(ip_2_ip6(lwip_netif->ip6_addr[i])->addr)); + // TODO revisit + netint->mask = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 128); #endif -} - -size_t netint_get_num_interfaces() -{ - size_t num_interfaces = 0; - struct netif* netint; - for (netint = netif_list; netint; netint = netint->next) - { - /* Skip loopback interfaces */ - if (!ip4_addr_isloopback(netif_ip4_addr(netint))) - ++num_interfaces; + /* +IAsyncSocketServ::netintinfo v6info = info; +v6info.addr.SetV6Address(reinterpret_cast( +ip_2_ip6(&iface->ip6_addr[i])->addr)); +v6info.id = m_ifaces.size(); + +if (iface == netif_default) +m_defaultiface = v6info.id; +*/ + } } - return num_interfaces; } -size_t netint_get_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size) +lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) { - size_t num_interfaces = 0; - struct netif* lwip_netint; - - if (!netint_arr || netint_arr_size == 0) - return 0; + struct netif* lwip_netif; - for (lwip_netint = netif_list; lwip_netint; lwip_netint = lwip_netint->next) +#if LWPA_EMBOS_USE_MALLOC + size_t num_lwip_netints = 0; + NETIF_FOREACH(lwip_netif) { #if LWIP_IPV4 - /* Skip loopback interfaces */ - if (ip4_addr_isloopback(netif_ip4_addr(lwip_netint))) - continue; + ++num_lwip_netints; +#endif +#if LWIP_IPV6 + for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) + { + if (ip6_addr_isvalid(lwip_netif->ip6_addr_state[i])) + ++num_lwip_netints; + } #endif - - copy_interface_info(lwip_netint, &netint_arr[num_interfaces++]); - if (num_interfaces >= netint_arr_size) - break; } + cache->netints = (LwpaNetintInfo*)calloc(sizeof(LwpaNetintInfo), num_lwip_netints); + if (!cache->netints) + return kLwpaErrNoMem; +#endif - return num_interfaces; -} + num_static_netints = 0; -bool netint_get_default_interface(LwpaNetintInfo* netint) -{ - if (netint && netif_default) + // Make sure the default netint is included +#if LWIP_IPV4 + copy_interface_info_v4(netif_default, &static_netints[num_static_netints++]); +#endif +#if LWIP_IPV6 + for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - copy_interface_info(netif_default, netint); - return true; +#if !LWPA_EMBOS_USE_MALLOC + if (num_static_netints >= LWPA_EMBOS_MAX_NETINTS) + break; +#endif + copy_interface_info_v6(netif_default, i, &static_netints[num_static_netints++]); } - return false; -} +#endif -bool mask_compare(const LwpaIpAddr* ip1, const LwpaIpAddr* ip2, const LwpaIpAddr* mask) -{ - if (LWPA_IP_IS_V4(ip1) && LWPA_IP_IS_V4(ip2) && LWPA_IP_IS_V4(mask)) + NETIF_FOREACH(lwip_netif) { - return ((LWPA_IP_V4_ADDRESS(ip1) & LWPA_IP_V4_ADDRESS(mask)) == - (LWPA_IP_V4_ADDRESS(ip2) & LWPA_IP_V4_ADDRESS(mask))); - } - else if (LWPA_IP_IS_V6(ip1) && LWPA_IP_IS_V6(ip2) && LWPA_IP_IS_V6(mask)) - { - size_t i; - const uint32_t* p1 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip1); - const uint32_t* p2 = (const uint32_t*)LWPA_IP_V6_ADDRESS(ip2); - const uint32_t* pm = (const uint32_t*)LWPA_IP_V6_ADDRESS(mask); + if (lwip_netif == netif_default) + continue; - for (i = 0; i < IPV6_BYTES / 4; ++i, ++p1, ++p2, ++pm) +#if !LWPA_EMBOS_USE_MALLOC + if (num_static_netints >= LWPA_EMBOS_MAX_NETINTS) + break; +#endif + +#if LWIP_IPV4 + copy_interface_info_v4(lwip_netif, &static_netints[num_static_netints++]); +#endif +#if LWIP_IPV6 + for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if ((*p1 & *pm) != (*p2 & *pm)) - return false; +#if !LWPA_EMBOS_USE_MALLOC + if (num_static_netints >= LWPA_EMBOS_MAX_NETINTS) + break; +#endif + copy_interface_info_v6(lwip_netif, i, &static_netints[num_static_netints++]); } - return true; +#endif } - return false; + + cache->netints = static_netints; + cache->num_netints = num_static_netints; + return kLwpaErrOk; } -bool mask_is_empty(const LwpaIpAddr* mask) +void os_free_interfaces(CachedNetintInfo* cache) { - uint32_t mask_part = 0; - - if (LWPA_IP_IS_V4(mask)) - mask_part = LWPA_IP_V4_ADDRESS(mask); - else if (LWPA_IP_IS_V6(mask)) +#if LWPA_EMBOS_USE_MALLOC + if (cache->netints) { - size_t i; - const uint32_t* p = (const uint32_t*)LWPA_IP_V6_ADDRESS(mask); - for (i = 0; i < IPV6_BYTES / 4; ++i, ++p) - mask_part |= *p; + free(cache->netints); + cache->netints = NULL; } - return (mask_part == 0); +#endif } -const LwpaNetintInfo* netint_get_iface_for_dest(const LwpaIpAddr* dest, const LwpaNetintInfo* netint_arr, - size_t netint_arr_size) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) { - const LwpaNetintInfo* res = NULL; - const LwpaNetintInfo* def = NULL; - const LwpaNetintInfo* netint; - - if (!dest || !netint_arr || netint_arr_size == 0) - return false; + unsigned int index_found = 0; - for (netint = netint_arr; netint < netint_arr + netint_arr_size; ++netint) + for (const LwpaNetintInfo* netint = static_netints; netint < static_netints + num_static_netints; ++netint) { - if (netint->is_default) - def = netint; - if (!mask_is_empty(&netint->mask) && mask_compare(&netint->addr, dest, &netint->mask)) + if (!lwpa_ip_is_wildcard(&netint->mask) && lwpa_ip_network_portions_equal(&netint->addr, dest, &netint->mask)) { - res = netint; + index_found = netint->index; break; } } - if (!res) - res = def; - return res; + if (index_found == 0) + index_found = static_netints[default_index].index; + + *index = index_found; + return kLwpaErrOk; } From 42455adbee06aa65028aebf0df4e00261e6be21e Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 23 Aug 2019 16:49:02 -0500 Subject: [PATCH 117/264] Halfway through os_socket.c, the last one to go. --- CMakeLists.txt | 5 + include/lwpa/bool.h | 2 - include/lwpa/pack.h | 11 +- include/lwpa/pack64.h | 45 ++ src/CMakeLists.txt | 21 +- src/lwpa/pack.c | 5 +- src/lwpa/private/opts.h | 8 + src/os/linux/lwpa/os_inet.c | 8 +- src/os/lwip/lwpa/os_error.c | 93 +++ .../opts.h => src/os/lwip/lwpa/os_error.h | 17 +- src/os/lwip/lwpa/os_inet.c | 136 ++++ src/os/lwip/lwpa/os_netint.c | 40 +- src/os/lwip/lwpa/os_socket.c | 628 +++++++++--------- src/os/macos/lwpa/os_inet.c | 8 +- src/os/mqx/lwpa/os_inet.c | 4 +- tools/cmake/lwpa-os.cmake | 20 +- tools/cmake/net/lwip.cmake | 6 +- 17 files changed, 670 insertions(+), 387 deletions(-) create mode 100644 include/lwpa/pack64.h create mode 100644 src/os/lwip/lwpa/os_error.c rename include/lwpa/opts.h => src/os/lwip/lwpa/os_error.h (76%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8402cb5be..aaebe51e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,9 @@ else() set(CMAKE_SOURCE_DIR_LC ${CMAKE_SOURCE_DIR}) endif() +# Set options based on whether this project is being built on its own, or added as a dependency to +# another project via add_subdirectory(). In the latter case, we don't override any global compile +# options, or build tests or examples by default. if(PROJECT_SOURCE_DIR_LC STREQUAL CMAKE_SOURCE_DIR_LC) if (MSVC) add_compile_options(/W4) @@ -34,6 +37,8 @@ else() set(OPTION_DEFAULTS OFF) endif() +set(LWPA_ROOT ${CMAKE_CURRENT_LIST_DIR}) + option(LWPA_BUILD_MOCK_LIB "Build the lwpa_mock library" OFF) option(LWPA_BUILD_TESTS "Build the lwpa unit tests" ${OPTION_DEFAULTS}) option(LWPA_BUILD_EXAMPLES "Build the lwpa example apps" ${OPTION_DEFAULTS}) diff --git a/include/lwpa/bool.h b/include/lwpa/bool.h index 9faa00411..cca5222df 100644 --- a/include/lwpa/bool.h +++ b/include/lwpa/bool.h @@ -40,8 +40,6 @@ * @{ */ -#include "lwpa/opts.h" - #if (!defined(__cplusplus)) || defined(DOXYGEN) #if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) || \ diff --git a/include/lwpa/pack.h b/include/lwpa/pack.h index 45cb04bc9..00dbb4b6e 100644 --- a/include/lwpa/pack.h +++ b/include/lwpa/pack.h @@ -22,13 +22,15 @@ #define _LWPA_PACK_H_ #include "lwpa/int.h" -#include "lwpa/opts.h" /*! \defgroup lwpa_pack lwpa_pack * \ingroup lwpa * \brief Platform- and endianness-independent buffer packing and unpacking. * + * For 16- and 32-bit integer packing and unpacking: * \#include "lwpa/pack.h" + * For 64-bit integer packing and unpacking: + * \#include "lwpa/pack64.h" * * This module defines macros for packing and unpacking integer types to/from a byte buffer. They * are architected in such a way that the endianness of the integer in the buffer is always known, @@ -50,13 +52,6 @@ void lwpa_pack_32b(uint8_t* buf, uint32_t val); uint32_t lwpa_upack_32l(const uint8_t* buf); void lwpa_pack_32l(uint8_t* buf, uint32_t val); -#if LWPA_64BIT_SUPPORT -uint64_t lwpa_upack_64b(const uint8_t* buf); -void lwpa_pack_64b(uint8_t* buf, uint64_t val); -uint64_t lwpa_upack_64l(const uint8_t* buf); -void lwpa_pack_64l(uint8_t* buf, uint64_t val); -#endif - #ifdef __cplusplus } #endif diff --git a/include/lwpa/pack64.h b/include/lwpa/pack64.h new file mode 100644 index 000000000..f2049e57c --- /dev/null +++ b/include/lwpa/pack64.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +/* lwpa/pack64.h: Optional extensions to lwpa_pack for 64-bit types. */ +#ifndef _LWPA_PACK64_H_ +#define _LWPA_PACK64_H_ + +#include "lwpa/int.h" + +/*! \addtogroup lwpa_pack + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +uint64_t lwpa_upack_64b(const uint8_t* buf); +void lwpa_pack_64b(uint8_t* buf, uint64_t val); +uint64_t lwpa_upack_64l(const uint8_t* buf); +void lwpa_pack_64l(uint8_t* buf, uint64_t val); + +#ifdef __cplusplus +} +#endif + +/*! @} */ + +#endif /* _LWPA_PACK64_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da2bf5eab..c39ff8352 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,8 +8,6 @@ endif() # Core lwpa library ############################################################################### -set(LWPA_ROOT ${CMAKE_CURRENT_LIST_DIR}/..) - add_library(lwpa # lwpa headers ${LWPA_ROOT}/include/lwpa/acn_prot.h @@ -22,7 +20,6 @@ add_library(lwpa ${LWPA_ROOT}/include/lwpa/log.h ${LWPA_ROOT}/include/lwpa/mempool.h ${LWPA_ROOT}/include/lwpa/netint.h - ${LWPA_ROOT}/include/lwpa/opts.h ${LWPA_ROOT}/include/lwpa/pack.h ${LWPA_ROOT}/include/lwpa/pdu.h ${LWPA_ROOT}/include/lwpa/rbtree.h @@ -33,8 +30,8 @@ add_library(lwpa ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_lock.h ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_thread.h - ${LWPA_ROOT}/include/os/${LWPA_NETWORK_TARGET}/lwpa/os_socket.h - ${LWPA_ROOT}/include/os/${LWPA_NETWORK_TARGET}/lwpa/os_inet.h + ${LWPA_ROOT}/include/os/${LWPA_NET_TARGET}/lwpa/os_socket.h + ${LWPA_ROOT}/include/os/${LWPA_NET_TARGET}/lwpa/os_inet.h # lwpa sources ${LWPA_ROOT}/src/lwpa/common.c @@ -57,21 +54,21 @@ add_library(lwpa ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_thread.c ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_timer.c - ${LWPA_ROOT}/src/os/${LWPA_NETWORK_TARGET}/lwpa/os_inet.c - ${LWPA_ROOT}/src/os/${LWPA_NETWORK_TARGET}/lwpa/os_netint.c - ${LWPA_ROOT}/src/os/${LWPA_NETWORK_TARGET}/lwpa/os_socket.c + ${LWPA_ROOT}/src/os/${LWPA_NET_TARGET}/lwpa/os_inet.c + ${LWPA_ROOT}/src/os/${LWPA_NET_TARGET}/lwpa/os_netint.c + ${LWPA_ROOT}/src/os/${LWPA_NET_TARGET}/lwpa/os_socket.c ${LWPA_OS_ADDITIONAL_SOURCES} - ${LWPA_NETWORK_ADDITIONAL_SOURCES} + ${LWPA_NET_ADDITIONAL_SOURCES} ) # lwpa public include directories and library dependencies target_include_directories(lwpa PUBLIC ${LWPA_ROOT}/include ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET} - ${LWPA_ROOT}/include/os/${LWPA_NETWORK_TARGET} + ${LWPA_ROOT}/include/os/${LWPA_NET_TARGET} ${LWPA_OS_ADDITIONAL_INCLUDE_DIRS} - ${LWPA_NETWORK_ADDITIONAL_INCLUDE_DIRS} + ${LWPA_NET_ADDITIONAL_INCLUDE_DIRS} ${LWPA_TOOLCHAIN_ADDITIONAL_INCLUDE_DIRS} ${LWPA_CONFIG_FILE_LOC} ) @@ -80,7 +77,7 @@ target_compile_definitions(lwpa PRIVATE ${LWPA_HAVE_CONFIG_H}) if(LWPA_NETINT_DEBUG_OUTPUT) target_compile_definitions(lwpa PRIVATE LWPA_NETINT_DEBUG_OUTPUT) endif() -target_link_libraries(lwpa PUBLIC ${LWPA_OS_ADDITIONAL_LIBS} ${LWPA_NETWORK_ADDITIONAL_LIBS}) +target_link_libraries(lwpa PUBLIC ${LWPA_OS_ADDITIONAL_LIBS} ${LWPA_NET_ADDITIONAL_LIBS}) set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) diff --git a/src/lwpa/pack.c b/src/lwpa/pack.c index 323735243..7f27f8bdd 100644 --- a/src/lwpa/pack.c +++ b/src/lwpa/pack.c @@ -18,6 +18,7 @@ ******************************************************************************/ #include "lwpa/pack.h" +#include "lwpa/private/opts.h" /*************************** Function definitions ****************************/ @@ -141,7 +142,7 @@ void lwpa_pack_32l(uint8_t* buf, uint32_t val) } } -#if LWPA_64BIT_SUPPORT +#if LWPA_INCLUDE_PACK_64 /*! \brief Unpack a uint64_t from a known big-endian buffer. * \param buf Pointer to the buffer from which to unpack a uint64_t. @@ -223,4 +224,4 @@ void lwpa_pack_64l(uint8_t* buf, uint64_t val) } } -#endif +#endif /* LWPA_INCLUDE_PACK_64 */ diff --git a/src/lwpa/private/opts.h b/src/lwpa/private/opts.h index 681a8ac16..58ef9674c 100644 --- a/src/lwpa/private/opts.h +++ b/src/lwpa/private/opts.h @@ -41,6 +41,14 @@ * @{ */ +/*! \brief Whether to build the lwpa/pack64.h functions. + * + * This can be defined to 0 if you are on a platform that does not provide a int64_t/uint64_t type. + */ +#ifndef LWPA_INCLUDE_PACK_64 +#define LWPA_INCLUDE_PACK_64 1 +#endif + /*! \brief Whether a malloc() implementation is available. * * Currently this only affects network interface enumeration using lwIP. diff --git a/src/os/linux/lwpa/os_inet.c b/src/os/linux/lwpa/os_inet.c index f17ca5e27..4b4e8f133 100644 --- a/src/os/linux/lwpa/os_inet.c +++ b/src/os/linux/lwpa/os_inet.c @@ -103,7 +103,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); if (NULL != inet_ntop(AF_INET, &addr, dest, (socklen_t)size)) return kLwpaErrOk; - return kLwpaErrSys; + return kLwpaErrInvalid; } case kLwpaIpTypeV6: { @@ -111,7 +111,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); if (NULL != inet_ntop(AF_INET6, &addr, dest, (socklen_t)size)) return kLwpaErrOk; - return kLwpaErrSys; + return kLwpaErrInvalid; } default: return kLwpaErrInvalid; @@ -129,7 +129,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des { struct in_addr addr; if (1 != inet_pton(AF_INET, src, &addr)) - return kLwpaErrSys; + return kLwpaErrInvalid; LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); return kLwpaErrOk; } @@ -137,7 +137,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des { struct in6_addr addr; if (1 != inet_pton(AF_INET6, src, &addr)) - return kLwpaErrSys; + return kLwpaErrInvalid; LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); return kLwpaErrOk; } diff --git a/src/os/lwip/lwpa/os_error.c b/src/os/lwip/lwpa/os_error.c new file mode 100644 index 000000000..c5ac86a13 --- /dev/null +++ b/src/os/lwip/lwpa/os_error.c @@ -0,0 +1,93 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "os_error.h" +#include + +lwpa_error_t errno_lwip_to_lwpa(int lwip_errno) +{ + switch (lwip_errno) + { + case EPERM: + case EACCES: + return kLwpaErrPerm; + case ENOENT: + case EBADF: + case ENOTSOCK: + return kLwpaErrNotFound; + case EFAULT: + case EINVAL: + case EDESTADDRREQ: + case EPROTOTYPE: + case EOPNOTSUPP: + return kLwpaErrInvalid; + // case EAGAIN: // EWOULDBLOCK defined to EAGAIN + case EWOULDBLOCK: + return kLwpaErrWouldBlock; + case EBUSY: + return kLwpaErrBusy; + case ENOMEM: + case ENOBUFS: + return kLwpaErrNoMem; + case EEXIST: + return kLwpaErrExists; + case ENOSYS: + return kLwpaErrNotImpl; + case EPROTO: + return kLwpaErrProtocol; + case EMSGSIZE: + return kLwpaErrMsgSize; + case EADDRINUSE: + return kLwpaErrAddrInUse; + case EADDRNOTAVAIL: + return kLwpaErrAddrNotAvail; + case ENETDOWN: + case ENETUNREACH: + case ENETRESET: + return kLwpaErrNetwork; + case ECONNABORTED: + return kLwpaErrConnAborted; + case ECONNRESET: + return kLwpaErrConnReset; + case EISCONN: + return kLwpaErrIsConn; + case ENOTCONN: + return kLwpaErrNotConn; + case ESHUTDOWN: + return kLwpaErrShutdown; + case ETIMEDOUT: + return kLwpaErrTimedOut; + case ECONNREFUSED: + return kLwpaErrConnRefused; + case EALREADY: + return kLwpaErrAlready; + case EINPROGRESS: + return kLwpaErrInProgress; + case EINTR: + case ENFILE: + case EMFILE: + case ENOSPC: + case EPFNOSUPPORT: + case EAFNOSUPPORT: + case EPROTONOSUPPORT: + case ESOCKTNOSUPPORT: + default: + return kLwpaErrSys; + } +} diff --git a/include/lwpa/opts.h b/src/os/lwip/lwpa/os_error.h similarity index 76% rename from include/lwpa/opts.h rename to src/os/lwip/lwpa/os_error.h index 1c8886906..7c1bfda8c 100644 --- a/include/lwpa/opts.h +++ b/src/os/lwip/lwpa/os_error.h @@ -17,15 +17,16 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ -#ifndef _LWPA_OPTS_H_ -#define _LWPA_OPTS_H_ +#ifndef _LWPA_OS_ERROR_H_ +#define _LWPA_OS_ERROR_H_ -#if HAVE_LWPA_CONFIG_H -#include "lwpa_config.h" -#endif /* HAVE_LWPA_CONFIG_H */ +#include "lwpa/error.h" +#include -#ifndef LWPA_64BIT_SUPPORT -#define LWPA_64BIT_SUPPORT 1 +#if !LWIP_PROVIDE_ERRNO && !LWIP_ERRNO_STDINCLUDE && !defined(LWIP_ERRNO_INCLUDE) +#include #endif -#endif /* _LWPA_OPTS_H_ */ +lwpa_error_t errno_lwip_to_lwpa(int lwip_errno); + +#endif /* _LWPA_OS_ERROR_H_ */ diff --git a/src/os/lwip/lwpa/os_inet.c b/src/os/lwip/lwpa/os_inet.c index e69de29bb..5e2a3ce48 100644 --- a/src/os/lwip/lwpa/os_inet.c +++ b/src/os/lwip/lwpa/os_inet.c @@ -0,0 +1,136 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ + +#include "lwpa/inet.h" + +#include +#include "os_error.h" + +#if !LWIP_SOCKET +#error "LWIP_SOCKET is necessary in lwipopts.h to use the lwpa_inet module." +#endif + +bool sockaddr_os_to_lwpa(const lwpa_os_sockaddr_t* os_sa, LwpaSockaddr* sa) +{ + if (os_sa->sa_family == AF_INET) + { +#if LWIP_IPV4 + struct sockaddr_in* sin = (struct sockaddr_in*)os_sa; + sa->port = ntohs(sin->sin_port); + LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); + return true; +#else + return false; +#endif + } + else if (os_sa->sa_family == AF_INET6) + { +#if LWIP_IPV6 + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_sa; + sa->port = ntohs(sin6->sin6_port); + LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); + return true; +#else + return false; +#endif + } + return false; +} + +socklen_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, lwpa_os_sockaddr_t* os_sa) +{ + socklen_t ret = 0; + if (LWPA_IP_IS_V4(&sa->ip)) + { +#if LWIP_IPV4 + struct sockaddr_in* sin = (struct sockaddr_in*)os_sa; + sin->sin_family = AF_INET; + sin->sin_port = htons(sa->port); + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); + ret = sizeof(struct sockaddr_in); +#endif + } + else if (LWPA_IP_IS_V6(&sa->ip)) + { +#if LWIP_IPV6 + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_sa; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = htons(sa->port); + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); + ret = sizeof(struct sockaddr_in6); +#endif + } + return ret; +} + +lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (src->type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); + if (NULL != inet_ntop(AF_INET, &addr, dest, size)) + return kLwpaErrOk; + return errno_lwip_to_lwpa(errno); + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); + if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) + return kLwpaErrOk; + return errno_lwip_to_lwpa(errno); + } + default: + return kLwpaErrInvalid; + } +} + +lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) +{ + if (!src || !dest) + return kLwpaErrInvalid; + + switch (type) + { + case kLwpaIpTypeV4: + { + struct in_addr addr; + if (inet_pton(AF_INET, src, &addr) <= 0) + return kLwpaErrInvalid; + LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); + return kLwpaErrOk; + } + case kLwpaIpTypeV6: + { + struct in6_addr addr; + if (inet_pton(AF_INET6, src, &addr) <= 0) + return kLwpaErrInvalid; + LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); + return kLwpaErrOk; + } + default: + return kLwpaErrInvalid; + } +} diff --git a/src/os/lwip/lwpa/os_netint.c b/src/os/lwip/lwpa/os_netint.c index 4a23dcdae..7690e7554 100644 --- a/src/os/lwip/lwpa/os_netint.c +++ b/src/os/lwip/lwpa/os_netint.c @@ -21,6 +21,7 @@ #include #include #include "lwpa/private/opts.h" +#include "lwpa/private/netint.h" #if LWPA_EMBOS_USE_MALLOC #include @@ -38,7 +39,7 @@ static void copy_common_interface_info(const struct netif* lwip_netif, LwpaNetin memcpy(netint->mac, lwip_netif->hwaddr, lwip_netif->hwaddr_len); char lwip_name[NETIF_NAMESIZE]; - if (NULL != netif_index_to_name(netint->index, lwip_name)) + if (NULL != netif_index_to_name((u8_t)netint->index, lwip_name)) { strncpy(netint->name, lwip_name, LWPA_NETINTINFO_NAME_LEN); strncpy(netint->friendly_name, lwip_name, LWPA_NETINTINFO_FRIENDLY_NAME_LEN); @@ -49,10 +50,10 @@ static void copy_interface_info_v4(const struct netif* lwip_netif, LwpaNetintInf { copy_common_interface_info(lwip_netif, netint); - if (!ip_addr_isany(netif_ip_addr4(lwip_netint))) + if (!ip_addr_isany(netif_ip_addr4(lwip_netif))) { - LWPA_IP_SET_V4_ADDRESS(&netint->addr, ntohl(netif_ip4_addr(lwip_netint)->addr)); - LWPA_IP_SET_V4_ADDRESS(&netint->mask, ntohl(netif_ip4_netmask(lwip_netint)->addr)); + LWPA_IP_SET_V4_ADDRESS(&netint->addr, ntohl(netif_ip4_addr(lwip_netif)->addr)); + LWPA_IP_SET_V4_ADDRESS(&netint->mask, ntohl(netif_ip4_netmask(lwip_netif)->addr)); } if (lwip_netif == netif_default) @@ -65,34 +66,27 @@ static void copy_interface_info_v6(const struct netif* lwip_netif, size_t v6_add { copy_common_interface_info(lwip_netif, netint); - /* TODO port this IPv6 code copied from AsyncSocket */ - /* Add all of the IPv6 addresses that are valid, each gets its own - * netintinfo */ + /* Finish filling in a netintinfo for a single IPv6 address. */ - /* NOTE: We are not currently supporting IPv6 in any lwIP products, and - * this implementation will probably need to be revisited before we do, - * especially the default interface code. */ + /* NOTE: We are not currently supporting IPv6 in any lwIP products, and this implementation will + * probably need to be revisited before we do, especially the default interface code. */ for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if (ip6_addr_isvalid(iface->ip6_addr_mca_state[i])) + if (ip6_addr_isvalid(lwip_netif->ip6_addr_state[i])) { #if LWIP_IPV6_SCOPES - LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&netint->addr, &(ip_2_ip6(lwip_netif->ip6_addr[i])->addr), - ip_2_ip6(lwip_netif->ip6_addr[i])->zone); + LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&netint->addr, &(ip_2_ip6(&lwip_netif->ip6_addr[i])->addr), + ip_2_ip6(&lwip_netif->ip6_addr[i])->zone); #else - LWPA_IP_SET_V6_ADDRESS(&netint->addr, &(ip_2_ip6(lwip_netif->ip6_addr[i])->addr)); + LWPA_IP_SET_V6_ADDRESS(&netint->addr, &(ip_2_ip6(&lwip_netif->ip6_addr[i])->addr)); // TODO revisit netint->mask = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 128); #endif - /* -IAsyncSocketServ::netintinfo v6info = info; -v6info.addr.SetV6Address(reinterpret_cast( -ip_2_ip6(&iface->ip6_addr[i])->addr)); -v6info.id = m_ifaces.size(); - -if (iface == netif_default) -m_defaultiface = v6info.id; -*/ + + if (lwip_netif == netif_default && i == 0) + netint->is_default = true; + else + netint->is_default = false; } } } diff --git a/src/os/lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c index a563aecdd..d1ffda43e 100644 --- a/src/os/lwip/lwpa/os_socket.c +++ b/src/os/lwip/lwpa/os_socket.c @@ -21,6 +21,13 @@ #include #include #include +#include "os_error.h" + +/**************************** Private constants ******************************/ + +/****************************** Private types ********************************/ + +/**************************** Private variables ******************************/ /* clang-format off */ @@ -85,60 +92,17 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = /* clang-format on */ -static bool sockaddr_os_to_lwpa(LwpaSockaddr* sa, const struct sockaddr* pfsa) -{ - if (pfsa->sa_family == AF_INET) - { -#if LWIP_IPV4 - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sa->port = ntohs(sin->sin_port); - LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); - return true; -#else - return false; -#endif - } - else if (pfsa->sa_family == AF_INET6) - { -#if LWIP_IPV6 - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sa->port = ntohs(sin6->sin6_port); - LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); - return true; -#else - return false; -#endif - } - return false; -} +/*********************** Private function prototypes *************************/ -static socklen_t sockaddr_lwpa_to_os(struct sockaddr* pfsa, const LwpaSockaddr* sa) -{ - socklen_t ret = 0; - if (LWPA_IP_IS_V4(&sa->ip)) - { -#if LWIP_IPV4 - struct sockaddr_in* sin = (struct sockaddr_in*)pfsa; - sin->sin_family = AF_INET; - sin->sin_port = htons(sa->port); - sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); - ret = sizeof(struct sockaddr_in); -#endif - } - else if (LWPA_IP_IS_V6(&sa->ip)) - { -#if LWIP_IPV6 - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)pfsa; - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(sa->port); - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), IPV6_BYTES); - ret = sizeof(struct sockaddr_in6); -#endif - } - return ret; -} +// Helpers for lwpa_setsockopt() +static void ms_to_timeval(int ms, struct timeval* tv); +static int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); + +/*************************** Function definitions ****************************/ -lwpa_error_t lwpa_socket_init(void* os_data) +lwpa_error_t lwpa_socket_init(lwpa_socket_t os_data) { /* No initialization is necessary on this os. */ (void)os_data; @@ -150,287 +114,385 @@ void lwpa_socket_deinit() /* No deinitialization is necessary on this os. */ } -int lwpa_accept(void* id, LwpaSockaddr* address) +lwpa_error_t lwpa_accept(lwpa_socket_t id, LwpaSockaddr* address, lwpa_socket_t* conn_sock) { - /* TODO */ - return -1; -} + if (!conn_sock) + return kLwpaErrInvalid; -int lwpa_bind(void* id, const LwpaSockaddr* address) -{ - int res = -1; - if (address) + struct sockaddr_storage ss; + socklen_t sa_size = sizeof ss; + int res = accept(id, (struct sockaddr*)&ss, &sa_size); + + if (res != -1) { - struct sockaddr_storage ss; - socklen_t sa_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, address); - if (sa_size > 0) - res = bind((int)id, (struct sockaddr*)&ss, sa_size); + if (address && !sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&ss, address)) + { + close(res); + return kLwpaErrSys; + } + *conn_sock = res; + return kLwpaErrOk; } - return res; + return errno_lwip_to_lwpa(errno); } -int lwpa_close(void* id) +lwpa_error_t lwpa_bind(lwpa_socket_t id, const LwpaSockaddr* address) { - return close((int)id); + if (!address) + return kLwpaErrInvalid; + + struct sockaddr_storage ss; + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os(address, (lwpa_os_sockaddr_t*)&ss); + if (sa_size == 0) + return kLwpaErrInvalid; + + int res = bind(id, (struct sockaddr*)&ss, sa_size); + return (res == 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); } -int lwpa_connect(void* id, const LwpaSockaddr* address) +lwpa_error_t lwpa_close(lwpa_socket_t id) { - /* TODO */ - return -1; + int res = close(id); + return (res == 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); } -int lwpa_getpeername(void* id, LwpaSockaddr* address) +lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) { - /* TODO */ - return -1; + if (!address) + return kLwpaErrInvalid; + + struct sockaddr_storage ss; + socklen_t sa_size = (socklen_t)sockaddr_lwpa_to_os(address, (lwpa_os_sockaddr_t*)&ss); + if (sa_size == 0) + return kLwpaErrInvalid; + + int res = connect(id, (struct sockaddr*)&ss, sa_size); + return (res == 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); } -int lwpa_getsockname(void* id, LwpaSockaddr* address) +lwpa_error_t lwpa_getpeername(lwpa_error_t id, LwpaSockaddr* address) { - int res = -1; - if (address) - { - struct sockaddr_storage ss; - socklen_t size = sizeof ss; - if (0 == getsockname((int)id, (struct sockaddr*)&ss, &size)) - { - if (sockaddr_os_to_lwpa(address, (struct sockaddr*)&ss)) - res = 0; - } - } - return res; + // TODO + (void)id; + (void)address; + return kLwpaErrNotImpl; } -int lwpa_getsockopt(void* id, int level, int option_name, void* option_value, size_t* option_len) +lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) { - /* TODO */ - return -1; + if (!address) + return kLwpaErrInvalid; + + struct sockaddr_storage ss; + socklen_t size = (socklen_t)sizeof ss; + int res = getsockname(id, (struct sockaddr*)&ss, &size); + if (res == 0) + { + if (!sockaddr_os_to_lwpa((lwpa_os_sockadr_t*)&ss, address)) + return kLwpaErrSys; + return kLwpaErrOk; + } + return errno_lwip_to_lwpa(errno); } -int lwpa_listen(void* id, int backlog) +int lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, lwpa_socket_t option_value, size_t* option_len) { - /* TODO */ + // TODO return -1; } -int lwpa_recv(void* id, void* buffer, size_t length, int flags) +int lwpa_listen(lwpa_socket_t id, int backlog) { - /* TODO */ - return -1; + int res = listen(id, backlog); + return (res == 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); } -int lwpa_recvfrom(void* id, void* buffer, size_t length, int flags, LwpaSockaddr* address) +int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) { - int res = -1; + if (!buffer) + return (int)kLwpaErrInvalid; + + struct sockaddr_storage from_addr; + socklen_t from_len = (socklen_t)sizeof from_addr; int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; - struct sockaddr_storage fromaddr; - socklen_t fromlen = sizeof fromaddr; + int res = (int)recv(id, buffer, length, impl_flags); + return (res >= 0 ? res : (int)errno_lwip_to_lwpa(errno)); +} +int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, LwpaSockaddr* address) +{ if (!buffer) - return res; + return (int)kLwpaErrInvalid; - res = recvfrom((int)id, buffer, length, impl_flags, (struct sockaddr*)&fromaddr, &fromlen); + struct sockaddr_storage fromaddr; + socklen_t fromlen = (socklen_t)sizeof fromaddr; + int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; + int res = (int)recvfrom(id, buffer, length, impl_flags, (struct sockaddr*)&fromaddr, &fromlen); if (res >= 0) { if (address && fromlen > 0) { if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) - res = -1; + return (int)kLwpaErrSys; } + return res; } - - return res; + return (int)errno_lwip_to_lwpa(errno); } -int lwpa_send(void* id, const void* message, size_t length, int flags) +int lwpa_send(lwpa_socket_t id, const void* message, size_t length, int flags) { - /* TODO */ - return -1; + (void)flags; + + if (!message) + return (int)kLwpaErrInvalid; + + int res = (int)send(id, message, length, 0); + return (res >= 0 ? res : (int)errno_lwip_to_lwpa(errno)); } -int lwpa_sendto(void* id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) +int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, const LwpaSockaddr* dest_addr) { - int res = -1; - socklen_t ss_size; - struct sockaddr_storage ss; + (void)flags; if (!dest_addr || !message) - return res; + return (int)kLwpaErrInvalid; - if ((ss_size = sockaddr_lwpa_to_os((struct sockaddr*)&ss, dest_addr)) > 0) - res = sendto((int)id, message, length, 0, (struct sockaddr*)&ss, ss_size); - return res; + struct sockaddr_storage ss; + socklen_t ss_size = (socklen_t)sockaddr_lwpa_to_os(dest_addr, (lwpa_os_sockaddr_t*)&ss); + if (ss_size == 0) + return (int)kLwpaErrSys; + + int res = (int)sendto(id, message, length, 0, (struct sockaddr*)&ss, ss_size); + return (res >= 0 ? res : (int)errno_os_to_lwpa(errno)); } -int lwpa_setsockopt(void* id, int level, int option_name, const void* option_value, size_t option_len) +int lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) { int res = -1; if (!option_value) - return res; + return (int)kLwpaErrInvalid; - /* TODO this os implementation could be simplified by use of socket - * option lookup arrays. */ switch (level) { case LWPA_SOL_SOCKET: - switch (option_name) + res = setsockopt_socket(id, option_name, option_value, option_len); + break; + case LWPA_IPPROTO_IP: + res = setsockopt_ip(id, option_name, option_value, option_len); + break; + case LWPA_IPPROTO_IPV6: + res = setsockopt_ip6(id, option_name, option_value, option_len); + break; + default: + break; + } + return res; +} + +int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_SO_RCVBUF: + return setsockopt(id, SOL_SOCKET, SO_RCVBUF, option_value, option_len); + case LWPA_SO_SNDBUF: + return setsockopt(id, SOL_SOCKET, SO_SNDBUF, option_value, option_len); + case LWPA_SO_RCVTIMEO: + if (option_len == sizeof(int)) { - case LWPA_SO_RCVBUF: - res = setsockopt((int)id, SOL_SOCKET, SO_RCVBUF, option_value, option_len); - break; - case LWPA_SO_SNDBUF: - res = setsockopt((int)id, SOL_SOCKET, SO_SNDBUF, option_value, option_len); - break; - case LWPA_SO_RCVTIMEO: - if (option_len == sizeof(int)) - { - int ms = *(int*)option_value; - struct timeval val = {ms / 1000, (ms % 1000) * 1000}; - res = setsockopt((int)id, SOL_SOCKET, SO_RCVTIMEO, &val, sizeof val); - } - break; - case LWPA_SO_SNDTIMEO: - if (option_len == sizeof(int)) - { - int ms = *(int*)option_value; - struct timeval val = {ms / 1000, (ms % 1000) * 1000}; - res = setsockopt((int)id, SOL_SOCKET, SO_SNDTIMEO, &val, sizeof val); - } - break; - case LWPA_SO_REUSEADDR: - res = setsockopt((int)id, SOL_SOCKET, SO_REUSEADDR, option_value, option_len); - break; - case LWPA_SO_REUSEPORT: - res = setsockopt((int)id, SOL_SOCKET, SO_REUSEPORT, option_value, option_len); - break; - case LWPA_SO_BROADCAST: - res = setsockopt((int)id, SOL_SOCKET, SO_BROADCAST, option_value, option_len); - break; - case LWPA_SO_KEEPALIVE: - res = setsockopt((int)id, SOL_SOCKET, SO_KEEPALIVE, option_value, option_len); - break; - case LWPA_SO_ERROR: /* Set not supported */ - case LWPA_SO_LINGER: /* TODO */ - case LWPA_SO_TYPE: /* Not supported */ - default: - break; + int ms = *(int*)option_value; + struct timeval val; + ms_to_timeval(ms, &val); + return setsockopt(id, SOL_SOCKET, SO_RCVTIMEO, &val, sizeof val); } break; - case LWPA_IPPROTO_IP: - switch (option_name) + case LWPA_SO_SNDTIMEO: + if (option_len == sizeof(int)) { - case LWPA_IP_TTL: - res = setsockopt((int)id, IPPROTO_IP, IP_TTL, option_value, option_len); - break; - case LWPA_MCAST_JOIN_GROUP: - if (option_len == sizeof(struct lwpa_mreq)) - { - LwpaMreq* amreq = (LwpaMreq*)option_value; - if (LWPA_IP_IS_V4(&amreq->group)) - { - struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); - val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); - res = setsockopt((int)id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &val, sizeof val); - } - } - break; - case LWPA_MCAST_LEAVE_GROUP: - if (option_len == sizeof(struct lwpa_mreq)) - { - LwpaMreq* amreq = (LwpaMreq*)option_value; - if (LWPA_IP_IS_V4(&amreq->group)) - { - struct ip_mreq val; - val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); - val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); - res = setsockopt((int)id, IPPROTO_IP, IP_DROP_MEMBERSHIP, &val, sizeof val); - } - } - break; - case LWPA_IP_MULTICAST_IF: - if (option_len == sizeof(struct lwpa_ip)) - { - LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (LWPA_IP_IS_V4(netint)) - { - struct in_addr val; - val.s_addr = htonl(LWPA_IP_V4_ADDRESS(netint)); - res = setsockopt((int)id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); - } - } - break; - case LWPA_IP_MULTICAST_TTL: + int ms = *(int*)option_value; + struct timeval val; + ms_to_timeval(ms, &val); + return setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, &val, sizeof val); + } + case LWPA_SO_REUSEADDR: + return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, option_value, option_len); + case LWPA_SO_REUSEPORT: + return setsockopt(id, SOL_SOCKET, SO_REUSEPORT, option_value, option_len); + case LWPA_SO_BROADCAST: + return setsockopt(id, SOL_SOCKET, SO_BROADCAST, option_value, option_len); + case LWPA_SO_KEEPALIVE: + return setsockopt(id, SOL_SOCKET, SO_KEEPALIVE, option_value, option_len); + case LWPA_SO_LINGER: + if (option_len == sizeof(LwpaLinger)) + { + LwpaLinger* ll = (LwpaLinger*)option_value; + struct linger val; + val.l_onoff = ll->onoff; + val.l_linger = ll->linger; + return setsockopt(id, SOL_SOCKET, SO_LINGER, &val, sizeof val); + } + break; + case LWPA_SO_ERROR: // Set not supported + case LWPA_SO_TYPE: // Set not supported + default: + break; + } + // If we got here, something was invalid. Set errno accordingly. + errno = EINVAL; + return -1; +} + +static bool netif_index_to_ipv4_addr(unsigned int netif_index, struct in_addr* addr) +{ +} + +int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_IP_TTL: + return setsockopt(id, IPPROTO_IP, IP_TTL, option_value, option_len); + break; +#if LWIP_IGMP || 1 + case LWPA_IP_ADD_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) { - unsigned char val = (unsigned char)*(int*)option_value; - res = setsockopt((int)id, IPPROTO_IP, IP_MULTICAST_TTL, &val, sizeof val); + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + return setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &val, sizeof val); } - break; - case LWPA_IP_MULTICAST_LOOP: + } + break; + case LWPA_IP_DROP_MEMBERSHIP: + if (option_len == sizeof(LwpaMreq)) + { + LwpaMreq* amreq = (LwpaMreq*)option_value; + if (LWPA_IP_IS_V4(&amreq->group)) { - unsigned char val = (unsigned char)*(int*)option_value; - res = setsockopt((int)id, IPPROTO_IP, IP_MULTICAST_LOOP, &val, sizeof val); + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->group)); + val.imr_interface.s_addr = htonl(LWPA_IP_V4_ADDRESS(&amreq->netint)); + return setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, &val, sizeof val); } - break; - default: - break; } break; - case LWPA_IPPROTO_IPV6: - switch (option_name) + case LWPA_MCAST_JOIN_GROUP: + if (option_len == sizeof(LwpaGroupReq)) { - case LWPA_MCAST_JOIN_GROUP: - /* This is not supported in lwip yet. - if (option_len == sizeof(struct lwpa_mreq)) - { - LwpaMreq *amreq = (LwpaMreq *)option_value; - if (LWPA_IP_IS_V6(&amreq->group)) - { - struct ipv6_mreq val; - val.ipv6imr_interface = 0; - memcpy(&val.ipv6imr_multiaddr.s6_addr, - LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); - res = setsockopt((int)id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - sizeof val); - } - } - */ - break; - case LWPA_MCAST_LEAVE_GROUP: - /* This is not supported in lwip yet. - if (option_len == sizeof(struct lwpa_mreq)) - { - LwpaMreq *amreq = (LwpaMreq *)option_value; - if (LWPA_IP_IS_V6(&amreq->group)) - { - struct ipv6_mreq val; - val.ipv6imr_interface = 0; - memcpy(&val.ipv6imr_multiaddr.s6_addr, - LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); - res = setsockopt((int)id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - sizeof val); - } - } - */ - break; - default: /* lwip does not have a lot of IPV6 socket option support - * yet. */ - break; + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + if (!netif_index_to_ipv4_addr(greq->ifindex, &val.imr_interface)) + return -1; + return setsockopt(id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &val, sizeof val); } break; + case LWPA_MCAST_LEAVE_GROUP: + if (option_len == sizeof(LwpaGroupReq)) + { + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + struct ip_mreq val; + val.imr_multiaddr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&greq->group)); + if (!netif_index_to_ipv4_addr(greq->ifindex, &val.imr_interface)) + return -1; + return setsockopt(id, IPPROTO_IP, IP_DROP_MEMBERSHIP, &val, sizeof val); + } + break; +#endif // LWIP_IGMP +#if LWIP_MULTICAST_TX_OPTIONS + case LWPA_IP_MULTICAST_IF: + if (option_len == sizeof(unsigned int)) + { + LwpaIpAddr* netint = (LwpaIpAddr*)option_value; + if (LWPA_IP_IS_V4(netint)) + { + struct in_addr val; + val.s_addr = htonl(LWPA_IP_V4_ADDRESS(netint)); + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); + } + } + break; + case LWPA_IP_MULTICAST_TTL: + { + unsigned char val = (unsigned char)*(int*)option_value; + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, &val, sizeof val); + } + break; + case LWPA_IP_MULTICAST_LOOP: + { + unsigned char val = (unsigned char)*(int*)option_value; + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, &val, sizeof val); + } + break; +#endif // LWIP_MULTICAST_TX_OPTIONS default: break; } - return res; + // If we got here, something was invalid. Set errno accordingly. + errno = EINVAL; + return -1; } -int lwpa_shutdown(void* id, int how) +int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) +{ + switch (option_name) + { + case LWPA_MCAST_JOIN_GROUP: + /* This is not supported in lwip yet. + if (option_len == sizeof(struct lwpa_mreq)) + { + LwpaMreq *amreq = (LwpaMreq *)option_value; + if (LWPA_IP_IS_V6(&amreq->group)) + { + struct ipv6_mreq val; + val.ipv6imr_interface = 0; + memcpy(&val.ipv6imr_multiaddr.s6_addr, + LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); + res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, + sizeof val); + } + } + */ + break; + case LWPA_MCAST_LEAVE_GROUP: + /* This is not supported in lwip yet. + if (option_len == sizeof(struct lwpa_mreq)) + { + LwpaMreq *amreq = (LwpaMreq *)option_value; + if (LWPA_IP_IS_V6(&amreq->group)) + { + struct ipv6_mreq val; + val.ipv6imr_interface = 0; + memcpy(&val.ipv6imr_multiaddr.s6_addr, + LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); + res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, + sizeof val); + } + } + */ + break; + default: // lwIP does not have a lot of IPV6 socket option support yet. + break; + } +} + +void ms_to_timeval(int ms, struct timeval* tv) +{ + tv->tv_usec = ms / 1000; + tv->tv_sec = (ms % 1000) * 1000; +} + +int lwpa_shutdown(lwpa_socket_t id, int how) { if (how >= 0 && how < LWPA_NUM_SHUT) - return shutdown((int)id, shutmap[how]); + return shutdown(id, shutmap[how]); return -1; } @@ -481,7 +543,7 @@ void lwpa_poll_context_deinit(LwpaPollContext* context) } lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, - void* user_data) + lwpa_socket_t user_data) { if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) return kLwpaErrInvalid; @@ -507,7 +569,7 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket } lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, - void* new_user_data) + lwpa_socket_t new_user_data) { if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) return kLwpaErrInvalid; @@ -755,59 +817,3 @@ void lwpa_freeaddrinfo(LwpaAddrinfo* ai) if (ai) freeaddrinfo((struct addrinfo*)ai->pd[0]); } - -lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (src->type) - { - case LWPA_IPV4: - { - struct in_addr addr; - addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); - if (NULL != inet_ntop(AF_INET, &addr, dest, size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - case LWPA_IPV6: - { - struct in6_addr addr; - memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), IPV6_BYTES); - if (NULL != inet_ntop(AF_INET6, &addr, dest, size)) - return kLwpaErrOk; - return kLwpaErrSys; - } - default: - return kLwpaErrInvalid; - } -} - -lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* dest) -{ - if (!src || !dest) - return kLwpaErrInvalid; - - switch (type) - { - case LWPA_IPV4: - { - struct in_addr addr; - if (1 != inet_pton(AF_INET, src, &addr)) - return kLwpaErrSys; - LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); - return kLwpaErrOk; - } - case LWPA_IPV6: - { - struct in6_addr addr; - if (1 != inet_pton(AF_INET6, src, &addr)) - return kLwpaErrSys; - LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); - return kLwpaErrOk; - } - default: - return kLwpaErrInvalid; - } -} diff --git a/src/os/macos/lwpa/os_inet.c b/src/os/macos/lwpa/os_inet.c index f17ca5e27..4b4e8f133 100644 --- a/src/os/macos/lwpa/os_inet.c +++ b/src/os/macos/lwpa/os_inet.c @@ -103,7 +103,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(src)); if (NULL != inet_ntop(AF_INET, &addr, dest, (socklen_t)size)) return kLwpaErrOk; - return kLwpaErrSys; + return kLwpaErrInvalid; } case kLwpaIpTypeV6: { @@ -111,7 +111,7 @@ lwpa_error_t lwpa_inet_ntop(const LwpaIpAddr* src, char* dest, size_t size) memcpy(addr.s6_addr, LWPA_IP_V6_ADDRESS(src), LWPA_IPV6_BYTES); if (NULL != inet_ntop(AF_INET6, &addr, dest, (socklen_t)size)) return kLwpaErrOk; - return kLwpaErrSys; + return kLwpaErrInvalid; } default: return kLwpaErrInvalid; @@ -129,7 +129,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des { struct in_addr addr; if (1 != inet_pton(AF_INET, src, &addr)) - return kLwpaErrSys; + return kLwpaErrInvalid; LWPA_IP_SET_V4_ADDRESS(dest, ntohl(addr.s_addr)); return kLwpaErrOk; } @@ -137,7 +137,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des { struct in6_addr addr; if (1 != inet_pton(AF_INET6, src, &addr)) - return kLwpaErrSys; + return kLwpaErrInvalid; LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); return kLwpaErrOk; } diff --git a/src/os/mqx/lwpa/os_inet.c b/src/os/mqx/lwpa/os_inet.c index 56b07e428..1295151ed 100644 --- a/src/os/mqx/lwpa/os_inet.c +++ b/src/os/mqx/lwpa/os_inet.c @@ -149,7 +149,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des { struct in_addr addr; if (RTCS_OK != inet_pton(AF_INET, src, &addr, sizeof addr)) - return kLwpaErrSys; + return kLwpaErrInvalid; /* RTCS gives us host byte order in their in_addrs. Thus no htonl is needed. */ LWPA_IP_SET_V4_ADDRESS(dest, addr.s_addr); return kLwpaErrOk; @@ -158,7 +158,7 @@ lwpa_error_t lwpa_inet_pton(lwpa_iptype_t type, const char* src, LwpaIpAddr* des { struct in6_addr addr; if (RTCS_OK != inet_pton(AF_INET6, src, &addr, sizeof addr)) - return kLwpaErrSys; + return kLwpaErrInvalid; LWPA_IP_SET_V6_ADDRESS(dest, addr.s6_addr); return kLwpaErrOk; } diff --git a/tools/cmake/lwpa-os.cmake b/tools/cmake/lwpa-os.cmake index 2ee57d0a0..4b21bb13b 100644 --- a/tools/cmake/lwpa-os.cmake +++ b/tools/cmake/lwpa-os.cmake @@ -7,7 +7,7 @@ set(VALID_LWPA_OS_TARGETS mqx windows ) -set(VALID_LWPA_NETWORK_TARGETS +set(VALID_LWPA_NET_TARGETS linux lwip macos @@ -16,7 +16,7 @@ set(VALID_LWPA_NETWORK_TARGETS ) set(LWPA_OS_TARGET "" CACHE STRING "OS provider for lwpa. See tools/cmake/lwpa-os.cmake for valid values.") -set(LWPA_NETWORK_TARGET "" CACHE STRING "Network stack provider for lwpa. Often (but not always) the same as LWPA_OS_TARGET. See src/CMakeLists.txt for valid values.") +set(LWPA_NET_TARGET "" CACHE STRING "Network stack provider for lwpa. Often (but not always) the same as LWPA_OS_TARGET. See src/CMakeLists.txt for valid values.") if(NOT LWPA_OS_TARGET) message(STATUS "LWPA_OS_TARGET not supplied, assuming native compile by default...") @@ -32,9 +32,9 @@ if(NOT LWPA_OS_TARGET) endif() endif() -if(NOT LWPA_NETWORK_TARGET) - if(${LWPA_OS_TARGET} IN_LIST VALID_LWPA_NETWORK_TARGETS) - set(LWPA_NETWORK_TARGET ${LWPA_OS_TARGET}) +if(NOT LWPA_NET_TARGET) + if(${LWPA_OS_TARGET} IN_LIST VALID_LWPA_NET_TARGETS) + set(LWPA_NET_TARGET ${LWPA_OS_TARGET}) endif() endif() @@ -43,14 +43,14 @@ if(NOT ${LWPA_OS_TARGET} IN_LIST VALID_LWPA_OS_TARGETS) "Specify LWPA_OS_TARGET from these options: ${VALID_LWPA_OS_TARGETS}") endif() -if(NOT ${LWPA_NETWORK_TARGET} IN_LIST VALID_LWPA_NETWORK_TARGETS) - message(FATAL_ERROR "${LWPA_NETWORK_TARGET} is not a valid target network stack. " - "Specify LWPA_NETWORK_TARGET from these options: ${VALID_LWPA_NETWORK_TARGETS}") +if(NOT ${LWPA_NET_TARGET} IN_LIST VALID_LWPA_NET_TARGETS) + message(FATAL_ERROR "${LWPA_NET_TARGET} is not a valid target network stack. " + "Specify LWPA_NET_TARGET from these options: ${VALID_LWPA_NET_TARGETS}") endif() if(EXISTS ${PROJECT_SOURCE_DIR}/tools/cmake/os/${LWPA_OS_TARGET}.cmake) include(${PROJECT_SOURCE_DIR}/tools/cmake/os/${LWPA_OS_TARGET}.cmake) endif() -if(EXISTS ${PROJECT_SOURCE_DIR}/tools/cmake/net/${LWPA_NETWORK_TARGET}.cmake) - include(${PROJECT_SOURCE_DIR}/tools/cmake/net/${LWPA_NETWORK_TARGET}.cmake) +if(EXISTS ${PROJECT_SOURCE_DIR}/tools/cmake/net/${LWPA_NET_TARGET}.cmake) + include(${PROJECT_SOURCE_DIR}/tools/cmake/net/${LWPA_NET_TARGET}.cmake) endif() diff --git a/tools/cmake/net/lwip.cmake b/tools/cmake/net/lwip.cmake index df36936f5..61306bacf 100644 --- a/tools/cmake/net/lwip.cmake +++ b/tools/cmake/net/lwip.cmake @@ -8,4 +8,8 @@ if(NOT LWPA_LWIP_INCLUDE_DIRS OR NOT LWPA_LWIPOPTS_DIR) ) endif() -set(LWPA_NETWORK_ADDITIONAL_INCLUDE_DIRS ${LWPA_LWIP_INCLUDE_DIRS} ${LWPA_LWIPOPTS_DIR}) +set(LWPA_NET_ADDITIONAL_SOURCES + ${LWPA_ROOT}/src/os/lwip/lwpa/os_error.h + ${LWPA_ROOT}/src/os/lwip/lwpa/os_error.c +) +set(LWPA_NET_ADDITIONAL_INCLUDE_DIRS ${LWPA_LWIP_INCLUDE_DIRS} ${LWPA_LWIPOPTS_DIR}) From 6508c1ebd9d0c337e45525dd2b418b66c6a8883b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 26 Aug 2019 14:45:27 -0500 Subject: [PATCH 118/264] All FreeRTOS and lwIP sources now building. Next step - make unit tests run --- include/lwpa/socket.h | 2 +- include/os/freertos/lwpa/os_thread.h | 2 +- include/os/lwip/lwpa/os_socket.h | 24 ++- src/CMakeLists.txt | 1 + src/lwpa/socket.dox | 11 + src/os/lwip/lwpa/os_error.c | 1 - src/os/lwip/lwpa/os_socket.c | 312 +++++++++++++++++---------- tests/unit/test_socket.c | 25 ++- 8 files changed, 258 insertions(+), 120 deletions(-) diff --git a/include/lwpa/socket.h b/include/lwpa/socket.h index 866b9f37e..4da46f138 100644 --- a/include/lwpa/socket.h +++ b/include/lwpa/socket.h @@ -178,12 +178,12 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len); lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how); lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* id); -/* int protocol - not necessary */ /* socketpair - not implemented */ /**************************** Mimic fcntl() API ******************************/ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking); +lwpa_error_t lwpa_getblocking(lwpa_socket_t id, bool* blocking); /**************************** Mimic poll() API *******************************/ diff --git a/include/os/freertos/lwpa/os_thread.h b/include/os/freertos/lwpa/os_thread.h index e369bc972..2b93782b4 100644 --- a/include/os/freertos/lwpa/os_thread.h +++ b/include/os/freertos/lwpa/os_thread.h @@ -31,7 +31,7 @@ extern "C" { #endif #define LWPA_THREAD_DEFAULT_PRIORITY (configMAX_PRIORITIES / 2) -#define LWPA_THREAD_DEFAULT_STACK 2000 +#define LWPA_THREAD_DEFAULT_STACK 500 #define LWPA_THREAD_DEFAULT_NAME "lwpa_thread" typedef struct diff --git a/include/os/lwip/lwpa/os_socket.h b/include/os/lwip/lwpa/os_socket.h index 2a23121c2..f1e938d5b 100644 --- a/include/os/lwip/lwpa/os_socket.h +++ b/include/os/lwip/lwpa/os_socket.h @@ -38,11 +38,30 @@ typedef int lwpa_socket_t; /* Definitions for lwpa_poll API */ +typedef struct LwpaPollSocket +{ + lwpa_socket_t sock; + lwpa_poll_events_t events; + void* user_data; +} LwpaPollSocket; + +typedef struct LwpaPollFdSet +{ + fd_set set; + int count; +} LwpaPollFdSet; + typedef struct LwpaPollContext { bool valid; - int epoll_fd; - LwpaRbTree sockets; + + LwpaPollSocket sockets[LWPA_SOCKET_MAX_POLL_SIZE]; + size_t num_valid_sockets; + int max_fd; + + LwpaPollFdSet readfds; + LwpaPollFdSet writefds; + LwpaPollFdSet exceptfds; } LwpaPollContext; #ifdef __cplusplus @@ -50,4 +69,3 @@ typedef struct LwpaPollContext #endif #endif /* _LWPA_OS_SOCKET_H_ */ - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c39ff8352..6e7cdac3a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,6 +85,7 @@ set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) install(TARGETS lwpa ARCHIVE DESTINATION lib) install(DIRECTORY ${LWPA_ROOT}/include/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") install(DIRECTORY ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") +install(DIRECTORY ${LWPA_ROOT}/include/os/${LWPA_NET_TARGET}/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") ############################################################################### # Mock lwpa library diff --git a/src/lwpa/socket.dox b/src/lwpa/socket.dox index 30733123d..f0369ed3d 100644 --- a/src/lwpa/socket.dox +++ b/src/lwpa/socket.dox @@ -239,6 +239,17 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t * */ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking); +/*! \brief Get the current blocking behavior of a socket. + * + * This is similar to checking the state of the O_NONBLOCK flag through the fcntl() function on a + * BSD socket. + * + * \param[in] id Socket for which to read the blocking behavior. + * \param[out] blocking Filled in with whether the socket is currently blocking or not. + * \return #kLwpaErrOk (success) or #lwpa_error_t code from system (error occurred). + */ +lwpa_error_t lwpa_getblocking(lwpa_socket_t id, bool* blocking); + /*! \name lwpa_poll API * * The lwpa_poll functions enable monitoring several sockets at once. diff --git a/src/os/lwip/lwpa/os_error.c b/src/os/lwip/lwpa/os_error.c index c5ac86a13..c5b30e8fe 100644 --- a/src/os/lwip/lwpa/os_error.c +++ b/src/os/lwip/lwpa/os_error.c @@ -18,7 +18,6 @@ ******************************************************************************/ #include "os_error.h" -#include lwpa_error_t errno_lwip_to_lwpa(int lwip_errno) { diff --git a/src/os/lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c index d1ffda43e..502979438 100644 --- a/src/os/lwip/lwpa/os_socket.c +++ b/src/os/lwip/lwpa/os_socket.c @@ -23,9 +23,21 @@ #include #include "os_error.h" -/**************************** Private constants ******************************/ +/***************************** Private macros ********************************/ -/****************************** Private types ********************************/ +#define LWPA_FD_ZERO(setptr) \ + FD_ZERO(&(setptr)->set); \ + (setptr)->count = 0 + +#define LWPA_FD_SET(sock, setptr) \ + FD_SET(sock, &(setptr)->set); \ + (setptr)->count++ + +#define LWPA_FD_CLEAR(sock, setptr) \ + FD_CLR(sock, &(setptr)->set); \ + (setptr)->count-- + +#define LWPA_FD_ISSET(sock, setptr) FD_ISSET(sock, &(setptr)->set) /**************************** Private variables ******************************/ @@ -54,6 +66,8 @@ static const int stmap[LWPA_NUM_TYPE] = SOCK_DGRAM }; +#if LWIP_DNS + #define LWPA_NUM_AIF 8 static const int aiflagmap[LWPA_NUM_AIF] = { @@ -90,6 +104,8 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = IPPROTO_UDP }; +#endif // LWIP_DNS + /* clang-format on */ /*********************** Private function prototypes *************************/ @@ -97,8 +113,20 @@ static const int aiprotmap[LWPA_NUM_IPPROTO] = // Helpers for lwpa_setsockopt() static void ms_to_timeval(int ms, struct timeval* tv); static int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +#if LWIP_IPV4 static int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +#endif +#if LWIP_IPV6 static int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len); +#endif + +// Helper functions for the lwpa_poll API +static void init_context_socket_array(LwpaPollContext* context); +static LwpaPollSocket* find_socket(LwpaPollContext* context, lwpa_socket_t sock); +static LwpaPollSocket* find_hole(LwpaPollContext* context); +static void set_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* sock); +static void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* sock); +static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event); /*************************** Function definitions ****************************/ @@ -170,7 +198,7 @@ lwpa_error_t lwpa_connect(lwpa_socket_t id, const LwpaSockaddr* address) return (res == 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); } -lwpa_error_t lwpa_getpeername(lwpa_error_t id, LwpaSockaddr* address) +lwpa_error_t lwpa_getpeername(lwpa_socket_t id, LwpaSockaddr* address) { // TODO (void)id; @@ -188,20 +216,20 @@ lwpa_error_t lwpa_getsockname(lwpa_socket_t id, LwpaSockaddr* address) int res = getsockname(id, (struct sockaddr*)&ss, &size); if (res == 0) { - if (!sockaddr_os_to_lwpa((lwpa_os_sockadr_t*)&ss, address)) + if (!sockaddr_os_to_lwpa((lwpa_os_sockaddr_t*)&ss, address)) return kLwpaErrSys; return kLwpaErrOk; } return errno_lwip_to_lwpa(errno); } -int lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, lwpa_socket_t option_value, size_t* option_len) +lwpa_error_t lwpa_getsockopt(lwpa_socket_t id, int level, int option_name, void* option_value, size_t* option_len) { // TODO return -1; } -int lwpa_listen(lwpa_socket_t id, int backlog) +lwpa_error_t lwpa_listen(lwpa_socket_t id, int backlog) { int res = listen(id, backlog); return (res == 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); @@ -212,8 +240,6 @@ int lwpa_recv(lwpa_socket_t id, void* buffer, size_t length, int flags) if (!buffer) return (int)kLwpaErrInvalid; - struct sockaddr_storage from_addr; - socklen_t from_len = (socklen_t)sizeof from_addr; int impl_flags = (flags & LWPA_MSG_PEEK) ? MSG_PEEK : 0; int res = (int)recv(id, buffer, length, impl_flags); return (res >= 0 ? res : (int)errno_lwip_to_lwpa(errno)); @@ -233,7 +259,7 @@ int lwpa_recvfrom(lwpa_socket_t id, void* buffer, size_t length, int flags, Lwpa { if (address && fromlen > 0) { - if (!sockaddr_os_to_lwpa(address, (struct sockaddr*)&fromaddr)) + if (!sockaddr_os_to_lwpa((const lwpa_os_sockaddr_t*)&fromaddr, address)) return (int)kLwpaErrSys; } return res; @@ -265,15 +291,15 @@ int lwpa_sendto(lwpa_socket_t id, const void* message, size_t length, int flags, return (int)kLwpaErrSys; int res = (int)sendto(id, message, length, 0, (struct sockaddr*)&ss, ss_size); - return (res >= 0 ? res : (int)errno_os_to_lwpa(errno)); + return (res >= 0 ? res : (int)errno_lwip_to_lwpa(errno)); } -int lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) +lwpa_error_t lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* option_value, size_t option_len) { int res = -1; if (!option_value) - return (int)kLwpaErrInvalid; + return kLwpaErrInvalid; switch (level) { @@ -281,15 +307,24 @@ int lwpa_setsockopt(lwpa_socket_t id, int level, int option_name, const void* op res = setsockopt_socket(id, option_name, option_value, option_len); break; case LWPA_IPPROTO_IP: +#if LWIP_IPV4 res = setsockopt_ip(id, option_name, option_value, option_len); +#else + errno = EAFNOSUPPORT; +#endif break; case LWPA_IPPROTO_IPV6: +#if LWIP_IPV6 res = setsockopt_ip6(id, option_name, option_value, option_len); +#else + errno = EAFNOSUPPORT; +#endif break; default: break; } - return res; + + return (res == 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); } int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) @@ -317,6 +352,7 @@ int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_valu ms_to_timeval(ms, &val); return setsockopt(id, SOL_SOCKET, SO_SNDTIMEO, &val, sizeof val); } + break; case LWPA_SO_REUSEADDR: return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, option_value, option_len); case LWPA_SO_REUSEPORT: @@ -345,8 +381,17 @@ int setsockopt_socket(lwpa_socket_t id, int option_name, const void* option_valu return -1; } +#if LWIP_IPV4 static bool netif_index_to_ipv4_addr(unsigned int netif_index, struct in_addr* addr) { + struct netif* lwip_netif = netif_get_by_index((u8_t)netif_index); + if (lwip_netif) + { + const ip4_addr_t* lwip_addr = netif_ip4_addr(lwip_netif); + addr->s_addr = lwip_addr->addr; + return true; + } + return false; } int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) @@ -355,8 +400,7 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s { case LWPA_IP_TTL: return setsockopt(id, IPPROTO_IP, IP_TTL, option_value, option_len); - break; -#if LWIP_IGMP || 1 +#if LWIP_IGMP case LWPA_IP_ADD_MEMBERSHIP: if (option_len == sizeof(LwpaMreq)) { @@ -410,13 +454,11 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s case LWPA_IP_MULTICAST_IF: if (option_len == sizeof(unsigned int)) { - LwpaIpAddr* netint = (LwpaIpAddr*)option_value; - if (LWPA_IP_IS_V4(netint)) - { - struct in_addr val; - val.s_addr = htonl(LWPA_IP_V4_ADDRESS(netint)); - return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); - } + unsigned int netint_index = *((unsigned int*)option_value); + struct in_addr val; + if (!netif_index_to_ipv4_addr(netint_index, &val)) + return -1; + return setsockopt(id, IPPROTO_IP, IP_MULTICAST_IF, &val, sizeof val); } break; case LWPA_IP_MULTICAST_TTL: @@ -424,13 +466,11 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s unsigned char val = (unsigned char)*(int*)option_value; return setsockopt(id, IPPROTO_IP, IP_MULTICAST_TTL, &val, sizeof val); } - break; case LWPA_IP_MULTICAST_LOOP: { unsigned char val = (unsigned char)*(int*)option_value; return setsockopt(id, IPPROTO_IP, IP_MULTICAST_LOOP, &val, sizeof val); } - break; #endif // LWIP_MULTICAST_TX_OPTIONS default: break; @@ -439,49 +479,49 @@ int setsockopt_ip(lwpa_socket_t id, int option_name, const void* option_value, s errno = EINVAL; return -1; } +#endif // LWIP_IPV4 +#if LWIP_IPV6 int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, size_t option_len) { switch (option_name) { case LWPA_MCAST_JOIN_GROUP: - /* This is not supported in lwip yet. - if (option_len == sizeof(struct lwpa_mreq)) + if (option_len == sizeof(LwpaGroupReq)) { - LwpaMreq *amreq = (LwpaMreq *)option_value; - if (LWPA_IP_IS_V6(&amreq->group)) + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group)) { struct ipv6_mreq val; - val.ipv6imr_interface = 0; - memcpy(&val.ipv6imr_multiaddr.s6_addr, - LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); - res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - sizeof val); + val.ipv6mr_interface = greq->ifindex; + memcpy(&val.ipv6mr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, IPV6_JOIN_GROUP, &val, sizeof val); } } - */ break; case LWPA_MCAST_LEAVE_GROUP: - /* This is not supported in lwip yet. - if (option_len == sizeof(struct lwpa_mreq)) + if (option_len == sizeof(LwpaGroupReq)) { - LwpaMreq *amreq = (LwpaMreq *)option_value; - if (LWPA_IP_IS_V6(&amreq->group)) + LwpaGroupReq* greq = (LwpaGroupReq*)option_value; + if (LWPA_IP_IS_V6(&greq->group)) { struct ipv6_mreq val; - val.ipv6imr_interface = 0; - memcpy(&val.ipv6imr_multiaddr.s6_addr, - LWPA_IP_V6_ADDRESS(&amreq->group), IPV6_BYTES); - res = setsockopt(id, IPPROTO_IPV6, MCAST_JOIN_GROUP, &val, - sizeof val); + val.ipv6mr_interface = greq->ifindex; + memcpy(&val.ipv6mr_multiaddr.s6_addr, LWPA_IP_V6_ADDRESS(&greq->group), LWPA_IPV6_BYTES); + return setsockopt(id, IPPROTO_IPV6, IPV6_JOIN_GROUP, &val, sizeof val); } } - */ break; - default: // lwIP does not have a lot of IPV6 socket option support yet. + case LWPA_IPV6_V6ONLY: + return setsockopt(id, IPPROTO_IPV6, IPV6_V6ONLY, option_value, option_len); + default: // lwIP does not have support for the IPv6 multicast TX options yet. break; } + // If we got here, something was invalid. Set errno accordingly. + errno = EINVAL; + return -1; } +#endif // LWIP_IPV6 void ms_to_timeval(int ms, struct timeval* tv) { @@ -489,10 +529,13 @@ void ms_to_timeval(int ms, struct timeval* tv) tv->tv_sec = (ms % 1000) * 1000; } -int lwpa_shutdown(lwpa_socket_t id, int how) +lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) { if (how >= 0 && how < LWPA_NUM_SHUT) - return shutdown(id, shutmap[how]); + { + int res = shutdown(id, shutmap[how]); + return (res == 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); + } return -1; } @@ -511,7 +554,7 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* else { *id = LWPA_SOCKET_INVALID; - return err_os_to_lwpa(errno); + return errno_lwip_to_lwpa(errno); } } else @@ -522,28 +565,54 @@ lwpa_error_t lwpa_socket(unsigned int family, unsigned int type, lwpa_socket_t* return kLwpaErrInvalid; } +lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) +{ + int val = fcntl(id, F_GETFL, 0); + if (val >= 0) + { + val = fcntl(id, F_SETFL, (blocking ? (val & (int)(~O_NONBLOCK)) : (val | O_NONBLOCK))); + } + return (val >= 0 ? kLwpaErrOk : errno_lwip_to_lwpa(errno)); +} + +lwpa_error_t lwpa_getblocking(lwpa_socket_t id, bool* blocking) +{ + if (blocking) + { + int val = fcntl(id, F_GETFL, 0); + if (val >= 0) + { + *blocking = (val & O_NONBLOCK) != 0; + return kLwpaErrOk; + } + return errno_lwip_to_lwpa(errno); + } + return kLwpaErrInvalid; +} + lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { if (!context) return kLwpaErrInvalid; init_context_socket_array(context); + context->max_fd = -1; LWPA_FD_ZERO(&context->readfds); LWPA_FD_ZERO(&context->writefds); + LWPA_FD_ZERO(&context->exceptfds); context->valid = true; return kLwpaErrOk; } void lwpa_poll_context_deinit(LwpaPollContext* context) { - if (!context || !context->valid) + if (!context) return; - context->valid = false; } lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t events, - lwpa_socket_t user_data) + void* user_data) { if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) return kLwpaErrInvalid; @@ -554,14 +623,17 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket } else { - LwpaPollCtxSocket* new_sock = find_hole(context); + LwpaPollSocket* new_sock = find_hole(context); if (new_sock) { - new_sock->socket = socket; + new_sock->sock = socket; new_sock->events = events; new_sock->user_data = user_data; set_in_fd_sets(context, new_sock); context->num_valid_sockets++; + if (socket > context->max_fd) + context->max_fd = socket; + return kLwpaErrOk; } return kLwpaErrNoMem; @@ -569,12 +641,12 @@ lwpa_error_t lwpa_poll_add_socket(LwpaPollContext* context, lwpa_socket_t socket } lwpa_error_t lwpa_poll_modify_socket(LwpaPollContext* context, lwpa_socket_t socket, lwpa_poll_events_t new_events, - lwpa_socket_t new_user_data) + void* new_user_data) { if (!context || !context->valid || socket == LWPA_SOCKET_INVALID || !(new_events & LWPA_POLL_VALID_INPUT_EVENT_MASK)) return kLwpaErrInvalid; - LwpaPollCtxSocket* sock_desc = find_socket(context, socket); + LwpaPollSocket* sock_desc = find_socket(context, socket); if (sock_desc) { clear_in_fd_sets(context, sock_desc); @@ -594,12 +666,21 @@ void lwpa_poll_remove_socket(LwpaPollContext* context, lwpa_socket_t socket) if (!context || !context->valid || socket == LWPA_SOCKET_INVALID) return; - LwpaPollCtxSocket* sock_desc = find_socket(context, socket); + LwpaPollSocket* sock_desc = find_socket(context, socket); if (sock_desc) { clear_in_fd_sets(context, sock_desc); - sock_desc->socket = LWPA_SOCKET_INVALID; + sock_desc->sock = LWPA_SOCKET_INVALID; context->num_valid_sockets--; + if (socket == context->max_fd) + { + while (context->max_fd > 0 && + (LWPA_FD_ISSET(context->max_fd, &context->readfds) || LWPA_FD_ISSET(context->max_fd, &context->writefds) || + LWPA_FD_ISSET(context->max_fd, &context->exceptfds))) + { + --context->max_fd; + } + } } } @@ -608,35 +689,24 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int if (!context || !context->valid || !event) return kLwpaErrInvalid; - if (context->readfds.count == 0 && context->writefds.count == 0) + if (context->readfds.count == 0 && context->writefds.count == 0 && context->exceptfds.count == 0) { // No valid sockets are currently added to the context. return kLwpaErrNoSockets; } - uint32_t os_timeout; - if (timeout_ms == LWPA_WAIT_FOREVER) - os_timeout = 0; - else if (timeout_ms == 0) - os_timeout = 0xffffffff; - else - os_timeout = (uint32_t)timeout_ms; + struct timeval os_timeout; + if (timeout_ms != LWPA_WAIT_FOREVER) + ms_to_timeval(timeout_ms, &os_timeout); - int32_t nfds = - (int32_t)((context->readfds.count > context->writefds.count) ? context->readfds.count : context->writefds.count); - int32_t sel_res = select(nfds, context->readfds.count ? &context->readfds.set : NULL, - context->writefds.count ? &context->writefds.set : NULL, NULL, os_timeout); + int sel_res = select(context->max_fd + 1, context->readfds.count ? &context->readfds.set : NULL, + context->writefds.count ? &context->writefds.set : NULL, + context->exceptfds.count ? &context->exceptfds.set : NULL, + timeout_ms == LWPA_WAIT_FOREVER ? NULL : &os_timeout); - if (sel_res == RTCS_ERROR) + if (sel_res < 0) { - // RTCS handles some socket errors by returning them from select(). - uint32_t rtcs_err = RTCS_get_errno(); - if (rtcs_err == RTCSERR_SOCK_ESHUTDOWN) - return handle_select_result(context, event, kLwpaErrConnClosed); - else if (rtcs_err == RTCSERR_SOCK_CLOSED) - return handle_select_result(context, event, kLwpaErrNotFound); - else - return err_os_to_lwpa(rtcs_err); + return errno_lwip_to_lwpa(errno); } else if (sel_res == 0) { @@ -644,11 +714,11 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int } else { - return handle_select_result(context, event, kLwpaErrOk); + return handle_select_result(context, event); } } -lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, lwpa_error_t socket_error) +lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event) { // Init the event data. event->socket = LWPA_SOCKET_INVALID; @@ -659,38 +729,41 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event // gone wrong. lwpa_error_t res = kLwpaErrSys; - for (LwpaPollCtxSocket* sock_desc = context->sockets; sock_desc < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; + for (LwpaPollSocket* sock_desc = context->sockets; sock_desc < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; ++sock_desc) { - if (sock_desc->socket == LWPA_SOCKET_INVALID) + if (sock_desc->sock == LWPA_SOCKET_INVALID) continue; - if (LWPA_FD_ISSET(sock_desc->socket, &context->readfds) || LWPA_FD_ISSET(sock_desc->socket, &context->writefds)) + if (LWPA_FD_ISSET(sock_desc->sock, &context->readfds) || LWPA_FD_ISSET(sock_desc->sock, &context->writefds) || + LWPA_FD_ISSET(sock_desc->sock, &context->exceptfds)) { res = kLwpaErrOk; - event->socket = sock_desc->socket; + event->socket = sock_desc->sock; event->user_data = sock_desc->user_data; - /* Check for errors */ - if (socket_error != kLwpaErrOk) - { - event->events |= LWPA_POLL_ERR; - event->err = socket_error; - } - - if (LWPA_FD_ISSET(sock_desc->socket, &context->readfds)) + if (LWPA_FD_ISSET(sock_desc->sock, &context->readfds)) { if (sock_desc->events & LWPA_POLL_IN) event->events |= LWPA_POLL_IN; } - if (LWPA_FD_ISSET(sock_desc->socket, &context->writefds)) + if (LWPA_FD_ISSET(sock_desc->sock, &context->writefds)) { if (sock_desc->events & LWPA_POLL_CONNECT) event->events |= LWPA_POLL_CONNECT; else if (sock_desc->events & LWPA_POLL_OUT) event->events |= LWPA_POLL_OUT; } - // LWPA_POLL_OOB/exceptfds is not handled properly on this OS + if (LWPA_FD_ISSET(sock_desc->sock, &context->exceptfds)) + { + event->events |= LWPA_POLL_ERR; + int err; + socklen_t err_size = (socklen_t)sizeof err; + if (getsockopt(sock_desc->sock, SOL_SOCKET, SO_ERROR, &err, &err_size) == 0) + event->err = errno_lwip_to_lwpa(err); + else + event->err = kLwpaErrSys; + } break; // We handle one event at a time. } @@ -701,54 +774,60 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event void init_context_socket_array(LwpaPollContext* context) { context->num_valid_sockets = 0; - for (LwpaPollCtxSocket* ctx_socket = context->sockets; ctx_socket < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; - ++ctx_socket) + for (LwpaPollSocket* poll_sock = context->sockets; poll_sock < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; + ++poll_sock) { - ctx_socket->socket = LWPA_SOCKET_INVALID; + poll_sock->sock = LWPA_SOCKET_INVALID; } } -LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t socket) +LwpaPollSocket* find_socket(LwpaPollContext* context, lwpa_socket_t sock) { - for (LwpaPollCtxSocket* cur = context->sockets; cur < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; ++cur) + for (LwpaPollSocket* poll_sock = context->sockets; poll_sock < context->sockets + LWPA_SOCKET_MAX_POLL_SIZE; + ++poll_sock) { - if (cur->socket == socket) - return cur; + if (poll_sock->sock == sock) + return poll_sock; } return NULL; } -LwpaPollCtxSocket* find_hole(LwpaPollContext* context) +LwpaPollSocket* find_hole(LwpaPollContext* context) { return find_socket(context, LWPA_SOCKET_INVALID); } -void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) +void set_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* poll_sock) { - if (sock->events & LWPA_POLL_IN) + if (poll_sock->events & LWPA_POLL_IN) { - LWPA_FD_SET(sock->socket, &context->readfds); + LWPA_FD_SET(poll_sock->sock, &context->readfds); } - if (sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + if (poll_sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) { - LWPA_FD_SET(sock->socket, &context->writefds); + LWPA_FD_SET(poll_sock->sock, &context->writefds); } + // exceptfds is used for errors on this platform, so set it regardless + LWPA_FD_SET(poll_sock->sock, &context->exceptfds); } -void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock) +void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* poll_sock) { - if (sock->events & LWPA_POLL_IN) + if (poll_sock->events & LWPA_POLL_IN) { - LWPA_FD_CLEAR(sock->socket, &context->readfds); + LWPA_FD_CLEAR(poll_sock->sock, &context->readfds); } - if (sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) + if (poll_sock->events & (LWPA_POLL_OUT | LWPA_POLL_CONNECT)) { - LWPA_FD_CLEAR(sock->socket, &context->writefds); + LWPA_FD_CLEAR(poll_sock->sock, &context->writefds); } + LWPA_FD_CLEAR(poll_sock->sock, &context->exceptfds); } -int lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, LwpaAddrinfo* result) +lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrinfo* hints, + LwpaAddrinfo* result) { +#if LWIP_DNS int res; struct addrinfo* pf_res; struct addrinfo pf_hints; @@ -774,10 +853,14 @@ int lwpa_getaddrinfo(const char* hostname, const char* service, const LwpaAddrin res = -1; } return res; +#else // LWIP_DNS + return kLwpaErrNotImpl; +#endif // LWIP_DNS } bool lwpa_nextaddr(LwpaAddrinfo* ai) { +#if LWIP_DNS if (ai && ai->pd[1]) { struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; @@ -809,11 +892,14 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) return true; } +#endif // LWIP_DNS return false; } void lwpa_freeaddrinfo(LwpaAddrinfo* ai) { +#if LWIP_DNS if (ai) freeaddrinfo((struct addrinfo*)ai->pd[0]); +#endif // LWIP_DNS } diff --git a/tests/unit/test_socket.c b/tests/unit/test_socket.c index 02bee870d..01a90daef 100644 --- a/tests/unit/test_socket.c +++ b/tests/unit/test_socket.c @@ -66,6 +66,27 @@ TEST(lwpa_socket, sockopts) // TODO, need getsockopt() implemented for this } +TEST(lwpa_socket, blocking_state_is_consistent) +{ + lwpa_socket_t sock; + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_STREAM, &sock); + TEST_ASSERT_NOT_EQUAL(sock, LWPA_SOCKET_INVALID); + + // Set the socket to non-blocking, make sure it reads as non-blocking + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setblocking(sock, false)); + bool is_blocking; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_getblocking(sock, &is_blocking)); + TEST_ASSERT_FALSE(is_blocking); + + // Set the socket back to blocking, make sure it reads as blocking + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setblocking(sock, true)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_getblocking(sock, &is_blocking)); + TEST_ASSERT_TRUE(is_blocking); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(sock)); +} + // Test to make sure various invalid calls to lwpa_poll_* functions fail properly. TEST(lwpa_socket, poll_invalid_calls_fail) { @@ -105,6 +126,8 @@ TEST(lwpa_socket, poll_invalid_calls_fail) // Deinit and make sure we cannot modify lwpa_poll_context_deinit(&context); TEST_ASSERT_NOT_EQUAL(kLwpaErrOk, lwpa_poll_modify_socket(&context, sock, LWPA_POLL_OUT, NULL)); + + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(sock)); } TEST(lwpa_socket, poll_user_data_works) @@ -348,4 +371,4 @@ TEST_GROUP_RUNNER(lwpa_socket) void run_all_tests(void) { RUN_TEST_GROUP(lwpa_socket); -} \ No newline at end of file +} From 4157b4e5d9d37364882031130f971243d4c17e4a Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Mon, 26 Aug 2019 18:49:35 -0500 Subject: [PATCH 119/264] Integration tests - 6 of 8 passing --- external/unity/CMakeLists.txt | 3 +++ src/os/lwip/lwpa/os_socket.c | 4 ++-- src/os/windows/lwpa/os_socket.c | 6 ++++++ tests/CMakeLists.txt | 3 ++- tests/integration/CMakeLists.txt | 23 +++++++++++++++------ tests/integration/mutex_integration_test.c | 4 +++- tests/integration/rwlock_integration_test.c | 9 ++++++-- tests/integration/signal_integration_test.c | 6 ++++-- tests/integration/socket_integration_test.c | 10 ++++----- tests/unit/test_socket.c | 3 ++- 10 files changed, 50 insertions(+), 21 deletions(-) diff --git a/external/unity/CMakeLists.txt b/external/unity/CMakeLists.txt index 3f5e2bb19..de17489d1 100644 --- a/external/unity/CMakeLists.txt +++ b/external/unity/CMakeLists.txt @@ -12,5 +12,8 @@ if(NOT TARGET ThrowTheSwitch::Unity) ${CMAKE_CURRENT_LIST_DIR}/src ${CMAKE_CURRENT_LIST_DIR}/extras/fixture/src ) + install(TARGETS unity ARCHIVE DESTINATION lib) + install(DIRECTORY src/ DESTINATION include/unity FILES_MATCHING PATTERN "*.h") + install(DIRECTORY extras/fixture/src/ DESTINATION include/unity FILES_MATCHING PATTERN "*.h") add_library(ThrowTheSwitch::Unity ALIAS unity) endif() diff --git a/src/os/lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c index 502979438..e6c38e7b2 100644 --- a/src/os/lwip/lwpa/os_socket.c +++ b/src/os/lwip/lwpa/os_socket.c @@ -525,8 +525,8 @@ int setsockopt_ip6(lwpa_socket_t id, int option_name, const void* option_value, void ms_to_timeval(int ms, struct timeval* tv) { - tv->tv_usec = ms / 1000; - tv->tv_sec = (ms % 1000) * 1000; + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; } lwpa_error_t lwpa_shutdown(lwpa_socket_t id, int how) diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index e4afa53a2..fbc5876ee 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -638,6 +638,12 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) return (res == 0 ? kLwpaErrOk : err_winsock_to_lwpa(WSAGetLastError())); } +lwpa_error_t lwpa_getblocking(lwpa_socket_t id, bool* blocking) +{ + *blocking = false; + return kLwpaErrOk; +} + lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { if (!context) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a575caaca..f8d86794c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,6 +4,7 @@ set(LWPA_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) set(LWPA_SRC ${CMAKE_CURRENT_LIST_DIR}/../src) option(LWPA_TEST_IPV6 "Test IPv6 socket functions in the lwpa unit and integration tests" ON) +option(LWPA_TEST_BUILD_AS_LIBRARIES "Build the lwpa unit and integration tests as libraries rather than executables" OFF) if(WIN32 OR APPLE OR UNIX) set(LWPA_TEST_ENTRYPOINT main_default.c) @@ -30,5 +31,5 @@ if(APPLE) list(APPEND LWPA_TEST_COMPILE_DEFINITIONS LWPA_BULK_POLL_TEST_NUM_SOCKETS=200) endif() -add_subdirectory(unit) +# add_subdirectory(unit) add_subdirectory(integration) diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index 213b525de..1210bd05f 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -2,23 +2,34 @@ # These are "live" tests which use multiple parts of the lwpa library. Most of what is tested here # are the locking, threading and synchronization functions. -add_executable(lwpa_integration_tests +set(LWPA_INTEGRATION_TEST_SOURCES mutex_integration_test.c rwlock_integration_test.c signal_integration_test.c socket_integration_test.c test_main.c - - entrypoint/${LWPA_TEST_ENTRYPOINT} ) + +if(LWPA_TEST_BUILD_AS_LIBRARIES) + add_library(lwpa_integration_tests + ${LWPA_INTEGRATION_TEST_SOURCES} + ) + install(TARGETS lwpa_integration_tests ARCHIVE DESTINATION lib) +else() + add_executable(lwpa_integration_tests + ${LWPA_INTEGRATION_TEST_SOURCES} + entrypoint/${LWPA_TEST_ENTRYPOINT} + ) + lwpa_add_to_ctest(lwpa_integration_tests) +endif() + set_target_properties(lwpa_integration_tests PROPERTIES FOLDER tests) target_compile_options(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) target_compile_definitions(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) -target_link_libraries(lwpa_integration_tests PRIVATE lwpa ThrowTheSwitch::Unity) -lwpa_add_to_ctest(lwpa_integration_tests) +target_link_libraries(lwpa_integration_tests PUBLIC lwpa ThrowTheSwitch::Unity) # The macOS hosted agents have some unknown restriction on multicast traffic which causes the # multicast tests to fail. if(APPLE AND LWPA_BUILDING_FOR_AZURE_PIPELINES_CI) target_compile_definitions(lwpa_integration_tests PRIVATE LWPA_TEST_DISABLE_MCAST_INTEGRATION_TESTS) -endif() \ No newline at end of file +endif() diff --git a/tests/integration/mutex_integration_test.c b/tests/integration/mutex_integration_test.c index 25b8c5f13..8e146f435 100644 --- a/tests/integration/mutex_integration_test.c +++ b/tests/integration/mutex_integration_test.c @@ -72,7 +72,9 @@ TEST(mutex_integration, mutex_thread_test) for (size_t i = 0; i < NUM_THREADS; ++i) { - TEST_ASSERT_TRUE(lwpa_thread_create(&threads[i], ¶ms, mutex_test_thread, NULL)); + char error_msg[50]; + sprintf(error_msg, "Failed on iteration %zu", i); + TEST_ASSERT_TRUE_MESSAGE(lwpa_thread_create(&threads[i], ¶ms, mutex_test_thread, NULL), error_msg); } for (size_t i = 0; i < NUM_THREADS; ++i) diff --git a/tests/integration/rwlock_integration_test.c b/tests/integration/rwlock_integration_test.c index 5688723af..853d05dc4 100644 --- a/tests/integration/rwlock_integration_test.c +++ b/tests/integration/rwlock_integration_test.c @@ -100,11 +100,16 @@ TEST(rwlock_integration, rwlock_thread_test) for (size_t i = 0; i < NUM_WRITE_THREADS; ++i) { - TEST_ASSERT_TRUE(lwpa_thread_create(&write_threads[i], ¶ms, write_test_thread, NULL)); + char error_msg[50]; + sprintf(error_msg, "Failed on iteration %zu", i); + TEST_ASSERT_TRUE_MESSAGE(lwpa_thread_create(&write_threads[i], ¶ms, write_test_thread, NULL), error_msg); } for (size_t i = 0; i < NUM_WRITE_THREADS; ++i) + { TEST_ASSERT_TRUE(lwpa_thread_join(&write_threads[i])); + } + TEST_ASSERT_TRUE(lwpa_thread_join(&read_thread)); TEST_ASSERT(read_thread_pass); @@ -114,4 +119,4 @@ TEST(rwlock_integration, rwlock_thread_test) TEST_GROUP_RUNNER(rwlock_integration) { RUN_TEST_CASE(rwlock_integration, rwlock_thread_test); -} \ No newline at end of file +} diff --git a/tests/integration/signal_integration_test.c b/tests/integration/signal_integration_test.c index 413cb08f6..be987e09b 100644 --- a/tests/integration/signal_integration_test.c +++ b/tests/integration/signal_integration_test.c @@ -55,7 +55,9 @@ TEST(signal_integration, signal_thread_test) for (size_t i = 0; i < 2; ++i) { - TEST_ASSERT_TRUE(lwpa_thread_create(&threads[i], ¶ms, signal_test_thread, NULL)); + char error_msg[50]; + sprintf(error_msg, "Failed on iteration %zu", i); + TEST_ASSERT_TRUE_MESSAGE(lwpa_thread_create(&threads[i], ¶ms, signal_test_thread, NULL), error_msg); } for (size_t i = 0; i < 6; ++i) @@ -71,4 +73,4 @@ TEST(signal_integration, signal_thread_test) TEST_GROUP_RUNNER(signal_integration) { RUN_TEST_CASE(signal_integration, signal_thread_test); -} \ No newline at end of file +} diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index 7b8db868d..dc3c04393 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -81,9 +81,7 @@ static void select_network_interface_v4() } } // We haven't found a network interface... - UnityPrint( - "WARNING: No IPv4 non-loopback, non-link-local network interfaces found. Disabling multicast IPv4 " - "test...\n"); + TEST_MESSAGE("No IPv4 non-loopback, non-link-local network interfaces found. Disabling multicast IPv4 test..."); run_ipv4_mcast_test = false; } } @@ -114,7 +112,7 @@ static void select_network_interface_v6() } } // We haven't found a network interface... - UnityPrint("WARNING: No IPv6 non-loopback network interfaces found. Disabling multicast IPv6 test...\n"); + TEST_MESSAGE("WARNING: No IPv6 non-loopback network interfaces found. Disabling multicast IPv6 test..."); run_ipv6_mcast_test = false; } } @@ -181,7 +179,7 @@ void unicast_udp_test(lwpa_iptype_t ip_type, lwpa_socket_t rcvsock1, lwpa_socket } else { - TEST_ASSERT_EQUAL(res, kLwpaErrTimedOut); + TEST_ASSERT(res == kLwpaErrTimedOut || res == kLwpaErrWouldBlock); break; } @@ -281,7 +279,7 @@ void multicast_udp_test(lwpa_socket_t rcvsock1, lwpa_socket_t rcvsock2) } else { - TEST_ASSERT_EQUAL(res, kLwpaErrWouldBlock); + TEST_ASSERT(res == kLwpaErrTimedOut || res == kLwpaErrWouldBlock); break; } diff --git a/tests/unit/test_socket.c b/tests/unit/test_socket.c index 01a90daef..79c29ac13 100644 --- a/tests/unit/test_socket.c +++ b/tests/unit/test_socket.c @@ -70,7 +70,7 @@ TEST(lwpa_socket, blocking_state_is_consistent) { lwpa_socket_t sock; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_STREAM, &sock); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_STREAM, &sock)); TEST_ASSERT_NOT_EQUAL(sock, LWPA_SOCKET_INVALID); // Set the socket to non-blocking, make sure it reads as non-blocking @@ -360,6 +360,7 @@ TEST_GROUP_RUNNER(lwpa_socket) { RUN_TEST_CASE(lwpa_socket, bind_works_as_expected); RUN_TEST_CASE(lwpa_socket, sockopts); + RUN_TEST_CASE(lwpa_socket, blocking_state_is_consistent); RUN_TEST_CASE(lwpa_socket, poll_invalid_calls_fail); RUN_TEST_CASE(lwpa_socket, poll_user_data_works); RUN_TEST_CASE(lwpa_socket, poll_modify_socket_works); From e8d726235afcc533833717136b2a382327e99fd8 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 27 Aug 2019 17:58:31 -0500 Subject: [PATCH 120/264] Fix bulk_poll test --- external/unity/CMakeLists.txt | 9 ++ src/CMakeLists.txt | 7 +- src/os/lwip/lwpa/os_inet.c | 96 ++++++++++++++------- src/os/lwip/lwpa/os_socket.c | 29 ++++--- src/os/mqx/lwpa/os_socket.c | 25 +++--- tests/integration/socket_integration_test.c | 19 ++-- 6 files changed, 121 insertions(+), 64 deletions(-) diff --git a/external/unity/CMakeLists.txt b/external/unity/CMakeLists.txt index de17489d1..55b8adb97 100644 --- a/external/unity/CMakeLists.txt +++ b/external/unity/CMakeLists.txt @@ -1,4 +1,5 @@ if(NOT TARGET ThrowTheSwitch::Unity) + add_library(unity src/unity.h src/unity_internals.h @@ -12,8 +13,16 @@ if(NOT TARGET ThrowTheSwitch::Unity) ${CMAKE_CURRENT_LIST_DIR}/src ${CMAKE_CURRENT_LIST_DIR}/extras/fixture/src ) + + set(UNITY_CONFIG_FILE_DIR "" CACHE STRING "The directory path of the unity_config.h file, if provided.") + if(UNITY_CONFIG_FILE_DIR) + target_compile_definitions(unity PUBLIC UNITY_INCLUDE_CONFIG_H) + target_include_directories(unity PUBLIC ${UNITY_CONFIG_FILE_DIR}) + endif() + install(TARGETS unity ARCHIVE DESTINATION lib) install(DIRECTORY src/ DESTINATION include/unity FILES_MATCHING PATTERN "*.h") install(DIRECTORY extras/fixture/src/ DESTINATION include/unity FILES_MATCHING PATTERN "*.h") + add_library(ThrowTheSwitch::Unity ALIAS unity) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6e7cdac3a..cebbe85ee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ -set(LWPA_CONFIG_FILE_LOC "" CACHE STRING "The directory path of the lwpa_config.h file, if provided") -if(LWPA_CONFIG_FILE_LOC) +set(LWPA_CONFIG_FILE_DIR "" CACHE STRING "The directory path of the lwpa_config.h file, if provided") +if(LWPA_CONFIG_FILE_DIR) set(${LWPA_HAVE_CONFIG_H} LWPA_HAVE_CONFIG_H) endif() @@ -69,8 +69,7 @@ target_include_directories(lwpa PUBLIC ${LWPA_ROOT}/include/os/${LWPA_NET_TARGET} ${LWPA_OS_ADDITIONAL_INCLUDE_DIRS} ${LWPA_NET_ADDITIONAL_INCLUDE_DIRS} - ${LWPA_TOOLCHAIN_ADDITIONAL_INCLUDE_DIRS} - ${LWPA_CONFIG_FILE_LOC} + ${LWPA_CONFIG_FILE_DIR} ) target_include_directories(lwpa PRIVATE ${LWPA_ROOT}/src) target_compile_definitions(lwpa PRIVATE ${LWPA_HAVE_CONFIG_H}) diff --git a/src/os/lwip/lwpa/os_inet.c b/src/os/lwip/lwpa/os_inet.c index 5e2a3ce48..620e8f630 100644 --- a/src/os/lwip/lwpa/os_inet.c +++ b/src/os/lwip/lwpa/os_inet.c @@ -26,54 +26,90 @@ #error "LWIP_SOCKET is necessary in lwipopts.h to use the lwpa_inet module." #endif -bool sockaddr_os_to_lwpa(const lwpa_os_sockaddr_t* os_sa, LwpaSockaddr* sa) +bool ip_os_to_lwpa(const lwpa_os_ipaddr_t* os_ip, LwpaIpAddr* ip) { - if (os_sa->sa_family == AF_INET) - { #if LWIP_IPV4 - struct sockaddr_in* sin = (struct sockaddr_in*)os_sa; - sa->port = ntohs(sin->sin_port); - LWPA_IP_SET_V4_ADDRESS(&sa->ip, ntohl(sin->sin_addr.s_addr)); + if (os_ip->sa_family == AF_INET) + { + struct sockaddr_in* sin = (struct sockaddr_in*)os_ip; + LWPA_IP_SET_V4_ADDRESS(ip, ntohl(sin->sin_addr.s_addr)); return true; -#else - return false; -#endif } - else if (os_sa->sa_family == AF_INET6) - { +#endif #if LWIP_IPV6 - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_sa; - sa->port = ntohs(sin6->sin6_port); - LWPA_IP_SET_V6_ADDRESS(&sa->ip, sin6->sin6_addr.s6_addr); + if (os_ip->sa_family == AF_INET6) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_ip; + LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(ip, sin6->sin6_addr.s6_addr, sin6->sin6_scope_id); return true; -#else - return false; -#endif } +#endif return false; } -socklen_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, lwpa_os_sockaddr_t* os_sa) +size_t ip_lwpa_to_os(const LwpaIpAddr* ip, lwpa_os_ipaddr_t* os_ip) { - socklen_t ret = 0; - if (LWPA_IP_IS_V4(&sa->ip)) - { + size_t ret = 0; #if LWIP_IPV4 - struct sockaddr_in* sin = (struct sockaddr_in*)os_sa; + if (LWPA_IP_IS_V4(ip)) + { + struct sockaddr_in* sin = (struct sockaddr_in*)os_ip; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_len = sizeof(struct sockaddr_in6); sin->sin_family = AF_INET; - sin->sin_port = htons(sa->port); - sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(&sa->ip)); + sin->sin_addr.s_addr = htonl(LWPA_IP_V4_ADDRESS(ip)); ret = sizeof(struct sockaddr_in); -#endif } - else if (LWPA_IP_IS_V6(&sa->ip)) - { +#endif #if LWIP_IPV6 - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_sa; + if (LWPA_IP_IS_V6(ip)) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)os_ip; + memset(sin6, 0, sizeof(struct sockaddr_in6)); + sin6->sin6_len = sizeof(struct sockaddr_in6); sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(sa->port); - memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(&sa->ip), LWPA_IPV6_BYTES); + sin6->sin6_scope_id = ip->addr.v6.scope_id; + memcpy(sin6->sin6_addr.s6_addr, LWPA_IP_V6_ADDRESS(ip), LWPA_IPV6_BYTES); ret = sizeof(struct sockaddr_in6); + } +#endif + return ret; +} + +bool sockaddr_os_to_lwpa(const lwpa_os_sockaddr_t* os_sa, LwpaSockaddr* sa) +{ + if (ip_os_to_lwpa(os_sa, &sa->ip)) + { +#if LWIP_IPV4 + if (os_sa->sa_family == AF_INET) + { + sa->port = ntohs(((const struct sockaddr_in*)os_sa)->sin_port); + return true; + } +#endif +#if LWIP_IPV6 + if (os_sa->sa_family == AF_INET6) + { + sa->port = ntohs(((const struct sockaddr_in6*)os_sa)->sin6_port); + return true; + } +#endif + } + return false; +} + +size_t sockaddr_lwpa_to_os(const LwpaSockaddr* sa, lwpa_os_sockaddr_t* os_sa) +{ + size_t ret = ip_lwpa_to_os(&sa->ip, os_sa); + if (ret != 0) + { +#if LWIP_IPV4 + if (LWPA_IP_IS_V4(&sa->ip)) + ((struct sockaddr_in*)os_sa)->sin_port = htons(sa->port); +#endif +#if LWIP_IPV6 + if (LWPA_IP_IS_V6(&sa->ip)) + ((struct sockaddr_in6*)os_sa)->sin6_port = htons(sa->port); #endif } return ret; diff --git a/src/os/lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c index e6c38e7b2..8d411d77d 100644 --- a/src/os/lwip/lwpa/os_socket.c +++ b/src/os/lwip/lwpa/os_socket.c @@ -126,7 +126,8 @@ static LwpaPollSocket* find_socket(LwpaPollContext* context, lwpa_socket_t sock) static LwpaPollSocket* find_hole(LwpaPollContext* context); static void set_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* sock); static void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollSocket* sock); -static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event); +static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, const fd_set* readfds, + const fd_set* writefds, const fd_set* exceptfds); /*************************** Function definitions ****************************/ @@ -695,14 +696,17 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int return kLwpaErrNoSockets; } + fd_set readfds = context->readfds.set; + fd_set writefds = context->writefds.set; + fd_set exceptfds = context->exceptfds.set; + struct timeval os_timeout; if (timeout_ms != LWPA_WAIT_FOREVER) ms_to_timeval(timeout_ms, &os_timeout); - int sel_res = select(context->max_fd + 1, context->readfds.count ? &context->readfds.set : NULL, - context->writefds.count ? &context->writefds.set : NULL, - context->exceptfds.count ? &context->exceptfds.set : NULL, - timeout_ms == LWPA_WAIT_FOREVER ? NULL : &os_timeout); + int sel_res = + select(context->max_fd + 1, context->readfds.count ? &readfds : NULL, context->writefds.count ? &writefds : NULL, + context->exceptfds.count ? &exceptfds : NULL, timeout_ms == LWPA_WAIT_FOREVER ? NULL : &os_timeout); if (sel_res < 0) { @@ -714,11 +718,12 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int } else { - return handle_select_result(context, event); + return handle_select_result(context, event, &readfds, &writefds, &exceptfds); } } -lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event) +lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, const fd_set* readfds, + const fd_set* writefds, const fd_set* exceptfds) { // Init the event data. event->socket = LWPA_SOCKET_INVALID; @@ -735,26 +740,26 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event if (sock_desc->sock == LWPA_SOCKET_INVALID) continue; - if (LWPA_FD_ISSET(sock_desc->sock, &context->readfds) || LWPA_FD_ISSET(sock_desc->sock, &context->writefds) || - LWPA_FD_ISSET(sock_desc->sock, &context->exceptfds)) + if (FD_ISSET(sock_desc->sock, readfds) || FD_ISSET(sock_desc->sock, writefds) || + FD_ISSET(sock_desc->sock, exceptfds)) { res = kLwpaErrOk; event->socket = sock_desc->sock; event->user_data = sock_desc->user_data; - if (LWPA_FD_ISSET(sock_desc->sock, &context->readfds)) + if (FD_ISSET(sock_desc->sock, readfds)) { if (sock_desc->events & LWPA_POLL_IN) event->events |= LWPA_POLL_IN; } - if (LWPA_FD_ISSET(sock_desc->sock, &context->writefds)) + if (FD_ISSET(sock_desc->sock, writefds)) { if (sock_desc->events & LWPA_POLL_CONNECT) event->events |= LWPA_POLL_CONNECT; else if (sock_desc->events & LWPA_POLL_OUT) event->events |= LWPA_POLL_OUT; } - if (LWPA_FD_ISSET(sock_desc->sock, &context->exceptfds)) + if (FD_ISSET(sock_desc->sock, exceptfds)) { event->events |= LWPA_POLL_ERR; int err; diff --git a/src/os/mqx/lwpa/os_socket.c b/src/os/mqx/lwpa/os_socket.c index ff4a7e563..a1a4895b1 100644 --- a/src/os/mqx/lwpa/os_socket.c +++ b/src/os/mqx/lwpa/os_socket.c @@ -110,7 +110,8 @@ static LwpaPollCtxSocket* find_socket(LwpaPollContext* context, lwpa_socket_t so static LwpaPollCtxSocket* find_hole(LwpaPollContext* context); static void set_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock); static void clear_in_fd_sets(LwpaPollContext* context, const LwpaPollCtxSocket* sock); -static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, lwpa_error_t socket_error); +static lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, lwpa_error_t socket_error, + const rtcs_fd_set* readfds, const rtcs_fd_set* writefds); // Helper functions for lwpa_setsockopt() static int32_t join_leave_mcast_group_ipv4(lwpa_socket_t id, const struct LwpaMreq* mreq, bool join); @@ -635,6 +636,9 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int return kLwpaErrNoSockets; } + rtcs_fd_set readfds = context->readfds.set; + rtcs_fd_set writefds = context->writefds.set; + uint32_t os_timeout; if (timeout_ms == LWPA_WAIT_FOREVER) os_timeout = 0; @@ -645,17 +649,17 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int int32_t nfds = (int32_t)((context->readfds.count > context->writefds.count) ? context->readfds.count : context->writefds.count); - int32_t sel_res = select(nfds, context->readfds.count ? &context->readfds.set : NULL, - context->writefds.count ? &context->writefds.set : NULL, NULL, os_timeout); + int32_t sel_res = select(nfds, context->readfds.count ? &readfds : NULL, context->writefds.count ? &writefds : NULL, + NULL, os_timeout); if (sel_res == RTCS_ERROR) { // RTCS handles some socket errors by returning them from select(). uint32_t rtcs_err = RTCS_get_errno(); if (rtcs_err == RTCSERR_SOCK_ESHUTDOWN) - return handle_select_result(context, event, kLwpaErrConnClosed); + return handle_select_result(context, event, kLwpaErrConnClosed, &readfds, &writefds); else if (rtcs_err == RTCSERR_SOCK_CLOSED) - return handle_select_result(context, event, kLwpaErrNotFound); + return handle_select_result(context, event, kLwpaErrNotFound, &readfds, &writefds); else return err_os_to_lwpa(rtcs_err); } @@ -665,11 +669,12 @@ lwpa_error_t lwpa_poll_wait(LwpaPollContext* context, LwpaPollEvent* event, int } else { - return handle_select_result(context, event, kLwpaErrOk); + return handle_select_result(context, event, kLwpaErrOk, &readfds, &writefds); } } -lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, lwpa_error_t socket_error) +lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event, lwpa_error_t socket_error, + const rtcs_fd_set* readfds, const rtcs_fd_set* writefds) { // Init the event data. event->socket = LWPA_SOCKET_INVALID; @@ -686,7 +691,7 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event if (sock_desc->socket == LWPA_SOCKET_INVALID) continue; - if (LWPA_FD_ISSET(sock_desc->socket, &context->readfds) || LWPA_FD_ISSET(sock_desc->socket, &context->writefds)) + if (RTCS_FD_ISSET(sock_desc->socket, readfds) || RTCS_FD_ISSET(sock_desc->socket, writefds)) { res = kLwpaErrOk; event->socket = sock_desc->socket; @@ -699,12 +704,12 @@ lwpa_error_t handle_select_result(LwpaPollContext* context, LwpaPollEvent* event event->err = socket_error; } - if (LWPA_FD_ISSET(sock_desc->socket, &context->readfds)) + if (RTCS_FD_ISSET(sock_desc->socket, readfds)) { if (sock_desc->events & LWPA_POLL_IN) event->events |= LWPA_POLL_IN; } - if (LWPA_FD_ISSET(sock_desc->socket, &context->writefds)) + if (RTCS_FD_ISSET(sock_desc->socket, writefds)) { if (sock_desc->events & LWPA_POLL_CONNECT) event->events |= LWPA_POLL_CONNECT; diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index dc3c04393..052af8ebd 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -20,6 +20,7 @@ #include "unity_fixture.h" #include +#include #include "lwpa/netint.h" #include "lwpa/thread.h" @@ -33,7 +34,7 @@ // Limit the bulk socket test to a reasonable number #define LWPA_BULK_POLL_TEST_NUM_SOCKETS 512 #else -#define LWPA_BULK_POLL_TEST_NUM_SOCKETS LWPA_SOCKET_MAX_POLL_SIZE +#define LWPA_BULK_POLL_TEST_NUM_SOCKETS (LWPA_SOCKET_MAX_POLL_SIZE - 1) #endif #endif @@ -95,7 +96,6 @@ static void select_network_interface_v6() NULL == strstr(v6_netint.name, "utun")) { run_ipv6_mcast_test = true; - printf("IPv6 selecting default interface index %u\n", v6_netint.index); } else { @@ -225,6 +225,7 @@ TEST(socket_integration, unicast_udp_ipv4) TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); } +#if LWPA_TEST_IPV6 TEST(socket_integration, unicast_udp_ipv6) { lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; @@ -250,6 +251,7 @@ TEST(socket_integration, unicast_udp_ipv6) TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); } +#endif // LWPA_TEST_IPV6 #define MULTICAST_UDP_PORT_BASE 7000 @@ -374,10 +376,10 @@ TEST(socket_integration, multicast_udp_ipv6) TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &send_sock)); TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); - TEST_ASSERT_EQUAL(kLwpaErrOk, - lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_IF, &v6_netint.index, - sizeof v6_netint.index)); + // TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int)); //); + // TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_IF, &v6_netint.index, sizeof v6_netint.index); //); // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV6, &bind_addr.ip); @@ -399,7 +401,7 @@ TEST(socket_integration, multicast_udp_ipv6) TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); - LWPA_IP_SET_V6_ADDRESS(&send_addr.ip, kTestMcastAddrIPv6); + LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&send_addr.ip, kTestMcastAddrIPv6, v6_netint.index); send_addr.port = MULTICAST_UDP_PORT_BASE; multicast_udp_test(rcvsock1, rcvsock2); @@ -408,7 +410,7 @@ TEST(socket_integration, multicast_udp_ipv6) TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); } -#endif +#endif // LWPA_TEST_IPV6 // Test to make sure lwpa_poll_* functions work properly with a large number of sockets. // (Tests the maximum number defined by LWPA_SOCKET_MAX_POLL_SIZE if that number is well-defined and @@ -469,6 +471,7 @@ TEST(socket_integration, bulk_poll) TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_close(socket_arr[i]), error_msg); } + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(poll_send_sock)); } TEST_GROUP_RUNNER(socket_integration) From 8e11caaa1ce8dc2726597cf57f8b3b666eb770ab Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 30 Aug 2019 18:03:07 -0500 Subject: [PATCH 121/264] Move live unit tests to new method --- src/CMakeLists.txt | 4 ++ src/os/freertos/lwpa/os_lock.c | 17 +++--- src/os/lwip/lwpa/os_socket.c | 2 +- tests/CMakeLists.txt | 39 ++++++++++++- tests/integration/mutex_integration_test.c | 1 + tests/integration/rwlock_integration_test.c | 1 + tests/integration/signal_integration_test.c | 1 + tests/unit/CMakeLists.txt | 56 +++++++------------ tests/unit/live/CMakeLists.txt | 17 ++++++ tests/unit/{ => live}/test_common.c | 15 ++--- tests/unit/{ => live}/test_inet.c | 5 -- tests/unit/{ => live}/test_lock.c | 5 -- tests/unit/{ => live}/test_log.c | 21 ++----- tests/unit/live/test_main.c | 38 +++++++++++++ tests/unit/{ => live}/test_mempool.c | 9 +-- tests/unit/{ => live}/test_netint.c | 7 +-- tests/unit/{ => live}/test_pack.c | 6 +- tests/unit/{ => live}/test_rbtree.c | 10 +--- tests/unit/{ => live}/test_socket.c | 17 ++++-- tests/unit/{ => live}/test_thread.c | 5 -- tests/unit/{ => live}/test_timer.c | 5 -- tests/unit/{ => live}/test_uuid.c | 30 +++++++--- .../unit/{ => timer}/test_timer_wraparound.c | 0 23 files changed, 174 insertions(+), 137 deletions(-) create mode 100644 tests/unit/live/CMakeLists.txt rename tests/unit/{ => live}/test_common.c (92%) rename tests/unit/{ => live}/test_inet.c (99%) rename tests/unit/{ => live}/test_lock.c (98%) rename tests/unit/{ => live}/test_log.c (97%) create mode 100644 tests/unit/live/test_main.c rename tests/unit/{ => live}/test_mempool.c (96%) rename tests/unit/{ => live}/test_netint.c (98%) rename tests/unit/{ => live}/test_pack.c (99%) rename tests/unit/{ => live}/test_rbtree.c (99%) rename tests/unit/{ => live}/test_socket.c (97%) rename tests/unit/{ => live}/test_thread.c (98%) rename tests/unit/{ => live}/test_timer.c (97%) rename tests/unit/{ => live}/test_uuid.c (88%) rename tests/unit/{ => timer}/test_timer_wraparound.c (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cebbe85ee..b7ddac01e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -80,6 +80,10 @@ target_link_libraries(lwpa PUBLIC ${LWPA_OS_ADDITIONAL_LIBS} ${LWPA_NET_ADDITION set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) +if(NOT MSVC) + set_target_properties(lwpa PROPERTIES C_STANDARD 99) +endif() + # Installation install(TARGETS lwpa ARCHIVE DESTINATION lib) install(DIRECTORY ${LWPA_ROOT}/include/lwpa DESTINATION include FILES_MATCHING PATTERN "*.h") diff --git a/src/os/freertos/lwpa/os_lock.c b/src/os/freertos/lwpa/os_lock.c index b79baa6a8..70878e302 100644 --- a/src/os/freertos/lwpa/os_lock.c +++ b/src/os/freertos/lwpa/os_lock.c @@ -20,7 +20,6 @@ #include "lwpa/lock.h" #include - /*********************** Private function prototypes *************************/ static void reader_atomic_increment(lwpa_rwlock_t* id); @@ -35,7 +34,7 @@ bool lwpa_mutex_create(lwpa_mutex_t* id) bool lwpa_mutex_take(lwpa_mutex_t* id) { - if (id) + if (id && *id) { return (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, portMAX_DELAY)); } @@ -44,7 +43,7 @@ bool lwpa_mutex_take(lwpa_mutex_t* id) bool lwpa_mutex_try_take(lwpa_mutex_t* id) { - if (id) + if (id && *id) { return (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, 0)); } @@ -53,13 +52,13 @@ bool lwpa_mutex_try_take(lwpa_mutex_t* id) void lwpa_mutex_give(lwpa_mutex_t* id) { - if (id) + if (id && *id) xSemaphoreGive((SemaphoreHandle_t)*id); } void lwpa_mutex_destroy(lwpa_mutex_t* id) { - if (id) + if (id && *id) { vSemaphoreDelete((SemaphoreHandle_t)*id); *id = (lwpa_mutex_t)NULL; @@ -73,17 +72,17 @@ bool lwpa_signal_create(lwpa_signal_t* id) bool lwpa_signal_wait(lwpa_signal_t* id) { - return id ? (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, portMAX_DELAY)) : false; + return (id && *id) ? (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, portMAX_DELAY)) : false; } bool lwpa_signal_poll(lwpa_signal_t* id) { - return id ? (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, 0)) : false; + return (id && *id) ? (pdTRUE == xSemaphoreTake((SemaphoreHandle_t)*id, 0)) : false; } void lwpa_signal_post(lwpa_signal_t* id) { - if (id) + if (id && *id) xSemaphoreGive((SemaphoreHandle_t)*id); } @@ -156,7 +155,7 @@ bool lwpa_rwlock_writelock(lwpa_rwlock_t* id) // Wait until there are no readers, keeping the lock so that no new readers can get in. while (id->reader_count > 0) { - vTaskDelay(1); // Wait one tick at a time + vTaskDelay(1); // Wait one tick at a time } // Hold on to the lock until writeunlock() is called return true; diff --git a/src/os/lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c index 8d411d77d..3006ac6af 100644 --- a/src/os/lwip/lwpa/os_socket.c +++ b/src/os/lwip/lwpa/os_socket.c @@ -583,7 +583,7 @@ lwpa_error_t lwpa_getblocking(lwpa_socket_t id, bool* blocking) int val = fcntl(id, F_GETFL, 0); if (val >= 0) { - *blocking = (val & O_NONBLOCK) != 0; + *blocking = ((val & O_NONBLOCK) == 0); return kLwpaErrOk; } return errno_lwip_to_lwpa(errno); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f8d86794c..28aa6aeb5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,8 +16,8 @@ endif() if(WIN32) set(LWPA_TEST_COMPILE_OPTIONS /wd4210) -elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(LWPA_TEST_COMPILE_OPTIONS -Wno-format-security) +elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") + set(LWPA_TEST_COMPILE_OPTIONS -Wno-format-security -Wno-conversion) else() set(LWPA_TEST_COMPILE_OPTIONS "") endif() @@ -28,8 +28,41 @@ if(LWPA_TEST_IPV6) endif() if(APPLE) + # Darwin has a low default setting for the maximum number of socket descriptors a process can + # have open. list(APPEND LWPA_TEST_COMPILE_DEFINITIONS LWPA_BULK_POLL_TEST_NUM_SOCKETS=200) endif() -# add_subdirectory(unit) +# Add a "live" test, which links the entire lwpa library, unmodified +function(lwpa_add_live_test target_name) + if(LWPA_TEST_BUILD_AS_LIBRARIES) + add_library(${target_name} ${ARGN}) + install(TARGETS ${target_name} ARCHIVE DESTINATION lib) + else() + add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) + lwpa_add_to_ctest(${target_name}) + endif() + set_target_properties(${target_name} PROPERTIES FOLDER tests) + target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) + target_compile_definitions(${target_name} PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) + target_link_libraries(${target_name} PUBLIC lwpa ThrowTheSwitch::Unity meekrosoft::fff) +endfunction() + +# Add a "custom" test, which doesn't link the lwpa library - lwpa sources must then be selectively +# added to the target. +function(lwpa_add_custom_test target_name) + if(LWPA_TEST_BUILD_AS_LIBRARIES) + add_library(${target_name} ${ARGN}) + install(TARGETS ${target_name} ARCHIVE DESTINATION lib) + else() + add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) + lwpa_add_to_ctest(${target_name}) + endif() + set_target_properties(${target_name} PROPERTIES FOLDER tests) + target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) + target_compile_definitions(${target_name} PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) + target_link_libraries(${target_name} PUBLIC ThrowTheSwitch::Unity meekrosoft::fff) +endfunction() + +add_subdirectory(unit) add_subdirectory(integration) diff --git a/tests/integration/mutex_integration_test.c b/tests/integration/mutex_integration_test.c index 8e146f435..f520d5a4e 100644 --- a/tests/integration/mutex_integration_test.c +++ b/tests/integration/mutex_integration_test.c @@ -19,6 +19,7 @@ #include "lwpa/lock.h" #include "unity_fixture.h" +#include #include "lwpa/thread.h" // Constants diff --git a/tests/integration/rwlock_integration_test.c b/tests/integration/rwlock_integration_test.c index 853d05dc4..b05554f29 100644 --- a/tests/integration/rwlock_integration_test.c +++ b/tests/integration/rwlock_integration_test.c @@ -19,6 +19,7 @@ #include "lwpa/lock.h" #include "unity_fixture.h" +#include #include "lwpa/thread.h" #define NUM_WRITE_THREADS 10 diff --git a/tests/integration/signal_integration_test.c b/tests/integration/signal_integration_test.c index be987e09b..c87e10421 100644 --- a/tests/integration/signal_integration_test.c +++ b/tests/integration/signal_integration_test.c @@ -19,6 +19,7 @@ #include "lwpa/lock.h" #include "unity_fixture.h" +#include #include "lwpa/thread.h" // For general usage diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 7dfee65ef..5ce12df6c 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -5,47 +5,29 @@ # *is* the abstraction, so it must be done in a live-dependency environment and run on each target # platform. -# Add a "live" test, which links the entire lwpa library, unmodified -function(lwpa_add_live_test target_name) - add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) - set_target_properties(${target_name} PROPERTIES FOLDER tests) - target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) - target_compile_definitions(${target_name} PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) - target_link_libraries(${target_name} PRIVATE lwpa ThrowTheSwitch::Unity meekrosoft::fff) - lwpa_add_to_ctest(${target_name}) -endfunction() - -# Add a "custom" test, which doesn't link the lwpa library - lwpa sources must then be selectively -# added to the target. -function(lwpa_add_custom_test target_name) - add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) - set_target_properties(${target_name} PROPERTIES FOLDER tests) - target_compile_options(${target_name} PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) - target_compile_definitions(${target_name} PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) - target_link_libraries(${target_name} PRIVATE ThrowTheSwitch::Unity meekrosoft::fff) - lwpa_add_to_ctest(${target_name}) -endfunction() +add_subdirectory(live) +# add_subdirectory(timer) # Each test builds a different executable. CTest then combines them all and runs them as one # session. This is the way the Unity test framework nudges you to do things, and it's valuable for # separating symbols when testing C code. -lwpa_add_live_test(test_common test_common.c) -lwpa_add_live_test(test_inet test_inet.c) -lwpa_add_live_test(test_lock test_lock.c) -lwpa_add_live_test(test_log test_log.c) -lwpa_add_live_test(test_mempool test_mempool.c) -lwpa_add_live_test(test_netint test_netint.c) -lwpa_add_live_test(test_pack test_pack.c) -lwpa_add_live_test(test_rbtree test_rbtree.c) -lwpa_add_live_test(test_socket test_socket.c) -lwpa_add_live_test(test_thread test_thread.c) -lwpa_add_live_test(test_timer test_timer.c) -lwpa_add_live_test(test_uuid test_uuid.c) +#lwpa_add_live_test(test_common test_common.c) +#lwpa_add_live_test(test_inet test_inet.c) +#lwpa_add_live_test(test_lock test_lock.c) +#lwpa_add_live_test(test_log test_log.c) +#lwpa_add_live_test(test_mempool test_mempool.c) +#lwpa_add_live_test(test_netint test_netint.c) +#lwpa_add_live_test(test_pack test_pack.c) +#lwpa_add_live_test(test_rbtree test_rbtree.c) +#lwpa_add_live_test(test_socket test_socket.c) +#lwpa_add_live_test(test_thread test_thread.c) +#lwpa_add_live_test(test_timer test_timer.c) +#lwpa_add_live_test(test_uuid test_uuid.c) -lwpa_add_custom_test(test_timer_wraparound - test_timer_wraparound.c - ${LWPA_SRC}/lwpa/timer.c -) -target_include_directories(test_timer_wraparound PRIVATE ${LWPA_INCLUDE}) +# lwpa_add_custom_test(test_timer_wraparound +# test_timer_wraparound.c +# ${LWPA_SRC}/lwpa/timer.c +# ) +# target_include_directories(test_timer_wraparound PRIVATE ${LWPA_INCLUDE}) diff --git a/tests/unit/live/CMakeLists.txt b/tests/unit/live/CMakeLists.txt new file mode 100644 index 000000000..8af1e772c --- /dev/null +++ b/tests/unit/live/CMakeLists.txt @@ -0,0 +1,17 @@ +# The "live" lwpa tests, all built as one executable or library for now. + +lwpa_add_live_test(lwpa_live_unit_tests + test_common.c + test_inet.c + test_lock.c + test_log.c + test_main.c + test_mempool.c + test_netint.c + test_pack.c + test_rbtree.c + test_socket.c + test_thread.c + test_timer.c + test_uuid.c +) diff --git a/tests/unit/test_common.c b/tests/unit/live/test_common.c similarity index 92% rename from tests/unit/test_common.c rename to tests/unit/live/test_common.c index 3b488efae..20888149c 100644 --- a/tests/unit/test_common.c +++ b/tests/unit/live/test_common.c @@ -23,8 +23,6 @@ #include "lwpa/netint.h" #include "lwpa/log.h" -DEFINE_FFF_GLOBALS; - TEST_GROUP(lwpa_common); TEST_SETUP(lwpa_common) @@ -67,7 +65,7 @@ TEST(lwpa_common, netint_double_init_works) } // A shim from the lwpa_log module to fff. -FAKE_VOID_FUNC(log_callback, void*, const LwpaLogStrings*); +FAKE_VOID_FUNC(common_test_log_callback, void*, const LwpaLogStrings*); // Test multiple calls of lwpa_init() for the log module. TEST(lwpa_common, log_double_init_works) @@ -77,7 +75,7 @@ TEST(lwpa_common, log_double_init_works) LwpaLogParams params; params.action = kLwpaLogCreateHumanReadableLog; - params.log_fn = log_callback; + params.log_fn = common_test_log_callback; params.log_mask = LWPA_LOG_UPTO(LWPA_LOG_DEBUG); params.time_fn = NULL; params.context = NULL; @@ -85,14 +83,14 @@ TEST(lwpa_common, log_double_init_works) TEST_ASSERT_TRUE(lwpa_validate_log_params(¶ms)); lwpa_log(¶ms, LWPA_LOG_INFO, "Log message"); - TEST_ASSERT_EQUAL(log_callback_fake.call_count, 1); + TEST_ASSERT_EQUAL(common_test_log_callback_fake.call_count, 1); lwpa_deinit(LWPA_FEATURE_LOGGING); // After 2 inits and one deinit, we should still be able to use the lwpa_log() function and get // callbacks. lwpa_log(¶ms, LWPA_LOG_INFO, "Log message"); - TEST_ASSERT_EQUAL(log_callback_fake.call_count, 2); + TEST_ASSERT_EQUAL(common_test_log_callback_fake.call_count, 2); lwpa_deinit(LWPA_FEATURE_LOGGING); } @@ -103,8 +101,3 @@ TEST_GROUP_RUNNER(lwpa_common) RUN_TEST_CASE(lwpa_common, netint_double_init_works); RUN_TEST_CASE(lwpa_common, log_double_init_works); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_common); -} diff --git a/tests/unit/test_inet.c b/tests/unit/live/test_inet.c similarity index 99% rename from tests/unit/test_inet.c rename to tests/unit/live/test_inet.c index 1ecc4969c..5a9b640f2 100644 --- a/tests/unit/test_inet.c +++ b/tests/unit/live/test_inet.c @@ -370,8 +370,3 @@ TEST_GROUP_RUNNER(lwpa_inet) RUN_TEST_CASE(lwpa_inet, ip_mask_from_length_works); RUN_TEST_CASE(lwpa_inet, inet_string_functions_work); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_inet); -} diff --git a/tests/unit/test_lock.c b/tests/unit/live/test_lock.c similarity index 98% rename from tests/unit/test_lock.c rename to tests/unit/live/test_lock.c index 9ed01c686..97ca1307c 100644 --- a/tests/unit/test_lock.c +++ b/tests/unit/live/test_lock.c @@ -110,8 +110,3 @@ TEST_GROUP_RUNNER(lwpa_lock) RUN_TEST_CASE(lwpa_lock, rwlock_create_and_destroy_works); RUN_TEST_CASE(lwpa_lock, signal_create_and_destroy_works); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_lock); -} diff --git a/tests/unit/test_log.c b/tests/unit/live/test_log.c similarity index 97% rename from tests/unit/test_log.c rename to tests/unit/live/test_log.c index 8b0c6a23d..ba757eb67 100644 --- a/tests/unit/test_log.c +++ b/tests/unit/live/test_log.c @@ -31,14 +31,16 @@ #pragma warning(disable : 4996) #endif -DEFINE_FFF_GLOBALS; - FAKE_VOID_FUNC(log_callback, void*, const LwpaLogStrings*); FAKE_VOID_FUNC(time_callback, void*, LwpaLogTimeParams*); LwpaLogTimeParams cur_time; LwpaLogStrings last_log_strings_received; +// Buffers for tests of the create_*_str functions +static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; +static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; + static void fill_time_params(void* context, LwpaLogTimeParams* time_params) { (void)context; @@ -223,7 +225,6 @@ TEST(lwpa_log, context_pointer_is_passed_unmodified) TEST(lwpa_log, syslog_header_is_well_formed) { LwpaLogParams lparams; - static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; // A string with a non-ASCII character: "host\xC8name" // Should be sanitized to "host?name" @@ -293,7 +294,6 @@ TEST(lwpa_log, syslog_header_is_well_formed) TEST(lwpa_log, syslog_prival_is_correct) { - static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; LwpaSyslogParams syslog_params; memset(&syslog_params, 0, sizeof(LwpaSyslogParams)); @@ -380,8 +380,6 @@ TEST(lwpa_log, log_mask_is_honored) TEST(lwpa_log, time_header_is_well_formed) { LwpaSyslogParams syslog_params; - static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; memset(&syslog_params, 0, sizeof syslog_params); TEST_ASSERT(lwpa_create_syslog_str(syslog_buf, LWPA_SYSLOG_STR_MAX_LEN, &cur_time, &syslog_params, LWPA_LOG_EMERG, @@ -416,8 +414,6 @@ TEST(lwpa_log, time_header_is_well_formed) TEST(lwpa_log, formatting_int_values_works) { LwpaLogParams lparams; - static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; - static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; lparams.action = kLwpaLogCreateBoth; lparams.log_fn = log_callback; @@ -457,8 +453,6 @@ TEST(lwpa_log, formatting_int_values_works) TEST(lwpa_log, formatting_string_values_works) { LwpaLogParams lparams; - static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; lparams.action = kLwpaLogCreateBoth; lparams.log_fn = log_callback; @@ -511,8 +505,6 @@ static unsigned char get_sanitized_char(size_t i) TEST(lwpa_log, logging_maximum_length_string_works) { LwpaLogParams lparams; - static char syslog_buf[LWPA_SYSLOG_STR_MAX_LEN]; - static char human_buf[LWPA_HUMAN_LOG_STR_MAX_LEN]; lparams.action = kLwpaLogCreateBoth; lparams.log_fn = log_callback; @@ -623,8 +615,3 @@ TEST_GROUP_RUNNER(lwpa_log) RUN_TEST_CASE(lwpa_log, formatting_string_values_works); RUN_TEST_CASE(lwpa_log, logging_maximum_length_string_works); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_log); -} diff --git a/tests/unit/live/test_main.c b/tests/unit/live/test_main.c new file mode 100644 index 000000000..9d37517e9 --- /dev/null +++ b/tests/unit/live/test_main.c @@ -0,0 +1,38 @@ +/****************************************************************************** + * Copyright 2019 ETC Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* + * This file is a part of lwpa. For more information, go to: + * https://github.com/ETCLabs/lwpa + ******************************************************************************/ +#include "unity_fixture.h" +#include "fff.h" + +DEFINE_FFF_GLOBALS; + +void run_all_tests(void) +{ + RUN_TEST_GROUP(lwpa_common); + RUN_TEST_GROUP(lwpa_inet); + RUN_TEST_GROUP(lwpa_lock); + RUN_TEST_GROUP(lwpa_log); + RUN_TEST_GROUP(lwpa_mempool); + RUN_TEST_GROUP(lwpa_netint); + RUN_TEST_GROUP(lwpa_pack); + RUN_TEST_GROUP(lwpa_rbtree); + RUN_TEST_GROUP(lwpa_socket); + RUN_TEST_GROUP(lwpa_thread); + RUN_TEST_GROUP(lwpa_timer); + RUN_TEST_GROUP(lwpa_uuid); +} diff --git a/tests/unit/test_mempool.c b/tests/unit/live/test_mempool.c similarity index 96% rename from tests/unit/test_mempool.c rename to tests/unit/live/test_mempool.c index d3cae357a..e2973c58e 100644 --- a/tests/unit/test_mempool.c +++ b/tests/unit/live/test_mempool.c @@ -24,7 +24,7 @@ #include #define ALLOC_TEST_MEMP_SIZE 500 -#define ALLOC_TEST_MEMP_ARR_SIZE 30 +#define ALLOC_TEST_MEMP_ARR_SIZE 5 typedef struct TestElem { @@ -46,7 +46,7 @@ static void create_shuffled_index_array(size_t* array, size_t size) for (size_t i = 0; i < size - 1; ++i) { // srand() is taken care of at the entry point. - size_t j = i + rand() / (RAND_MAX / (size - i) + 1); + size_t j = (size_t)(i + rand()) / (size_t)(RAND_MAX / (size - i) + 1); size_t swap_val = array[j]; array[j] = array[i]; array[i] = swap_val; @@ -150,8 +150,3 @@ TEST_GROUP_RUNNER(lwpa_mempool) RUN_TEST_CASE(lwpa_mempool, alloc_and_free_works); RUN_TEST_CASE(lwpa_mempool, alloc_and_free_array_works); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_mempool); -} diff --git a/tests/unit/test_netint.c b/tests/unit/live/test_netint.c similarity index 98% rename from tests/unit/test_netint.c rename to tests/unit/live/test_netint.c index 9c34b8a56..44db6f623 100644 --- a/tests/unit/test_netint.c +++ b/tests/unit/live/test_netint.c @@ -35,7 +35,7 @@ TEST_SETUP(lwpa_netint) TEST_TEAR_DOWN(lwpa_netint) { - lwpa_deinit(LWPA_FEATURE_NETINTS); + lwpa_deinit(LWPA_FEATURE_NETINTS); } TEST(lwpa_netint, netint_enumeration_works) @@ -151,8 +151,3 @@ TEST_GROUP_RUNNER(lwpa_netint) RUN_TEST_CASE(lwpa_netint, default_netint_is_consistent); RUN_TEST_CASE(lwpa_netint, get_interface_for_dest_works_ipv4); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_netint); -} diff --git a/tests/unit/test_pack.c b/tests/unit/live/test_pack.c similarity index 99% rename from tests/unit/test_pack.c rename to tests/unit/live/test_pack.c index b6fe16c5c..3cc5b9dc6 100644 --- a/tests/unit/test_pack.c +++ b/tests/unit/live/test_pack.c @@ -17,6 +17,7 @@ * https://github.com/ETCLabs/lwpa ******************************************************************************/ #include "lwpa/pack.h" +#include "lwpa/pack64.h" #include "unity_fixture.h" #include @@ -242,8 +243,3 @@ TEST_GROUP_RUNNER(lwpa_pack) RUN_TEST_CASE(lwpa_pack, pack_32_functions_work); RUN_TEST_CASE(lwpa_pack, pack_64_functions_work); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_pack); -} \ No newline at end of file diff --git a/tests/unit/test_rbtree.c b/tests/unit/live/test_rbtree.c similarity index 99% rename from tests/unit/test_rbtree.c rename to tests/unit/live/test_rbtree.c index d0e85591d..9eab9d10c 100644 --- a/tests/unit/test_rbtree.c +++ b/tests/unit/live/test_rbtree.c @@ -20,16 +20,15 @@ #include "unity_fixture.h" #include "fff.h" -#include #include +#include +#include // Disable sprintf() warning on Windows/MSVC #ifdef _MSC_VER #pragma warning(disable : 4996) #endif -DEFINE_FFF_GLOBALS; - #define INT_ARRAY_SIZE 100 #define RANDOM_INT_IN_ARRAY() (int)(rand() / ((RAND_MAX + 1.0) / INT_ARRAY_SIZE)) @@ -280,8 +279,3 @@ TEST_GROUP_RUNNER(lwpa_rbtree) RUN_TEST_CASE(lwpa_rbtree, iterators_work_as_expected); RUN_TEST_CASE(lwpa_rbtree, max_height_is_within_bounds); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_rbtree); -} diff --git a/tests/unit/test_socket.c b/tests/unit/live/test_socket.c similarity index 97% rename from tests/unit/test_socket.c rename to tests/unit/live/test_socket.c index 79c29ac13..ae5a4a95a 100644 --- a/tests/unit/test_socket.c +++ b/tests/unit/live/test_socket.c @@ -76,7 +76,17 @@ TEST(lwpa_socket, blocking_state_is_consistent) // Set the socket to non-blocking, make sure it reads as non-blocking TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setblocking(sock, false)); bool is_blocking; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_getblocking(sock, &is_blocking)); + lwpa_error_t gb_result = lwpa_getblocking(sock, &is_blocking); + + // Special case - this function isn't implemented on all platforms, so we abort this test + // prematurely if that's the case. + if (gb_result == kLwpaErrNotImpl) + { + lwpa_close(sock); + TEST_PASS_MESSAGE("lwpa_getblocking() not implemented on this platform. Skipping the remainder of the test."); + } + + TEST_ASSERT_EQUAL(kLwpaErrOk, gb_result); TEST_ASSERT_FALSE(is_blocking); // Set the socket back to blocking, make sure it reads as blocking @@ -368,8 +378,3 @@ TEST_GROUP_RUNNER(lwpa_socket) RUN_TEST_CASE(lwpa_socket, poll_for_writability_on_udp_sockets_works); RUN_TEST_CASE(lwpa_socket, getaddrinfo_works_as_expected); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_socket); -} diff --git a/tests/unit/test_thread.c b/tests/unit/live/test_thread.c similarity index 98% rename from tests/unit/test_thread.c rename to tests/unit/live/test_thread.c index 6747804f5..8e6086fe7 100644 --- a/tests/unit/test_thread.c +++ b/tests/unit/live/test_thread.c @@ -117,8 +117,3 @@ TEST_GROUP_RUNNER(lwpa_thread) RUN_TEST_CASE(lwpa_thread, create_and_destroy_functions_work); RUN_TEST_CASE(lwpa_thread, threads_are_time_sliced); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_thread); -} \ No newline at end of file diff --git a/tests/unit/test_timer.c b/tests/unit/live/test_timer.c similarity index 97% rename from tests/unit/test_timer.c rename to tests/unit/live/test_timer.c index c806f7274..b4028851b 100644 --- a/tests/unit/test_timer.c +++ b/tests/unit/live/test_timer.c @@ -81,8 +81,3 @@ TEST_GROUP_RUNNER(lwpa_timer) RUN_TEST_CASE(lwpa_timer, getms_gets_increasing_values); RUN_TEST_CASE(lwpa_timer, timers_report_expired_properly); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_timer); -} diff --git a/tests/unit/test_uuid.c b/tests/unit/live/test_uuid.c similarity index 88% rename from tests/unit/test_uuid.c rename to tests/unit/live/test_uuid.c index 01fab3275..7b6352d9d 100644 --- a/tests/unit/test_uuid.c +++ b/tests/unit/live/test_uuid.c @@ -20,6 +20,7 @@ #include "unity_fixture.h" #include +#include // Disable sprintf() warning on Windows/MSVC #ifdef _MSC_VER @@ -103,7 +104,17 @@ TEST(lwpa_uuid, generates_correct_v1_uuids) char error_msg[100]; sprintf(error_msg, "This failure occurred on UUID attempt %d of %d", i + 1, NUM_V1_UUID_GENERATIONS); - TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_generate_v1_uuid(&uuid), error_msg); + lwpa_error_t generate_result = lwpa_generate_v1_uuid(&uuid); + + // Special case - this function isn't implemented on all platforms, so we abort this test + // prematurely if that's the case. + if (generate_result == kLwpaErrNotImpl) + { + TEST_PASS_MESSAGE( + "lwpa_generate_v1_uuid() not implemented on this platform. Skipping the remainder of the test."); + } + + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, generate_result, error_msg); // We should always have Variant 1, Version 1. TEST_ASSERT_EQUAL_UINT8_MESSAGE((uuid.data[6] & 0xf0u), 0x10u, error_msg); @@ -165,7 +176,17 @@ TEST(lwpa_uuid, generates_correct_v4_uuids) char error_msg[100]; sprintf(error_msg, "This failure occurred on UUID attempt %d of %d", i + 1, NUM_V4_UUID_GENERATIONS); - TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_generate_v4_uuid(&uuid), error_msg); + lwpa_error_t generate_result = lwpa_generate_v4_uuid(&uuid); + + // Special case - this function isn't implemented on all platforms, so we abort this test + // prematurely if that's the case. + if (generate_result == kLwpaErrNotImpl) + { + TEST_PASS_MESSAGE( + "lwpa_generate_v4_uuid() not implemented on this platform. Skipping the remainder of the test."); + } + + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, generate_result, error_msg); // We should always have Variant 1, Version 4. TEST_ASSERT_EQUAL_MESSAGE((uuid.data[6] & 0xf0u), 0x40u, error_msg); @@ -188,8 +209,3 @@ TEST_GROUP_RUNNER(lwpa_uuid) RUN_TEST_CASE(lwpa_uuid, generates_correct_v3_uuids); RUN_TEST_CASE(lwpa_uuid, generates_correct_v4_uuids); } - -void run_all_tests(void) -{ - RUN_TEST_GROUP(lwpa_uuid); -} diff --git a/tests/unit/test_timer_wraparound.c b/tests/unit/timer/test_timer_wraparound.c similarity index 100% rename from tests/unit/test_timer_wraparound.c rename to tests/unit/timer/test_timer_wraparound.c From 4ef6892ac24fb7f160201d3416371382b5a5339b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Fri, 30 Aug 2019 20:14:34 -0500 Subject: [PATCH 122/264] Make unit tests work again on Windows --- src/os/windows/lwpa/os_socket.c | 5 +- tests/CMakeLists.txt | 5 +- tests/{unit => }/entrypoint/main_default.c | 0 tests/integration/CMakeLists.txt | 20 +---- tests/integration/entrypoint/main_default.c | 27 ------ tests/integration/mutex_integration_test.c | 5 ++ tests/integration/rwlock_integration_test.c | 5 ++ tests/integration/signal_integration_test.c | 5 ++ tests/unit/CMakeLists.txt | 33 +------ .../entrypoint/main_freertos_lwip_kinetis.c | 90 ------------------- tests/unit/timer/CMakeLists.txt | 7 ++ 11 files changed, 30 insertions(+), 172 deletions(-) rename tests/{unit => }/entrypoint/main_default.c (100%) delete mode 100644 tests/integration/entrypoint/main_default.c delete mode 100644 tests/unit/entrypoint/main_freertos_lwip_kinetis.c create mode 100644 tests/unit/timer/CMakeLists.txt diff --git a/src/os/windows/lwpa/os_socket.c b/src/os/windows/lwpa/os_socket.c index fbc5876ee..1703bd4ae 100644 --- a/src/os/windows/lwpa/os_socket.c +++ b/src/os/windows/lwpa/os_socket.c @@ -640,8 +640,9 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) lwpa_error_t lwpa_getblocking(lwpa_socket_t id, bool* blocking) { - *blocking = false; - return kLwpaErrOk; + (void)id; + (void)blocking; + return kLwpaErrNotImpl; } lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 28aa6aeb5..b20271edc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,7 @@ set(LWPA_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include) set(LWPA_SRC ${CMAKE_CURRENT_LIST_DIR}/../src) +set(LWPA_TEST ${CMAKE_CURRENT_LIST_DIR}) option(LWPA_TEST_IPV6 "Test IPv6 socket functions in the lwpa unit and integration tests" ON) option(LWPA_TEST_BUILD_AS_LIBRARIES "Build the lwpa unit and integration tests as libraries rather than executables" OFF) @@ -39,7 +40,7 @@ function(lwpa_add_live_test target_name) add_library(${target_name} ${ARGN}) install(TARGETS ${target_name} ARCHIVE DESTINATION lib) else() - add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) + add_executable(${target_name} ${ARGN} ${LWPA_TEST}/entrypoint/${LWPA_TEST_ENTRYPOINT}) lwpa_add_to_ctest(${target_name}) endif() set_target_properties(${target_name} PROPERTIES FOLDER tests) @@ -55,7 +56,7 @@ function(lwpa_add_custom_test target_name) add_library(${target_name} ${ARGN}) install(TARGETS ${target_name} ARCHIVE DESTINATION lib) else() - add_executable(${target_name} ${ARGN} ${CMAKE_CURRENT_LIST_DIR}/entrypoint/${LWPA_TEST_ENTRYPOINT}) + add_executable(${target_name} ${ARGN} ${LWPA_TEST}/entrypoint/${LWPA_TEST_ENTRYPOINT}) lwpa_add_to_ctest(${target_name}) endif() set_target_properties(${target_name} PROPERTIES FOLDER tests) diff --git a/tests/unit/entrypoint/main_default.c b/tests/entrypoint/main_default.c similarity index 100% rename from tests/unit/entrypoint/main_default.c rename to tests/entrypoint/main_default.c diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index 1210bd05f..211925f82 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -2,7 +2,7 @@ # These are "live" tests which use multiple parts of the lwpa library. Most of what is tested here # are the locking, threading and synchronization functions. -set(LWPA_INTEGRATION_TEST_SOURCES +lwpa_add_live_test(lwpa_integration_tests mutex_integration_test.c rwlock_integration_test.c signal_integration_test.c @@ -10,24 +10,6 @@ set(LWPA_INTEGRATION_TEST_SOURCES test_main.c ) -if(LWPA_TEST_BUILD_AS_LIBRARIES) - add_library(lwpa_integration_tests - ${LWPA_INTEGRATION_TEST_SOURCES} - ) - install(TARGETS lwpa_integration_tests ARCHIVE DESTINATION lib) -else() - add_executable(lwpa_integration_tests - ${LWPA_INTEGRATION_TEST_SOURCES} - entrypoint/${LWPA_TEST_ENTRYPOINT} - ) - lwpa_add_to_ctest(lwpa_integration_tests) -endif() - -set_target_properties(lwpa_integration_tests PROPERTIES FOLDER tests) -target_compile_options(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_OPTIONS}) -target_compile_definitions(lwpa_integration_tests PRIVATE ${LWPA_TEST_COMPILE_DEFINITIONS}) -target_link_libraries(lwpa_integration_tests PUBLIC lwpa ThrowTheSwitch::Unity) - # The macOS hosted agents have some unknown restriction on multicast traffic which causes the # multicast tests to fail. if(APPLE AND LWPA_BUILDING_FOR_AZURE_PIPELINES_CI) diff --git a/tests/integration/entrypoint/main_default.c b/tests/integration/entrypoint/main_default.c deleted file mode 100644 index 20f73bc63..000000000 --- a/tests/integration/entrypoint/main_default.c +++ /dev/null @@ -1,27 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ - -#include "unity_fixture.h" - -extern void run_all_tests(void); - -int main(int argc, char* argv[]) -{ - return UnityMain(argc, (const char**)argv, run_all_tests); -} diff --git a/tests/integration/mutex_integration_test.c b/tests/integration/mutex_integration_test.c index f520d5a4e..7776ea33f 100644 --- a/tests/integration/mutex_integration_test.c +++ b/tests/integration/mutex_integration_test.c @@ -22,6 +22,11 @@ #include #include "lwpa/thread.h" +// Disable sprintf() warning on Windows/MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + // Constants #define NUM_THREADS 10 #define NUM_ITERATIONS 10000 diff --git a/tests/integration/rwlock_integration_test.c b/tests/integration/rwlock_integration_test.c index b05554f29..dd885d929 100644 --- a/tests/integration/rwlock_integration_test.c +++ b/tests/integration/rwlock_integration_test.c @@ -22,6 +22,11 @@ #include #include "lwpa/thread.h" +// Disable sprintf() warning on Windows/MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + #define NUM_WRITE_THREADS 10 #define NUM_ITERATIONS 10000 diff --git a/tests/integration/signal_integration_test.c b/tests/integration/signal_integration_test.c index c87e10421..84a3a2f08 100644 --- a/tests/integration/signal_integration_test.c +++ b/tests/integration/signal_integration_test.c @@ -22,6 +22,11 @@ #include #include "lwpa/thread.h" +// Disable sprintf() warning on Windows/MSVC +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + // For general usage static lwpa_signal_t sig; diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 5ce12df6c..8ba17f138 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,33 +1,2 @@ -# lwpa unit tests. -# Most of these are "live" tests which use system calls of the underlying OS to ensure consistent -# behavior across platforms. This is intentionally contrary to normal unit testing philosophy, -# which emphasizes abstraction and separation of dependencies; in this case, what we are testing -# *is* the abstraction, so it must be done in a live-dependency environment and run on each target -# platform. - add_subdirectory(live) -# add_subdirectory(timer) - -# Each test builds a different executable. CTest then combines them all and runs them as one -# session. This is the way the Unity test framework nudges you to do things, and it's valuable for -# separating symbols when testing C code. - -#lwpa_add_live_test(test_common test_common.c) -#lwpa_add_live_test(test_inet test_inet.c) -#lwpa_add_live_test(test_lock test_lock.c) -#lwpa_add_live_test(test_log test_log.c) -#lwpa_add_live_test(test_mempool test_mempool.c) -#lwpa_add_live_test(test_netint test_netint.c) -#lwpa_add_live_test(test_pack test_pack.c) -#lwpa_add_live_test(test_rbtree test_rbtree.c) -#lwpa_add_live_test(test_socket test_socket.c) -#lwpa_add_live_test(test_thread test_thread.c) -#lwpa_add_live_test(test_timer test_timer.c) -#lwpa_add_live_test(test_uuid test_uuid.c) - -# lwpa_add_custom_test(test_timer_wraparound -# test_timer_wraparound.c -# ${LWPA_SRC}/lwpa/timer.c -# ) -# target_include_directories(test_timer_wraparound PRIVATE ${LWPA_INCLUDE}) - +add_subdirectory(timer) diff --git a/tests/unit/entrypoint/main_freertos_lwip_kinetis.c b/tests/unit/entrypoint/main_freertos_lwip_kinetis.c deleted file mode 100644 index 0751eeb15..000000000 --- a/tests/unit/entrypoint/main_freertos_lwip_kinetis.c +++ /dev/null @@ -1,90 +0,0 @@ -/****************************************************************************** - * Copyright 2019 ETC Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************* - * This file is a part of lwpa. For more information, go to: - * https://github.com/ETCLabs/lwpa - ******************************************************************************/ -#include -#include - -#include -#include "ethernetif.h" -#include "lwip/tcpip.h" - -#include "fsl_debug_console.h" -#include "board.h" -#include "fsl_phy.h" -#include "pin_mux.h" -#include "clock_config.h" - -#include "unity_fixture.h" - -extern void run_all_tests(void); - -void main_task(void* pvParameters) -{ - const char* fake_argv[] = {"freertos_test_runner", "-v"}; - - UnityMain(2, fake_argv, run_all_tests); -} - -void main(void) -{ - ip4_addr_t fsl_netif0_ipaddr, fsl_netif0_netmask, fsl_netif0_gw; - SYSMPU_Type* base = SYSMPU; - ethernetif_config_t enet_config0; - - /* Init board hardware. */ - BOARD_InitPins(); - BOARD_BootClockRUN(); - BOARD_InitDebugConsole(); - - /* Disable MPU. */ - base->CESR &= ~SYSMPU_CESR_VLD_MASK; - - PRINTF("TCP/IP initializing...\n"); - tcpip_init(NULL, NULL); - PRINTF("TCP/IP initialized.\n"); - - IP4_ADDR(&fsl_netif0_ipaddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3); - IP4_ADDR(&fsl_netif0_netmask, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3); - IP4_ADDR(&fsl_netif0_gw, configGW_ADDR0, configGW_ADDR1, configGW_ADDR2, configGW_ADDR3); - - enet_config0.phyAddress = ENET_PHY_ADDRESS; - enet_config0.clockName = kCLOCK_CoreSysClk; - memcpy(enet_config0.macAddress, g_EnetMacAddr, sizeof g_EnetMacAddr); - - netif_add(&fsl_netif0, &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, &enet_config0, ethernetif0_init, - tcpip_input); - netif_set_default(&fsl_netif0); - netif_set_up(&fsl_netif0); - - phy_speed_t speed; - phy_duplex_t duplex; - if (kStatus_Success == PHY_GetLinkSpeedDuplex(ENET, ENET_PHY_ADDRESS, &speed, &duplex)) - { - PRINTF("Ethernet link: %s %s\n", speed == kPHY_Speed10M ? "10M" : "100M", - duplex == kPHY_HalfDuplex ? "half duplex" : "full duplex"); - } - - /* Create RTOS tasks */ - xTaskCreate(main_task, "test", 2000, NULL, 4, NULL); - vTaskStartScheduler(); - - for (;;) - { /* Infinite loop to avoid leaving the main function */ - __asm("NOP"); /* something to use as a breakpoint stop while looping */ - } -} diff --git a/tests/unit/timer/CMakeLists.txt b/tests/unit/timer/CMakeLists.txt new file mode 100644 index 000000000..3940e1543 --- /dev/null +++ b/tests/unit/timer/CMakeLists.txt @@ -0,0 +1,7 @@ +# A custom test to make sure that the lwpa_timer module handles wraparound cases correctly. + +lwpa_add_custom_test(test_timer_wraparound + test_timer_wraparound.c + ${LWPA_SRC}/lwpa/timer.c +) +target_include_directories(test_timer_wraparound PRIVATE ${LWPA_INCLUDE}) \ No newline at end of file From 742771daa9b34a5f466a7b55d305737eb997ba0c Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Tue, 3 Sep 2019 17:29:06 -0500 Subject: [PATCH 123/264] Slight refactor of netint API to fix an issue with netint indexes. --- examples/netint/netint_example.c | 24 +++-- include/lwpa/inet.h | 7 +- include/lwpa/netint.h | 6 +- src/lwpa/netint.c | 109 +++++++++++--------- src/lwpa/private/netint.h | 7 +- src/os/linux/lwpa/os_netint.c | 17 ++- src/os/lwip/lwpa/os_netint.c | 77 +++++++++----- src/os/macos/lwpa/os_netint.c | 16 ++- src/os/mqx/lwpa/os_netint.c | 9 +- src/os/windows/lwpa/os_netint.c | 22 ++-- tests/integration/socket_integration_test.c | 42 +++++--- tests/unit/live/test_common.c | 2 +- tests/unit/live/test_netint.c | 88 ++++++++++++---- 13 files changed, 287 insertions(+), 139 deletions(-) diff --git a/examples/netint/netint_example.c b/examples/netint/netint_example.c index 5e253cebe..2db68bad2 100644 --- a/examples/netint/netint_example.c +++ b/examples/netint/netint_example.c @@ -102,6 +102,7 @@ int main() printf("Network interfaces found:\n"); printf(header_format, NAME_COL_HEADER, ADDR_COL_HEADER, NETMASK_COL_HEADER, MAC_COL_HEADER, INDEX_COL_HEADER); + for (const LwpaNetintInfo* netint = netint_arr; netint < netint_arr + num_interfaces; ++netint) { char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; @@ -115,19 +116,26 @@ int main() printf(line_format, netint->name, addr_str, netmask_str, mac_str, netint->index); } - LwpaNetintInfo default_v4; + unsigned int default_v4; if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV4, &default_v4)) { - char addr_str[LWPA_INET_ADDRSTRLEN] = {'\0'}; - lwpa_inet_ntop(&default_v4.addr, addr_str, LWPA_INET_ADDRSTRLEN); - printf("Default IPv4 interface: %s (%s)\n", addr_str, default_v4.name); + const LwpaNetintInfo* addr_arr; + size_t addr_arr_size; + if (kLwpaErrOk == lwpa_netint_get_interfaces_by_index(default_v4, &addr_arr, &addr_arr_size)) + { + printf("Default IPv4 interface: %s (%u)\n", addr_arr->friendly_name, default_v4); + } } - LwpaNetintInfo default_v6; + + unsigned int default_v6; if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV6, &default_v6)) { - char addr_str[LWPA_INET6_ADDRSTRLEN] = {'\0'}; - lwpa_inet_ntop(&default_v6.addr, addr_str, LWPA_INET6_ADDRSTRLEN); - printf("Default IPv6 interface: %s (%s)\n", addr_str, default_v6.name); + const LwpaNetintInfo* addr_arr; + size_t addr_arr_size; + if (kLwpaErrOk == lwpa_netint_get_interfaces_by_index(default_v4, &addr_arr, &addr_arr_size)) + { + printf("Default IPv6 interface: %s (%u)\n", addr_arr->friendly_name, default_v6); + } } lwpa_deinit(LWPA_FEATURE_NETINTS); diff --git a/include/lwpa/inet.h b/include/lwpa/inet.h index bef13b2fe..df1e8cdbd 100644 --- a/include/lwpa/inet.h +++ b/include/lwpa/inet.h @@ -160,10 +160,13 @@ typedef struct LwpaSockaddr #define LWPA_NETINTINFO_NAME_LEN 64 #define LWPA_NETINTINFO_FRIENDLY_NAME_LEN 64 -/*! A description of a network interface. */ +/*! A description of a single address assigned to a network interface. */ typedef struct LwpaNetintInfo { - /*! The OS-specific network interface number. Used for IPv6, multicast and IP-version-neutral + /*! The OS-specific network interface number. Since interfaces can have multiple IPv4 and IPv6 + * addresses assigned simultaneously, there can be a one-to-many relationship between physical + * network interfaces and LwpaNetintInfo descriptions on the same system, all of which will have + * the same value for this field. It is also used for IPv6, multicast and IP-version-neutral * APIs. See \ref interface_indexes for more information. */ unsigned int index; /*! The interface ip address. */ diff --git a/include/lwpa/netint.h b/include/lwpa/netint.h index a1a687805..465d5677e 100644 --- a/include/lwpa/netint.h +++ b/include/lwpa/netint.h @@ -42,9 +42,11 @@ extern "C" { size_t lwpa_netint_get_num_interfaces(); const LwpaNetintInfo* lwpa_netint_get_interfaces(); size_t lwpa_netint_copy_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr_size); +lwpa_error_t lwpa_netint_get_interfaces_by_index(unsigned int index, const LwpaNetintInfo** netint_arr, + size_t* netint_arr_size); -lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint); -lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint); +lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, unsigned int* netint_index); +lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, unsigned int* netint_index); #ifdef __cplusplus } diff --git a/src/lwpa/netint.c b/src/lwpa/netint.c index 116cdf0df..b7857c49f 100644 --- a/src/lwpa/netint.c +++ b/src/lwpa/netint.c @@ -26,7 +26,6 @@ static unsigned int init_count; static CachedNetintInfo netint_cache; -static DefaultNetint default_netint; /*********************** Private function prototypes *************************/ @@ -44,22 +43,6 @@ lwpa_error_t lwpa_netint_init() { // Sort the interfaces by OS index qsort(netint_cache.netints, netint_cache.num_netints, sizeof(LwpaNetintInfo), compare_netints); - - // Store the locations of the default netints for access by the API function - for (size_t i = 0; i < netint_cache.num_netints; ++i) - { - LwpaNetintInfo* netint = &netint_cache.netints[i]; - if (LWPA_IP_IS_V4(&netint->addr) && netint->is_default) - { - default_netint.v4_valid = true; - default_netint.v4_index = i; - } - else if (LWPA_IP_IS_V6(&netint->addr) && netint->is_default) - { - default_netint.v6_valid = true; - default_netint.v6_index = i; - } - } } } @@ -122,31 +105,80 @@ size_t lwpa_netint_copy_interfaces(LwpaNetintInfo* netint_arr, size_t netint_arr return addrs_copied; } +/*! \brief Get a set of network interface addresses that have the index specified. + * + * See \ref interface_indexes for more information. + * + * \param[in] index Index for which to get interfaces. + * \param[out] netint_arr Filled in on success with the array of matching interfaces. + * \param[out] netint_arr_size Filled in on success with the size of the matching interface array. + * \return #kLwpaErrOk: netint_arr and netint_arr_size were filled in. + * \return #kLwpaErrInvalid: Invalid argument provided. + * \return #kLwpaErrNotFound: No interfaces found for this index. + */ +lwpa_error_t lwpa_netint_get_interfaces_by_index(unsigned int index, const LwpaNetintInfo** netint_arr, + size_t* netint_arr_size) +{ + if (index == 0 || !netint_arr || !netint_arr_size) + return kLwpaErrInvalid; + + size_t arr_size = 0; + for (const LwpaNetintInfo* netint = netint_cache.netints; netint < netint_cache.netints + netint_cache.num_netints; + ++netint) + { + if (netint->index == index) + { + if (arr_size == 0) + { + // Found the beginning of the array slice. + *netint_arr = netint; + } + ++arr_size; + } + else if (netint->index > index) + { + // Done. + break; + } + // Else we haven't gotten there yet, continue + } + + if (arr_size != 0) + { + *netint_arr_size = arr_size; + return kLwpaErrOk; + } + else + { + return kLwpaErrNotFound; + } +} + /*! \brief Get information about the default network interface. * * For our purposes, the 'default' network interface is defined as the interface that is chosen - * for the default IP route. Note: If the network interfaces have already been enumerated with - * lwpa_netint_get_interfaces(), it is more efficient to inspect the is_default flag of each - * interface in that existing array. + * for the default IP route. The default interface is given as an OS network interface index - see + * \ref interface_indexes for more information. Note that since network interfaces can have + * multiple IP addresses assigned, this index may be shared by many entries returned by + * lwpa_netint_get_interfaces(). * * \param[in] type The IP protocol for which to get the default network interface, either * #kLwpaIpTypeV4 or #kLwpaIpTypeV6. A separate default interface is maintained for * each. - * \param[out] netint Pointer to network interface description struct to fill with the information - * about the default interface. + * \param[out] netint_index Pointer to value to fill with the index of the default interface. * \return #kLwpaErrOk: netint was filled in. * \return #kLwpaErrInvalid: Invalid argument provided. * \return #kLwpaErrNotFound: No default interface found for this type. */ -lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInfo* netint) +lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, unsigned int* netint_index) { - if (init_count && netint) + if (init_count && netint_index) { if (type == kLwpaIpTypeV4) { - if (default_netint.v4_valid) + if (netint_cache.def.v4_valid) { - *netint = netint_cache.netints[default_netint.v4_index]; + *netint_index = netint_cache.def.v4_index; return kLwpaErrOk; } else @@ -156,9 +188,9 @@ lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInf } else if (type == kLwpaIpTypeV6) { - if (default_netint.v6_valid) + if (netint_cache.def.v6_valid) { - *netint = netint_cache.netints[default_netint.v6_index]; + *netint_index = netint_cache.def.v6_index; return kLwpaErrOk; } else @@ -182,31 +214,16 @@ lwpa_error_t lwpa_netint_get_default_interface(lwpa_iptype_t type, LwpaNetintInf * \return #kLwpaErrNoNetints: No network interfaces found on system. * \return #kLwpaErrNotFound: No route was able to be resolved to the destination. */ -lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, LwpaNetintInfo* netint) +lwpa_error_t lwpa_netint_get_interface_for_dest(const LwpaIpAddr* dest, unsigned int* netint_index) { - if (!dest || !netint) + if (!dest || !netint_index) return kLwpaErrInvalid; if (!init_count) return kLwpaErrNotInit; if (netint_cache.num_netints == 0) return kLwpaErrNoNetints; - unsigned int index; - lwpa_error_t res = os_resolve_route(dest, &index); - if (res == kLwpaErrOk) - { - for (LwpaNetintInfo* netint_entry = netint_cache.netints; - netint_entry < netint_cache.netints + netint_cache.num_netints; ++netint_entry) - { - if (netint_entry->addr.type == dest->type && netint_entry->index == index) - { - *netint = *netint_entry; - return kLwpaErrOk; - } - } - return kLwpaErrNotFound; - } - return res; + return os_resolve_route(dest, &netint_cache, netint_index); } int compare_netints(const void* a, const void* b) diff --git a/src/lwpa/private/netint.h b/src/lwpa/private/netint.h index 7abd7685a..80d676a2d 100644 --- a/src/lwpa/private/netint.h +++ b/src/lwpa/private/netint.h @@ -26,16 +26,17 @@ typedef struct DefaultNetint { bool v4_valid; - size_t v4_index; + unsigned int v4_index; bool v6_valid; - size_t v6_index; + unsigned int v6_index; } DefaultNetint; typedef struct CachedNetintInfo { size_t num_netints; LwpaNetintInfo* netints; + DefaultNetint def; } CachedNetintInfo; lwpa_error_t lwpa_netint_init(); @@ -43,6 +44,6 @@ void lwpa_netint_deinit(); lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache); void os_free_interfaces(CachedNetintInfo* cache); -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index); +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, const CachedNetintInfo* cache, unsigned int* index); #endif /* _LWPA_PRIVATE_NETINT_H_ */ diff --git a/src/os/linux/lwpa/os_netint.c b/src/os/linux/lwpa/os_netint.c index 18ae6ffdf..8e6f558ef 100644 --- a/src/os/linux/lwpa/os_netint.c +++ b/src/os/linux/lwpa/os_netint.c @@ -122,6 +122,19 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) if (res != kLwpaErrOk) return res; + // Fill in the default index information + if (routing_table_v4.default_route) + { + cache->def.v4_valid = true; + cache->def.v4_index = routing_table_v4.default_route->interface_index; + } + if (routing_table_v6.default_route) + { + cache->def.v6_valid = true; + cache->def.v6_index = routing_table_v6.default_route->interface_index; + } + + // Create the OS resources necessary to enumerate the interfaces int ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); if (ioctl_sock == -1) return errno_os_to_lwpa(errno); @@ -229,8 +242,10 @@ void os_free_interfaces(CachedNetintInfo* cache) free_routing_tables(); } -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, const CachedNetintInfo* cache, unsigned int* index) { + (void)cache; // unused + RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &routing_table_v6 : &routing_table_v4); unsigned int index_found = 0; diff --git a/src/os/lwip/lwpa/os_netint.c b/src/os/lwip/lwpa/os_netint.c index 7690e7554..93f0ace6b 100644 --- a/src/os/lwip/lwpa/os_netint.c +++ b/src/os/lwip/lwpa/os_netint.c @@ -62,33 +62,31 @@ static void copy_interface_info_v4(const struct netif* lwip_netif, LwpaNetintInf netint->is_default = false; } -static void copy_interface_info_v6(const struct netif* lwip_netif, size_t v6_addr_index, LwpaNetintInfo* netint) +static bool copy_interface_info_v6(const struct netif* lwip_netif, size_t v6_addr_index, LwpaNetintInfo* netint) { copy_common_interface_info(lwip_netif, netint); /* Finish filling in a netintinfo for a single IPv6 address. */ - /* NOTE: We are not currently supporting IPv6 in any lwIP products, and this implementation will - * probably need to be revisited before we do, especially the default interface code. */ - for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) + if (ip6_addr_isvalid(lwip_netif->ip6_addr_state[v6_addr_index])) { - if (ip6_addr_isvalid(lwip_netif->ip6_addr_state[i])) - { #if LWIP_IPV6_SCOPES - LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&netint->addr, &(ip_2_ip6(&lwip_netif->ip6_addr[i])->addr), - ip_2_ip6(&lwip_netif->ip6_addr[i])->zone); + LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&netint->addr, &(ip_2_ip6(&lwip_netif->ip6_addr[v6_addr_index])->addr), + ip_2_ip6(&lwip_netif->ip6_addr[v6_addr_index])->zone); #else - LWPA_IP_SET_V6_ADDRESS(&netint->addr, &(ip_2_ip6(&lwip_netif->ip6_addr[i])->addr)); - // TODO revisit - netint->mask = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 128); + LWPA_IP_SET_V6_ADDRESS(&netint->addr, &(ip_2_ip6(&lwip_netif->ip6_addr[v6_addr_index])->addr)); + // TODO revisit + netint->mask = lwpa_ip_mask_from_length(kLwpaIpTypeV6, 128); #endif - if (lwip_netif == netif_default && i == 0) - netint->is_default = true; - else - netint->is_default = false; - } + if (lwip_netif == netif_default) + netint->is_default = true; + else + netint->is_default = false; + + return true; } + return false; } lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) @@ -119,18 +117,29 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) // Make sure the default netint is included #if LWIP_IPV4 - copy_interface_info_v4(netif_default, &static_netints[num_static_netints++]); + if (netif_default) + { + cache->def.v4_valid = true; + cache->def.v4_index = netif_get_index(netif_default); + copy_interface_info_v4(netif_default, &static_netints[num_static_netints++]); + } #endif #if LWIP_IPV6 - for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) + if (netif_default) { + cache->def.v6_valid = true; + cache->def.v6_index = netif_get_index(netif_default); + for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) + { #if !LWPA_EMBOS_USE_MALLOC - if (num_static_netints >= LWPA_EMBOS_MAX_NETINTS) - break; + if (num_static_netints >= LWPA_EMBOS_MAX_NETINTS) + break; #endif - copy_interface_info_v6(netif_default, i, &static_netints[num_static_netints++]); - } + if (copy_interface_info_v6(netif_default, i, &static_netints[num_static_netints])) + ++num_static_netints; + } #endif + } NETIF_FOREACH(lwip_netif) { @@ -152,7 +161,8 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) if (num_static_netints >= LWPA_EMBOS_MAX_NETINTS) break; #endif - copy_interface_info_v6(lwip_netif, i, &static_netints[num_static_netints++]); + if (copy_interface_info_v6(lwip_netif, i, &static_netints[num_static_netints])) + ++num_static_netints; } #endif } @@ -173,7 +183,7 @@ void os_free_interfaces(CachedNetintInfo* cache) #endif } -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, const CachedNetintInfo* cache, unsigned int* index) { unsigned int index_found = 0; @@ -185,9 +195,22 @@ lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) break; } } + if (index_found == 0) - index_found = static_netints[default_index].index; + { + if (LWPA_IP_IS_V4(dest) && cache->def.v4_valid) + index_found = cache->def.v4_index; + else if (LWPA_IP_IS_V6(dest) && cache->def.v6_valid) + index_found = cache->def.v6_index; + } - *index = index_found; - return kLwpaErrOk; + if (index_found == 0) + { + return kLwpaErrNotFound; + } + else + { + *index = index_found; + return kLwpaErrOk; + } } diff --git a/src/os/macos/lwpa/os_netint.c b/src/os/macos/lwpa/os_netint.c index aeb72fa97..a97e73d6e 100644 --- a/src/os/macos/lwpa/os_netint.c +++ b/src/os/macos/lwpa/os_netint.c @@ -128,6 +128,18 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) if (res != kLwpaErrOk) return res; + // Fill in the default index information + if (routing_table_v4.default_route) + { + cache->def.v4_valid = true; + cache->def.v4_index = routing_table_v4.default_route->interface_index; + } + if (routing_table_v6.default_route) + { + cache->def.v6_valid = true; + cache->def.v6_index = routing_table_v6.default_route->interface_index; + } + struct ifaddrs* os_addrs; if (getifaddrs(&os_addrs) < 0) { @@ -236,8 +248,10 @@ void os_free_interfaces(CachedNetintInfo* cache) free_routing_tables(); } -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, const CachedNetintInfo* cache, unsigned int* index) { + (void)cache; // unused + RoutingTable* table_to_use = (LWPA_IP_IS_V6(dest) ? &routing_table_v6 : &routing_table_v4); unsigned int index_found = 0; diff --git a/src/os/mqx/lwpa/os_netint.c b/src/os/mqx/lwpa/os_netint.c index 222ab3705..b986774e0 100644 --- a/src/os/mqx/lwpa/os_netint.c +++ b/src/os/mqx/lwpa/os_netint.c @@ -59,8 +59,13 @@ lwpa_error_t os_enumerate_interfaces(CachedNetintInfo* cache) { copy_interface_info(i, &netints[i]); } + cache->netints = netints; cache->num_netints = BSP_ENET_DEVICE_COUNT; + + cache->def.v4_valid = true; + cache->def.v4_index = BSP_DEFAULT_ENET_DEVICE + 1; + return kLwpaErrOk; } @@ -69,8 +74,10 @@ void os_free_interfaces(CachedNetintInfo* cache) cache->netints = NULL; } -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, const CachedNetintInfo* cache, unsigned int* index) { + (void)cache; // unused + unsigned int index_found = 0; for (const LwpaNetintInfo* netint = netints; netint < netints + BSP_ENET_DEVICE_COUNT; ++netint) diff --git a/src/os/windows/lwpa/os_netint.c b/src/os/windows/lwpa/os_netint.c index 6738aa516..d37f581a6 100644 --- a/src/os/windows/lwpa/os_netint.c +++ b/src/os/windows/lwpa/os_netint.c @@ -40,8 +40,10 @@ static void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNet /*************************** Function definitions ****************************/ -lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, unsigned int* index) +lwpa_error_t os_resolve_route(const LwpaIpAddr* dest, const CachedNetintInfo* cache, unsigned int* index) { + (void)cache; // unused + struct sockaddr_storage os_addr; if (ip_lwpa_to_os(dest, (lwpa_os_ipaddr_t*)&os_addr)) { @@ -170,21 +172,25 @@ void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNetintInfo // Get the index of the default interface for IPv4 DWORD def_ifindex_v4; - bool have_def_index_v4 = false; struct sockaddr_in v4_dest; memset(&v4_dest, 0, sizeof v4_dest); v4_dest.sin_family = AF_INET; if (NO_ERROR == GetBestInterfaceEx((struct sockaddr*)&v4_dest, &def_ifindex_v4)) - have_def_index_v4 = true; + { + cache->def.v4_valid = true; + cache->def.v4_index = def_ifindex_v4; + } // And the same for IPv6 DWORD def_ifindex_v6; - bool have_def_index_v6 = false; struct sockaddr_in6 v6_dest; memset(&v6_dest, 0, sizeof v6_dest); v6_dest.sin6_family = AF_INET6; if (NO_ERROR == GetBestInterfaceEx((struct sockaddr*)&v6_dest, &def_ifindex_v6)) - have_def_index_v6 = true; + { + cache->def.v6_valid = true; + cache->def.v6_index = def_ifindex_v6; + } size_t netint_index = 0; @@ -199,10 +205,9 @@ void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNetintInfo { case AF_INET: copy_ipv4_info(pip, info); - if (have_def_index_v4 && pcur->IfIndex == def_ifindex_v4) + if (cache->def.v4_valid && pcur->IfIndex == def_ifindex_v4) { info->is_default = true; - have_def_index_v4 = false; } else { @@ -212,10 +217,9 @@ void copy_all_netint_info(const IP_ADAPTER_ADDRESSES* adapters, CachedNetintInfo break; case AF_INET6: copy_ipv6_info(pip, info); - if (have_def_index_v6 && pcur->IfIndex == def_ifindex_v6) + if (cache->def.v6_valid && pcur->IfIndex == def_ifindex_v6) { info->is_default = true; - have_def_index_v6 = false; } else { diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index 052af8ebd..d3986eec3 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -40,10 +40,10 @@ #define NUM_TEST_PACKETS 1000 -static LwpaNetintInfo v4_netint; +static unsigned int v4_netint; bool run_ipv4_mcast_test; #if LWPA_TEST_IPV6 -static LwpaNetintInfo v6_netint; +static unsigned int v6_netint; bool run_ipv6_mcast_test; #endif @@ -61,10 +61,15 @@ static LwpaSockaddr send_addr; // if not. static void select_network_interface_v4() { - if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV4, &v4_netint) && - NULL == strstr(v4_netint.name, "utun")) + if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV4, &v4_netint)) { - run_ipv4_mcast_test = true; + const LwpaNetintInfo* netint_arr; + size_t netint_arr_size; + if (kLwpaErrOk == lwpa_netint_get_interfaces_by_index(v4_netint, &netint_arr, &netint_arr_size) && + NULL == strstr(netint_arr->name, "utun")) + { + run_ipv4_mcast_test = true; + } } else { @@ -76,7 +81,7 @@ static void select_network_interface_v4() if (LWPA_IP_IS_V4(&netint->addr) && !lwpa_ip_is_link_local(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr) && NULL == strstr(netint->name, "utun")) { - v4_netint = *netint; + v4_netint = netint->index; run_ipv4_mcast_test = true; return; } @@ -92,10 +97,15 @@ static void select_network_interface_v4() // Select the default interface if available, the very first non-loopback interface if not. static void select_network_interface_v6() { - if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV6, &v6_netint) && - NULL == strstr(v6_netint.name, "utun")) + if (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV6, &v6_netint)) { - run_ipv6_mcast_test = true; + const LwpaNetintInfo* netint_arr; + size_t netint_arr_size; + if (kLwpaErrOk == lwpa_netint_get_interfaces_by_index(v6_netint, &netint_arr, &netint_arr_size) && + NULL == strstr(netint_arr->name, "utun")) + { + run_ipv6_mcast_test = true; + } } else { @@ -106,7 +116,7 @@ static void select_network_interface_v6() { if (LWPA_IP_IS_V6(&netint->addr) && !lwpa_ip_is_loopback(&netint->addr) && NULL == strstr(netint->name, "utun")) { - v6_netint = *netint; + v6_netint = netint->index; run_ipv6_mcast_test = true; return; } @@ -324,8 +334,8 @@ TEST(socket_integration, multicast_udp_ipv4) TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int))); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &v4_netint.index, - sizeof v4_netint.index)); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(send_sock, LWPA_IPPROTO_IP, LWPA_IP_MULTICAST_IF, &v4_netint, sizeof v4_netint)); // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); @@ -338,7 +348,7 @@ TEST(socket_integration, multicast_udp_ipv4) // Subscribe socket 1 to the multicast address. LwpaGroupReq greq; - greq.ifindex = v4_netint.index; + greq.ifindex = v4_netint; LWPA_IP_SET_V4_ADDRESS(&greq.group, kTestMcastAddrIPv4); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); @@ -379,7 +389,7 @@ TEST(socket_integration, multicast_udp_ipv6) // TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_LOOP, &intval, sizeof(int)); //); // TEST_ASSERT_EQUAL(kLwpaErrOk, - lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_IF, &v6_netint.index, sizeof v6_netint.index); //); + lwpa_setsockopt(send_sock, LWPA_IPPROTO_IPV6, LWPA_IP_MULTICAST_IF, &v6_netint, sizeof v6_netint); //); // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV6, &bind_addr.ip); @@ -392,7 +402,7 @@ TEST(socket_integration, multicast_udp_ipv6) // Subscribe socket 1 to the multicast address. LwpaGroupReq greq; - greq.ifindex = v6_netint.index; + greq.ifindex = v6_netint; LWPA_IP_SET_V6_ADDRESS(&greq.group, kTestMcastAddrIPv6); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); @@ -401,7 +411,7 @@ TEST(socket_integration, multicast_udp_ipv6) TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); - LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&send_addr.ip, kTestMcastAddrIPv6, v6_netint.index); + LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&send_addr.ip, kTestMcastAddrIPv6, v6_netint); send_addr.port = MULTICAST_UDP_PORT_BASE; multicast_udp_test(rcvsock1, rcvsock2); diff --git a/tests/unit/live/test_common.c b/tests/unit/live/test_common.c index 20888149c..483098147 100644 --- a/tests/unit/live/test_common.c +++ b/tests/unit/live/test_common.c @@ -58,7 +58,7 @@ TEST(lwpa_common, netint_double_init_works) lwpa_deinit(LWPA_FEATURE_NETINTS); // After 2 inits and one deinit, we should still be able to make valid calls to the module. - LwpaNetintInfo def_netint; + unsigned int def_netint; TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_netint)); lwpa_deinit(LWPA_FEATURE_NETINTS); diff --git a/tests/unit/live/test_netint.c b/tests/unit/live/test_netint.c index 44db6f623..e94db5edc 100644 --- a/tests/unit/live/test_netint.c +++ b/tests/unit/live/test_netint.c @@ -42,18 +42,28 @@ TEST(lwpa_netint, netint_enumeration_works) { TEST_ASSERT_GREATER_THAN_UINT(0u, num_netints); - size_t num_defaults = 0; const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); TEST_ASSERT_NOT_NULL(netint_list); + for (const LwpaNetintInfo* netint = netint_list; netint < netint_list + num_netints; ++netint) { - if (netint->is_default) - ++num_defaults; + TEST_ASSERT_GREATER_THAN_UINT(0u, netint->index); TEST_ASSERT_GREATER_THAN_UINT(0u, strlen(netint->name)); TEST_ASSERT_GREATER_THAN_UINT(0u, strlen(netint->friendly_name)); } - // There can be a maximum of two default interfaces: one each for IPv4 and IPv6. - TEST_ASSERT_LESS_OR_EQUAL_UINT(2u, num_defaults); +} + +TEST(lwpa_netint, netints_are_in_index_order) +{ + TEST_ASSERT_GREATER_THAN_UINT(0u, num_netints); + + const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); + unsigned int last_index = netint_list->index; + for (const LwpaNetintInfo* netint = netint_list + 1; netint < netint_list + num_netints; ++netint) + { + TEST_ASSERT_GREATER_OR_EQUAL(last_index, netint->index); + last_index = netint->index; + } } /* TODO Figure out how we're gonna handle mallocing @@ -69,25 +79,56 @@ TEST(lwpa_netint, copy_interfaces_works) } */ +TEST(lwpa_netint, get_netints_by_index_works) +{ + TEST_ASSERT_GREATER_THAN_UINT(0u, num_netints); + + const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); + unsigned int current_index = 0; + // There are other tests covering that the netint list should be in order by index and that the + // indexes must all be greater than 0, which simplifies this code. + const LwpaNetintInfo* current_arr_by_index = NULL; + size_t current_index_arr_size = 0; + for (const LwpaNetintInfo* netint = netint_list; netint < netint_list + num_netints; ++netint) + { + if (netint->index > current_index) + { + // The previous get-by-index array should be exhausted + TEST_ASSERT_EQUAL_UINT(current_index_arr_size, 0u); + + // Get the new one + current_index = netint->index; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_interfaces_by_index(netint->index, ¤t_arr_by_index, + ¤t_index_arr_size)); + TEST_ASSERT_GREATER_THAN_UINT(0u, current_index_arr_size); + } + + // Now check that we're still in the get-by-index array and it gives the correct slice of the + // total netint array. + TEST_ASSERT_GREATER_THAN_UINT(0u, current_index_arr_size); + TEST_ASSERT_EQUAL_PTR(current_arr_by_index, netint); + ++current_arr_by_index; + --current_index_arr_size; + } +} + TEST(lwpa_netint, default_netint_is_consistent) { TEST_ASSERT_GREATER_THAN_UINT(0u, num_netints); - LwpaNetintInfo def_v4; - LwpaNetintInfo def_v6; - memset(&def_v4, 0, sizeof def_v4); - memset(&def_v6, 0, sizeof def_v6); + unsigned int def_v4 = 0; + unsigned int def_v6 = 0; bool have_default_v4 = (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV4, &def_v4)); bool have_default_v6 = (kLwpaErrOk == lwpa_netint_get_default_interface(kLwpaIpTypeV6, &def_v6)); if (have_default_v4) { - TEST_ASSERT(def_v4.is_default); + TEST_ASSERT_NOT_EQUAL(def_v4, 0u); } if (have_default_v6) { - TEST_ASSERT(def_v6.is_default); + TEST_ASSERT_NOT_EQUAL(def_v6, 0u); } const LwpaNetintInfo* netint_list = lwpa_netint_get_interfaces(); @@ -98,11 +139,11 @@ TEST(lwpa_netint, default_netint_is_consistent) { if (netint->addr.type == kLwpaIpTypeV4) { - TEST_ASSERT_EQUAL_MEMORY(netint, &def_v4, sizeof def_v4); + TEST_ASSERT_EQUAL_UINT(netint->index, def_v4); } else if (netint->addr.type == kLwpaIpTypeV6) { - TEST_ASSERT_EQUAL_MEMORY(netint, &def_v6, sizeof def_v6); + TEST_ASSERT_EQUAL_UINT(netint->index, def_v6); } } } @@ -124,30 +165,33 @@ TEST(lwpa_netint, get_interface_for_dest_works_ipv4) continue; LwpaIpAddr test_addr = netint->addr; - LwpaNetintInfo netint_res; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&test_addr, &netint_res)); + unsigned int netint_index_res; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&test_addr, &netint_index_res)); // Put addresses in print form to test meaningful information in case of test failure char test_addr_str[LWPA_INET6_ADDRSTRLEN]; - char result_str[LWPA_INET6_ADDRSTRLEN]; lwpa_inet_ntop(&test_addr, test_addr_str, LWPA_INET6_ADDRSTRLEN); - lwpa_inet_ntop(&netint_res.addr, result_str, LWPA_INET6_ADDRSTRLEN); char test_msg[150]; - snprintf(test_msg, 150, "Address tried: %s, interface returned: %s", test_addr_str, result_str); + snprintf(test_msg, 150, "Address tried: %s (interface %u), interface returned: %u", test_addr_str, netint->index, + netint_index_res); - TEST_ASSERT_TRUE_MESSAGE(lwpa_ip_equal(&netint_res.addr, &netint->addr), test_msg); + TEST_ASSERT_EQUAL_UINT_MESSAGE(netint_index_res, netint->index, test_msg); } LwpaIpAddr ext_addr; LWPA_IP_SET_V4_ADDRESS(&ext_addr, 0xc8dc0302); // 200.220.3.2 - LwpaNetintInfo def; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&ext_addr, &def)); - TEST_ASSERT(def.is_default); + unsigned int netint_index_res; + unsigned int netint_index_default; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_default_interface(kLwpaIpTypeV4, &netint_index_default)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_netint_get_interface_for_dest(&ext_addr, &netint_index_res)); + TEST_ASSERT_EQUAL_UINT(netint_index_res, netint_index_default); } TEST_GROUP_RUNNER(lwpa_netint) { RUN_TEST_CASE(lwpa_netint, netint_enumeration_works); + RUN_TEST_CASE(lwpa_netint, netints_are_in_index_order); + RUN_TEST_CASE(lwpa_netint, get_netints_by_index_works); RUN_TEST_CASE(lwpa_netint, default_netint_is_consistent); RUN_TEST_CASE(lwpa_netint, get_interface_for_dest_works_ipv4); } From a2cfc7162511aa4003b66a49c9bb12fea7b7f0f5 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 09:23:47 -0500 Subject: [PATCH 124/264] Fix mock lib --- src/CMakeLists.txt | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7ddac01e..4ff0a2f93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -50,9 +50,9 @@ add_library(lwpa ${LWPA_ROOT}/src/lwpa/uuid.c ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_lock.c - ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_uuid.c ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_thread.c ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_timer.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_uuid.c ${LWPA_ROOT}/src/os/${LWPA_NET_TARGET}/lwpa/os_inet.c ${LWPA_ROOT}/src/os/${LWPA_NET_TARGET}/lwpa/os_netint.c @@ -77,7 +77,6 @@ if(LWPA_NETINT_DEBUG_OUTPUT) target_compile_definitions(lwpa PRIVATE LWPA_NETINT_DEBUG_OUTPUT) endif() target_link_libraries(lwpa PUBLIC ${LWPA_OS_ADDITIONAL_LIBS} ${LWPA_NET_ADDITIONAL_LIBS}) - set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) if(NOT MSVC) @@ -107,48 +106,60 @@ if(LWPA_BUILD_MOCK_LIB) ${LWPA_ROOT}/include/lwpa/log.h ${LWPA_ROOT}/include/lwpa/mempool.h ${LWPA_ROOT}/include/lwpa/netint.h - ${LWPA_ROOT}/include/lwpa/opts.h ${LWPA_ROOT}/include/lwpa/pack.h ${LWPA_ROOT}/include/lwpa/pdu.h ${LWPA_ROOT}/include/lwpa/rbtree.h ${LWPA_ROOT}/include/lwpa/root_layer_pdu.h ${LWPA_ROOT}/include/lwpa/socket.h ${LWPA_ROOT}/include/lwpa/timer.h + ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_lock.h - ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_socket.h ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET}/lwpa/os_thread.h + ${LWPA_ROOT}/include/os/${LWPA_NET_TARGET}/lwpa/os_socket.h + ${LWPA_ROOT}/include/os/${LWPA_NET_TARGET}/lwpa/os_inet.h + ${LWPA_ROOT}/include/lwpa_mock/socket.h # lwpa sources # We will gradually substitute these with mocks as needed - ${LWPA_ROOT}/src/lwpa/uuid.c + ${LWPA_ROOT}/src/lwpa/common.c ${LWPA_ROOT}/src/lwpa/error.c + ${LWPA_ROOT}/src/lwpa/inet.c ${LWPA_ROOT}/src/lwpa/log.c + ${LWPA_ROOT}/src/lwpa/md5.h + ${LWPA_ROOT}/src/lwpa/md5.c ${LWPA_ROOT}/src/lwpa/mempool.c + ${LWPA_ROOT}/src/lwpa/netint.c + ${LWPA_ROOT}/src/lwpa/pack.c ${LWPA_ROOT}/src/lwpa/pdu.c ${LWPA_ROOT}/src/lwpa/rbtree.c ${LWPA_ROOT}/src/lwpa/root_layer_pdu.c - ${LWPA_ROOT}/src/lwpa/md5.h - ${LWPA_ROOT}/src/lwpa/md5.c + ${LWPA_ROOT}/src/lwpa/timer.c + ${LWPA_ROOT}/src/lwpa/uuid.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_lock.c - ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_netint.c - ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_uuid.c - ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_socket.c ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_thread.c ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_timer.c + ${LWPA_ROOT}/src/os/${LWPA_OS_TARGET}/lwpa/os_uuid.c + + ${LWPA_ROOT}/src/os/${LWPA_NET_TARGET}/lwpa/os_inet.c + ${LWPA_ROOT}/src/os/${LWPA_NET_TARGET}/lwpa/os_netint.c + ${LWPA_ROOT}/src/os/${LWPA_NET_TARGET}/lwpa/os_socket.c ${LWPA_ROOT}/src/lwpa_mock/socket.c ) target_include_directories(lwpa_mock PUBLIC ${LWPA_ROOT}/include ${LWPA_ROOT}/include/os/${LWPA_OS_TARGET} + ${LWPA_ROOT}/include/os/${LWPA_NET_TARGET} ) target_include_directories(lwpa_mock PRIVATE ${LWPA_ROOT}/src) target_compile_definitions(lwpa_mock PRIVATE LWPA_BUILDING_MOCK_LIB) target_link_libraries(lwpa_mock PUBLIC meekrosoft::fff) - if(LWPA_OS_TARGET STREQUAL windows) - target_link_libraries(lwpa_mock PUBLIC winmm ws2_32 Iphlpapi Rpcrt4) - endif() + target_link_libraries(lwpa_mock PUBLIC ${LWPA_OS_ADDITIONAL_LIBS} ${LWPA_NET_ADDITIONAL_LIBS}) set_target_properties(lwpa PROPERTIES DEBUG_POSTFIX d) + if(NOT MSVC) + set_target_properties(lwpa PROPERTIES C_STANDARD 99) + endif() endif() From b7583f2cd1671b5a4bd6c6db8afd2357e19095cc Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 09:51:58 -0500 Subject: [PATCH 125/264] Fix getaddrinfo unit test --- src/os/lwip/lwpa/os_error.c | 23 +++++++++++++++++++++++ src/os/lwip/lwpa/os_error.h | 1 + src/os/lwip/lwpa/os_socket.c | 4 ++-- tests/unit/live/test_socket.c | 7 +++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/os/lwip/lwpa/os_error.c b/src/os/lwip/lwpa/os_error.c index c5b30e8fe..cdbee2f6a 100644 --- a/src/os/lwip/lwpa/os_error.c +++ b/src/os/lwip/lwpa/os_error.c @@ -18,6 +18,7 @@ ******************************************************************************/ #include "os_error.h" +#include lwpa_error_t errno_lwip_to_lwpa(int lwip_errno) { @@ -90,3 +91,25 @@ lwpa_error_t errno_lwip_to_lwpa(int lwip_errno) return kLwpaErrSys; } } + +lwpa_error_t err_gai_to_lwpa(int gai_error) +{ +#if LWIP_DNS + switch (gai_error) + { + case EAI_SERVICE: + case EAI_FAIL: + case EAI_NONAME: + return kLwpaErrNotFound; + case EAI_MEMORY: + return kLwpaErrNoMem; + case EAI_FAMILY: + return kLwpaErrInvalid; + default: + return kLwpaErrSys; + } +#else + (void)gai_error; // unused + return kLwpaErrSys; +#endif +} diff --git a/src/os/lwip/lwpa/os_error.h b/src/os/lwip/lwpa/os_error.h index 7c1bfda8c..916cd3fc3 100644 --- a/src/os/lwip/lwpa/os_error.h +++ b/src/os/lwip/lwpa/os_error.h @@ -28,5 +28,6 @@ #endif lwpa_error_t errno_lwip_to_lwpa(int lwip_errno); +lwpa_error_t err_gai_to_lwpa(int gai_error); #endif /* _LWPA_OS_ERROR_H_ */ diff --git a/src/os/lwip/lwpa/os_socket.c b/src/os/lwip/lwpa/os_socket.c index 3006ac6af..c23efc6cb 100644 --- a/src/os/lwip/lwpa/os_socket.c +++ b/src/os/lwip/lwpa/os_socket.c @@ -857,7 +857,7 @@ lwpa_error_t lwpa_getaddrinfo(const char* hostname, const char* service, const L if (!lwpa_nextaddr(result)) res = -1; } - return res; + return (res == 0 ? kLwpaErrOk : err_gai_to_lwpa(res)); #else // LWIP_DNS return kLwpaErrNotImpl; #endif // LWIP_DNS @@ -870,7 +870,7 @@ bool lwpa_nextaddr(LwpaAddrinfo* ai) { struct addrinfo* pf_ai = (struct addrinfo*)ai->pd[1]; ai->ai_flags = 0; - if (!sockaddr_os_to_lwpa(&ai->ai_addr, pf_ai->ai_addr)) + if (!sockaddr_os_to_lwpa(pf_ai->ai_addr, &ai->ai_addr)) return false; /* Can't use reverse maps, because we have no guarantee of the numeric * values of the os constants. Ugh. */ diff --git a/tests/unit/live/test_socket.c b/tests/unit/live/test_socket.c index ae5a4a95a..630a0afde 100644 --- a/tests/unit/live/test_socket.c +++ b/tests/unit/live/test_socket.c @@ -23,8 +23,10 @@ #include // For getaddrinfo +#if 0 static const char* test_hostname = "www.google.com"; static const char* test_service = "http"; +#endif static const char* test_gai_ip_str = "10.101.1.1"; static const uint32_t test_gai_ip = 0x0a650101; @@ -354,16 +356,21 @@ TEST(lwpa_socket, getaddrinfo_works_as_expected) LwpaAddrinfo ai; memset(&ai_hints, 0, sizeof ai_hints); + + // We can't currently assume internet access for our tests. +#if 0 ai_hints.ai_family = LWPA_AF_INET; TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_getaddrinfo(test_hostname, test_service, &ai_hints, &ai)); TEST_ASSERT(LWPA_IP_IS_V4(&ai.ai_addr.ip)); lwpa_freeaddrinfo(&ai); +#endif ai_hints.ai_flags = LWPA_AI_NUMERICHOST; TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_getaddrinfo(test_gai_ip_str, test_gai_port_str, &ai_hints, &ai)); TEST_ASSERT(LWPA_IP_IS_V4(&ai.ai_addr.ip)); TEST_ASSERT_EQUAL_UINT32(LWPA_IP_V4_ADDRESS(&ai.ai_addr.ip), test_gai_ip); TEST_ASSERT_EQUAL_UINT16(ai.ai_addr.port, test_gai_port); + lwpa_freeaddrinfo(&ai); } TEST_GROUP_RUNNER(lwpa_socket) From 572b8a6bb9956239ffc6566a991a179d3a8cfa1d Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 09:55:37 -0500 Subject: [PATCH 126/264] Add missing symbols on macOS and Linux --- src/os/linux/lwpa/os_socket.c | 15 +++++++++++++++ src/os/macos/lwpa/os_socket.c | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 6ad5a20db..58c1619f5 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -593,6 +593,21 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) return (val >= 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } +lwpa_error_t lwpa_getblocking(lwpa_socket_t id, bool* blocking) +{ + if (blocking) + { + int val = fcntl(id, F_GETFL, 0); + if (val >= 0) + { + *blocking = ((val & O_NONBLOCK) == 0); + return kLwpaErrOk; + } + return errno_os_to_lwpa(errno); + } + return kLwpaErrInvalid; +} + lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { if (!context) diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index 7b010e519..d44cd488e 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -580,6 +580,21 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) return (val >= 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } +lwpa_error_t lwpa_getblocking(lwpa_socket_t id, bool* blocking) +{ + if (blocking) + { + int val = fcntl(id, F_GETFL, 0); + if (val >= 0) + { + *blocking = ((val & O_NONBLOCK) == 0); + return kLwpaErrOk; + } + return errno_os_to_lwpa(errno); + } + return kLwpaErrInvalid; +} + lwpa_error_t lwpa_poll_context_init(LwpaPollContext* context) { if (!context) From fd816caa5029a6750eda538566d0d051c994e9a3 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 10:00:20 -0500 Subject: [PATCH 127/264] And fix bugs exposed by the new function and tests --- src/os/linux/lwpa/os_socket.c | 2 +- src/os/macos/lwpa/os_socket.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/os/linux/lwpa/os_socket.c b/src/os/linux/lwpa/os_socket.c index 58c1619f5..fc25d2565 100644 --- a/src/os/linux/lwpa/os_socket.c +++ b/src/os/linux/lwpa/os_socket.c @@ -588,7 +588,7 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) int val = fcntl(id, F_GETFL, 0); if (val >= 0) { - val = fcntl(id, F_SETFL, val | O_NONBLOCK); + val = fcntl(id, F_SETFL, (blocking ? (val & (int)(~O_NONBLOCK)) : (val | O_NONBLOCK))); } return (val >= 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } diff --git a/src/os/macos/lwpa/os_socket.c b/src/os/macos/lwpa/os_socket.c index d44cd488e..f7f1140a9 100644 --- a/src/os/macos/lwpa/os_socket.c +++ b/src/os/macos/lwpa/os_socket.c @@ -575,7 +575,7 @@ lwpa_error_t lwpa_setblocking(lwpa_socket_t id, bool blocking) int val = fcntl(id, F_GETFL, 0); if (val >= 0) { - val = fcntl(id, F_SETFL, val | O_NONBLOCK); + val = fcntl(id, F_SETFL, (blocking ? (val & (int)(~O_NONBLOCK)) : (val | O_NONBLOCK))); } return (val >= 0 ? kLwpaErrOk : errno_os_to_lwpa(errno)); } From c74f7326b2dffb2517bff5736501b17c760f0ba4 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 11:12:41 -0500 Subject: [PATCH 128/264] Fix socket integration test to better clean up resources --- tests/integration/socket_integration_test.c | 195 +++++++++----------- tests/integration/test_main.c | 2 +- 2 files changed, 87 insertions(+), 110 deletions(-) diff --git a/tests/integration/socket_integration_test.c b/tests/integration/socket_integration_test.c index d3986eec3..0092ef4f9 100644 --- a/tests/integration/socket_integration_test.c +++ b/tests/integration/socket_integration_test.c @@ -56,6 +56,7 @@ static const uint8_t kTestMcastAddrIPv6[LWPA_IPV6_BYTES] = {0xff, 0x12, 0x00, 0x static lwpa_socket_t send_sock; static LwpaSockaddr send_addr; +static lwpa_socket_t recv_socks[LWPA_BULK_POLL_TEST_NUM_SOCKETS]; // Select the default interface if available, the very first non-loopback, non-link-local interface // if not. @@ -129,14 +130,20 @@ static void select_network_interface_v6() } #endif -TEST_GROUP(socket_integration); +TEST_GROUP(socket_integration_udp); -TEST_SETUP(socket_integration) +TEST_SETUP(socket_integration_udp) { + send_sock = LWPA_SOCKET_INVALID; + for (size_t i = 0; i < LWPA_BULK_POLL_TEST_NUM_SOCKETS; ++i) + recv_socks[i] = LWPA_SOCKET_INVALID; } -TEST_TEAR_DOWN(socket_integration) +TEST_TEAR_DOWN(socket_integration_udp) { + lwpa_close(send_sock); + for (size_t i = 0; i < LWPA_BULK_POLL_TEST_NUM_SOCKETS; ++i) + lwpa_close(recv_socks[i]); } // For UDP testing we apply strength in numbers to get around the inherent unreliability of UDP. @@ -152,21 +159,23 @@ static void send_thread(void* arg) #define UNICAST_UDP_PORT_BASE 6000 -void unicast_udp_test(lwpa_iptype_t ip_type, lwpa_socket_t rcvsock1, lwpa_socket_t rcvsock2) +void unicast_udp_test(lwpa_iptype_t ip_type) { int intval = 500; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[0], LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); intval = 1; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[1], LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); LwpaSockaddr bind_addr; lwpa_ip_set_wildcard(ip_type, &bind_addr.ip); bind_addr.port = UNICAST_UDP_PORT_BASE; // Bind socket 1 to the wildcard address and a specific port. - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(recv_socks[0], &bind_addr)); // Bind socket 2 to the wildcard address and a different port. bind_addr.port = UNICAST_UDP_PORT_BASE + 1; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(recv_socks[1], &bind_addr)); send_addr.port = UNICAST_UDP_PORT_BASE; @@ -182,7 +191,7 @@ void unicast_udp_test(lwpa_iptype_t ip_type, lwpa_socket_t rcvsock1, lwpa_socket LwpaSockaddr from_addr; uint8_t buf[SOCKET_TEST_MESSAGE_LENGTH + 1]; - int res = lwpa_recvfrom(rcvsock1, buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr); + int res = lwpa_recvfrom(recv_socks[0], buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr); if (res == SOCKET_TEST_MESSAGE_LENGTH) { ++num_packets_received; @@ -206,46 +215,36 @@ void unicast_udp_test(lwpa_iptype_t ip_type, lwpa_socket_t rcvsock1, lwpa_socket // timeout option on this socket. LwpaSockaddr from_addr; uint8_t buf[SOCKET_TEST_MESSAGE_LENGTH + 1]; - TEST_ASSERT_LESS_OR_EQUAL_INT(0, lwpa_recvfrom(rcvsock2, buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr)); + TEST_ASSERT_LESS_OR_EQUAL_INT(0, lwpa_recvfrom(recv_socks[1], buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr)); // Let the send thread end TEST_ASSERT_TRUE(lwpa_thread_join(&send_thr_handle)); } -TEST(socket_integration, unicast_udp_ipv4) +TEST(socket_integration_udp, unicast_udp_ipv4) { - lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &recv_socks[0])); + TEST_ASSERT_NOT_EQUAL(recv_socks[0], LWPA_SOCKET_INVALID); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); - TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); - - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); - TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &recv_socks[1])); + TEST_ASSERT_NOT_EQUAL(recv_socks[1], LWPA_SOCKET_INVALID); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, 0x7f000001u); - unicast_udp_test(kLwpaIpTypeV4, rcvsock1, rcvsock2); - - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); + unicast_udp_test(kLwpaIpTypeV4); } #if LWPA_TEST_IPV6 -TEST(socket_integration, unicast_udp_ipv6) +TEST(socket_integration_udp, unicast_udp_ipv6) { - lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; - - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &rcvsock1)); - TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &recv_socks[0])); + TEST_ASSERT_NOT_EQUAL(recv_socks[0], LWPA_SOCKET_INVALID); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &rcvsock2)); - TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &recv_socks[1])); + TEST_ASSERT_NOT_EQUAL(recv_socks[1], LWPA_SOCKET_INVALID); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &send_sock)); TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); @@ -255,22 +254,20 @@ TEST(socket_integration, unicast_udp_ipv6) v6_loopback[15] = 1; LWPA_IP_SET_V6_ADDRESS(&send_addr.ip, &v6_loopback); - unicast_udp_test(kLwpaIpTypeV6, rcvsock1, rcvsock2); - - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); + unicast_udp_test(kLwpaIpTypeV6); } #endif // LWPA_TEST_IPV6 #define MULTICAST_UDP_PORT_BASE 7000 -void multicast_udp_test(lwpa_socket_t rcvsock1, lwpa_socket_t rcvsock2) +void multicast_udp_test(void) { int intval = 500; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[0], LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); intval = 1; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[1], LWPA_SOL_SOCKET, LWPA_SO_RCVTIMEO, &intval, sizeof(int))); // Start the send thread LwpaThreadParams thread_params; @@ -284,7 +281,7 @@ void multicast_udp_test(lwpa_socket_t rcvsock1, lwpa_socket_t rcvsock2) LwpaSockaddr from_addr; uint8_t buf[SOCKET_TEST_MESSAGE_LENGTH + 1]; - int res = lwpa_recvfrom(rcvsock1, buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr); + int res = lwpa_recvfrom(recv_socks[0], buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr); if (res == SOCKET_TEST_MESSAGE_LENGTH) { ++num_packets_received; @@ -306,28 +303,27 @@ void multicast_udp_test(lwpa_socket_t rcvsock1, lwpa_socket_t rcvsock2) uint8_t buf[SOCKET_TEST_MESSAGE_LENGTH + 1]; // recvfrom should time out because this socket is bound to a different port and we set the // timeout option on this socket. - TEST_ASSERT_LESS_OR_EQUAL_INT(0, lwpa_recvfrom(rcvsock2, buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr)); + TEST_ASSERT_LESS_OR_EQUAL_INT(0, lwpa_recvfrom(recv_socks[1], buf, SOCKET_TEST_MESSAGE_LENGTH, 0, &from_addr)); // Let the send thread end TEST_ASSERT(lwpa_thread_join(&send_thr_handle)); } -TEST(socket_integration, multicast_udp_ipv4) +TEST(socket_integration_udp, multicast_udp_ipv4) { LwpaSockaddr bind_addr; - lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; - - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock1)); - TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &recv_socks[0])); + TEST_ASSERT_NOT_EQUAL(recv_socks[0], LWPA_SOCKET_INVALID); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &rcvsock2)); - TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &recv_socks[1])); + TEST_ASSERT_NOT_EQUAL(recv_socks[1], LWPA_SOCKET_INVALID); int intval = 1; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[0], LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[1], LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); @@ -340,48 +336,45 @@ TEST(socket_integration, multicast_udp_ipv4) // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); bind_addr.port = MULTICAST_UDP_PORT_BASE; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(recv_socks[0], &bind_addr)); // Bind socket 2 to the wildcard address and a different port. bind_addr.port = MULTICAST_UDP_PORT_BASE + 1; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(recv_socks[1], &bind_addr)); // Subscribe socket 1 to the multicast address. LwpaGroupReq greq; greq.ifindex = v4_netint; LWPA_IP_SET_V4_ADDRESS(&greq.group, kTestMcastAddrIPv4); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[0], LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); // Subscribe socket 2 to the multicast address - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[1], LWPA_IPPROTO_IP, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, kTestMcastAddrIPv4); send_addr.port = MULTICAST_UDP_PORT_BASE; - multicast_udp_test(rcvsock1, rcvsock2); - - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); + multicast_udp_test(); } #if LWPA_TEST_IPV6 -TEST(socket_integration, multicast_udp_ipv6) +TEST(socket_integration_udp, multicast_udp_ipv6) { LwpaSockaddr bind_addr; - lwpa_socket_t rcvsock1 = LWPA_SOCKET_INVALID; - lwpa_socket_t rcvsock2 = LWPA_SOCKET_INVALID; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &recv_socks[0])); + TEST_ASSERT_NOT_EQUAL(recv_socks[0], LWPA_SOCKET_INVALID); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &rcvsock1)); - TEST_ASSERT_NOT_EQUAL(rcvsock1, LWPA_SOCKET_INVALID); - - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &rcvsock2)); - TEST_ASSERT_NOT_EQUAL(rcvsock2, LWPA_SOCKET_INVALID); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &recv_socks[1])); + TEST_ASSERT_NOT_EQUAL(recv_socks[1], LWPA_SOCKET_INVALID); int intval = 1; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock1, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_setsockopt(rcvsock2, LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[0], LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); + TEST_ASSERT_EQUAL(kLwpaErrOk, + lwpa_setsockopt(recv_socks[1], LWPA_SOL_SOCKET, LWPA_SO_REUSEADDR, &intval, sizeof(int))); TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET6, LWPA_DGRAM, &send_sock)); TEST_ASSERT_NOT_EQUAL(send_sock, LWPA_SOCKET_INVALID); @@ -394,97 +387,81 @@ TEST(socket_integration, multicast_udp_ipv6) // Bind socket 1 to the wildcard address and a specific port. lwpa_ip_set_wildcard(kLwpaIpTypeV6, &bind_addr.ip); bind_addr.port = MULTICAST_UDP_PORT_BASE; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock1, &bind_addr)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(recv_socks[0], &bind_addr)); // Bind socket 2 to the wildcard address and a different port. bind_addr.port = MULTICAST_UDP_PORT_BASE + 1; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(rcvsock2, &bind_addr)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_bind(recv_socks[1], &bind_addr)); // Subscribe socket 1 to the multicast address. LwpaGroupReq greq; greq.ifindex = v6_netint; LWPA_IP_SET_V6_ADDRESS(&greq.group, kTestMcastAddrIPv6); TEST_ASSERT_EQUAL(kLwpaErrOk, - lwpa_setsockopt(rcvsock1, LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); + lwpa_setsockopt(recv_socks[0], LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); // Subscribe socket 2 to the multicast address TEST_ASSERT_EQUAL(kLwpaErrOk, - lwpa_setsockopt(rcvsock2, LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); + lwpa_setsockopt(recv_socks[1], LWPA_IPPROTO_IPV6, LWPA_MCAST_JOIN_GROUP, &greq, sizeof greq)); LWPA_IP_SET_V6_ADDRESS_WITH_SCOPE_ID(&send_addr.ip, kTestMcastAddrIPv6, v6_netint); send_addr.port = MULTICAST_UDP_PORT_BASE; - multicast_udp_test(rcvsock1, rcvsock2); - - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock1)); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(rcvsock2)); - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(send_sock)); + multicast_udp_test(); } #endif // LWPA_TEST_IPV6 // Test to make sure lwpa_poll_* functions work properly with a large number of sockets. // (Tests the maximum number defined by LWPA_SOCKET_MAX_POLL_SIZE if that number is well-defined and // reasonable). -TEST(socket_integration, bulk_poll) +TEST(socket_integration_udp, bulk_poll) { LwpaPollContext context; TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_poll_context_init(&context)); - static lwpa_socket_t socket_arr[LWPA_BULK_POLL_TEST_NUM_SOCKETS]; static uint16_t bind_ports[LWPA_BULK_POLL_TEST_NUM_SOCKETS]; for (size_t i = 0; i < LWPA_BULK_POLL_TEST_NUM_SOCKETS; ++i) { char error_msg[50]; sprintf(error_msg, "Failed on iteration %zu", i); - TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &socket_arr[i]), error_msg); - TEST_ASSERT_NOT_EQUAL_MESSAGE(socket_arr[i], LWPA_SOCKET_INVALID, error_msg); + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &recv_socks[i]), error_msg); + TEST_ASSERT_NOT_EQUAL_MESSAGE(recv_socks[i], LWPA_SOCKET_INVALID, error_msg); LwpaSockaddr bind_addr; lwpa_ip_set_wildcard(kLwpaIpTypeV4, &bind_addr.ip); bind_addr.port = 0; - TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_bind(socket_arr[i], &bind_addr), error_msg); - TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_getsockname(socket_arr[i], &bind_addr), error_msg); + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_bind(recv_socks[i], &bind_addr), error_msg); + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_getsockname(recv_socks[i], &bind_addr), error_msg); bind_ports[i] = bind_addr.port; - TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_poll_add_socket(&context, socket_arr[i], LWPA_POLL_IN, NULL), error_msg); + TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_poll_add_socket(&context, recv_socks[i], LWPA_POLL_IN, NULL), error_msg); } - lwpa_socket_t poll_send_sock; - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &poll_send_sock)); + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_socket(LWPA_AF_INET, LWPA_DGRAM, &send_sock)); - LwpaSockaddr poll_send_addr; - LWPA_IP_SET_V4_ADDRESS(&poll_send_addr.ip, 0x7f000001); + LWPA_IP_SET_V4_ADDRESS(&send_addr.ip, 0x7f000001); for (size_t i = 0; i < LWPA_BULK_POLL_TEST_NUM_SOCKETS; ++i) { char error_msg[50]; sprintf(error_msg, "Failed on iteration %zu", i); // Send to each socket in turn and make sure poll works for it - poll_send_addr.port = bind_ports[i]; - lwpa_sendto(poll_send_sock, kSocketTestMessage, SOCKET_TEST_MESSAGE_LENGTH, 0, &poll_send_addr); + send_addr.port = bind_ports[i]; + lwpa_sendto(send_sock, kSocketTestMessage, SOCKET_TEST_MESSAGE_LENGTH, 0, &send_addr); LwpaPollEvent event; TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_poll_wait(&context, &event, 100), error_msg); - TEST_ASSERT_EQUAL_MESSAGE(event.socket, socket_arr[i], error_msg); + TEST_ASSERT_EQUAL_MESSAGE(event.socket, recv_socks[i], error_msg); TEST_ASSERT_EQUAL_MESSAGE(event.events, LWPA_POLL_IN, error_msg); TEST_ASSERT_EQUAL_MESSAGE(event.err, kLwpaErrOk, error_msg); uint8_t recv_buf[SOCKET_TEST_MESSAGE_LENGTH]; - TEST_ASSERT_GREATER_THAN(0, lwpa_recvfrom(socket_arr[i], recv_buf, SOCKET_TEST_MESSAGE_LENGTH, 0, NULL)); - } - - for (size_t i = 0; i < LWPA_BULK_POLL_TEST_NUM_SOCKETS; ++i) - { - char error_msg[50]; - sprintf(error_msg, "Failed on iteration %zu", i); - - TEST_ASSERT_EQUAL_MESSAGE(kLwpaErrOk, lwpa_close(socket_arr[i]), error_msg); + TEST_ASSERT_GREATER_THAN(0, lwpa_recvfrom(recv_socks[i], recv_buf, SOCKET_TEST_MESSAGE_LENGTH, 0, NULL)); } - TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_close(poll_send_sock)); } -TEST_GROUP_RUNNER(socket_integration) +TEST_GROUP_RUNNER(socket_integration_udp) { TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_init(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS)); @@ -495,16 +472,16 @@ TEST_GROUP_RUNNER(socket_integration) #endif #endif - RUN_TEST_CASE(socket_integration, unicast_udp_ipv4); + RUN_TEST_CASE(socket_integration_udp, unicast_udp_ipv4); if (run_ipv4_mcast_test) - RUN_TEST_CASE(socket_integration, multicast_udp_ipv4); + RUN_TEST_CASE(socket_integration_udp, multicast_udp_ipv4); #if LWPA_TEST_IPV6 - RUN_TEST_CASE(socket_integration, unicast_udp_ipv6); + RUN_TEST_CASE(socket_integration_udp, unicast_udp_ipv6); if (run_ipv6_mcast_test) - RUN_TEST_CASE(socket_integration, multicast_udp_ipv6); + RUN_TEST_CASE(socket_integration_udp, multicast_udp_ipv6); #endif - RUN_TEST_CASE(socket_integration, bulk_poll); + RUN_TEST_CASE(socket_integration_udp, bulk_poll); lwpa_deinit(LWPA_FEATURE_SOCKETS | LWPA_FEATURE_NETINTS); } diff --git a/tests/integration/test_main.c b/tests/integration/test_main.c index 0fe19b2fd..9b48a612b 100644 --- a/tests/integration/test_main.c +++ b/tests/integration/test_main.c @@ -23,5 +23,5 @@ void run_all_tests(void) RUN_TEST_GROUP(mutex_integration); RUN_TEST_GROUP(rwlock_integration); RUN_TEST_GROUP(signal_integration); - RUN_TEST_GROUP(socket_integration); + RUN_TEST_GROUP(socket_integration_udp); } From 4ce63bc771624f7f633e9eea884b1e21dd1c5fcd Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 14:16:01 -0500 Subject: [PATCH 129/264] update all documentation --- README.md | 4 +- docs/interface_indexes.md | 1 + docs/mainpage.md | 63 +++++++++++++------ src/lwpa/lock.dox | 28 ++++----- src/lwpa/socket.dox | 13 ++-- .../FreeRTOS-lwIP-GNU-C-K65F180M.cmake | 55 ++++++++++++++++ .../Platform/FreeRTOS-lwIP.cmake | 8 +++ .../Platform/MQX-GNU-C-K61F120M.cmake | 29 +++++++++ .../Platform/MQX-IAR-C-K61F120M.cmake | 20 ++++++ .../cmake/cross-toolchains/Platform/MQX.cmake | 16 +++++ .../codewarrior-k61-mqx.cmake | 38 +++++++++++ .../codewarrior-kinetis-mqx.cmake | 63 ------------------- .../cross-toolchains/iar-kinetis-mqx.cmake | 43 +++++-------- .../mcuxpresso-k65-freertos-lwip.cmake | 38 +++++++++++ tools/cmake/net/lwip.cmake | 3 +- tools/cmake/os/freertos.cmake | 3 +- 16 files changed, 291 insertions(+), 134 deletions(-) create mode 100644 tools/cmake/cross-toolchains/Platform/FreeRTOS-lwIP-GNU-C-K65F180M.cmake create mode 100644 tools/cmake/cross-toolchains/Platform/FreeRTOS-lwIP.cmake create mode 100644 tools/cmake/cross-toolchains/Platform/MQX-GNU-C-K61F120M.cmake create mode 100644 tools/cmake/cross-toolchains/Platform/MQX-IAR-C-K61F120M.cmake create mode 100644 tools/cmake/cross-toolchains/Platform/MQX.cmake create mode 100644 tools/cmake/cross-toolchains/codewarrior-k61-mqx.cmake delete mode 100644 tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake create mode 100644 tools/cmake/cross-toolchains/mcuxpresso-k65-freertos-lwip.cmake diff --git a/README.md b/README.md index 3e789e1cb..13b2cda68 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,12 @@ The lwpa library serves two main purposes: ## Platform Ports lwpa is currently ported for the following platforms: ++ FreeRTOS + Linux ++ lwIP + macOS + Microsoft Windows -+ MQX RTOS ++ MQX ## Building diff --git a/docs/interface_indexes.md b/docs/interface_indexes.md index 93e0a5146..be359a2b8 100644 --- a/docs/interface_indexes.md +++ b/docs/interface_indexes.md @@ -35,4 +35,5 @@ or derived in each stack is listed below. | macOS | Standard / RFC 3493, can also be inferred from data in `ifconfig` and `netstat -rn` | | Microsoft Windows | Indicated in [IP_ADAPTER_ADDRESSES](https://docs.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh) structure, also visible via `route print` at command line | | Linux | Standard / RFC 3493, visible via `ip link` on newer/systemd systems, or can be inferred from data in `ifconfig` | +| lwIP | Standard / RFC 3493 as of lwIP 2.1.0. Also available using the lwIP API function netif_get_index(). | | MQX RTOS | The index is derived from the RTCS _device identifier_ (an index starting from 0 into a linked list of network interfaces) plus 1. This is translated internally for relevant socket calls. | diff --git a/docs/mainpage.md b/docs/mainpage.md index 05d361195..7d22fd441 100644 --- a/docs/mainpage.md +++ b/docs/mainpage.md @@ -8,8 +8,9 @@ modules to abstract common system calls. There are also a few platform-neutral utilities (i.e. data structures, logging) thrown in here and there for convenience. -lwpa modules are typically optimized for embedded platforms and thus designed -to be as thin a wrapper over the underlying OS functionality as possible. +lwpa modules are designed to run with low overhead on embedded platforms, and +thus are designed to be as thin a wrapper over the underlying OS functionality +as possible. To jump right into the documentation, check out the [Modules Overview](@ref lwpa). @@ -20,7 +21,7 @@ the sources for lwpa are located in the heirarchy: ``` src/ os/ - [OS name]/ + [OS or network stack provider]/ [platform-specific lwpa sources] [platform-neutral lwpa sources] ``` @@ -29,22 +30,36 @@ The includes are in the heirarchy: ``` include/ os/ - [OS name]/ + [OS or network stack provider]/ [platform-specific lwpa headers] [platform-neutral lwpa headers] ``` -Some lwpa headers are platform-specific and duplicated for each OS. +Some lwpa headers are platform-specific and duplicated for each platform. Platform-specific headers for the same module will always conform to an identical interface, as documented in that module's documentation. ## Supported Platforms -lwpa is currently ported for the following operating systems: +lwpa distinguishes between two major constructs which provide services to +applications. 'OS' targets provide threading, synchronization and other +utilities not provided by the C standard library. 'Network' targets provide a +network stack. + +lwpa is currently ported for the following OS targets: + ++ FreeRTOS ++ macOS ++ Microsoft Windows ++ Linux ++ MQX + +And the following network targets: + macOS + Microsoft Windows + Linux -+ MQX RTOS ++ lwIP ++ MQX (RTCS) ### Building lwpa for Your Platform @@ -62,9 +77,12 @@ To configure and build lwpa on its own using CMake, follow these steps: $ cd build ``` This directory can be inside or outside the lwpa repository. +3. Optionally, provide a CMake toolchain file for cross-compilation. Those + building native code can skip this step. There are some examples in + `tools/cmake/cross-toolchains`. 3. Run CMake to configure the lwpa project: ``` - $ cmake path/to/lwpa/root + $ cmake [-DCMAKE_TOOLCHAIN_FILE=path/to/toolchain/file] path/to/lwpa/root ``` You can optionally specify your build system with the `-G` option; otherwise, CMake will choose a system-appropriate default. Use `cmake --help` @@ -81,14 +99,14 @@ To configure and build lwpa on its own using CMake, follow these steps: ``` 5. To run the unit tests after building: ``` - # On Windows - > .\test\[Build_Configuration]\test_lwpa.exe - - # Elsewhere - $ ./test/test_lwpa + $ ctest [-C Configuration] ``` - Or, if you are generating IDE project files, simply run the test_lwpa - project from your IDE. + Or, if you are generating IDE project files, simply run the projects in the + 'tests' folder in your IDE. + + Alternatively, you can define `LWPA_TEST_BUILD_AS_LIBRARIES=ON` to compile + the unit and integration tests into static libraries, which is often useful + for running tests on embedded targets. Alternatively, if you don't want to use CMake, your project can simply build in the lwpa sources directly using the appropriate directories for your target @@ -97,9 +115,13 @@ platform. ### Platform Dependencies The platform ports of lwpa have the following dependencies: ++ FreeRTOS + - Tested back to FreeRTOS 9.0.0. Not guaranteed to work with older versions. + - Optional Features: + * lwpa_uuid: Creation of V1 and V4 UUIDs not implemented (not provided by + FreeRTOS). + macOS - - The macOS port has been tested back to macOS 10.11. It is not guaranteed to - work on older versions. + - Tested back to macOS 10.11. Not guaranteed to work with older versions. - If compiling with macOS 10.7 or earlier, you might need to install a UUID package like `ossp-uuid`. + Microsoft Windows @@ -110,8 +132,11 @@ The platform ports of lwpa have the following dependencies: * lwpa_socket (socket interface): Iphlpapi.lib, Ws2_32.lib * lwpa_uuid (UUID creation): Rpcrt4.lib * lwpa_timer (system timers): Winmm.lib -+ MQX RTOS ++ MQX - MQX 4.2.0 + - Optional Features: + * lwpa_uuid: Creation of V1 and V4 UUIDs not implemented (not provided by + MQX) + Linux - Optional Features: * lwpa_netint (network interfaces): Linux 2.2, glibc 2.3.3 @@ -119,3 +144,5 @@ The platform ports of lwpa have the following dependencies: * lwpa_uuid (UUID creation): libuuid (if compiling lwpa, use `sudo apt-get install uuid-dev` or the equivalent method for your distribution) ++ lwIP + - lwIP 2.1.0 or later diff --git a/src/lwpa/lock.dox b/src/lwpa/lock.dox index 756554c5b..7cf86e29e 100644 --- a/src/lwpa/lock.dox +++ b/src/lwpa/lock.dox @@ -20,13 +20,13 @@ macros, etc.), so the documentation needs somewhere to pull a standard interface * * lwpa_mutex implementations use the following constructs under the hood on various platforms: * - * | On: | lwpa_mutex uses: | - * |---------------|------------------| - * | FreeRTOS/lwIP | [Mutexes](https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html) | - * | Linux | [pthread_mutex](https://linux.die.net/man/3/pthread_mutex_init) | - * | macOS | [pthread_mutex](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/pthread_mutex_init.3.html) - * | MQX | Lightweight Semaphores | - * | Windows | [Critical Section objects](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx) | + * | On: | lwpa_mutex uses: | + * |----------|------------------| + * | FreeRTOS | [Mutexes](https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html) | + * | Linux | [pthread_mutex](https://linux.die.net/man/3/pthread_mutex_init) | + * | macOS | [pthread_mutex](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/pthread_mutex_init.3.html) + * | MQX | Lightweight Semaphores | + * | Windows | [Critical Section objects](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx) | * * @{ */ @@ -85,13 +85,13 @@ void lwpa_mutex_destroy(lwpa_mutex_t *id); * * lwpa_signal implementations use the following constructs under the hood on various platforms: * - * | On: | lwpa_mutex uses: | - * |---------------|------------------| - * | FreeRTOS/lwIP | [Binary Semaphores](https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html) | - * | Linux | [pthread_cond](https://linux.die.net/man/3/pthread_cond_init) | - * | macOS | [pthread_cond](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/pthread_cond_init.3.html) - * | MQX | Lightweight Events | - * | Windows | [Event objects](https://docs.microsoft.com/en-us/windows/desktop/sync/using-event-objects) | + * | On: | lwpa_mutex uses: | + * |----------|------------------| + * | FreeRTOS | [Binary Semaphores](https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html) | + * | Linux | [pthread_cond](https://linux.die.net/man/3/pthread_cond_init) | + * | macOS | [pthread_cond](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/pthread_cond_init.3.html) + * | MQX | Lightweight Events | + * | Windows | [Event objects](https://docs.microsoft.com/en-us/windows/desktop/sync/using-event-objects) | * * @{ */ diff --git a/src/lwpa/socket.dox b/src/lwpa/socket.dox index f0369ed3d..833f4c895 100644 --- a/src/lwpa/socket.dox +++ b/src/lwpa/socket.dox @@ -352,12 +352,13 @@ void lwpa_poll_remove_socket(LwpaPollContext *context, lwpa_socket_t socket); * * Uses OS-specific APIs for monitoring multiple sockets under the hood. Details: * - * | Platform: | API used: | Notes: | - * |-----------|-----------|--------| - * | Linux | epoll() | | - * | macOS | kqueue() | | - * | MQX | select() | #LWPA_SOCKET_MAX_POLL_SIZE is controlled by the RTCS config constant RTCSCFG_FD_SETSIZE. | - * | Windows | select() | #LWPA_SOCKET_MAX_POLL_SIZE defaults to 64, but can be increased by setting FD_SETSIZE=[new_value] as a compile-time definition. | + * | Platform: | API used: | Notes: | + * |-------------------|-----------|--------| + * | Linux | epoll() | | + * | lwIP | select() | #LWPA_SOCKET_MAX_POLL_SIZE is controlled by FD_SETSIZE which is in turn controlled by MEMP_NUM_NETCONN in lwipopts.h. | + * | macOS | kqueue() | | + * | MQX (RTCS) | select() | #LWPA_SOCKET_MAX_POLL_SIZE is controlled by the RTCS config constant RTCSCFG_FD_SETSIZE. | + * | Microsoft Windows | select() | #LWPA_SOCKET_MAX_POLL_SIZE defaults to 64, but can be increased by setting FD_SETSIZE=[new_value] as a compile-time definition. | * * \param[in] context Pointer to LwpaPollContext for which to wait for events. * \param[out] event On success, contains information about the event that occurred. diff --git a/tools/cmake/cross-toolchains/Platform/FreeRTOS-lwIP-GNU-C-K65F180M.cmake b/tools/cmake/cross-toolchains/Platform/FreeRTOS-lwIP-GNU-C-K65F180M.cmake new file mode 100644 index 000000000..deb76b2e9 --- /dev/null +++ b/tools/cmake/cross-toolchains/Platform/FreeRTOS-lwIP-GNU-C-K65F180M.cmake @@ -0,0 +1,55 @@ +# This file contains specific settings for compiling lwpa for a specific target, using a specific +# SDK and compiler. This is a convenient place to set up some global compile settings needed by +# everything compiled for this target with this SDK and toolchain. + +# This example uses an MCUXpresso SDK (mcuxpresso.nxp.com) built for the K65. +# Some of the options set below are required by the lwpa CMake target config. + +set(MCUX_SDK_DIR path/to/k65/sdk) + +set(LWPA_FREERTOS_INCLUDE_DIRS "${MCUX_SDK_DIR}/amazon-freertos/include;${MCUX_SDK_DIR}/amazon-freertos/freertos/portable" CACHE STRING "Override from toolchain file" FORCE) +set(LWPA_FREERTOSCONFIG_DIR path/to/freertosconfig/dot/h CACHE STRING "Override from toolchain file" FORCE) + +set(LWPA_LWIP_INCLUDE_DIRS "${MCUX_SDK_DIR}/lwip/src/include;${MCUX_SDK_DIR}/lwip/port" CACHE STRING "Override from toolchain file" FORCE) +set(LWPA_LWIPOPTS_DIR path/to/lwipopts/dot/h CACHE STRING "Override from toolchain file" FORCE) + +# Set up a global include of the SDK directories we are going to need. +include_directories( + ${MCUX_SDK_DIR}/utilities + ${MCUX_SDK_DIR}/drivers + ${MCUX_SDK_DIR}/CMSIS + ${MCUX_SDK_DIR}/component/serial_manager + ${MCUX_SDK_DIR}/device +) + +# Compile settings required to compile for this target with the MCUXpresso ARM GCC and Newlib +# toolchain. It's highly recommended that you make these match your project's build settings as +# closely as possible. In the Eclipse-based embedded IDEs that I typically use, I generally just +# grab a line of build output and add all the flags I see to these lines. +add_compile_definitions( + __NEWLIB__ + __STRICT_ANSI__ + CPU_MK65FN2M0VMI18 + CPU_MK65FN2M0VMI18_cm4 + SDK_DEBUGCONSOLE=1 + CR_INTEGER_PRINTF + PRINTF_FLOAT_ENABLE=0 + FSL_RTOS_FREE_RTOS + SDK_RTOS_FREE_RTOS + __MCUXPRESSO + __USE_CMSIS + USE_RTOS +) +add_compile_options( + -fno-common + -Wall + -ffunction-sections + -fdata-sections + -ffreestanding + -fno-builtin + -mcpu=cortex-m4 + -mfpu=fpv4-sp-d16 + -mfloat-abi=hard + -mthumb + -fstack-usage +) diff --git a/tools/cmake/cross-toolchains/Platform/FreeRTOS-lwIP.cmake b/tools/cmake/cross-toolchains/Platform/FreeRTOS-lwIP.cmake new file mode 100644 index 000000000..035569f3e --- /dev/null +++ b/tools/cmake/cross-toolchains/Platform/FreeRTOS-lwIP.cmake @@ -0,0 +1,8 @@ + +set(LWPA_OS_TARGET freertos CACHE STRING "Override from toolchain file" FORCE) +set(LWPA_NET_TARGET lwip CACHE STRING "Override from toolchain file" FORCE) + +set(LWPA_TEST_BUILD_AS_LIBRARIES ON CACHE BOOL "Override from toolchain file" FORCE) + +set(LWPA_BUILD_TESTS ON CACHE BOOL "Build the lwpa tests" FORCE) +set(LWPA_BUILD_EXAMPLES OFF CACHE BOOL "Build the lwpa examples" FORCE) diff --git a/tools/cmake/cross-toolchains/Platform/MQX-GNU-C-K61F120M.cmake b/tools/cmake/cross-toolchains/Platform/MQX-GNU-C-K61F120M.cmake new file mode 100644 index 000000000..ea3f0471d --- /dev/null +++ b/tools/cmake/cross-toolchains/Platform/MQX-GNU-C-K61F120M.cmake @@ -0,0 +1,29 @@ +# This file contains specific settings for compiling lwpa for a specific target, using a specific +# SDK and compiler. This is a convenient place to set up some global compile settings needed by +# everything compiled for this target with this SDK and toolchain. + +# This example uses MQX compiled for the K61 and a specific board. +# Some of the options set below are required by the lwpa CMake target config. + +# The MQX board directory usually takes the form [MQX_DIR]/lib/[board_name].cw10gcc +set(MQX_BOARD_DIR path/to/mqx/board/dir) + +# Compile settings required to compile for this target with the Codewarrior GCC and library +# toolchain. It's highly recommended that you make these match your project's build settings as +# closely as possible. In the Eclipse-based embedded IDEs that I typically use, I generally just +# grab a line of build output and add all the flags I see to these lines. +add_compile_options( + -nostdinc + -ffunction-sections + -fdata-sections + -Wall + -std=gnu99 + -fno-strict-aliasing + -fmessage-length=0 + -specs=ewl_c9x.specs +) +add_compile_definitions(_EWL_C99 _DEBUG) +include_directories( + ${CODEWARRIOR_INSTALL_DIR}/MCU/ARM_GCC_Support/ewl/EWL_C/include + ${CODEWARRIOR_INSTALL_DIR}/MCU/ARM_GCC_Support/ewl/EWL_Runtime/include +) diff --git a/tools/cmake/cross-toolchains/Platform/MQX-IAR-C-K61F120M.cmake b/tools/cmake/cross-toolchains/Platform/MQX-IAR-C-K61F120M.cmake new file mode 100644 index 000000000..18ff0b760 --- /dev/null +++ b/tools/cmake/cross-toolchains/Platform/MQX-IAR-C-K61F120M.cmake @@ -0,0 +1,20 @@ +# This file contains specific settings for compiling lwpa for a specific target, using a specific +# SDK and compiler. This is a convenient place to set up some global compile settings needed by +# everything compiled for this target with this SDK and toolchain. + +# This example uses MQX compiled for the K61 and a specific board. +# Some of the options set below are required by the lwpa CMake target config. + +# The MQX board directory usually takes the form [MQX_DIR]/lib/[board_name].iar +set(MQX_BOARD_DIR path/to/mqx/board/dir) + +# Compile settings required to compile for this target with the IAR C compiler and library +# toolchain. It's highly recommended that you make these match your project's build settings as +# closely as possible. In the Eclipse-based embedded IDEs that I typically use, I generally just +# grab a line of build output and add all the flags I see to these lines. +add_compile_options( + --endian=little + --cpu=Cortex-M4 + --fpu=VFPv4_sp + --dlib_config normal +) diff --git a/tools/cmake/cross-toolchains/Platform/MQX.cmake b/tools/cmake/cross-toolchains/Platform/MQX.cmake new file mode 100644 index 000000000..9a73d539f --- /dev/null +++ b/tools/cmake/cross-toolchains/Platform/MQX.cmake @@ -0,0 +1,16 @@ +# This file contains the settings that apply to targeting MQX as both an OS and +# network target with lwpa. + +set(LWPA_OS_TARGET mqx CACHE STRING "Override from toolchain file" FORCE) +set(LWPA_NET_TARGET mqx CACHE STRING "Override from toolchain file" FORCE) + +# Build the unit and integration tests as static libraries which can be linked into an on-target +# test executable +set(LWPA_BUILD_TESTS ON CACHE BOOL "Override from toolchain file" FORCE) +set(LWPA_TEST_BUILD_AS_LIBRARIES ON CACHE BOOL "Override from toolchain file" FORCE) + +# Alternatively, remove the above and uncomment this to simply turn the tests off +# set (LWPA_BUILD_TESTS OFF CACHE BOOL "Override from toolchain file" FORCE) + +# The examples will not build properly from CMake on this platform. +set(LWPA_BUILD_EXAMPLES OFF CACHE BOOL "Override from toolchain file" FORCE) diff --git a/tools/cmake/cross-toolchains/codewarrior-k61-mqx.cmake b/tools/cmake/cross-toolchains/codewarrior-k61-mqx.cmake new file mode 100644 index 000000000..51131239c --- /dev/null +++ b/tools/cmake/cross-toolchains/codewarrior-k61-mqx.cmake @@ -0,0 +1,38 @@ +# An example CMake toolchain file for cross-compiling for NXP Kinetis K61 (ARM Cortex-M4) with MQX +# RTOS and the CodeWarrior 10.6 gcc toolchain. +# +# You need to pick the type of build files that CMake generates (the Generator). If you have a +# build system already that uses GNU Make, or are building on a macOS or Unix-based host, +# "Unix Makefiles" will cover most cases. On Windows, you need to use a non-Visual-Studio generator. +# This requires you to have some kind of non-VS build system installed. Some options are: +# - MinGW64 (must be available on PATH) +# - Strawberry Perl (use 'Unix Makefiles' generator) +# - NMake (comes with VS, but must be in a developer command prompt) +# +# Usage: cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=path/to/this/file .. + +# Setting these names causes CMake to look in the Platform subdirectory for files called: +# Platform/MQX.cmake +# Platform/MQX-GNU-C-K61F120M.cmake +set(CMAKE_SYSTEM_NAME MQX) +set(CMAKE_SYSTEM_PROCESSOR K61F120M) + +if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) + message(FATAL_ERROR "CodeWarrior is Windows-only.") +endif() + +# The CodeWarrior installation directory, highly likely to require customization +set(CODEWARRIOR_INSTALL_DIR "C:/Freescale/CW MCU v10.6" CACHE STRING "The CodeWarrior install directory") + +set(TOOLS_DIR ${CODEWARRIOR_INSTALL_DIR}/Cross_Tools/arm-none-eabi-gcc-4_7_3) +set(CMAKE_C_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-gcc.exe CACHE FILEPATH "CodeWarrior/gcc C Compiler") +set(CMAKE_CXX_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-g++.exe CACHE FILEPATH "CodeWarrior/gcc C++ Compiler") + +# This tells CMake to use a static library program to do its minimal compiler +# test instead of an executable - this translates well to embedded toolchains. +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# If that doesn't work, you might need to comment the line above and uncomment +# this line to bypass the compiler checks. +# set(CMAKE_C_COMPILER_WORKS 1) +# set(CMAKE_CXX_COMPILER_WORKS 1) diff --git a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake deleted file mode 100644 index 4fd1e31e2..000000000 --- a/tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake +++ /dev/null @@ -1,63 +0,0 @@ -# A CMake toolchain file for cross-compiling for NXP Kinetis (ARM Cortex-M4) with MQX RTOS and the -# CodeWarrior 10.6 gcc toolchain. -# -# On Windows, you need to use a non-Visual-Studio generator. This requires you to have some kind of -# non-VS build system installed. Some options are: -# - MinGW64 (must be available on PATH) -# - Strawberry Perl (use 'Unix Makefiles' generator) -# - NMake (comes with VS, but must be in a developer command prompt) -# -# Usage: cmake -G "Unix Makefiles" \ -# -DCMAKE_TOOLCHAIN_FILE=../tools/cmake/cross-toolchains/codewarrior-kinetis-mqx.cmake \ -# -DMQX_BOARD_DIR=path/to/mqx/board/dir .. -# -# MQX_BOARD_DIR can also be set in this file so that it does not have to be provided at the command -# line, like so: -# set(MQX_BOARD_DIR ${CMAKE_CURRENT_LIST_DIR}/path/to/mqx/board/dir) - -set(CMAKE_SYSTEM_NAME Generic) # This is CMake's name for 'bare-metal' or RTOS environments -set(CMAKE_SYSTEM_PROCESSOR ARM) - -if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) - message(FATAL_ERROR "CodeWarrior is Windows-only.") -endif() - -if(NOT DEFINED CODEWARRIOR_INSTALL_DIR) - # The default install location on Windows. - # You may need to tweak the CodeWarrior version. - set(CODEWARRIOR_INSTALL_DIR "C:/Freescale/CW MCU v10.6") -endif() - -set(TOOLS_DIR ${CODEWARRIOR_INSTALL_DIR}/Cross_Tools/arm-none-eabi-gcc-4_7_3) -set(CMAKE_C_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-gcc.exe CACHE FILEPATH "CodeWarrior/gcc C Compiler") -set(CMAKE_CXX_COMPILER ${TOOLS_DIR}/bin/arm-none-eabi-g++.exe CACHE FILEPATH "CodeWarrior/gcc C++ Compiler") - -set(LWPA_TARGET_OS mqx) -add_compile_options( - -nostdinc - -ffunction-sections - -fdata-sections - -Wall - -std=gnu99 - -fno-strict-aliasing - -fmessage-length=0 - -specs=ewl_c9x.specs -) -add_compile_definitions(_EWL_C99 _DEBUG) -include_directories( - ${CODEWARRIOR_INSTALL_DIR}/MCU/ARM_GCC_Support/ewl/EWL_C/include - ${CODEWARRIOR_INSTALL_DIR}/MCU/ARM_GCC_Support/ewl/EWL_Runtime/include -) - -# This tells CMake to use a static library program to do its minimal compiler -# test instead of an executable - this translates well to embedded toolchains. -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) - -# If that doesn't work, you might need to comment the line above and uncomment -# this line to bypass the compiler checks. -# set(CMAKE_C_COMPILER_WORKS 1) -# set(CMAKE_CXX_COMPILER_WORKS 1) - -# The unit tests and examples will not build properly from CMake on this platform. -set(LWPA_BUILD_TESTS OFF CACHE BOOL "Build the lwpa unit tests" FORCE) -set(LWPA_BUILD_EXAMPLES OFF CACHE BOOL "Build the lwpa examples" FORCE) diff --git a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake index 39e938c67..e2adc0585 100644 --- a/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake +++ b/tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake @@ -1,44 +1,35 @@ # A CMake toolchain file for cross-compiling for NXP Kinetis (ARM Cortex-M4) with MQX RTOS and the # IAR Embedded Workbench toolchain. # -# On Windows, you need to use a non-Visual-Studio generator. This requires you to have some kind of -# non-VS build system installed. Some options are: +# You need to pick the type of build files that CMake generates (the Generator). If you have a +# build system already that uses GNU Make, or are building on a macOS or Unix-based host, +# "Unix Makefiles" will cover most cases. On Windows, you need to use a non-Visual-Studio generator. +# This requires you to have some kind of non-VS build system installed. Some options are: # - MinGW64 (must be available on PATH) # - Strawberry Perl (use 'Unix Makefiles' generator) # - NMake (comes with VS, but must be in a developer command prompt) # -# Usage: cmake -G "Unix Makefiles" \ -# -DCMAKE_TOOLCHAIN_FILE=../tools/cmake/cross-toolchains/iar-kinetis-mqx.cmake \ -# -DMQX_BOARD_DIR=path/to/mqx/board/dir .. -# -# MQX_BOARD_DIR can also be set in this file so that it does not have to be provided at the command -# line, like so: -# set(MQX_BOARD_DIR ${CMAKE_CURRENT_LIST_DIR}/path/to/mqx/board/dir) +# Usage: cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=path/to/this/file .. + +# Setting these names causes CMake to look in the Platform subdirectory for files called: +# Platform/MQX.cmake +# Platform/MQX-IAR-C-K61F120M.cmake +set(CMAKE_SYSTEM_NAME MQX) +set(CMAKE_SYSTEM_PROCESSOR K61F120M) -set(CMAKE_SYSTEM_NAME Generic) # This is CMake's name for 'bare-metal' or RTOS environments -set(CMAKE_SYSTEM_PROCESSOR ARM) +# Set this to the location of the Platform subdirectory containing the platform files. +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) if(NOT ${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) message(FATAL_ERROR "IAR is Windows-only.") endif() -if(NOT DEFINED IAR_INSTALL_DIR) - # The default install location on Windows. - # You may need to tweak the IAR version. - set(IAR_INSTALL_DIR "C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.5") -endif() +# The IAR installation directory, highly likely to require customization +set(IAR_INSTALL_DIR "C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.5" CACHE STRING "The IAR install directory") set(CMAKE_C_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe CACHE FILEPATH "IAR C Compiler") set(CMAKE_CXX_COMPILER ${IAR_INSTALL_DIR}/arm/bin/iccarm.exe CACHE FILEPATH "IAR C++ Compiler") -set(LWPA_TARGET_OS mqx) -add_compile_options( - --endian=little - --cpu=Cortex-M4 - --fpu=VFPv4_sp - --dlib_config normal -) - # This tells CMake to use a static library program to do its minimal compiler # test instead of an executable - this translates well to embedded toolchains. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) @@ -47,7 +38,3 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # this line to bypass the compiler checks. # set(CMAKE_C_COMPILER_WORKS 1) # set(CMAKE_CXX_COMPILER_WORKS 1) - -# The unit tests and examples will not build properly from CMake on this platform. -set(LWPA_BUILD_TESTS OFF CACHE BOOL "Build the lwpa unit tests" FORCE) -set(LWPA_BUILD_EXAMPLES OFF CACHE BOOL "Build the lwpa examples" FORCE) diff --git a/tools/cmake/cross-toolchains/mcuxpresso-k65-freertos-lwip.cmake b/tools/cmake/cross-toolchains/mcuxpresso-k65-freertos-lwip.cmake new file mode 100644 index 000000000..8ee3af4ea --- /dev/null +++ b/tools/cmake/cross-toolchains/mcuxpresso-k65-freertos-lwip.cmake @@ -0,0 +1,38 @@ +# A CMake toolchain file for cross-compiling for NXP Kinetis K65 (ARM Cortex-M4) with FreeRTOS, lwIP +# and the MCUXpresso gcc toolchain. +# +# You need to pick the type of build files that CMake generates (the Generator). If you have a +# build system already that uses GNU Make, or are building on a macOS or Unix-based host, +# "Unix Makefiles" will cover most cases. On Windows, you need to use a non-Visual-Studio generator. +# This requires you to have some kind of non-VS build system installed. Some options are: +# - MinGW64 (must be available on PATH) +# - Strawberry Perl (use 'Unix Makefiles' generator) +# - NMake (comes with VS, but must be in a developer command prompt) +# +# Usage: cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=path/to/this/file .. + +# Setting these names causes CMake to look in the Platform subdirectory for files called: +# Platform/FreeRTOS-lwIP.cmake +# Platform/FreeRTOS-lwIP-GNU-C-K65F180M.cmake +set(CMAKE_SYSTEM_NAME FreeRTOS-lwIP) +set(CMAKE_SYSTEM_PROCESSOR K65F180M) + +# Set this to the location of the Platform subdirectory containing the platform files. +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +# The MCUXpresso installation directory, highly likely to require customization +if(WIN32) + set(MCUXPRESSO_DEFAULT_INSTALL_DIR "C:/nxp/MCUXpressoIDE_11.0.0_2516") +endif() +set(MCUXPRESSO_INSTALL_DIR "${MCUXPRESSO_DEFAULT_INSTALL_DIR}" CACHE STRING "The MCUXpresso install directory") + +set(CMAKE_C_COMPILER ${MCUXPRESSO_INSTALL_DIR}/ide/tools/bin/arm-none-eabi-gcc.exe CACHE FILEPATH "MCUXpresso ARM GCC Compiler") + +# This tells CMake to use a static library program to do its minimal compiler +# test instead of an executable - this translates well to embedded toolchains. +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# If that doesn't work, you might need to comment the line above and uncomment +# this line to bypass the compiler checks. +# set(CMAKE_C_COMPILER_WORKS 1) +# set(CMAKE_CXX_COMPILER_WORKS 1) diff --git a/tools/cmake/net/lwip.cmake b/tools/cmake/net/lwip.cmake index 61306bacf..21d855260 100644 --- a/tools/cmake/net/lwip.cmake +++ b/tools/cmake/net/lwip.cmake @@ -4,8 +4,7 @@ set(LWPA_LWIP_INCLUDE_DIRS "" CACHE STRING "The include directories for the lwIP set(LWPA_LWIPOPTS_DIR "" CACHE STRING "The directory of the project's lwipopts.h file") if(NOT LWPA_LWIP_INCLUDE_DIRS OR NOT LWPA_LWIPOPTS_DIR) message(FATAL_ERROR "You must provide the options LWPA_LWIP_INCLUDE_DIRS to specify the lwIP include directories " - "and LWPA_LWIPOPTS_DIR to specify the location of the lwipopts.h file." - ) + "and LWPA_LWIPOPTS_DIR to specify the location of the lwipopts.h file.") endif() set(LWPA_NET_ADDITIONAL_SOURCES diff --git a/tools/cmake/os/freertos.cmake b/tools/cmake/os/freertos.cmake index 96a59a1aa..84b73c281 100644 --- a/tools/cmake/os/freertos.cmake +++ b/tools/cmake/os/freertos.cmake @@ -4,8 +4,7 @@ set(LWPA_FREERTOS_INCLUDE_DIRS "" CACHE STRING "The include directory for the Fr set(LWPA_FREERTOSCONFIG_DIR "" CACHE STRING "The directory of the project's FreeRTOSConfig.h file") if(NOT LWPA_FREERTOS_INCLUDE_DIRS OR NOT LWPA_FREERTOSCONFIG_DIR) message(FATAL_ERROR "You must provide the options LWPA_FREERTOS_INCLUDE_DIRS to specify the FreeRTOS include directories " - "and LWPA_FREERTOSCONFIG_DIR to specify the location of the FreeRTOSConfig.h." - ) + "and LWPA_FREERTOSCONFIG_DIR to specify the location of the FreeRTOSConfig.h.") endif() set(LWPA_OS_ADDITIONAL_INCLUDE_DIRS ${LWPA_FREERTOS_INCLUDE_DIRS} ${LWPA_FREERTOSCONFIG_DIR}) From eaac3edadaee01e3694b2f10a53bd7a4fc74da1a Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 14:17:35 -0500 Subject: [PATCH 130/264] Small clarification in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 13b2cda68..8f038205a 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,9 @@ The lwpa library serves two main purposes: ## Platform Ports lwpa is currently ported for the following platforms: -+ FreeRTOS ++ FreeRTOS (OS abstraction only) + Linux -+ lwIP ++ lwIP (Network abstraction only) + macOS + Microsoft Windows + MQX From ba481ca2c13db02769a210bc58e13b3ffba33e0b Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 15:02:59 -0500 Subject: [PATCH 131/264] LWPA-25 fix and add test --- src/lwpa/rbtree.c | 15 ++++++++++++++- tests/unit/live/test_rbtree.c | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/lwpa/rbtree.c b/src/lwpa/rbtree.c index 93663c736..9db477726 100644 --- a/src/lwpa/rbtree.c +++ b/src/lwpa/rbtree.c @@ -216,9 +216,22 @@ lwpa_error_t lwpa_rbtree_insert(LwpaRbTree* self, void* value) { LwpaRbNode* new_node = rb_node_create(self, value); if (new_node) - return lwpa_rbtree_insert_node(self, new_node); + { + lwpa_error_t insert_res = lwpa_rbtree_insert_node(self, new_node); + if (insert_res == kLwpaErrOk) + { + return kLwpaErrOk; + } + else + { + rb_node_dealloc(new_node, self); + return insert_res; + } + } else + { return kLwpaErrNoMem; + } } /*! \brief Insert a node containing a new value into a red-black tree. diff --git a/tests/unit/live/test_rbtree.c b/tests/unit/live/test_rbtree.c index 9eab9d10c..eaff2e603 100644 --- a/tests/unit/live/test_rbtree.c +++ b/tests/unit/live/test_rbtree.c @@ -191,6 +191,23 @@ TEST(lwpa_rbtree, insert_should_fail_if_element_already_exists) TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_insert(&tree, &duplicate)); } +TEST(lwpa_rbtree, insert_failure_should_not_leak_memory) +{ + LwpaRbTree tree; + TEST_ASSERT_NOT_NULL(lwpa_rbtree_init(&tree, int_compare, node_alloc, node_dealloc)); + + // Insert a value, then try to insert it again + int val = 0; + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_insert(&tree, &val)); + TEST_ASSERT_EQUAL(kLwpaErrExists, lwpa_rbtree_insert(&tree, &val)); + + // Now clear the tree + TEST_ASSERT_EQUAL(kLwpaErrOk, lwpa_rbtree_clear(&tree)); + + // The alloc and dealloc count should be equal - no memory should be leaked + TEST_ASSERT_EQUAL(node_alloc_fake.call_count, node_dealloc_fake.call_count); +} + TEST(lwpa_rbtree, iterators_work_as_expected) { LwpaRbTree tree; @@ -276,6 +293,7 @@ TEST_GROUP_RUNNER(lwpa_rbtree) RUN_TEST_CASE(lwpa_rbtree, insert_node_functions_work); RUN_TEST_CASE(lwpa_rbtree, insert_functions_work); RUN_TEST_CASE(lwpa_rbtree, insert_should_fail_if_element_already_exists); + RUN_TEST_CASE(lwpa_rbtree, insert_failure_should_not_leak_memory); RUN_TEST_CASE(lwpa_rbtree, iterators_work_as_expected); RUN_TEST_CASE(lwpa_rbtree, max_height_is_within_bounds); } From 7df5fb8aee3791c078bab292b19665291aecf26d Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 15:07:52 -0500 Subject: [PATCH 132/264] Update version files for lwpa build 0.3.0.2 --- include/lwpa/version.h | 6 +++--- tools/version/current_version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/lwpa/version.h b/include/lwpa/version.h index 3d8ff58df..bd335498f 100644 --- a/include/lwpa/version.h +++ b/include/lwpa/version.h @@ -32,14 +32,14 @@ #define LWPA_VERSION_MAJOR 0 #define LWPA_VERSION_MINOR 3 #define LWPA_VERSION_PATCH 0 -#define LWPA_VERSION_BUILD 1 +#define LWPA_VERSION_BUILD 2 /*! @} */ /*! \name lwpa version strings * @{ */ -#define LWPA_VERSION_STRING "0.3.0.1" -#define LWPA_VERSION_DATESTR "19.Jun.2019" +#define LWPA_VERSION_STRING "0.3.0.2" +#define LWPA_VERSION_DATESTR "04.Sep.2019" #define LWPA_VERSION_COPYRIGHT "Copyright 2019 ETC Inc." #define LWPA_VERSION_PRODUCTNAME "lwpa" /*! @} */ diff --git a/tools/version/current_version.txt b/tools/version/current_version.txt index fd72fe621..dac240a9a 100644 --- a/tools/version/current_version.txt +++ b/tools/version/current_version.txt @@ -1 +1 @@ -0.3.0.1 +0.3.0.2 From 28013052c4f89f648aa4e16f8034c4729bf08f15 Mon Sep 17 00:00:00 2001 From: Sam Kearney Date: Wed, 4 Sep 2019 18:59:45 -0500 Subject: [PATCH 133/264] Rename library to EtcPal (#9) Replace all "lwpa" names with their "EtcPal" variants. --- CHANGELOG.md | 53 +- CMakeLists.txt | 18 +- CONTRIBUTING.md | 10 +- README.md | 25 +- ThirdPartySoftware.txt | 6 +- azure-pipelines.yml | 32 +- docs/Doxyfile | 10 +- docs/etcpal.tag | 3197 +++++++++++++++++ docs/header.html | 4 +- docs/interface_indexes.md | 14 +- docs/lwpa.tag | 3135 ---------------- docs/mainpage.md | 79 +- examples/netint/CMakeLists.txt | 4 +- examples/netint/netint_example.c | 58 +- include/{lwpa => etcpal}/acn_prot.h | 6 +- include/{lwpa => etcpal}/bool.h | 18 +- include/etcpal/common.h | 91 + include/{lwpa => etcpal}/error.h | 90 +- include/etcpal/inet.h | 226 ++ include/{lwpa => etcpal}/int.h | 20 +- include/{lwpa => etcpal}/lock.h | 66 +- include/etcpal/log.h | 276 ++ include/{lwpa => etcpal}/mempool.h | 118 +- include/etcpal/netint.h | 57 + include/{lwpa => etcpal}/pack.h | 38 +- include/{lwpa => etcpal}/pack64.h | 24 +- include/{lwpa => etcpal}/pdu.h | 80 +- include/etcpal/rbtree.h | 186 + include/{lwpa => etcpal}/root_layer_pdu.h | 60 +- include/etcpal/socket.h | 261 ++ include/{lwpa => etcpal}/thread.h | 32 +- include/{lwpa => etcpal}/timer.h | 38 +- include/{lwpa => etcpal}/uuid.h | 66 +- include/{lwpa => etcpal}/version.h | 94 +- include/etcpal_mock/socket.h | 100 + include/lwpa/common.h | 87 - include/lwpa/inet.h | 225 -- include/lwpa/log.h | 276 -- include/lwpa/netint.h | 57 - include/lwpa/rbtree.h | 185 - include/lwpa/socket.h | 259 -- include/lwpa_mock/socket.h | 98 - include/os/freertos/etcpal/os_lock.h | 68 + .../os/freertos/{lwpa => etcpal}/os_thread.h | 24 +- include/os/freertos/lwpa/os_lock.h | 68 - include/os/linux/{lwpa => etcpal}/os_inet.h | 14 +- include/os/linux/etcpal/os_lock.h | 73 + include/os/linux/{lwpa => etcpal}/os_socket.h | 32 +- include/os/linux/{lwpa => etcpal}/os_thread.h | 24 +- include/os/linux/lwpa/os_lock.h | 73 - include/os/lwip/{lwpa => etcpal}/os_inet.h | 15 +- include/os/lwip/{lwpa => etcpal}/os_socket.h | 46 +- include/os/macos/{lwpa => etcpal}/os_inet.h | 14 +- include/os/macos/etcpal/os_lock.h | 73 + include/os/macos/{lwpa => etcpal}/os_socket.h | 32 +- include/os/macos/{lwpa => etcpal}/os_thread.h | 24 +- include/os/macos/lwpa/os_lock.h | 73 - include/os/mqx/{lwpa => etcpal}/os_inet.h | 14 +- include/os/mqx/etcpal/os_lock.h | 68 + include/os/mqx/{lwpa => etcpal}/os_socket.h | 48 +- include/os/mqx/{lwpa => etcpal}/os_thread.h | 32 +- include/os/mqx/lwpa/os_lock.h | 68 - include/os/windows/{lwpa => etcpal}/os_inet.h | 14 +- include/os/windows/{lwpa => etcpal}/os_lock.h | 56 +- .../os/windows/{lwpa => etcpal}/os_socket.h | 48 +- .../os/windows/{lwpa => etcpal}/os_thread.h | 30 +- src/CMakeLists.txt | 276 +- src/{lwpa => etcpal}/common.c | 85 +- src/etcpal/error.c | 57 + src/{lwpa => etcpal}/inet.c | 184 +- src/{lwpa => etcpal}/lock.dox | 84 +- src/{lwpa => etcpal}/log.c | 150 +- src/{lwpa => etcpal}/md5.c | 0 src/{lwpa => etcpal}/md5.h | 2 +- src/{lwpa => etcpal}/mempool.c | 48 +- src/{lwpa => etcpal}/netint.c | 97 +- src/{lwpa => etcpal}/pack.c | 36 +- src/{lwpa => etcpal}/pdu.c | 20 +- src/{lwpa => etcpal}/private/log.h | 16 +- src/{lwpa => etcpal}/private/netint.h | 24 +- src/{lwpa => etcpal}/private/opts.h | 48 +- src/{lwpa => etcpal}/private/socket.h | 16 +- src/{lwpa => etcpal}/private/timer.h | 16 +- src/{lwpa => etcpal}/rbtree.c | 234 +- src/{lwpa => etcpal}/root_layer_pdu.c | 134 +- src/{lwpa => etcpal}/socket.dox | 282 +- src/{lwpa => etcpal}/thread.dox | 42 +- src/{lwpa => etcpal}/timer.c | 40 +- src/{lwpa => etcpal}/uuid.c | 86 +- src/etcpal_mock/socket.c | 50 + src/lwpa/error.c | 57 - src/lwpa_mock/socket.c | 50 - src/os/freertos/{lwpa => etcpal}/os_lock.c | 58 +- src/os/freertos/{lwpa => etcpal}/os_thread.c | 14 +- src/os/freertos/{lwpa => etcpal}/os_timer.c | 16 +- src/os/freertos/{lwpa => etcpal}/os_uuid.c | 14 +- src/os/linux/{lwpa => etcpal}/os_error.c | 52 +- .../{macos/lwpa => linux/etcpal}/os_error.h | 14 +- src/os/linux/{lwpa => etcpal}/os_inet.c | 78 +- src/os/linux/{lwpa => etcpal}/os_lock.c | 40 +- src/os/linux/{lwpa => etcpal}/os_netint.c | 186 +- src/os/linux/{lwpa => etcpal}/os_socket.c | 489 +-- .../{macos/lwpa => linux/etcpal}/os_thread.c | 14 +- src/os/linux/{lwpa => etcpal}/os_timer.c | 18 +- src/os/linux/{lwpa => etcpal}/os_uuid.c | 30 +- src/os/lwip/{lwpa => etcpal}/os_error.c | 64 +- src/os/lwip/{lwpa => etcpal}/os_error.h | 16 +- src/os/lwip/{lwpa => etcpal}/os_inet.c | 80 +- src/os/lwip/{lwpa => etcpal}/os_netint.c | 76 +- src/os/lwip/{lwpa => etcpal}/os_socket.c | 480 +-- src/os/macos/{lwpa => etcpal}/os_error.c | 55 +- .../{linux/lwpa => macos/etcpal}/os_error.h | 14 +- src/os/macos/{lwpa => etcpal}/os_inet.c | 78 +- src/os/macos/{lwpa => etcpal}/os_lock.c | 40 +- src/os/macos/{lwpa => etcpal}/os_netint.c | 178 +- src/os/macos/{lwpa => etcpal}/os_socket.c | 514 +-- .../{linux/lwpa => macos/etcpal}/os_thread.c | 14 +- src/os/macos/{lwpa => etcpal}/os_timer.c | 16 +- src/os/macos/{lwpa => etcpal}/os_uuid.c | 30 +- src/os/mqx/{lwpa => etcpal}/os_common.c | 0 src/os/mqx/{lwpa => etcpal}/os_inet.c | 78 +- src/os/mqx/{lwpa => etcpal}/os_lock.c | 32 +- src/os/mqx/{lwpa => etcpal}/os_netint.c | 30 +- src/os/mqx/etcpal/os_socket.c | 846 +++++ src/os/mqx/{lwpa => etcpal}/os_thread.c | 20 +- src/os/mqx/{lwpa => etcpal}/os_timer.c | 16 +- src/os/mqx/{lwpa => etcpal}/os_uuid.c | 14 +- src/os/mqx/lwpa/os_socket.c | 846 ----- src/os/windows/{lwpa => etcpal}/os_error.c | 48 +- src/os/windows/{lwpa => etcpal}/os_error.h | 14 +- src/os/windows/{lwpa => etcpal}/os_inet.c | 82 +- src/os/windows/{lwpa => etcpal}/os_lock.c | 44 +- src/os/windows/{lwpa => etcpal}/os_netint.c | 66 +- src/os/windows/etcpal/os_socket.c | 1019 ++++++ src/os/windows/{lwpa => etcpal}/os_thread.c | 14 +- src/os/windows/{lwpa => etcpal}/os_timer.c | 24 +- src/os/windows/{lwpa => etcpal}/os_uuid.c | 40 +- src/os/windows/lwpa/os_socket.c | 1019 ------ tests/CMakeLists.txt | 56 +- tests/entrypoint/main_default.c | 4 +- tests/integration/CMakeLists.txt | 12 +- tests/integration/mutex_integration_test.c | 28 +- tests/integration/rwlock_integration_test.c | 42 +- tests/integration/signal_integration_test.c | 30 +- tests/integration/socket_integration_test.c | 338 +- tests/integration/test_main.c | 4 +- tests/unit/live/CMakeLists.txt | 4 +- tests/unit/live/test_common.c | 94 +- tests/unit/live/test_inet.c | 402 +-- tests/unit/live/test_lock.c | 82 +- tests/unit/live/test_log.c | 290 +- tests/unit/live/test_main.c | 28 +- tests/unit/live/test_mempool.c | 54 +- tests/unit/live/test_netint.c | 102 +- tests/unit/live/test_pack.c | 66 +- tests/unit/live/test_rbtree.c | 154 +- tests/unit/live/test_socket.c | 354 +- tests/unit/live/test_thread.c | 56 +- tests/unit/live/test_timer.c | 62 +- tests/unit/live/test_uuid.c | 146 +- tests/unit/timer/CMakeLists.txt | 8 +- tests/unit/timer/test_timer_wraparound.c | 40 +- .../FreeRTOS-lwIP-GNU-C-K65F180M.cmake | 12 +- .../Platform/FreeRTOS-lwIP.cmake | 10 +- .../Platform/MQX-GNU-C-K61F120M.cmake | 4 +- .../Platform/MQX-IAR-C-K61F120M.cmake | 4 +- .../cmake/cross-toolchains/Platform/MQX.cmake | 14 +- tools/cmake/etcpal-os.cmake | 56 + tools/cmake/lwpa-os.cmake | 56 - tools/cmake/net/lwip.cmake | 21 +- tools/cmake/os/freertos.cmake | 15 +- tools/cmake/os/linux.cmake | 10 +- tools/cmake/os/macos.cmake | 8 +- tools/cmake/os/mqx.cmake | 7 +- tools/cmake/os/windows.cmake | 10 +- tools/version/create_build.py | 38 +- tools/version/release_checklist.md | 4 +- tools/version/templates/version.h.in | 34 +- 178 files changed, 11364 insertions(+), 11269 deletions(-) create mode 100644 docs/etcpal.tag delete mode 100644 docs/lwpa.tag rename include/{lwpa => etcpal}/acn_prot.h (91%) rename include/{lwpa => etcpal}/bool.h (87%) create mode 100644 include/etcpal/common.h rename include/{lwpa => etcpal}/error.h (69%) create mode 100644 include/etcpal/inet.h rename include/{lwpa => etcpal}/int.h (88%) rename include/{lwpa => etcpal}/lock.h (57%) create mode 100644 include/etcpal/log.h rename include/{lwpa => etcpal}/mempool.h (50%) create mode 100644 include/etcpal/netint.h rename include/{lwpa => etcpal}/pack.h (63%) rename include/{lwpa => etcpal}/pack64.h (64%) rename include/{lwpa => etcpal}/pdu.h (71%) create mode 100644 include/etcpal/rbtree.h rename include/{lwpa => etcpal}/root_layer_pdu.h (64%) create mode 100644 include/etcpal/socket.h rename include/{lwpa => etcpal}/thread.h (60%) rename include/{lwpa => etcpal}/timer.h (68%) rename include/{lwpa => etcpal}/uuid.h (53%) rename include/{lwpa => etcpal}/version.h (58%) create mode 100644 include/etcpal_mock/socket.h delete mode 100644 include/lwpa/common.h delete mode 100644 include/lwpa/inet.h delete mode 100644 include/lwpa/log.h delete mode 100644 include/lwpa/netint.h delete mode 100644 include/lwpa/rbtree.h delete mode 100644 include/lwpa/socket.h delete mode 100644 include/lwpa_mock/socket.h create mode 100644 include/os/freertos/etcpal/os_lock.h rename include/os/freertos/{lwpa => etcpal}/os_thread.h (68%) delete mode 100644 include/os/freertos/lwpa/os_lock.h rename include/os/linux/{lwpa => etcpal}/os_inet.h (75%) create mode 100644 include/os/linux/etcpal/os_lock.h rename include/os/linux/{lwpa => etcpal}/os_socket.h (63%) rename include/os/linux/{lwpa => etcpal}/os_thread.h (64%) delete mode 100644 include/os/linux/lwpa/os_lock.h rename include/os/lwip/{lwpa => etcpal}/os_inet.h (75%) rename include/os/lwip/{lwpa => etcpal}/os_socket.h (57%) rename include/os/macos/{lwpa => etcpal}/os_inet.h (75%) create mode 100644 include/os/macos/etcpal/os_lock.h rename include/os/macos/{lwpa => etcpal}/os_socket.h (65%) rename include/os/macos/{lwpa => etcpal}/os_thread.h (64%) delete mode 100644 include/os/macos/lwpa/os_lock.h rename include/os/mqx/{lwpa => etcpal}/os_inet.h (75%) create mode 100644 include/os/mqx/etcpal/os_lock.h rename include/os/mqx/{lwpa => etcpal}/os_socket.h (56%) rename include/os/mqx/{lwpa => etcpal}/os_thread.h (63%) delete mode 100644 include/os/mqx/lwpa/os_lock.h rename include/os/windows/{lwpa => etcpal}/os_inet.h (76%) rename include/os/windows/{lwpa => etcpal}/os_lock.h (54%) rename include/os/windows/{lwpa => etcpal}/os_socket.h (61%) rename include/os/windows/{lwpa => etcpal}/os_thread.h (69%) rename src/{lwpa => etcpal}/common.c (51%) create mode 100644 src/etcpal/error.c rename src/{lwpa => etcpal}/inet.c (57%) rename src/{lwpa => etcpal}/lock.dox (75%) rename src/{lwpa => etcpal}/log.c (66%) rename src/{lwpa => etcpal}/md5.c (100%) rename src/{lwpa => etcpal}/md5.h (98%) rename src/{lwpa => etcpal}/mempool.c (64%) rename src/{lwpa => etcpal}/netint.c (69%) rename src/{lwpa => etcpal}/pack.c (88%) rename src/{lwpa => etcpal}/pdu.c (84%) rename src/{lwpa => etcpal}/private/log.h (74%) rename src/{lwpa => etcpal}/private/netint.h (67%) rename src/{lwpa => etcpal}/private/opts.h (52%) rename src/{lwpa => etcpal}/private/socket.h (73%) rename src/{lwpa => etcpal}/private/timer.h (73%) rename src/{lwpa => etcpal}/rbtree.c (69%) rename src/{lwpa => etcpal}/root_layer_pdu.c (74%) rename src/{lwpa => etcpal}/socket.dox (54%) rename src/{lwpa => etcpal}/thread.dox (64%) rename src/{lwpa => etcpal}/timer.c (60%) rename src/{lwpa => etcpal}/uuid.c (69%) create mode 100644 src/etcpal_mock/socket.c delete mode 100644 src/lwpa/error.c delete mode 100644 src/lwpa_mock/socket.c rename src/os/freertos/{lwpa => etcpal}/os_lock.c (71%) rename src/os/freertos/{lwpa => etcpal}/os_thread.c (79%) rename src/os/freertos/{lwpa => etcpal}/os_timer.c (79%) rename src/os/freertos/{lwpa => etcpal}/os_uuid.c (75%) rename src/os/linux/{lwpa => etcpal}/os_error.c (66%) rename src/os/{macos/lwpa => linux/etcpal}/os_error.h (75%) rename src/os/linux/{lwpa => etcpal}/os_inet.c (58%) rename src/os/linux/{lwpa => etcpal}/os_lock.c (82%) rename src/os/linux/{lwpa => etcpal}/os_netint.c (71%) rename src/os/linux/{lwpa => etcpal}/os_socket.c (51%) rename src/os/{macos/lwpa => linux/etcpal}/os_thread.c (80%) rename src/os/linux/{lwpa => etcpal}/os_timer.c (79%) rename src/os/linux/{lwpa => etcpal}/os_uuid.c (64%) rename src/os/lwip/{lwpa => etcpal}/os_error.c (64%) rename src/os/lwip/{lwpa => etcpal}/os_error.h (75%) rename src/os/lwip/{lwpa => etcpal}/os_inet.c (59%) rename src/os/lwip/{lwpa => etcpal}/os_netint.c (65%) rename src/os/lwip/{lwpa => etcpal}/os_socket.c (50%) rename src/os/macos/{lwpa => etcpal}/os_error.c (59%) rename src/os/{linux/lwpa => macos/etcpal}/os_error.h (75%) rename src/os/macos/{lwpa => etcpal}/os_inet.c (58%) rename src/os/macos/{lwpa => etcpal}/os_lock.c (82%) rename src/os/macos/{lwpa => etcpal}/os_netint.c (80%) rename src/os/macos/{lwpa => etcpal}/os_socket.c (51%) rename src/os/{linux/lwpa => macos/etcpal}/os_thread.c (80%) rename src/os/macos/{lwpa => etcpal}/os_timer.c (81%) rename src/os/macos/{lwpa => etcpal}/os_uuid.c (66%) rename src/os/mqx/{lwpa => etcpal}/os_common.c (100%) rename src/os/mqx/{lwpa => etcpal}/os_inet.c (65%) rename src/os/mqx/{lwpa => etcpal}/os_lock.c (79%) rename src/os/mqx/{lwpa => etcpal}/os_netint.c (71%) create mode 100644 src/os/mqx/etcpal/os_socket.c rename src/os/mqx/{lwpa => etcpal}/os_thread.c (76%) rename src/os/mqx/{lwpa => etcpal}/os_timer.c (79%) rename src/os/mqx/{lwpa => etcpal}/os_uuid.c (75%) delete mode 100644 src/os/mqx/lwpa/os_socket.c rename src/os/windows/{lwpa => etcpal}/os_error.c (72%) rename src/os/windows/{lwpa => etcpal}/os_error.h (76%) rename src/os/windows/{lwpa => etcpal}/os_inet.c (57%) rename src/os/windows/{lwpa => etcpal}/os_lock.c (77%) rename src/os/windows/{lwpa => etcpal}/os_netint.c (75%) create mode 100644 src/os/windows/etcpal/os_socket.c rename src/os/windows/{lwpa => etcpal}/os_thread.c (85%) rename src/os/windows/{lwpa => etcpal}/os_timer.c (65%) rename src/os/windows/{lwpa => etcpal}/os_uuid.c (60%) delete mode 100644 src/os/windows/lwpa/os_socket.c create mode 100644 tools/cmake/etcpal-os.cmake delete mode 100644 tools/cmake/lwpa-os.cmake diff --git a/CHANGELOG.md b/CHANGELOG.md index 30dba15c6..c33964d05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,38 +1,47 @@ # Changelog -All notable changes to the lwpa library will be documented in this file. +All notable changes to the EtcPal library will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Added -- OS port: Linux -- OS port: macOS -- lwpa_init() in lwpa/common.h. lwpa_init() must be called before using features - defined by feature macros defined in lwpa/common.h. +- New port: Linux +- New port: macOS +- New port: FreeRTOS +- New port: lwIP +- etcpal_init() in etcpal/common.h. etcpal_init() must be called before using + features defined by feature macros defined in etcpal/common.h. - Extra documentation page for network interface indexes. -- New function lwpa_netint_copy_interfaces() to perform the old behavior of - lwpa_netint_get_interfaces() (see Changed below) +- New function etcpal_netint_copy_interfaces() to perform the old behavior of + etcpal_netint_get_interfaces() (see Changed below) +- New function etcpal_netint_get_interfaces_by_index() ### Changed -- Naming: 'operating system' and 'platform' are used somewhat interchangably by - this library, but operating system more correctly refers to what lwpa targets. - Plus, 'os' makes for nicer names than 'plat'. A pass is made for consistency. -- Moved the sockaddr and inet_xtox conversion functions into the lwpa_inet +- Naming: Library name changed from lwpa to EtcPal. All API names updated + accordingly. +- Naming: Separated the platform-specific sources into 'os' and 'net' targets + to aid in targeting mix-and-match stack environments like FreeRTOS and lwIP. +- Moved the sockaddr and inet_xtox conversion functions into the etcpal_inet module -- lwpa_thread_stop() changed to lwpa_thread_join() to better describe behavior +- etcpal_thread_stop() changed to etcpal_thread_join() to better describe + behavior - LwpaNetintInfo: Removed 'gate' member, which has no consistent meaning across platforms. -- lwpa_log_callback interface tweak - combine the various log message pointers +- etcpal_log_callback interface tweak - combine the various log message pointers into a struct LwpaLogStrings. - LwpaNetintInfo: 'ifindex' renamed to 'index' and changed to type unsigned int for better compliance with RFC 3493 -- lwpa_netint_get_interface_for_dest(): Signature changed to return lwpa_error_t -- lwpa_socket: Multicast socket options now refer to network interfaces only by - interface index, for portability and compatibility with IPv6. -- lwpa_netint_get_interfaces() simply provides const access to the cached array - of network interfaces built at init time. -- lwpa_rbtree: Change some function signatures to give more meaningful return +- etcpal_netint_get_interface_for_dest(): Signature changed to return + etcpal_error_t +- etcpal_socket: Multicast socket options now refer to network interfaces only + by interface index, for portability and compatibility with IPv6. +- etcpal_netint_get_interfaces() simply provides const access to the cached + array of network interfaces built at init time. +- etcpal_netint_get_default_interface() and + etcpal_netint_get_interface_for_dest() now return network interface indexes + instead of addresses. +- etcpal_rbtree: Change some function signatures to give more meaningful return information. ### Removed @@ -69,6 +78,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Initial library modules, tests and documentation. -[Unreleased]: https://github.com/ETCLabs/lwpa/compare/master...develop -[0.2.0]: https://github.com/ETCLabs/lwpa/compare/v0.1.0...v0.2.0 -[0.1.0]: https://github.com/ETCLabs/lwpa/releases/tag/v0.1.0 +[Unreleased]: https://github.com/ETCLabs/EtcPal/compare/master...develop +[0.2.0]: https://github.com/ETCLabs/EtcPal/compare/v0.1.0...v0.2.0 +[0.1.0]: https://github.com/ETCLabs/EtcPal/releases/tag/v0.1.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index aaebe51e9..237a9a79d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.3) ########################## Global Project Attributes ########################## -project(lwpa VERSION 0.3.0) +project(EtcPal VERSION 0.3.0) # Sometimes the seems to be some weirdness with drive letter capitalization on Windows, so do a # case-insensitive comparision @@ -37,16 +37,16 @@ else() set(OPTION_DEFAULTS OFF) endif() -set(LWPA_ROOT ${CMAKE_CURRENT_LIST_DIR}) +set(ETCPAL_ROOT ${CMAKE_CURRENT_LIST_DIR}) -option(LWPA_BUILD_MOCK_LIB "Build the lwpa_mock library" OFF) -option(LWPA_BUILD_TESTS "Build the lwpa unit tests" ${OPTION_DEFAULTS}) -option(LWPA_BUILD_EXAMPLES "Build the lwpa example apps" ${OPTION_DEFAULTS}) +option(ETCPAL_BUILD_MOCK_LIB "Build the EtcPalMock library" OFF) +option(ETCPAL_BUILD_TESTS "Build the EtcPal unit tests" ${OPTION_DEFAULTS}) +option(ETCPAL_BUILD_EXAMPLES "Build the EtcPal example apps" ${OPTION_DEFAULTS}) # Platform support -include(${PROJECT_SOURCE_DIR}/tools/cmake/lwpa-os.cmake) +include(${PROJECT_SOURCE_DIR}/tools/cmake/etcpal-os.cmake) -if(LWPA_BUILD_MOCK_LIB OR LWPA_BUILD_TESTS) +if(ETCPAL_BUILD_MOCK_LIB OR ETCPAL_BUILD_TESTS) add_subdirectory(external/fff) endif() @@ -56,7 +56,7 @@ add_subdirectory(src) #################################### Tests #################################### -if(LWPA_BUILD_TESTS) +if(ETCPAL_BUILD_TESTS) add_subdirectory(external/unity) enable_testing() add_subdirectory(tests) @@ -64,6 +64,6 @@ endif() ################################## Examples ################################### -if(LWPA_BUILD_EXAMPLES) +if(ETCPAL_BUILD_EXAMPLES) add_subdirectory(examples) endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b392d9167..8a968491f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,11 @@ -# Contributing to lwpa +# Contributing to EtcPal -Thank you for your interest in contributing to the lwpa project! +Thank you for your interest in contributing to the EtcPal project! ## Pull requests -The lwpa library is currently in very early development. In order to keep -things as stable as possible, we are not accepting pull requests at this time. +The EtcPal library is currently in early development. In order to keep things +as stable as possible, we are not accepting pull requests at this time. ## Reporting issues @@ -25,6 +25,6 @@ A good bug report includes the following: * Which library code module(s) you were using and the library's version * A set of steps to reproduce the issue, in order * What you expected to see, and what happened instead -* If the bug has occured in code you wrote that uses the lwpa library, please +* If the bug has occured in code you wrote that uses the EtcPal library, please provide code snippets and try to reduce to a minimal reproducible example. * Any logging output that was produced when the issue occurred \ No newline at end of file diff --git a/README.md b/README.md index 8f038205a..b5611c787 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ -# LightWeight Platform Abstraction +# EtcPal: ETC Platform Abstraction Layer -[![Build Status](https://dev.azure.com/ETCLabs/lwpa/_apis/build/status/ETCLabs.lwpa?branchName=develop)](https://dev.azure.com/ETCLabs/lwpa/_build/latest?definitionId=1&branchName=develop) +[![Build Status](https://dev.azure.com/ETCLabs/EtcPal/_apis/build/status/ETCLabs.EtcPal?branchName=develop)](https://dev.azure.com/ETCLabs/EtcPal/_build/latest?definitionId=1&branchName=develop) -This repository contains the LightWeight Platform Abstraction (lwpa) library, -which supports other open-source libraries by [ETC](http://www.etcconnect.com). +This repository contains ETC's Platform Abstraction Layer (PAL), which supports +other open-source libraries by [ETC](http://www.etcconnect.com). -The lwpa library serves two main purposes: +ETC develops many software products which target a range of platforms from full +desktop OS down to 32-bit microcontrollers. Because of this, there is a need +for ETC's software libraries to be highly portable. The EtcPal library serves +this purpose in two main ways: * Provides a platform-neutral interface for common system calls, in order to simplify the writing of platform-neutral software libraries. @@ -14,7 +17,7 @@ The lwpa library serves two main purposes: ## Platform Ports -lwpa is currently ported for the following platforms: +EtcPal is currently ported for the following platforms: + FreeRTOS (OS abstraction only) + Linux + lwIP (Network abstraction only) @@ -24,16 +27,16 @@ lwpa is currently ported for the following platforms: ## Building -lwpa is typically included as a dependency by other software libraries. -However, if you would like to build lwpa on its own as a static lib, there are -instructions in the [documentation](https://etclabs.github.io/lwpa). +EtcPal is typically included as a dependency by other software libraries. +However, if you would like to build EtcPal on its own, there are instructions +in the [documentation](https://etclabs.github.io/EtcPal). ## About this ETCLabs Project -lwpa is official, open-source software developed by ETC employees and is +EtcPal is official, open-source software developed by ETC employees and is designed to interact with ETC products. For challenges using, integrating, compiling, or modifying this software, we encourage posting on the -[issues page](https://github.com/ETCLabs/lwpa/issues) of this project. +[issues page](https://github.com/ETCLabs/EtcPal/issues) of this project. Before posting an issue or opening a pull request, please read the [contribution guidelines](./CONTRIBUTING.md). diff --git a/ThirdPartySoftware.txt b/ThirdPartySoftware.txt index 6660a1d47..ab4c56d80 100644 --- a/ThirdPartySoftware.txt +++ b/ThirdPartySoftware.txt @@ -1,6 +1,6 @@ Third-Party Software -lwpa incorporates components of the following third-party software, under the +EtcPal incorporates components of the following third-party software, under the respective terms of the license of each third-party software component. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -24,7 +24,7 @@ Public domain, under the Unlicense (http://unlicense.org) The following sources in this repository are based on sources obtained from mirek/rb_tree: -include/lwpa/rbtree.h -src/lwpa_rbtree.c +include/etcpal/rbtree.h +src/etcpal/rbtree.c See the license information at the top of those source files for more details. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2b3090315..a1529d0c8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,4 +1,4 @@ -# The lwpa build and test pipeline. +# The EtcPal build and test pipeline. trigger: - develop @@ -9,10 +9,10 @@ pr: - develop variables: - cmake_definitions: -DLWPA_BUILD_MOCK_LIB=ON -DLWPA_BUILDING_FOR_AZURE_PIPELINES_CI=1 + cmake_definitions: -DETCPAL_BUILD_MOCK_LIB=ON -DETCPAL_BUILDING_FOR_AZURE_PIPELINES_CI=1 jobs: -# Build and test lwpa on Windows using CMake and Visual Studio 2017. +# Build and test EtcPal on Windows using CMake and Visual Studio 2017. - job: windows_build displayName: 'Windows Build and Test' pool: @@ -20,21 +20,21 @@ jobs: strategy: matrix: Debug: - LWPA_BUILD_CONFIG: 'Debug' + ETCPAL_BUILD_CONFIG: 'Debug' Release: - LWPA_BUILD_CONFIG: 'Release' + ETCPAL_BUILD_CONFIG: 'Release' steps: - script: | mkdir build cd build cmake --version cmake -G "Visual Studio 15 2017 Win64" $(cmake_definitions) .. - cmake --build . --config %LWPA_BUILD_CONFIG% - displayName: 'lwpa Windows build' + cmake --build . --config %ETCPAL_BUILD_CONFIG% + displayName: 'EtcPal Windows build' - script: | cd build - ctest --verbose -C %LWPA_BUILD_CONFIG% - displayName: 'lwpa Windows test' + ctest --verbose -C %ETCPAL_BUILD_CONFIG% + displayName: 'EtcPal Windows test' - job: macos_build displayName: 'macOS Build and Test' @@ -47,11 +47,11 @@ jobs: cmake --version cmake $(cmake_definitions) .. cmake --build . - displayName: 'lwpa macOS build' + displayName: 'EtcPal macOS build' - script: | cd build ctest --verbose - displayName: 'lwpa macOS test' + displayName: 'EtcPal macOS test' - job: linux_build displayName: 'Linux Build and Test' @@ -66,15 +66,15 @@ jobs: cmake --version cmake -G "Unix Makefiles" $(cmake_definitions) .. cmake --build . - displayName: 'lwpa Linux build' + displayName: 'EtcPal Linux build' - script: | cd build ctest --verbose - displayName: 'lwpa Linux test' + displayName: 'EtcPal Linux test' # Generate documentation with doxygen. Documentation is generated from the # develop branch and posted to the 'head' portion of the Github page -# (etclabs.github.io/lwpa) +# (etclabs.github.io/EtcPal) - job: docs displayName: 'Deploy documentation' condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop')) @@ -91,7 +91,7 @@ jobs: ./publish_docs.sh displayName: 'Generate and deploy documentation' env: - GH_REPO_NAME: lwpa - GH_REPO_REF: github.com/ETCLabs/lwpa.git + GH_REPO_NAME: EtcPal + GH_REPO_REF: github.com/ETCLabs/EtcPal.git GH_REPO_TOKEN: $(GH_ACCESS_TOKEN) \ No newline at end of file diff --git a/docs/Doxyfile b/docs/Doxyfile index 646d2d15c..0e8e3965e 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = lwpa +PROJECT_NAME = EtcPal # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -44,7 +44,7 @@ PROJECT_NUMBER = 0.3.0 # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "LightWeight Platform Abstraction (lwpa)" +PROJECT_BRIEF = "ETC Platform Abstraction Layer (EtcPal)" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 @@ -790,8 +790,8 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ../src/lwpa \ - ../include/lwpa \ +INPUT = ../src/etcpal \ + ../include/etcpal \ mainpage.md \ additional_docs.md \ interface_indexes.md @@ -2166,7 +2166,7 @@ TAGFILES = # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. -GENERATE_TAGFILE = lwpa.tag +GENERATE_TAGFILE = etcpal.tag # If the ALLEXTERNALS tag is set to YES, all external class will be listed in # the class index. If set to NO, only the inherited external classes will be diff --git a/docs/etcpal.tag b/docs/etcpal.tag new file mode 100644 index 000000000..445a13a52 --- /dev/null +++ b/docs/etcpal.tag @@ -0,0 +1,3197 @@ + + + + version.h + D:/git/ETCLabs/EtcPal/include/etcpal/ + version_8h + + + EtcPalIpAddr::AddrUnion + union_etc_pal_ip_addr_1_1_addr_union.html + EtcPalIpAddr::AddrUnion::EtcPalIpv6Addr + + + CachedNetintInfo + struct_cached_netint_info.html + + + DefaultNetint + struct_default_netint.html + + + EtcPalAddrinfo + struct_etc_pal_addrinfo.html + + int + ai_flags + struct_etc_pal_addrinfo.html + a92528a848ebf34ab99687dd06a09cc93 + + + + int + ai_family + struct_etc_pal_addrinfo.html + a4dc44d22f13bc5c59bff73e549e96a5c + + + + int + ai_socktype + struct_etc_pal_addrinfo.html + a2109130e73586150c41fed16311e1af6 + + + + int + ai_protocol + struct_etc_pal_addrinfo.html + a6ade486587feaa03d492eb84cfc83451 + + + + char * + ai_canonname + struct_etc_pal_addrinfo.html + a9fcbdd64fcb9adcf195a78b10f1fe8f6 + + + + EtcPalSockaddr + ai_addr + struct_etc_pal_addrinfo.html + a838f45940224c6e6bb31a64c3dd1961f + + + + void * + pd + struct_etc_pal_addrinfo.html + aecf048e565653706ca7120829d06e047 + [2] + + + + EtcPalGroupReq + struct_etc_pal_group_req.html + + unsigned int + ifindex + struct_etc_pal_group_req.html + a452f46bf9904a02408a12d9e406b4de7 + + + + EtcPalIpAddr + group + struct_etc_pal_group_req.html + ab8ed4113f331d191260b09e960e94254 + + + + + EtcPalIpAddr + struct_etc_pal_ip_addr.html + EtcPalIpAddr::AddrUnion + + etcpal_iptype_t + type + struct_etc_pal_ip_addr.html + a89368dca599010efedd3d8ca663d5953 + + + + + EtcPalIpAddr::AddrUnion::EtcPalIpv6Addr + struct_etc_pal_ip_addr_1_1_addr_union_1_1_etc_pal_ipv6_addr.html + + + EtcPalLinger + struct_etc_pal_linger.html + + int + onoff + struct_etc_pal_linger.html + a7730494d5c90b034d5937c758f354997 + + + + int + linger + struct_etc_pal_linger.html + a21667e862207c7c116b20764fcb8f931 + + + + + EtcPalLogParams + struct_etc_pal_log_params.html + + etcpal_log_action_t + action + struct_etc_pal_log_params.html + a97b4c2de584d731ffb8d8ce759930691 + + + + etcpal_log_callback + log_fn + struct_etc_pal_log_params.html + a878e8584783aed32b30a35697ffa27b5 + + + + EtcPalSyslogParams + syslog_params + struct_etc_pal_log_params.html + a6b5edefad9cb5463180d2f3cc9537c44 + + + + int + log_mask + struct_etc_pal_log_params.html + ac695d621aaa836a9d13d65a912be9518 + + + + etcpal_log_time_fn + time_fn + struct_etc_pal_log_params.html + aaeb7319ba51e6b5fe1f4df5dea2eabce + + + + void * + context + struct_etc_pal_log_params.html + ae376f130b17d169ee51be68077a89ed0 + + + + + EtcPalLogStrings + struct_etc_pal_log_strings.html + + const char * + syslog + struct_etc_pal_log_strings.html + a5911dbe6a47cb2b9cfbab87a8881b5b6 + + + + const char * + human_readable + struct_etc_pal_log_strings.html + a4ac8b9667178849660fd3b1f99e93366 + + + + const char * + raw + struct_etc_pal_log_strings.html + a8129637af8920bc9328bbce2a00bfeb4 + + + + + EtcPalLogTimeParams + struct_etc_pal_log_time_params.html + + int + year + struct_etc_pal_log_time_params.html + abeac221e38b7b9ce7df8722c842bf671 + + + + int + month + struct_etc_pal_log_time_params.html + aedb06abe5aff12fa3e7e0e71a374edfb + + + + int + day + struct_etc_pal_log_time_params.html + a4c11afc03fc3ee49bab660def6558f2a + + + + int + hour + struct_etc_pal_log_time_params.html + a15df9ba285cfd842f284025f904edc9c + + + + int + minute + struct_etc_pal_log_time_params.html + a5edffad982a0566ad01d95005474eae3 + + + + int + second + struct_etc_pal_log_time_params.html + a6cf35be1947a62f134392fcb1b3c54d2 + + + + int + msec + struct_etc_pal_log_time_params.html + ad957f34cd6e8272740bc231865080b22 + + + + int + utc_offset + struct_etc_pal_log_time_params.html + a0d5ceb6295477b5931bf54c002e36fe9 + + + + + EtcPalMempool + struct_etc_pal_mempool.html + + + EtcPalMempoolDesc + struct_etc_pal_mempool_desc.html + + const size_t + elem_size + struct_etc_pal_mempool_desc.html + a817b1b9f628c2698a9a3fb16ce738530 + + + + const size_t + pool_size + struct_etc_pal_mempool_desc.html + aaeb9b2d37542fba1b318e4fcde49d9b4 + + + + EtcPalMempool * + freelist + struct_etc_pal_mempool_desc.html + a6e77cf602471114d51631a441c42ab0c + + + + EtcPalMempool *const + list + struct_etc_pal_mempool_desc.html + a9bbae4d416583392b93135d8cc44d80e + + + + size_t + current_used + struct_etc_pal_mempool_desc.html + aff331a9d3e0fdee5a3a504a3fe685bf0 + + + + void *const + pool + struct_etc_pal_mempool_desc.html + aece14e36f8731b6f1c9602fee75c1544 + + + + + EtcPalModuleInit + struct_etc_pal_module_init.html + + + EtcPalMreq + struct_etc_pal_mreq.html + + EtcPalIpAddr + netint + struct_etc_pal_mreq.html + af4d9906a2a7fca6dfe6daf61b1ac55d2 + + + + EtcPalIpAddr + group + struct_etc_pal_mreq.html + ab8ed4113f331d191260b09e960e94254 + + + + + EtcPalNetintInfo + struct_etc_pal_netint_info.html + + unsigned int + index + struct_etc_pal_netint_info.html + a589d64202487f78e3cc30dd2e04c5201 + + + + EtcPalIpAddr + addr + struct_etc_pal_netint_info.html + ac10a4235b585003054f76871bad3fd85 + + + + EtcPalIpAddr + mask + struct_etc_pal_netint_info.html + a155577b467420f0877aa19b7265565f3 + + + + uint8_t + mac + struct_etc_pal_netint_info.html + aca9240e27db0f39672b30d0aac336e80 + [ETCPAL_NETINTINFO_MAC_LEN] + + + char + name + struct_etc_pal_netint_info.html + a6eaa1f18016764aa8812196745e36463 + [ETCPAL_NETINTINFO_NAME_LEN] + + + char + friendly_name + struct_etc_pal_netint_info.html + a3fa69022d71df27910811117d3e232fd + [ETCPAL_NETINTINFO_FRIENDLY_NAME_LEN] + + + bool + is_default + struct_etc_pal_netint_info.html + a0c9f19a7b68ad0dad836ee153d3a230a + + + + + EtcPalPdu + struct_etc_pal_pdu.html + + + EtcPalPduConstraints + struct_etc_pal_pdu_constraints.html + + size_t + vector_size + struct_etc_pal_pdu_constraints.html + a28e18243c88fd99888246e855cc116fd + + + + size_t + header_size + struct_etc_pal_pdu_constraints.html + a64f1d0c53909f30b0aac882348cd32f2 + + + + + EtcPalPollEvent + struct_etc_pal_poll_event.html + + etcpal_socket_t + socket + struct_etc_pal_poll_event.html + ad32899ff82c07979513229c6f83c5f05 + + + + etcpal_poll_events_t + events + struct_etc_pal_poll_event.html + a8c1a86a9a616989de3fcced4b0c0e1f7 + + + + etcpal_error_t + err + struct_etc_pal_poll_event.html + a13b5fda068afcd9c79a54263a9fe7b07 + + + + void * + user_data + struct_etc_pal_poll_event.html + a0f53d287ac7c064d1a49d4bd93ca1cb9 + + + + + EtcPalRbIter + struct_etc_pal_rb_iter.html + + EtcPalRbTree * + tree + struct_etc_pal_rb_iter.html + a3dc7beb088200d742f70c0c895b376c4 + + + + EtcPalRbNode * + node + struct_etc_pal_rb_iter.html + a46745baa1082347489f1dd6dd68c7afa + + + + EtcPalRbNode * + path + struct_etc_pal_rb_iter.html + a6d248403d379988dac19bf98cfeb84b9 + [ETCPAL_RB_ITER_MAX_HEIGHT] + + + size_t + top + struct_etc_pal_rb_iter.html + ab9332a87d0af5aa12cac847eff68b7af + + + + void * + info + struct_etc_pal_rb_iter.html + acb1df3a0f703b05bc4971f79cabe2597 + + + + + EtcPalRbNode + struct_etc_pal_rb_node.html + + int + red + struct_etc_pal_rb_node.html + a6761340706096510fd89edca40a63b9b + + + + EtcPalRbNode * + link + struct_etc_pal_rb_node.html + a629e7a1728cfe5d93fe2381d793ef93f + [2] + + + void * + value + struct_etc_pal_rb_node.html + a0f61d63b009d0880a89c843bd50d8d76 + + + + + EtcPalRbTree + struct_etc_pal_rb_tree.html + + EtcPalRbNode * + root + struct_etc_pal_rb_tree.html + ae96f5aa846cba3ae538255b01f066bea + + + + etcpal_rbtree_node_cmp_f + cmp + struct_etc_pal_rb_tree.html + a10ccc54f5d61567cc7831f8f415687d8 + + + + size_t + size + struct_etc_pal_rb_tree.html + a854352f53b148adc24983a58a1866d66 + + + + etcpal_rbnode_alloc_f + alloc_f + struct_etc_pal_rb_tree.html + af09735d8bf310cef3d8a0005138de5e3 + + + + etcpal_rbnode_dealloc_f + dealloc_f + struct_etc_pal_rb_tree.html + a163e7baba46efbe3c7fdd65c1c4051f2 + + + + void * + info + struct_etc_pal_rb_tree.html + acb1df3a0f703b05bc4971f79cabe2597 + + + + + EtcPalRootLayerPdu + struct_etc_pal_root_layer_pdu.html + + EtcPalUuid + sender_cid + struct_etc_pal_root_layer_pdu.html + a341064da4798492e212c14a9aeede58d + + + + uint32_t + vector + struct_etc_pal_root_layer_pdu.html + a513d751c7097b43b3968ac81f3a5715b + + + + const uint8_t * + pdata + struct_etc_pal_root_layer_pdu.html + a2f9eb29aa10e0d64f27f69db1e90bd07 + + + + size_t + datalen + struct_etc_pal_root_layer_pdu.html + a3d12e161726566d24a1d0cf6c6b416bb + + + + + EtcPalSockaddr + struct_etc_pal_sockaddr.html + + uint16_t + port + struct_etc_pal_sockaddr.html + a8e0798404bf2cf5dabb84c5ba9a4f236 + + + + EtcPalIpAddr + ip + struct_etc_pal_sockaddr.html + a19cc8016f534a565f984438cfe911a9e + + + + + EtcPalSyslogParams + struct_etc_pal_syslog_params.html + + int + facility + struct_etc_pal_syslog_params.html + a213afa2e73e0c2102f43d4067e41b90f + + + + char + hostname + struct_etc_pal_syslog_params.html + acf45ed2a37e15e83167bd1edcd9fbbbe + [ETCPAL_LOG_HOSTNAME_MAX_LEN] + + + char + app_name + struct_etc_pal_syslog_params.html + a6d20b2dcf8c2bc4f864b3d719ad00ad0 + [ETCPAL_LOG_APP_NAME_MAX_LEN] + + + char + procid + struct_etc_pal_syslog_params.html + aa3d06040894562832d2218511875b444 + [ETCPAL_LOG_PROCID_MAX_LEN] + + + + EtcPalTcpPreamble + struct_etc_pal_tcp_preamble.html + + const uint8_t * + rlp_block + struct_etc_pal_tcp_preamble.html + a6df9d0f27538da177c52996a97e0a1d8 + + + + size_t + rlp_block_len + struct_etc_pal_tcp_preamble.html + ab27f79ca664937f91e64f868ad233935 + + + + + EtcPalThreadParams + struct_etc_pal_thread_params.html + + unsigned int + thread_priority + struct_etc_pal_thread_params.html + a9cc3e9ae3970c47e150dc77065abd75f + + + + unsigned int + stack_size + struct_etc_pal_thread_params.html + adde5266300e9cdd7ca1134daba9adf24 + + + + char * + thread_name + struct_etc_pal_thread_params.html + a9c15c6e0b10239673fa9d8be6ad08128 + + + + void * + platform_data + struct_etc_pal_thread_params.html + abea5d4a9dc1ef714b423a1ae6afaf4ae + + + + + EtcPalTimer + struct_etc_pal_timer.html + + uint32_t + reset_time + struct_etc_pal_timer.html + a8fb66f63094794fbbdacc69af5cc55fa + + + + uint32_t + interval + struct_etc_pal_timer.html + acd9ed1ccc44de55e1d3eff5569663695 + + + + + EtcPalUdpPreamble + struct_etc_pal_udp_preamble.html + + const uint8_t * + rlp_block + struct_etc_pal_udp_preamble.html + a6df9d0f27538da177c52996a97e0a1d8 + + + + size_t + rlp_block_len + struct_etc_pal_udp_preamble.html + ab27f79ca664937f91e64f868ad233935 + + + + + EtcPalUuid + struct_etc_pal_uuid.html + + + MD5_CTX + struct_m_d5___c_t_x.html + + + etcpal::MutexGuard + classetcpal_1_1_mutex_guard.html + + + etcpal::ReadGuard + classetcpal_1_1_read_guard.html + + + etcpal::WriteGuard + classetcpal_1_1_write_guard.html + + + etcpal + namespaceetcpal.html + etcpal::MutexGuard + etcpal::ReadGuard + etcpal::WriteGuard + + + etcpal_lock + etcpal_lock + group__etcpal__lock.html + etcpal_mutex + etcpal_signal + etcpal_rwlock + etcpal::MutexGuard + etcpal::ReadGuard + etcpal::WriteGuard + + + etcpal_mutex + etcpal_mutex + group__etcpal__mutex.html + + UNDEFINED + etcpal_mutex_t + group__etcpal__mutex.html + ga1e6a1360f61ff249137e3f6757322698 + + + + bool + etcpal_mutex_create + group__etcpal__mutex.html + ga848f261552bf8c981590eb784ee5b3b8 + (etcpal_mutex_t *id) + + + bool + etcpal_mutex_take + group__etcpal__mutex.html + gac56c0f48e3bfc5e8e0d321a711816f67 + (etcpal_mutex_t *id) + + + bool + etcpal_mutex_try_take + group__etcpal__mutex.html + ga26e7c3d33f3ab2dd5a82de3cbc36d39e + (etcpal_mutex_t *id) + + + void + etcpal_mutex_give + group__etcpal__mutex.html + ga5a1ceebcbb5856a98dab50a13f894bcf + (etcpal_mutex_t *id) + + + void + etcpal_mutex_destroy + group__etcpal__mutex.html + ga4b71ed71a637a07c0fe5cd55222a209c + (etcpal_mutex_t *id) + + + + etcpal_signal + etcpal_signal + group__etcpal__signal.html + + UNDEFINED + etcpal_signal_t + group__etcpal__signal.html + ga9dc52b1097114b218c95970c599f01eb + + + + bool + etcpal_signal_create + group__etcpal__signal.html + ga4082ebadfba33b125930d5c5067139f0 + (etcpal_signal_t *id) + + + bool + etcpal_signal_wait + group__etcpal__signal.html + ga10e2d2cc15e6a30f38ba65f02c0905d7 + (etcpal_signal_t *id) + + + bool + etcpal_signal_poll + group__etcpal__signal.html + gad04fbc96ac93defb7ea545c81a880f12 + (etcpal_signal_t *id) + + + void + etcpal_signal_post + group__etcpal__signal.html + gafa2af190375bdb673563e2a029f0a89b + (etcpal_signal_t *id) + + + void + etcpal_signal_destroy + group__etcpal__signal.html + ga4ecc28a0f67939859d91c8e9e75701e4 + (etcpal_signal_t *id) + + + + etcpal_rwlock + etcpal_rwlock + group__etcpal__rwlock.html + + UNDEFINED + etcpal_rwlock_t + group__etcpal__rwlock.html + ga06eaed70bff366f707fdcae078a0333f + + + + bool + etcpal_rwlock_create + group__etcpal__rwlock.html + ga694477ee8932b83784f2d7a70ac856e3 + (etcpal_rwlock_t *id) + + + bool + etcpal_rwlock_readlock + group__etcpal__rwlock.html + ga846b8783133884b5fbce918811568825 + (etcpal_rwlock_t *id) + + + bool + etcpal_rwlock_try_readlock + group__etcpal__rwlock.html + ga473b7cb0a2bae2deb5477bb699e6cf9b + (etcpal_rwlock_t *id) + + + void + etcpal_rwlock_readunlock + group__etcpal__rwlock.html + ga3ab0cac4b091255a2694a4a472151160 + (etcpal_rwlock_t *id) + + + bool + etcpal_rwlock_writelock + group__etcpal__rwlock.html + gac6989af16cb55025d06ee35373739380 + (etcpal_rwlock_t *id) + + + bool + etcpal_rwlock_try_writelock + group__etcpal__rwlock.html + ga05a985e996a37e5a4c8aa7f9c3b1d654 + (etcpal_rwlock_t *id) + + + void + etcpal_rwlock_writeunlock + group__etcpal__rwlock.html + ga83fbb82557a70ad86c8a65fd53b0cb8b + (etcpal_rwlock_t *id) + + + void + etcpal_rwlock_destroy + group__etcpal__rwlock.html + ga2d4feb63613ff8dfb1f106f5ed63dee5 + (etcpal_rwlock_t *id) + + + + etcpal_opts + EtcPal config options + group__etcpal__opts.html + + #define + ETCPAL_INCLUDE_PACK_64 + group__etcpal__opts.html + ga5ababb448dd9ec260738821bd16d06cd + + + + #define + ETCPAL_EMBOS_USE_MALLOC + group__etcpal__opts.html + gaab67221f3adba4ea2b638e55341f8074 + + + + #define + ETCPAL_EMBOS_MAX_NETINTS + group__etcpal__opts.html + gaf5e80b2cbceca9bbe4e918610021a5ba + + + + + etcpal_thread + etcpal_thread + group__etcpal__thread.html + EtcPalThreadParams + + #define + ETCPAL_THREAD_DEFAULT_PRIORITY + group__etcpal__thread.html + ga3539233977b6e793b9b5a4c071fd6e78 + + + + #define + ETCPAL_THREAD_DEFAULT_STACK + group__etcpal__thread.html + gac4147a48a462f0c5b9758334b41243a9 + + + + #define + ETCPAL_THREAD_DEFAULT_NAME + group__etcpal__thread.html + ga41f1567e754166e758fc1fdda38fc300 + + + + #define + ETCPAL_THREAD_NAME_MAX_LENGTH + group__etcpal__thread.html + ga5a0a37d186ac57231b94c287a58b54a0 + + + + struct EtcPalThreadParams + EtcPalThreadParams + group__etcpal__thread.html + gabb277d1d3fc2b021ca7513d8af038ed4 + + + + UNDEFINED + etcpal_thread_t + group__etcpal__thread.html + gaf5e68040f0d382ecebc46735a8f53c93 + + + + bool + etcpal_thread_create + group__etcpal__thread.html + ga6622ac7af8e6cc018c28ba15cc824de5 + (etcpal_thread_t *id, const EtcPalThreadParams *params, void(*thread_fn)(void *), void *thread_arg) + + + bool + etcpal_thread_join + group__etcpal__thread.html + ga8841872731c92356965eac616aedc2ff + (etcpal_thread_t *id) + + + void + etcpal_thread_sleep + group__etcpal__thread.html + ga8c76ca9a8ebd49dcb4b376f351fb4517 + (int sleep_ms) + + + + etcpal_bool + etcpal_bool + group__etcpal__bool.html + + #define + bool + group__etcpal__bool.html + gabb452686968e48b67397da5f97445f5b + + + + #define + false + group__etcpal__bool.html + ga65e9886d74aaee76545e83dd09011727 + + + + #define + true + group__etcpal__bool.html + ga41f9c5fb8b08eb5dc3edce4dcb37fee7 + + + + + etcpal + EtcPal + group__etcpal.html + etcpal_lock + etcpal_opts + etcpal_thread + etcpal_bool + etcpal_error + etcpal_inet + etcpal_int + etcpal_log + etcpal_mempool + etcpal_netint + etcpal_pack + etcpal_pdu + etcpal_rbtree + etcpal_socket + etcpal_timer + etcpal_uuid + + #define + ETCPAL_WAIT_FOREVER + group__etcpal.html + ga1cfb33811295439bc08ce2e8b74c1d13 + + + + uint32_t + etcpal_features_t + group__etcpal.html + gae77772998c26f45618c26de1e1fc8305 + + + + etcpal_error_t + etcpal_init + group__etcpal.html + ga163b95dfe5ef6c68f2fb4d5b58a63843 + (etcpal_features_t features) + + + void + etcpal_deinit + group__etcpal.html + ga0792bdcd2f824009584744db01d7a352 + (etcpal_features_t features) + + + #define + ETCPAL_FEATURE_SOCKETS + group__etcpal.html + ga09f99422deaa7bb5d2625c317d1a66a6 + + + + #define + ETCPAL_FEATURE_NETINTS + group__etcpal.html + gaf5b3a81b975bbae1f6f54f43bfc0c6a7 + + + + #define + ETCPAL_FEATURE_TIMERS + group__etcpal.html + gaffb285a8108a672c01c33d921ee8be83 + + + + #define + ETCPAL_FEATURE_LOGGING + group__etcpal.html + ga8c7c1f9430362540e56af3a2742a25d4 + + + + #define + ETCPAL_FEATURES_ALL + group__etcpal.html + ga740dd7c89f16ff20992cf21970d1c521 + + + + #define + ETCPAL_FEATURES_ALL_BUT + group__etcpal.html + ga15560671c4e732ed46dc03a0e522d160 + (mask) + + + + etcpal_error + etcpal_error + group__etcpal__error.html + + #define + etcpal_strerror + group__etcpal__error.html + ga6c57f2a17ae4e5fcdf299b4210331f25 + (errcode) + + + + etcpal_error_t + group__etcpal__error.html + ga743b0648f0ca798ef29c9f69c6e255af + + + + kEtcPalErrOk + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afae403d046b4ba4e81dce121266c2cca8d + + + + kEtcPalErrNotFound + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa62c704cfc2d72f1fa91c04efe508c60f + + + + kEtcPalErrNoMem + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afad16b0fe51e8664f8b30b740ea1e51599 + + + + kEtcPalErrBusy + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa47b93a8acf0aad836afc5dda44551acc + + + + kEtcPalErrExists + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afaeab0ae4d277d52dc56a1d78f81868c2d + + + + kEtcPalErrInvalid + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afadb17bb2ec24e7755170e8afbd5b10bc2 + + + + kEtcPalErrWouldBlock + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa735dc55ef30ad08cca792cb41a1dfeb1 + + + + kEtcPalErrNoData + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa77e50551fc1c569578f0f9dd4d4a5712 + + + + kEtcPalErrProtocol + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa8396c97054393b3faf3849541fc99c43 + + + + kEtcPalErrMsgSize + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afaa980a5e26cf5086f916d12a485572f12 + + + + kEtcPalErrAddrInUse + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afae27e1c52937b3d1c1993f78160a0a778 + + + + kEtcPalErrAddrNotAvail + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa44ede5b2503ce2b1bb4ccd285d676b50 + + + + kEtcPalErrNetwork + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa4c458cd2885e27a726a1d9dedf4b4bec + + + + kEtcPalErrConnReset + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa15cf4f4905d98d94910c6cc76ae1218f + + + + kEtcPalErrConnClosed + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afafb8046b7504e0e9908654f939e74ee60 + + + + kEtcPalErrIsConn + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa9603628c356775915b437e3c15bdef53 + + + + kEtcPalErrNotConn + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa2eb8abeafb170747d185803ad0a2d527 + + + + kEtcPalErrShutdown + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa28e1dbbb288f3248d64378d83920259a + + + + kEtcPalErrTimedOut + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afac1a55c311993d815ab367c339f550956 + + + + kEtcPalErrConnAborted + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa39f50bbaad22488dba1944f129d1ecde + + + + kEtcPalErrConnRefused + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa4b119ec2231eb8bf73535b1375f5f232 + + + + kEtcPalErrAlready + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afaa9c6c39f7303953a99c50a981f36dff0 + + + + kEtcPalErrInProgress + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa99aabe562db1ed9acab67c6a2bc777a1 + + + + kEtcPalErrBufSize + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afaefe61c95876a3a7faba0f5da4ec03f37 + + + + kEtcPalErrNotInit + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afadfb4ade13d03ed30f6309d2f130f05f7 + + + + kEtcPalErrNoNetints + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa730afdd022ada726bdf8d940eda9759b + + + + kEtcPalErrNoSockets + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afaa45464bce734de8eca7f5a768386423b + + + + kEtcPalErrNotImpl + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afad0b98165ec7fb9169790675a67850d52 + + + + kEtcPalErrPerm + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa9fb1e2b91f204d8a01377796bddd867d + + + + kEtcPalErrSys + group__etcpal__error.html + gga743b0648f0ca798ef29c9f69c6e255afa38404e113508a0e291dbcc6c73743ae8 + + + + + etcpal_inet + etcpal_inet + group__etcpal__inet.html + EtcPalIpAddr + EtcPalSockaddr + EtcPalNetintInfo + + #define + ETCPAL_IPV6_BYTES + group__etcpal__inet.html + gad5f18940857b50304b956505fb77df20 + + + + #define + ETCPAL_INET_ADDRSTRLEN + group__etcpal__inet.html + gab44293e291772ce05ffa42c1ad51e4e0 + + + + #define + ETCPAL_INET6_ADDRSTRLEN + group__etcpal__inet.html + ga71fa8216f8c0c7472c8786e793a7b280 + + + + struct EtcPalIpAddr + EtcPalIpAddr + group__etcpal__inet.html + ga0f4fa2c5534edc2061c48b7d0a60941f + + + + struct EtcPalSockaddr + EtcPalSockaddr + group__etcpal__inet.html + gacd6641e07d027a38b3b275fd97dc948d + + + + struct EtcPalNetintInfo + EtcPalNetintInfo + group__etcpal__inet.html + gaed988a9502c1d15538ef945b3b5b234b + + + + + etcpal_iptype_t + group__etcpal__inet.html + ga847282e3fd17bf75ec83292326c455ee + + + + kEtcPalIpTypeInvalid + group__etcpal__inet.html + gga847282e3fd17bf75ec83292326c455eea0e789a4e187f4a7fdbda7271a754eca8 + + + + kEtcPalIpTypeV4 + group__etcpal__inet.html + gga847282e3fd17bf75ec83292326c455eea73ea615eceba61f26d92a63f3738f635 + + + + kEtcPalIpTypeV6 + group__etcpal__inet.html + gga847282e3fd17bf75ec83292326c455eead480ed8d686b23bdb2e5bfc06b93d7ae + + + + bool + etcpal_ip_is_link_local + group__etcpal__inet.html + gaa4b21b32f8776276e582d473e17bf768 + (const EtcPalIpAddr *ip) + + + bool + etcpal_ip_is_loopback + group__etcpal__inet.html + ga6f59d1ebf7873649f0812ee1cae171e7 + (const EtcPalIpAddr *ip) + + + bool + etcpal_ip_is_multicast + group__etcpal__inet.html + ga71b745e5bdc7c77bba5320241639f450 + (const EtcPalIpAddr *ip) + + + bool + etcpal_ip_is_wildcard + group__etcpal__inet.html + gaef79c0c7eac819d7decf1473246d3b82 + (const EtcPalIpAddr *ip) + + + void + etcpal_ip_set_wildcard + group__etcpal__inet.html + ga5d91044202026978c99000b6da2d226e + (etcpal_iptype_t type, EtcPalIpAddr *ip) + + + bool + etcpal_ip_equal + group__etcpal__inet.html + gaa5de56fa77b6190297ce164910c2eca0 + (const EtcPalIpAddr *ip1, const EtcPalIpAddr *ip2) + + + int + etcpal_ip_cmp + group__etcpal__inet.html + gaf766d207bd3e85c6b3d75768f28a00c6 + (const EtcPalIpAddr *ip1, const EtcPalIpAddr *ip2) + + + bool + etcpal_ip_and_port_equal + group__etcpal__inet.html + gac3f119aa04305d7cf485d1a86baf74cb + (const EtcPalSockaddr *sock1, const EtcPalSockaddr *sock2) + + + unsigned int + etcpal_ip_mask_length + group__etcpal__inet.html + ga9a86a44681bc856e5919578bbf652e38 + (const EtcPalIpAddr *netmask) + + + EtcPalIpAddr + etcpal_ip_mask_from_length + group__etcpal__inet.html + ga0f8ba14963ce91bfd74626f2a1e957f0 + (etcpal_iptype_t type, unsigned int mask_length) + + + bool + etcpal_ip_network_portions_equal + group__etcpal__inet.html + ga2112e37aae54451f5b7b03168183cace + (const EtcPalIpAddr *ip1, const EtcPalIpAddr *ip2, const EtcPalIpAddr *netmask) + + + #define + ETCPAL_IP_IS_V4 + group__etcpal__inet.html + ga4ed3a313f7503031100bb169ad03bc89 + (etcpal_ip_ptr) + + + #define + ETCPAL_IP_IS_V6 + group__etcpal__inet.html + ga85d241eed93be1b271e5dc68a56e9473 + (etcpal_ip_ptr) + + + #define + ETCPAL_IP_IS_INVALID + group__etcpal__inet.html + ga56a6933874bc52770eac5865f237e225 + (etcpal_ip_ptr) + + + #define + ETCPAL_IP_V4_ADDRESS + group__etcpal__inet.html + ga35262011f1ae20211d8aad5c79ab1b50 + (etcpal_ip_ptr) + + + #define + ETCPAL_IP_V6_ADDRESS + group__etcpal__inet.html + gaaee800da95371923f9375dec1a6c0a5c + (etcpal_ip_ptr) + + + #define + ETCPAL_IP_SET_V4_ADDRESS + group__etcpal__inet.html + ga5e36f7ec503aef51829aed6fbd88c889 + (etcpal_ip_ptr, val) + + + #define + ETCPAL_IP_SET_V6_ADDRESS + group__etcpal__inet.html + gae0d14b2f44b81a6687390839e0aea869 + (etcpal_ip_ptr, addr_val) + + + #define + ETCPAL_IP_SET_V6_ADDRESS_WITH_SCOPE_ID + group__etcpal__inet.html + gaeb96cdc37b6f57f448b0ac15971380d8 + (etcpal_ip_ptr, addr_val, scope_id_val) + + + #define + ETCPAL_IP_SET_INVALID + group__etcpal__inet.html + gab7df63744affbe2833fcb455e69b6ff5 + (etcpal_ip_ptr) + + + + etcpal_int + etcpal_int + group__etcpal__int.html + + #define + HAVE_STDINT_H + group__etcpal__int.html + gab6cd6d1c63c1e26ea2d4537b77148354 + + + + + etcpal_log + etcpal_log + group__etcpal__log.html + EtcPalLogTimeParams + EtcPalLogStrings + EtcPalSyslogParams + EtcPalLogParams + + #define + ETCPAL_LOG_NFACILITIES + group__etcpal__log.html + ga9c650b00d427b03b6169b18514627eb7 + + + + #define + ETCPAL_LOG_HOSTNAME_MAX_LEN + group__etcpal__log.html + gafc4fcfbaaffb603d10e2b27f54e122d2 + + + + #define + ETCPAL_LOG_APP_NAME_MAX_LEN + group__etcpal__log.html + ga2b336b7e2828f1f9c576fb4a6e357b1a + + + + #define + ETCPAL_LOG_PROCID_MAX_LEN + group__etcpal__log.html + ga1786d1616917fb0bf1315504e14060c4 + + + + #define + ETCPAL_LOG_MSG_MAX_LEN + group__etcpal__log.html + ga2ee8e585233bc73a2a299fc94230fed4 + + + + #define + ETCPAL_LOG_TIMESTAMP_LEN + group__etcpal__log.html + ga589d05713f16b04a0337399d5064e7c3 + + + + #define + ETCPAL_SYSLOG_HEADER_MAX_LEN + group__etcpal__log.html + ga6463250841fd9f0b87d84574d5ed561f + + + + #define + ETCPAL_SYSLOG_STR_MIN_LEN + group__etcpal__log.html + ga2b86d5334ad5c012a7b81ce1e9c90e33 + + + + #define + ETCPAL_HUMAN_LOG_STR_MIN_LEN + group__etcpal__log.html + gac2b8a36af28b78d0060a1d89b9b18211 + + + + #define + ETCPAL_SYSLOG_STR_MAX_LEN + group__etcpal__log.html + gae8f0782821bb95f1c2a0122b9819acac + + + + #define + ETCPAL_HUMAN_LOG_STR_MAX_LEN + group__etcpal__log.html + ga0fafd8567d72170461c34b0f4b4cde74 + + + + struct EtcPalLogTimeParams + EtcPalLogTimeParams + group__etcpal__log.html + ga3cfc242617ad25826b445fce64b800a0 + + + + struct EtcPalLogStrings + EtcPalLogStrings + group__etcpal__log.html + gaf51673a8ceea21c025198456ac795a12 + + + + void(* + etcpal_log_callback + group__etcpal__log.html + ga2149ec5b6a6311efd2c235358f3c49c7 + )(void *context, const EtcPalLogStrings *strings) + + + void(* + etcpal_log_time_fn + group__etcpal__log.html + ga738d510e7988bf2364ed059fb193a5ae + )(void *context, EtcPalLogTimeParams *time_params) + + + struct EtcPalSyslogParams + EtcPalSyslogParams + group__etcpal__log.html + ga3961fedc222b8d388ebcb2bbe6e00263 + + + + struct EtcPalLogParams + EtcPalLogParams + group__etcpal__log.html + gac6a69c52ee1d8dea2aa9d6a90d217050 + + + + + etcpal_log_action_t + group__etcpal__log.html + ga10855f3c1f3816d0bd5e4687108ea1c5 + + + + kEtcPalLogCreateSyslog + group__etcpal__log.html + gga10855f3c1f3816d0bd5e4687108ea1c5a1631725f7a5f65a9fb15767cecec5290 + + + + kEtcPalLogCreateHumanReadableLog + group__etcpal__log.html + gga10855f3c1f3816d0bd5e4687108ea1c5ae82eb0e5fc80d2657c033413df36224e + + + + kEtcPalLogCreateBoth + group__etcpal__log.html + gga10855f3c1f3816d0bd5e4687108ea1c5a8d083dc7d2d4359fd9ce6330b9d4c2bb + + + + bool + etcpal_create_syslog_str + group__etcpal__log.html + ga066f11ddd10e75d38a379a648d2dcba4 + (char *buf, size_t buflen, const EtcPalLogTimeParams *time, const EtcPalSyslogParams *syslog_params, int pri, const char *format,...) + + + bool + etcpal_create_human_log_str + group__etcpal__log.html + gaeb1f0786f9b553d05991a97db73e3dad + (char *buf, size_t buflen, const EtcPalLogTimeParams *time, const char *format,...) + + + void + etcpal_sanitize_syslog_params + group__etcpal__log.html + ga895ff8dd5230b10b4ab6d955e556d318 + (EtcPalSyslogParams *params) + + + bool + etcpal_validate_log_params + group__etcpal__log.html + ga949455773a4ecdd6a499940a19ec6080 + (EtcPalLogParams *params) + + + bool + etcpal_can_log + group__etcpal__log.html + gac44c39be61d1bf95239f9bd6fb1f11ad + (const EtcPalLogParams *params, int pri) + + + void + etcpal_log + group__etcpal__log.html + gab05a59d52b560561ce33a937f73aae5e + (const EtcPalLogParams *params, int pri, const char *format,...) + + + void + etcpal_vlog + group__etcpal__log.html + ga2f8f5602ed9ad8a869d40c4af8ba8d41 + (const EtcPalLogParams *params, int pri, const char *format, va_list args) + + + #define + ETCPAL_LOG_KERN + group__etcpal__log.html + ga6ae744f52d1ee08daa8fd36bf58597b3 + + + + #define + ETCPAL_LOG_USER + group__etcpal__log.html + ga6fc21fb437c4fa1d90dd8698cfa256f0 + + + + #define + ETCPAL_LOG_MAIL + group__etcpal__log.html + ga42fd837e598b56123c5d38fff2f5fbeb + + + + #define + ETCPAL_LOG_DAEMON + group__etcpal__log.html + ga525978d1bfe16fcd0a4450a7c5dc53ec + + + + #define + ETCPAL_LOG_AUTH + group__etcpal__log.html + gabc74c1a4cef75ebe20e917b68fa23d52 + + + + #define + ETCPAL_LOG_SYSLOG + group__etcpal__log.html + ga46bba655f9c87face73f5e2e680f0e6c + + + + #define + ETCPAL_LOG_LPR + group__etcpal__log.html + ga185481461d7f07edfd95fa80405b37c1 + + + + #define + ETCPAL_LOG_NEWS + group__etcpal__log.html + ga83c2035b9784a9cb0625bc4f33fbdc76 + + + + #define + ETCPAL_LOG_UUCP + group__etcpal__log.html + gaaa5608f22b53b0de9b6c4b1811d632ba + + + + #define + ETCPAL_LOG_CRON + group__etcpal__log.html + ga076221d5039086994c7b2a87963be388 + + + + #define + ETCPAL_LOG_AUTHPRIV + group__etcpal__log.html + ga0c3bcdd91c9d747dea59430a849556b2 + + + + #define + ETCPAL_LOG_FTP + group__etcpal__log.html + gaa3ad1dbc725353f2cd49cc55b32f3153 + + + + #define + ETCPAL_LOG_LOCAL0 + group__etcpal__log.html + ga64040cea6d8c1457ef47e65279f8bca2 + + + + #define + ETCPAL_LOG_LOCAL1 + group__etcpal__log.html + ga2f6c98d265250c28e6102c97a10dee17 + + + + #define + ETCPAL_LOG_LOCAL2 + group__etcpal__log.html + ga752539f8bfef40f0c19dc4ef67a59473 + + + + #define + ETCPAL_LOG_LOCAL3 + group__etcpal__log.html + ga92640deb4a6a2625e4fc36038cd8d45d + + + + #define + ETCPAL_LOG_LOCAL4 + group__etcpal__log.html + ga25a6a69270ce194f38d3d24e17c1d830 + + + + #define + ETCPAL_LOG_LOCAL5 + group__etcpal__log.html + gad7d901793d960e58420eb4025cfa51d1 + + + + #define + ETCPAL_LOG_LOCAL6 + group__etcpal__log.html + gabcdbdf6cbaeec1b06545372144162a79 + + + + #define + ETCPAL_LOG_LOCAL7 + group__etcpal__log.html + ga3b702549e92e23e2918d2fae9af6a84c + + + + #define + ETCPAL_LOG_EMERG + group__etcpal__log.html + gaaba03ada613553b9276df87d7387ae6f + + + + #define + ETCPAL_LOG_ALERT + group__etcpal__log.html + gaefbc8eee2db20c20586eaae217faa385 + + + + #define + ETCPAL_LOG_CRIT + group__etcpal__log.html + ga1f5ee8379832669d8cb7d5abc2e93b1f + + + + #define + ETCPAL_LOG_ERR + group__etcpal__log.html + ga0f39e099c1569ddf03e826eb4e831cf1 + + + + #define + ETCPAL_LOG_WARNING + group__etcpal__log.html + gac79a4a2a830ae8db541f33093b2d50df + + + + #define + ETCPAL_LOG_NOTICE + group__etcpal__log.html + ga2d71e55473353be02c7fd2a785b12b23 + + + + #define + ETCPAL_LOG_INFO + group__etcpal__log.html + ga9f05a0ad034946dfd20477e11d2923a7 + + + + #define + ETCPAL_LOG_DEBUG + group__etcpal__log.html + ga4e46d489885b63c38263e35ad5aca8b6 + + + + + etcpal_mempool + etcpal_mempool + group__etcpal__mempool.html + EtcPalMempool + EtcPalMempoolDesc + + #define + ETCPAL_MEMPOOL_DECLARE + group__etcpal__mempool.html + ga1da98d192da467dfb2ec751bad279178 + (name) + + + #define + ETCPAL_MEMPOOL_DEFINE + group__etcpal__mempool.html + ga0d56307540e32e74ce5a87a52ce447b8 + (name, type, size) + + + #define + ETCPAL_MEMPOOL_DEFINE_ARRAY + group__etcpal__mempool.html + ga3a974aa750cca64861b630f0a7776232 + (name, type, array_size, pool_size) + + + #define + etcpal_mempool_init + group__etcpal__mempool.html + ga2b7b0144747ea853ea526f283344c047 + (name) + + + #define + etcpal_mempool_alloc + group__etcpal__mempool.html + ga3cda8bdb4dc13e12ba5e75ccadb23274 + (name) + + + #define + etcpal_mempool_free + group__etcpal__mempool.html + gaf69c62d9c8df5f589fefbaf0283b2435 + (name, mem) + + + #define + etcpal_mempool_size + group__etcpal__mempool.html + ga8b10935dcb7665a6c4418831fd17c9cd + (name) + + + #define + etcpal_mempool_used + group__etcpal__mempool.html + gaa1a695b25f4ea895750e753303eb4f85 + (name) + + + struct EtcPalMempool + EtcPalMempool + group__etcpal__mempool.html + gacafad538d67632fc0278a608e1c019c7 + + + + struct EtcPalMempoolDesc + EtcPalMempoolDesc + group__etcpal__mempool.html + ga4b65b2221f81b94eba323dc3bd827cd4 + + + + + etcpal_netint + etcpal_netint + group__etcpal__netint.html + + size_t + etcpal_netint_get_num_interfaces + group__etcpal__netint.html + ga14c0e51d047bc84b5c4f783c640fc030 + () + + + const EtcPalNetintInfo * + etcpal_netint_get_interfaces + group__etcpal__netint.html + gafc68a9f3fc1342e3d747ab0b17029ee5 + () + + + size_t + etcpal_netint_copy_interfaces + group__etcpal__netint.html + ga2b88beeb498044aa1c390638346422b4 + (EtcPalNetintInfo *netint_arr, size_t netint_arr_size) + + + etcpal_error_t + etcpal_netint_get_interfaces_by_index + group__etcpal__netint.html + ga78f5df18395e14e959ed0c4dc26580dc + (unsigned int index, const EtcPalNetintInfo **netint_arr, size_t *netint_arr_size) + + + etcpal_error_t + etcpal_netint_get_default_interface + group__etcpal__netint.html + gae5cfdf3d1aa1edf3b6f3729491241911 + (etcpal_iptype_t type, unsigned int *netint_index) + + + etcpal_error_t + etcpal_netint_get_interface_for_dest + group__etcpal__netint.html + gae0297aaa85a237ffd910644cb414750a + (const EtcPalIpAddr *dest, unsigned int *netint_index) + + + + etcpal_pack + etcpal_pack + group__etcpal__pack.html + + uint16_t + etcpal_upack_16b + group__etcpal__pack.html + ga0880292ba3f725fb8085543b2d423be4 + (const uint8_t *buf) + + + void + etcpal_pack_16b + group__etcpal__pack.html + ga2902019cf1a188b98606319d43ed08a5 + (uint8_t *buf, uint16_t val) + + + uint16_t + etcpal_upack_16l + group__etcpal__pack.html + ga8bfbfc050e6a051ca3462c84948a8fcf + (const uint8_t *buf) + + + void + etcpal_pack_16l + group__etcpal__pack.html + gac0fc9d22170eb708008eb09f9bb22ced + (uint8_t *buf, uint16_t val) + + + uint32_t + etcpal_upack_32b + group__etcpal__pack.html + gaac2718bc037c1fb14fc08aa8976b3e0f + (const uint8_t *buf) + + + void + etcpal_pack_32b + group__etcpal__pack.html + gab516d6a148228ae6d76de7beb12e60ec + (uint8_t *buf, uint32_t val) + + + uint32_t + etcpal_upack_32l + group__etcpal__pack.html + gab002038413cf6518988bb965c879e265 + (const uint8_t *buf) + + + void + etcpal_pack_32l + group__etcpal__pack.html + gacc712186e152a6d7c03cc5f8af5a1cf2 + (uint8_t *buf, uint32_t val) + + + + etcpal_pdu + etcpal_pdu + group__etcpal__pdu.html + etcpal_rootlayerpdu + EtcPalPdu + EtcPalPduConstraints + + #define + ETCPAL_PDU_LENGTH + group__etcpal__pdu.html + gaa6aa65e575ec892582f10af1a312064e + (pdu_buf) + + + #define + ETCPAL_PDU_PACK_NORMAL_LEN + group__etcpal__pdu.html + ga6c795b26ea3e1c78b545a54e2599c7f9 + (pdu_buf, length) + + + #define + ETCPAL_PDU_PACK_EXT_LEN + group__etcpal__pdu.html + gabb06693a6eb3ed13c253c8324f3efbb5 + (pdu_buf, length) + + + #define + ETCPAL_PDU_INIT + group__etcpal__pdu.html + gafb7d5c94b80a01d37fa4ec4edcc833c7 + + + + #define + ETCPAL_INIT_PDU + group__etcpal__pdu.html + ga0c0d07635b8236c97bb21bbd1eb61c8f + (pduptr) + + + struct EtcPalPdu + EtcPalPdu + group__etcpal__pdu.html + gafd2b4bca589bf922a6458962a1fa1b49 + + + + struct EtcPalPduConstraints + EtcPalPduConstraints + group__etcpal__pdu.html + gaffe297ca0b89d8b738dad159ccae904c + + + + bool + etcpal_parse_pdu + group__etcpal__pdu.html + ga9a351fdaedcae30ce8999e4d9fbaf15e + (const uint8_t *buf, size_t buflen, const EtcPalPduConstraints *constraints, EtcPalPdu *pdu) + + + #define + ETCPAL_PDU_L_FLAG_SET + group__etcpal__pdu.html + gaadfa588e12322808723c598fef9b2509 + (flags_byte) + + + #define + ETCPAL_PDU_V_FLAG_SET + group__etcpal__pdu.html + ga183303aee9717e2c0e662bbfb98dcc1f + (flags_byte) + + + #define + ETCPAL_PDU_H_FLAG_SET + group__etcpal__pdu.html + gac6bd98193bb97a1745a87ef1eddec36e + (flags_byte) + + + #define + ETCPAL_PDU_D_FLAG_SET + group__etcpal__pdu.html + ga8395f03212e738c67fee8f6e458617a2 + (flags_byte) + + + #define + ETCPAL_PDU_SET_L_FLAG + group__etcpal__pdu.html + ga0aff4c299ef1edd12a62a94791787b05 + (flags_byte) + + + #define + ETCPAL_PDU_SET_V_FLAG + group__etcpal__pdu.html + gafd5bbef88b8bf08ead91ccf04f44123a + (flags_byte) + + + #define + ETCPAL_PDU_SET_H_FLAG + group__etcpal__pdu.html + ga895f3f23d5fc24feeaf6b9222960a7c0 + (flags_byte) + + + #define + ETCPAL_PDU_SET_D_FLAG + group__etcpal__pdu.html + gac7b3e21b8c080aea188a2d577fd31d31 + (flags_byte) + + + + etcpal_rbtree + etcpal_rbtree + group__etcpal__rbtree.html + EtcPalRbNode + EtcPalRbTree + EtcPalRbIter + + #define + ETCPAL_RB_ITER_MAX_HEIGHT + group__etcpal__rbtree.html + ga347976360fdafc669aab59abc1ff7d73 + + + + struct EtcPalRbIter + EtcPalRbIter + group__etcpal__rbtree.html + gaca406625e86f809e1d5b8e52ca3d3e40 + + + + int + etcpal_rbtree_node_cmp_ptr_cb + group__etcpal__rbtree.html + ga2c7b10e007e2221402426393cbbc3461 + (const EtcPalRbTree *self, const EtcPalRbNode *a, const EtcPalRbNode *b) + + + void + etcpal_rbtree_node_dealloc_cb + group__etcpal__rbtree.html + ga2041c16a4a4e745ccadd180cbb8bc93f + (const EtcPalRbTree *self, EtcPalRbNode *node) + + + EtcPalRbNode * + etcpal_rbnode_init + group__etcpal__rbtree.html + gaf901899ba23ab79070d5ed1440440eb2 + (EtcPalRbNode *self, void *value) + + + EtcPalRbTree * + etcpal_rbtree_init + group__etcpal__rbtree.html + gaf7b76e69622bca24f161d0998d6625b0 + (EtcPalRbTree *self, etcpal_rbtree_node_cmp_f cmp, etcpal_rbnode_alloc_f alloc_f, etcpal_rbnode_dealloc_f dealloc_f) + + + void * + etcpal_rbtree_find + group__etcpal__rbtree.html + ga4e42141273a433aad5e854780e321004 + (EtcPalRbTree *self, void *value) + + + etcpal_error_t + etcpal_rbtree_insert + group__etcpal__rbtree.html + gae87df653a152c3942b54a8f8e7c235c6 + (EtcPalRbTree *self, void *value) + + + etcpal_error_t + etcpal_rbtree_remove + group__etcpal__rbtree.html + ga948b09a65cbe24eefcfb5823641f39f1 + (EtcPalRbTree *self, void *value) + + + etcpal_error_t + etcpal_rbtree_clear + group__etcpal__rbtree.html + ga1347a53b2f8505e22707702f490949e8 + (EtcPalRbTree *self) + + + size_t + etcpal_rbtree_size + group__etcpal__rbtree.html + gae0aa64287211d3858cef5d0a7cffb033 + (EtcPalRbTree *self) + + + etcpal_error_t + etcpal_rbtree_insert_node + group__etcpal__rbtree.html + ga036f8c0aea4ac2050bd2deb904affed6 + (EtcPalRbTree *self, EtcPalRbNode *node) + + + etcpal_error_t + etcpal_rbtree_remove_with_cb + group__etcpal__rbtree.html + ga71a4587a7746d0e43beb9687de446723 + (EtcPalRbTree *self, void *value, etcpal_rbtree_node_f node_cb) + + + etcpal_error_t + etcpal_rbtree_clear_with_cb + group__etcpal__rbtree.html + ga8b115911ba175651df1c73bdb1c0a773 + (EtcPalRbTree *self, etcpal_rbtree_node_f node_cb) + + + int + etcpal_rbtree_test + group__etcpal__rbtree.html + ga3b194e280069ff3fbd105d9799dbea05 + (EtcPalRbTree *self, EtcPalRbNode *root) + + + EtcPalRbIter * + etcpal_rbiter_init + group__etcpal__rbtree.html + gae7d2f565a40d1ab86873e7bc9c5c5c02 + (EtcPalRbIter *self) + + + void * + etcpal_rbiter_first + group__etcpal__rbtree.html + ga1cd77fc10e7c983be2c12c5f14bc3721 + (EtcPalRbIter *self, EtcPalRbTree *tree) + + + void * + etcpal_rbiter_last + group__etcpal__rbtree.html + ga6f1279b41c60d92a808cc9b364f9eac9 + (EtcPalRbIter *self, EtcPalRbTree *tree) + + + void * + etcpal_rbiter_next + group__etcpal__rbtree.html + gaa3804b7146d1e8a72e4139a0f4d6507e + (EtcPalRbIter *self) + + + void * + etcpal_rbiter_prev + group__etcpal__rbtree.html + gad093318703094fd4bdb9ecb09443241d + (EtcPalRbIter *self) + + + int(* + etcpal_rbtree_node_cmp_f + group__etcpal__rbtree.html + gaa8464a406583530043f66b63955ebb1c + )(const EtcPalRbTree *self, const EtcPalRbNode *node_a, const EtcPalRbNode *node_b) + + + void(* + etcpal_rbtree_node_f + group__etcpal__rbtree.html + gac3929405ade6133edb8cf06d7fa6271b + )(const EtcPalRbTree *self, EtcPalRbNode *node) + + + EtcPalRbNode *(* + etcpal_rbnode_alloc_f + group__etcpal__rbtree.html + gadb6dac2a828f26ba2ae35656a738d685 + )() + + + void(* + etcpal_rbnode_dealloc_f + group__etcpal__rbtree.html + ga94fa4793990e233cddc87d1606b38f79 + )(EtcPalRbNode *node) + + + + etcpal_rootlayerpdu + etcpal_rootlayerpdu + group__etcpal__rootlayerpdu.html + EtcPalTcpPreamble + EtcPalUdpPreamble + EtcPalRootLayerPdu + + #define + ACN_TCP_PREAMBLE_SIZE + group__etcpal__rootlayerpdu.html + gab879b13847509e3bbd4b12a5e2cda0e7 + + + + #define + ACN_UDP_PREAMBLE_SIZE + group__etcpal__rootlayerpdu.html + ga86207e41512354a1a6e321d95afe8ab0 + + + + #define + ACN_RLP_HEADER_SIZE_NORMAL_LEN + group__etcpal__rootlayerpdu.html + ga29ae7e116cd77cc00366461415bf54a7 + + + + #define + ACN_RLP_HEADER_SIZE_EXT_LEN + group__etcpal__rootlayerpdu.html + ga9d9a7bd4498a28d5b0de8ed598141c66 + + + + struct EtcPalTcpPreamble + EtcPalTcpPreamble + group__etcpal__rootlayerpdu.html + ga479d29909ff291c75531e5e45de4af11 + + + + struct EtcPalUdpPreamble + EtcPalUdpPreamble + group__etcpal__rootlayerpdu.html + gabceea25a6773878d73d5c73cff3413db + + + + struct EtcPalRootLayerPdu + EtcPalRootLayerPdu + group__etcpal__rootlayerpdu.html + gafcee66c76b1dec0bbaf93f9589c0a8dd + + + + bool + etcpal_parse_tcp_preamble + group__etcpal__rootlayerpdu.html + ga9d42879935ab912ec15d30e9415f5c4b + (const uint8_t *buf, size_t buflen, EtcPalTcpPreamble *preamble) + + + bool + etcpal_parse_udp_preamble + group__etcpal__rootlayerpdu.html + ga9c5fe31670c57a02311d3d23f6b96904 + (const uint8_t *buf, size_t buflen, EtcPalUdpPreamble *preamble) + + + bool + etcpal_parse_root_layer_header + group__etcpal__rootlayerpdu.html + gaa454f9d1af3e45a1eefb61c3d4fd9496 + (const uint8_t *buf, size_t buflen, EtcPalRootLayerPdu *pdu, EtcPalRootLayerPdu *last_pdu) + + + bool + etcpal_parse_root_layer_pdu + group__etcpal__rootlayerpdu.html + gac604ba1761a3126ddf9095338ec2d4a4 + (const uint8_t *buf, size_t buflen, EtcPalRootLayerPdu *pdu, EtcPalPdu *last_pdu) + + + size_t + etcpal_pack_tcp_preamble + group__etcpal__rootlayerpdu.html + ga83602488410ff9d31fb781afd5898463 + (uint8_t *buf, size_t buflen, size_t rlp_block_len) + + + size_t + etcpal_pack_udp_preamble + group__etcpal__rootlayerpdu.html + ga205a77f2284495f4b9a16f07dcd43f83 + (uint8_t *buf, size_t buflen) + + + size_t + etcpal_root_layer_buf_size + group__etcpal__rootlayerpdu.html + ga0d9d71dfeb84b94149e146292144615b + (const EtcPalRootLayerPdu *pdu_block, size_t num_pdus) + + + size_t + etcpal_pack_root_layer_header + group__etcpal__rootlayerpdu.html + ga8d5021cdeed9c03dcc28d7f29fbac7d9 + (uint8_t *buf, size_t buflen, const EtcPalRootLayerPdu *pdu) + + + size_t + etcpal_pack_root_layer_block + group__etcpal__rootlayerpdu.html + gabdadb9de2e41045c2010e6085f6ff456 + (uint8_t *buf, size_t buflen, const EtcPalRootLayerPdu *pdu_block, size_t num_pdus) + + + + etcpal_socket + etcpal_socket + group__etcpal__socket.html + EtcPalLinger + EtcPalMreq + EtcPalGroupReq + EtcPalPollEvent + EtcPalAddrinfo + + #define + ETCPAL_SOCKET_INVALID + group__etcpal__socket.html + ga304e26b30c36b6c33319b9602c9fe276 + + + + #define + ETCPAL_SOCKET_MAX_POLL_SIZE + group__etcpal__socket.html + ga06b68eaa9d0e50e624659ed1b9c7f05a + + + + PLATFORM_DEFINED + etcpal_socket_t + group__etcpal__socket.html + gaf08a63353f05072ee3b28fd754985b66 + + + + uint32_t + etcpal_poll_events_t + group__etcpal__socket.html + ga625b9f37c09cda6d3f13330094fa97d9 + + + + struct EtcPalLinger + EtcPalLinger + group__etcpal__socket.html + gaf5335aecd65e931fa0c9dc0ead350978 + + + + struct EtcPalMreq + EtcPalMreq + group__etcpal__socket.html + ga3ca1dc73415b552ebca00df10e53a5e1 + + + + struct EtcPalGroupReq + EtcPalGroupReq + group__etcpal__socket.html + ga21df9f214a53c2f6b06b15496edfeca8 + + + + struct EtcPalPollEvent + EtcPalPollEvent + group__etcpal__socket.html + ga7b84da8c4de1182c5b7769a5f5b8034c + + + + struct EtcPalAddrinfo + EtcPalAddrinfo + group__etcpal__socket.html + ga83e2e233e87a88a7edf037928d203550 + + + + etcpal_error_t + etcpal_accept + group__etcpal__socket.html + ga135bc72cd29f02fec9e610397d1d212a + (etcpal_socket_t id, EtcPalSockaddr *address, etcpal_socket_t *conn_sock) + + + etcpal_error_t + etcpal_bind + group__etcpal__socket.html + ga408d5b56a68e54697dfa3c5febd82c99 + (etcpal_socket_t id, const EtcPalSockaddr *address) + + + etcpal_error_t + etcpal_close + group__etcpal__socket.html + gaccdfd06b91ca1632a59c68e819270825 + (etcpal_socket_t id) + + + etcpal_error_t + etcpal_connect + group__etcpal__socket.html + gac0a61cfe25dfa9691cc8064f5cc57341 + (etcpal_socket_t id, const EtcPalSockaddr *address) + + + etcpal_error_t + etcpal_getpeername + group__etcpal__socket.html + ga27daad6bd01f29e7cb9731783b4655e4 + (etcpal_socket_t id, EtcPalSockaddr *address) + + + etcpal_error_t + etcpal_getsockname + group__etcpal__socket.html + ga5097372bea204f9469f426a54cfab6af + (etcpal_socket_t id, EtcPalSockaddr *address) + + + etcpal_error_t + etcpal_getsockopt + group__etcpal__socket.html + ga653ed9405ec4cb21d958faab8b1c783e + (etcpal_socket_t id, int level, int option_name, void *option_value, size_t *option_len) + + + etcpal_error_t + etcpal_listen + group__etcpal__socket.html + ga39e660822d93588ea8723414567a2415 + (etcpal_socket_t id, int backlog) + + + int + etcpal_recv + group__etcpal__socket.html + gace688545de41aecba767639fa0c8f7b6 + (etcpal_socket_t id, void *buffer, size_t length, int flags) + + + int + etcpal_recvfrom + group__etcpal__socket.html + gaf3007bbae16c9cb60635fae38410b1e5 + (etcpal_socket_t id, void *buffer, size_t length, int flags, EtcPalSockaddr *address) + + + int + etcpal_send + group__etcpal__socket.html + ga52ba67993412de6dc69a582ca07f50d5 + (etcpal_socket_t id, const void *message, size_t length, int flags) + + + int + etcpal_sendto + group__etcpal__socket.html + gac3b8ee613e51b01a420ee6b820c8da63 + (etcpal_socket_t id, const void *message, size_t length, int flags, const EtcPalSockaddr *dest_addr) + + + etcpal_error_t + etcpal_setsockopt + group__etcpal__socket.html + ga0cc965b67084fb27214825cb893d2041 + (etcpal_socket_t id, int level, int option_name, const void *option_value, size_t option_len) + + + etcpal_error_t + etcpal_shutdown + group__etcpal__socket.html + ga3c51a1d50368f372ecd2c44c93f85cac + (etcpal_socket_t id, int how) + + + etcpal_error_t + etcpal_socket + group__etcpal__socket.html + gae0c8d9e036be592eba7db8736c7e1e0f + (unsigned int family, unsigned int type, etcpal_socket_t *id) + + + etcpal_error_t + etcpal_setblocking + group__etcpal__socket.html + ga72f16eec0ea5416ac4a553e1e78d7c77 + (etcpal_socket_t id, bool blocking) + + + etcpal_error_t + etcpal_getblocking + group__etcpal__socket.html + ga7134eafebb4ee73d160cd38d96ddeb9e + (etcpal_socket_t id, bool *blocking) + + + etcpal_error_t + etcpal_getaddrinfo + group__etcpal__socket.html + ga5e63f5fa7b1b4310a4bb317aa4873997 + (const char *hostname, const char *service, const EtcPalAddrinfo *hints, EtcPalAddrinfo *result) + + + bool + etcpal_nextaddr + group__etcpal__socket.html + ga669185d01901034d700f167fa23f3eb1 + (EtcPalAddrinfo *ai) + + + void + etcpal_freeaddrinfo + group__etcpal__socket.html + ga8cc1d9b7b5e8e2b88a337fc727b44535 + (EtcPalAddrinfo *ai) + + + etcpal_error_t + etcpal_inet_ntop + group__etcpal__socket.html + ga8f8b3a64cec296d5d896e10bf7a60ac3 + (const EtcPalIpAddr *src, char *dest, size_t size) + + + etcpal_error_t + etcpal_inet_pton + group__etcpal__socket.html + gacc09a02c09d9798f46d1fb6e9e84b900 + (etcpal_iptype_t type, const char *src, EtcPalIpAddr *dest) + + + PLATFORM_DEFINED + EtcPalPollContext + group__etcpal__socket.html + ga906fd2bcb17663f4de3fefd0b335656e + + + + etcpal_error_t + etcpal_poll_context_init + group__etcpal__socket.html + gaf566500c673f2e7941f9a399c61c1b68 + (EtcPalPollContext *context) + + + void + etcpal_poll_context_deinit + group__etcpal__socket.html + ga08a886e98949a8c0ba7f162e54cd1a72 + (EtcPalPollContext *context) + + + etcpal_error_t + etcpal_poll_add_socket + group__etcpal__socket.html + gab901f9cf32e98e0d99369366f2e1ffa4 + (EtcPalPollContext *context, etcpal_socket_t socket, etcpal_poll_events_t events, void *user_data) + + + etcpal_error_t + etcpal_poll_modify_socket + group__etcpal__socket.html + ga396b218eda2c3e52b4b917b73e18dab7 + (EtcPalPollContext *context, etcpal_socket_t socket, etcpal_poll_events_t new_events, void *new_user_data) + + + void + etcpal_poll_remove_socket + group__etcpal__socket.html + ga8233886a08aff8ba010dfa7384c76408 + (EtcPalPollContext *context, etcpal_socket_t socket) + + + etcpal_error_t + etcpal_poll_wait + group__etcpal__socket.html + gae5017e2346be12e91c6450fe9860614b + (EtcPalPollContext *context, EtcPalPollEvent *event, int timeout_ms) + + + #define + ETCPAL_SOL_SOCKET + group__etcpal__socket.html + ga30a8a29b624b2bef32f68b1fe2aa9e83 + + + + #define + ETCPAL_IPPROTO_IP + group__etcpal__socket.html + gaba74f8fca47e034d676049bd8eb61488 + + + + #define + ETCPAL_IPPROTO_ICMPV6 + group__etcpal__socket.html + ga66aa3d038609a999ad33370a6c0c3284 + + + + #define + ETCPAL_IPPROTO_IPV6 + group__etcpal__socket.html + ga7db66bcfc3f239baf6a5fef9058192de + + + + #define + ETCPAL_IPPROTO_TCP + group__etcpal__socket.html + gaa885355b90b8e92d7f9965b63790810f + + + + #define + ETCPAL_IPPROTO_UDP + group__etcpal__socket.html + ga19bf0e5a8ce939ea6c4ea034f4839bcc + + + + #define + ETCPAL_SO_BROADCAST + group__etcpal__socket.html + gab90f6d9eeabe39a57db6b808d24d9bd2 + + + + #define + ETCPAL_SO_ERROR + group__etcpal__socket.html + ga20fe86808f28b9a96ee808626e4e3293 + + + + #define + ETCPAL_SO_KEEPALIVE + group__etcpal__socket.html + ga085124fd101ed8c2feb6c224d54d0b39 + + + + #define + ETCPAL_SO_LINGER + group__etcpal__socket.html + gaf47bd53da2c92535aa6edcd8cc820259 + + + + #define + ETCPAL_SO_RCVBUF + group__etcpal__socket.html + gab07c26f5ae3d4786c824461a65ba0dcc + + + + #define + ETCPAL_SO_SNDBUF + group__etcpal__socket.html + ga7e246a346418dcd9b4318fd673d4b622 + + + + #define + ETCPAL_SO_RCVTIMEO + group__etcpal__socket.html + ga068a8f93c435a18f79b13e21ff30cfd0 + + + + #define + ETCPAL_SO_SNDTIMEO + group__etcpal__socket.html + gaf74d842c762e41c9a7e5a5a3404905ef + + + + #define + ETCPAL_SO_REUSEADDR + group__etcpal__socket.html + gac2fc9cd09dce99bb5681df96f65c31b8 + + + + #define + ETCPAL_SO_REUSEPORT + group__etcpal__socket.html + ga9fb28d8ce3fc93272b41ebe7b5d87989 + + + + #define + ETCPAL_SO_TYPE + group__etcpal__socket.html + gad8abc2b8b8d29d17c94b3493bbf30816 + + + + #define + ETCPAL_IP_TTL + group__etcpal__socket.html + gaa8067f3bea534148c077f2dd720a6d51 + + + + #define + ETCPAL_IP_MULTICAST_IF + group__etcpal__socket.html + ga972636e83a7c9cbc9bb0e5a950c9c241 + + + + #define + ETCPAL_IP_MULTICAST_TTL + group__etcpal__socket.html + ga53c1ba7904c7917177dea985809b12c4 + + + + #define + ETCPAL_IP_MULTICAST_LOOP + group__etcpal__socket.html + ga0adba5365cbc8344c77ba5a47b43590e + + + + #define + ETCPAL_IP_ADD_MEMBERSHIP + group__etcpal__socket.html + ga19b3047fe621a06b5cedc8043bb823cf + + + + #define + ETCPAL_IP_DROP_MEMBERSHIP + group__etcpal__socket.html + gacbe3547d777f101aaa432e602c4b8e69 + + + + #define + ETCPAL_MCAST_JOIN_GROUP + group__etcpal__socket.html + gacde51cd51d94c43625b96196d7b80f50 + + + + #define + ETCPAL_MCAST_LEAVE_GROUP + group__etcpal__socket.html + ga747194309fa23fa0e092e8bd010f1a2c + + + + #define + ETCPAL_IPV6_V6ONLY + group__etcpal__socket.html + ga6a502de1f396117da63bde901d88e434 + + + + #define + ETCPAL_POLL_IN + group__etcpal__socket.html + ga4e4bec5c7c2860538445ebdba2dd4283 + + + + #define + ETCPAL_POLL_OUT + group__etcpal__socket.html + ga04ebfb989375a6cf612d69f229a74954 + + + + #define + ETCPAL_POLL_CONNECT + group__etcpal__socket.html + gabbd670e11bf27a8a815b2d7985b9a364 + + + + #define + ETCPAL_POLL_OOB + group__etcpal__socket.html + ga1da970a4c0bd353ec963e4bb70c0f8b8 + + + + #define + ETCPAL_POLL_ERR + group__etcpal__socket.html + ga837082b33f4ca260e78373ee40bd25ec + + + + + etcpal_timer + etcpal_timer + group__etcpal__timer.html + EtcPalTimer + + struct EtcPalTimer + EtcPalTimer + group__etcpal__timer.html + gaa8f82d792cb262d907daa7b9586220ad + + + + uint32_t + etcpal_getms + group__etcpal__timer.html + ga9d277421b68caa9f0ad6f23bd775d5d6 + () + + + void + etcpal_timer_start + group__etcpal__timer.html + ga6e34d82478d4ad222a22df781b5f2f44 + (EtcPalTimer *timer, uint32_t interval) + + + void + etcpal_timer_reset + group__etcpal__timer.html + gae3f2a33d174900c2a2a67e2eef842069 + (EtcPalTimer *timer) + + + uint32_t + etcpal_timer_elapsed + group__etcpal__timer.html + ga5d73c9f8144f65719e8b319cdfdc05bb + (const EtcPalTimer *timer) + + + bool + etcpal_timer_is_expired + group__etcpal__timer.html + gaccc47c2970648c782918f8ab21d10ae9 + (const EtcPalTimer *timer) + + + uint32_t + etcpal_timer_remaining + group__etcpal__timer.html + ga8f0822e6e65f8e63b3776533ce1ff531 + (const EtcPalTimer *timer) + + + + etcpal_uuid + etcpal_uuid + group__etcpal__uuid.html + EtcPalUuid + + #define + ETCPAL_UUID_BYTES + group__etcpal__uuid.html + gadfd6e6a51b681c03b6422d1454ddc954 + + + + #define + ETCPAL_UUID_CMP + group__etcpal__uuid.html + ga6f2cff87ab29b0b26d0f641b065c998d + (uuid1ptr, uuid2ptr) + + + #define + ETCPAL_UUID_IS_NULL + group__etcpal__uuid.html + ga3f7c7f1f596e00536adbefb78899ebd1 + (uuidptr) + + + #define + ETCPAL_UUID_STRING_BYTES + group__etcpal__uuid.html + gabab14207e273082491f7be2a21275092 + + + + struct EtcPalUuid + EtcPalUuid + group__etcpal__uuid.html + ga472e79f55f51afda28c54c6967018922 + + + + void + etcpal_uuid_to_string + group__etcpal__uuid.html + ga6a5dcd27e638a9f7ed8c0953708363d4 + (char *buf, const EtcPalUuid *uuid) + + + bool + etcpal_string_to_uuid + group__etcpal__uuid.html + gaf0b1aeb14ab6cac80eac90066af53c8e + (EtcPalUuid *uuid, const char *buf, size_t buflen) + + + etcpal_error_t + etcpal_generate_v1_uuid + group__etcpal__uuid.html + ga7a2029b259cc4270fb721b976f21972a + (EtcPalUuid *uuid) + + + etcpal_error_t + etcpal_generate_v3_uuid + group__etcpal__uuid.html + ga7f16be65a1af810d045536230750604b + (EtcPalUuid *uuid, const char *devstr, const uint8_t *macaddr, uint32_t uuidnum) + + + etcpal_error_t + etcpal_generate_v4_uuid + group__etcpal__uuid.html + ga1cabb8b6f72752b1a2ae72f776301242 + (EtcPalUuid *uuid) + + + const EtcPalUuid + kEtcPalNullUuid + group__etcpal__uuid.html + gae518c32bbc7d2266568ee9a703bb4f5e + + + + + additional_docs + Additional Documentation + additional_docs + + + interface_indexes + Network Interface Indexes + interface_indexes + + + index + ETC Platform Abstraction Layer + index + + diff --git a/docs/header.html b/docs/header.html index 7f6b3693c..156511aaa 100644 --- a/docs/header.html +++ b/docs/header.html @@ -24,7 +24,7 @@