From 9b4a71aa70a8369eabc0e1a18420593592c15525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Lindel=C3=B6w?= Date: Fri, 10 Apr 2026 09:24:36 +0200 Subject: [PATCH] Move definitions to header file from cmakelists --- CMakeLists.txt | 23 +------- include/tinycsocket.h | 107 +++++++++++++++++++++---------------- src/tinycsocket_internal.h | 41 ++++++++++---- src/tinycsocket_posix.c | 66 +++++++++++------------ 4 files changed, 126 insertions(+), 111 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f878a0f..68f3e06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.10) # CMake fix for crosscompile (MinGW-w64) set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") +project(tinycsocket) + include(CheckSymbolExists) include(CheckIncludeFile) @@ -24,17 +26,11 @@ if(MSVC) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") endif() - add_definitions("-D_CRT_SECURE_NO_WARNINGS") elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter -Wall -Wextra -Wpedantic -Walloca -Wcast-align -Wcast-qual -Wdouble-promotion -Wduplicated-cond -Wenum-conversion -Wfloat-equal -Wformat-overflow=2 -Wformat-signedness -Wformat=2 -Wframe-larger-than=2048 -Wlogical-op -Wmissing-braces -Wmultichar -Wpointer-arith -Wrestrict -Wshadow -Wjump-misses-init -Wsuggest-attribute=format -Wsuggest-attribute=malloc -Wuninitialized -Wvla -Wwrite-strings -Wsign-conversion -std=c99" ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wall -Wextra -Wpedantic -Walloca -Wcast-align -Wcast-qual -Wcomma-subscript -Wctor-dtor-privacy -Wdeprecated-copy-dtor -Wdouble-promotion -Wduplicated-cond -Wenum-conversion -Wextra-semi -Wfloat-equal -Wformat-overflow=2 -Wformat-signedness -Wformat=2 -Wframe-larger-than=2048 -Wlogical-op -Wmismatched-tags -Wmissing-braces -Wmultichar -Wnoexcept -Wnon-virtual-dtor -Woverloaded-virtual -Wpointer-arith -Wrange-loop-construct -Wrestrict -Wshadow -Wstrict-null-sentinel -Wsuggest-attribute=format -Wsuggest-attribute=malloc -Wuninitialized -Wvla -Wvolatile -Wwrite-strings -Wsign-conversion") - add_definitions( - -D_POSIX_C_SOURCE=200112L - -D_DEFAULT_SOURCE - -D_ISOC99_SOURCE - ) else() message("WARNING: Unknown compiler, warning flags were not set") endif() @@ -44,21 +40,6 @@ option(TCS_ENABLE_EXAMPLES "Enable examples" OFF) option(TCS_WARNINGS_AS_ERRORS "Enable treat warnings as errors" OFF) option(TCS_GENERATE_COVERAGE "Enable for test coverage generation" OFF) -# ifaddrs crossplatform define -if (NOT MSVC) - check_symbol_exists(getifaddrs "sys/types.h;ifaddrs.h" TCS_IFADDRS_FOUND) - if(NOT TCS_IFADDRS_FOUND) - MESSAGE("TCS warning: Symbol getifaddrs not found. Workaround will be applied.") - add_definitions("-DTCS_MISSING_IFADDRS") - endif() - - check_include_file("linux/if_packet.h" TCS_AF_PACKET_FOUND) - if(NOT TCS_AF_PACKET_FOUND) - MESSAGE("TCS warning: Header sys/types.h does not exist. AF_PACKET will not be available.") - add_definitions("-DTCS_MISSING_AF_PACKET") - endif() -endif() - set(TINYCSOCKET_SRC "src/tinycsocket_internal.h" "src/tinydatastructures.h" diff --git a/include/tinycsocket.h b/include/tinycsocket.h index 0160f95..2794d23 100644 --- a/include/tinycsocket.h +++ b/include/tinycsocket.h @@ -29,14 +29,7 @@ #ifndef TINYCSOCKET_INTERNAL_H_ #define TINYCSOCKET_INTERNAL_H_ -#include -#include -#include - -/** @internal */ -#define tcs_static_assert(name, expr) typedef char tcs_sa_##name[(expr) ? 1 : -1] - -static const char* const TCS_VERSION_TXT = "v0.3.57"; +static const char* const TCS_VERSION_TXT = "v0.3.58"; static const char* const TCS_LICENSE_TXT = "Copyright 2018 Markus Lindelöw\n" "\n" @@ -168,7 +161,8 @@ static const char* const TCS_LICENSE_TXT = * - bool tcs_address_is_broadcast(const struct TcsAddress* addr); */ -// First we have some code to recognize which system we are compiling against +// Recognize which system we are compiling against + #if defined(WIN32) || defined(__MINGW32__) #define TINYCSOCKET_USE_WIN32_IMPL #elif defined(__linux__) || defined(__sun) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ @@ -195,6 +189,26 @@ extern "C" { typedef UINT_PTR TcsSocket; typedef unsigned int TcsInterfaceId; // TODO: GUID is used for in vista at newer. Change this type. #elif defined(TINYCSOCKET_USE_POSIX_IMPL) + +#if defined(TINYCSOCKET_IMPLEMENTATION) || defined(TCS_DEFINE_POSIX_MACROS) +// POSIX feature test macros must be set before any system header is included. +// Without these, glibc's (pulled in by ) locks in +// strict C99 defaults that hide AI_PASSIVE, struct addrinfo, struct timeval, +// u_short, SO_REUSEPORT, etc. +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 +#endif +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L +#endif +#ifndef _ISOC99_SOURCE +#define _ISOC99_SOURCE +#endif +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif +#endif + typedef int TcsSocket; typedef unsigned int TcsInterfaceId; #endif @@ -203,6 +217,15 @@ typedef unsigned int TcsInterfaceId; #define TCS_SENDV_STACK_MAX 112 #endif +// Declarations + +#include +#include +#include + +/** @internal */ +#define tcs_static_assert(name, expr) typedef char tcs_sa_##name[(expr) ? 1 : -1] + /** * @brief Address Family */ @@ -2641,18 +2664,9 @@ static inline int tds_map_remove(void** keys, * SOFTWARE. */ -#ifndef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200112L -#endif -#ifndef _ISOC99_SOURCE -#define _ISOC99_SOURCE -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE -#endif - // Header only should not need other files #ifndef TINYCSOCKET_INTERNAL_H_ +#define TCS_DEFINE_POSIX_MACROS // Helper to not lock to strict C99 #include "tinycsocket_internal.h" #endif #ifdef TINYCSOCKET_USE_POSIX_IMPL @@ -2665,9 +2679,26 @@ static inline int tds_map_remove(void** keys, #include "dbg_wrap.h" #endif +#ifndef TCS_HAS_AF_PACKET +#if defined(__linux__) +#define TCS_HAS_AF_PACKET 1 +#else +#define TCS_HAS_AF_PACKET 0 +#endif +#endif + +#ifndef TCS_HAS_GETIFADDRS +#if defined(__ANDROID__) && (__ANDROID_API__ >= 24) +#define TCS_HAS_GETIFADDRS 1 +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#define TCS_HAS_GETIFADDRS 1 +#else +#define TCS_HAS_GETIFADDRS 0 +#endif +#endif + #include #include // fcntl() for non-blocking -#include // getifaddr() #include // IOV_MAX #include // Flags for ifaddrs (?) #include // Protocols and custom return codes @@ -2682,24 +2713,10 @@ static inline int tds_map_remove(void** keys, #include // UIO_MAXIOV #include // close() -// The logic might seem a bit reversed but it is to allow header only usage without defining TCS_AVAILABLE_XXX -// You need to disable the default if your system does not support it. (Optimized for most common usage and easy to detect) - -// If you no not use cmake you may need to define TCS_MISSING_AF_PACKET yourself if your system does not support it -#if defined(__linux__) && !defined(TCS_MISSING_AF_PACKET) // __linux__ to disable default for header only no-linux users -#define TCS_AVAILABLE_AF_PACKET 1 -#else -#define TCS_AVAILABLE_AF_PACKET 0 -#endif - -// If you no not use cmake you may need to define TCS_MISSING_IFADDRS yourself if your system does not support it -#if !defined(TCS_MISSING_IFADDRS) -#define TCS_AVAILABLE_IFADDRS 1 -#else -#define TCS_AVAILABLE_IFADDRS 0 +#if TCS_HAS_GETIFADDRS +#include // getifaddr() #endif - -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET #include // sll_hatype (ethernet and not can or firewire etc.) #include // struct sockaddr_ll #endif @@ -2779,7 +2796,7 @@ const int TCS_SO_IP_MEMBERSHIP_ADD = IP_ADD_MEMBERSHIP; const int TCS_SO_IP_MEMBERSHIP_DROP = IP_DROP_MEMBERSHIP; const int TCS_SO_IP_MULTICAST_LOOP = IP_MULTICAST_LOOP; -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET const int TCS_SO_PACKET_MEMBERSHIP_ADD = PACKET_ADD_MEMBERSHIP; const int TCS_SO_PACKET_MEMBERSHIP_DROP = PACKET_DROP_MEMBERSHIP; #else @@ -2837,7 +2854,7 @@ static TcsResult family2native(const TcsAddressFamily family, sa_family_t* nativ return TCS_SUCCESS; case TCS_AF_PACKET: -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET *native_family = AF_PACKET; return TCS_SUCCESS; #else @@ -2886,7 +2903,7 @@ static TcsResult sockaddr2native(const struct TcsAddress* tcs_address, } else if (tcs_address->family == TCS_AF_PACKET) { -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET struct sockaddr_ll* addr = (struct sockaddr_ll*)out_address; addr->sll_family = (sa_family_t)AF_PACKET; addr->sll_ifindex = (int)tcs_address->data.packet.interface_id; @@ -2920,7 +2937,7 @@ static TcsResult native2family(const sa_family_t native_family, TcsAddressFamily case AF_INET6: *family = TCS_AF_IP6; return TCS_SUCCESS; -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET case AF_PACKET: *family = TCS_AF_PACKET; return TCS_SUCCESS; @@ -2951,7 +2968,7 @@ static TcsResult native2sockaddr(const struct sockaddr* in_addr, struct TcsAddre memcpy(out_addr->data.ip6.address.bytes, &addr->sin6_addr, 16); out_addr->data.ip6.scope_id = (TcsInterfaceId)addr->sin6_scope_id; } -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET else if (in_addr->sa_family == AF_PACKET) { struct sockaddr_ll const* addr = (struct sockaddr_ll const*)(const void*)in_addr; @@ -3858,7 +3875,7 @@ TcsResult tcs_opt_membership_add_to(TcsSocket socket_ctx, } else if (multicast_address->family == TCS_AF_PACKET) { -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET const struct sockaddr_ll* address_native_local_p = (struct sockaddr_ll*)&local_address_native; const struct sockaddr_ll* address_native_multicast_p = (struct sockaddr_ll*)&multicast_address_native; @@ -3959,7 +3976,7 @@ TcsResult tcs_opt_membership_drop_from(TcsSocket socket_ctx, } else if (multicast_address->family == TCS_AF_PACKET) { -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET const struct sockaddr_ll* address_native_local_p = (struct sockaddr_ll*)&local_address_native; const struct sockaddr_ll* address_native_multicast_p = (struct sockaddr_ll*)&multicast_address_native; @@ -4114,7 +4131,7 @@ TcsResult tcs_address_resolve(const char* hostname, return TCS_SUCCESS; } -#if TCS_AVAILABLE_IFADDRS // acquired from CMake +#if TCS_HAS_GETIFADDRS TcsResult tcs_address_list(unsigned int interface_id_filter, TcsAddressFamily address_family_filter, struct TcsInterfaceAddress interface_addresses[], diff --git a/src/tinycsocket_internal.h b/src/tinycsocket_internal.h index 383231e..b1e1ee9 100644 --- a/src/tinycsocket_internal.h +++ b/src/tinycsocket_internal.h @@ -23,14 +23,7 @@ #ifndef TINYCSOCKET_INTERNAL_H_ #define TINYCSOCKET_INTERNAL_H_ -#include -#include -#include - -/** @internal */ -#define tcs_static_assert(name, expr) typedef char tcs_sa_##name[(expr) ? 1 : -1] - -static const char* const TCS_VERSION_TXT = "v0.3.57"; +static const char* const TCS_VERSION_TXT = "v0.3.58"; static const char* const TCS_LICENSE_TXT = "Copyright 2018 Markus Lindelöw\n" "\n" @@ -162,7 +155,8 @@ static const char* const TCS_LICENSE_TXT = * - bool tcs_address_is_broadcast(const struct TcsAddress* addr); */ -// First we have some code to recognize which system we are compiling against +// Recognize which system we are compiling against + #if defined(WIN32) || defined(__MINGW32__) #define TINYCSOCKET_USE_WIN32_IMPL #elif defined(__linux__) || defined(__sun) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ @@ -189,6 +183,26 @@ extern "C" { typedef UINT_PTR TcsSocket; typedef unsigned int TcsInterfaceId; // TODO: GUID is used for in vista at newer. Change this type. #elif defined(TINYCSOCKET_USE_POSIX_IMPL) + +#if defined(TINYCSOCKET_IMPLEMENTATION) || defined(TCS_DEFINE_POSIX_MACROS) +// POSIX feature test macros must be set before any system header is included. +// Without these, glibc's (pulled in by ) locks in +// strict C99 defaults that hide AI_PASSIVE, struct addrinfo, struct timeval, +// u_short, SO_REUSEPORT, etc. +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 +#endif +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L +#endif +#ifndef _ISOC99_SOURCE +#define _ISOC99_SOURCE +#endif +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif +#endif + typedef int TcsSocket; typedef unsigned int TcsInterfaceId; #endif @@ -197,6 +211,15 @@ typedef unsigned int TcsInterfaceId; #define TCS_SENDV_STACK_MAX 112 #endif +// Declarations + +#include +#include +#include + +/** @internal */ +#define tcs_static_assert(name, expr) typedef char tcs_sa_##name[(expr) ? 1 : -1] + /** * @brief Address Family */ diff --git a/src/tinycsocket_posix.c b/src/tinycsocket_posix.c index 1e3fa1a..869a9f2 100644 --- a/src/tinycsocket_posix.c +++ b/src/tinycsocket_posix.c @@ -20,18 +20,9 @@ * SOFTWARE. */ -#ifndef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200112L -#endif -#ifndef _ISOC99_SOURCE -#define _ISOC99_SOURCE -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE -#endif - // Header only should not need other files #ifndef TINYCSOCKET_INTERNAL_H_ +#define TCS_DEFINE_POSIX_MACROS // Helper to not lock to strict C99 #include "tinycsocket_internal.h" #endif #ifdef TINYCSOCKET_USE_POSIX_IMPL @@ -44,9 +35,26 @@ #include "dbg_wrap.h" #endif +#ifndef TCS_HAS_AF_PACKET +#if defined(__linux__) +#define TCS_HAS_AF_PACKET 1 +#else +#define TCS_HAS_AF_PACKET 0 +#endif +#endif + +#ifndef TCS_HAS_GETIFADDRS +#if defined(__ANDROID__) && (__ANDROID_API__ >= 24) +#define TCS_HAS_GETIFADDRS 1 +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#define TCS_HAS_GETIFADDRS 1 +#else +#define TCS_HAS_GETIFADDRS 0 +#endif +#endif + #include #include // fcntl() for non-blocking -#include // getifaddr() #include // IOV_MAX #include // Flags for ifaddrs (?) #include // Protocols and custom return codes @@ -61,24 +69,10 @@ #include // UIO_MAXIOV #include // close() -// The logic might seem a bit reversed but it is to allow header only usage without defining TCS_AVAILABLE_XXX -// You need to disable the default if your system does not support it. (Optimized for most common usage and easy to detect) - -// If you no not use cmake you may need to define TCS_MISSING_AF_PACKET yourself if your system does not support it -#if defined(__linux__) && !defined(TCS_MISSING_AF_PACKET) // __linux__ to disable default for header only no-linux users -#define TCS_AVAILABLE_AF_PACKET 1 -#else -#define TCS_AVAILABLE_AF_PACKET 0 +#if TCS_HAS_GETIFADDRS +#include // getifaddr() #endif - -// If you no not use cmake you may need to define TCS_MISSING_IFADDRS yourself if your system does not support it -#if !defined(TCS_MISSING_IFADDRS) -#define TCS_AVAILABLE_IFADDRS 1 -#else -#define TCS_AVAILABLE_IFADDRS 0 -#endif - -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET #include // sll_hatype (ethernet and not can or firewire etc.) #include // struct sockaddr_ll #endif @@ -158,7 +152,7 @@ const int TCS_SO_IP_MEMBERSHIP_ADD = IP_ADD_MEMBERSHIP; const int TCS_SO_IP_MEMBERSHIP_DROP = IP_DROP_MEMBERSHIP; const int TCS_SO_IP_MULTICAST_LOOP = IP_MULTICAST_LOOP; -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET const int TCS_SO_PACKET_MEMBERSHIP_ADD = PACKET_ADD_MEMBERSHIP; const int TCS_SO_PACKET_MEMBERSHIP_DROP = PACKET_DROP_MEMBERSHIP; #else @@ -216,7 +210,7 @@ static TcsResult family2native(const TcsAddressFamily family, sa_family_t* nativ return TCS_SUCCESS; case TCS_AF_PACKET: -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET *native_family = AF_PACKET; return TCS_SUCCESS; #else @@ -265,7 +259,7 @@ static TcsResult sockaddr2native(const struct TcsAddress* tcs_address, } else if (tcs_address->family == TCS_AF_PACKET) { -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET struct sockaddr_ll* addr = (struct sockaddr_ll*)out_address; addr->sll_family = (sa_family_t)AF_PACKET; addr->sll_ifindex = (int)tcs_address->data.packet.interface_id; @@ -299,7 +293,7 @@ static TcsResult native2family(const sa_family_t native_family, TcsAddressFamily case AF_INET6: *family = TCS_AF_IP6; return TCS_SUCCESS; -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET case AF_PACKET: *family = TCS_AF_PACKET; return TCS_SUCCESS; @@ -330,7 +324,7 @@ static TcsResult native2sockaddr(const struct sockaddr* in_addr, struct TcsAddre memcpy(out_addr->data.ip6.address.bytes, &addr->sin6_addr, 16); out_addr->data.ip6.scope_id = (TcsInterfaceId)addr->sin6_scope_id; } -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET else if (in_addr->sa_family == AF_PACKET) { struct sockaddr_ll const* addr = (struct sockaddr_ll const*)(const void*)in_addr; @@ -1237,7 +1231,7 @@ TcsResult tcs_opt_membership_add_to(TcsSocket socket_ctx, } else if (multicast_address->family == TCS_AF_PACKET) { -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET const struct sockaddr_ll* address_native_local_p = (struct sockaddr_ll*)&local_address_native; const struct sockaddr_ll* address_native_multicast_p = (struct sockaddr_ll*)&multicast_address_native; @@ -1338,7 +1332,7 @@ TcsResult tcs_opt_membership_drop_from(TcsSocket socket_ctx, } else if (multicast_address->family == TCS_AF_PACKET) { -#if TCS_AVAILABLE_AF_PACKET +#if TCS_HAS_AF_PACKET const struct sockaddr_ll* address_native_local_p = (struct sockaddr_ll*)&local_address_native; const struct sockaddr_ll* address_native_multicast_p = (struct sockaddr_ll*)&multicast_address_native; @@ -1493,7 +1487,7 @@ TcsResult tcs_address_resolve(const char* hostname, return TCS_SUCCESS; } -#if TCS_AVAILABLE_IFADDRS // acquired from CMake +#if TCS_HAS_GETIFADDRS TcsResult tcs_address_list(unsigned int interface_id_filter, TcsAddressFamily address_family_filter, struct TcsInterfaceAddress interface_addresses[],