Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Bdd/Targets/FreeRtos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,14 @@ add_executable(SolidSyslogBddTarget
${CMAKE_SOURCE_DIR}/Platform/FatFs/Source/SolidSyslogFatFsFile.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogAddress.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosDatagram.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosDatagramStatic.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosMutex.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosMutexStatic.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosStaticResolver.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosStaticResolverStatic.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosSysUpTime.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosTcpStream.c
${CMAKE_SOURCE_DIR}/Platform/FreeRtos/Source/SolidSyslogFreeRtosTcpStreamStatic.c
${CMAKE_SOURCE_DIR}/Bdd/Targets/Common/BddTargetInteractive.c
${CMAKE_SOURCE_DIR}/Bdd/Targets/Common/BddTargetIps.c
${CMAKE_SOURCE_DIR}/Bdd/Targets/Common/BddTargetLanguage.c
Expand Down
16 changes: 5 additions & 11 deletions Bdd/Targets/FreeRtos/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,6 @@ static struct SolidSyslogMessage testMessage = {
static NetworkInterface_t networkInterface;
static NetworkEndPoint_t networkEndPoint;

static SolidSyslogFreeRtosStaticResolverStorage resolverStorage;
static SolidSyslogFreeRtosDatagramStorage datagramStorage;
static SolidSyslogFreeRtosTcpStreamStorage tcpStreamStorage;

/* CircularBuffer + FreeRtosMutex composition for cross-task emission.
* 8 max-sized messages is comfortably above the 3-message BDD scenarios
* with headroom for a brief Service drain stall, and ~16 KB of .bss is
Expand All @@ -169,14 +165,12 @@ enum
};

static uint8_t bufferRing[SOLIDSYSLOG_CIRCULAR_BUFFER_RING_BYTES(BDD_TARGET_BUFFER_MESSAGES)];
static SolidSyslogFreeRtosMutexStorage mutexStorage;

/* Lifecycle mutex serialises SolidSyslog_Service against the rebuild path
* (`set store file` swaps NullStore for the file-backed BlockStore by
* destroying and re-creating SolidSyslog mid-run). Service holds the lock
* for one Service() call per iteration; the rebuild path holds it across
* Destroy → BlockStore_Create → Create. */
static SolidSyslogFreeRtosMutexStorage lifecycleMutexStorage;
static struct SolidSyslogMutex* lifecycleMutex = NULL;
static volatile bool solidSyslogReady;
/* Signals Service to self-delete BEFORE Teardown destroys the lifecycle
Expand Down Expand Up @@ -775,8 +769,8 @@ static void InteractiveTask(void* argument)
{
(void) argument;

resolver = SolidSyslogFreeRtosStaticResolver_Create(&resolverStorage, TEST_DESTINATION_IPV4);
datagram = SolidSyslogFreeRtosDatagram_Create(&datagramStorage);
resolver = SolidSyslogFreeRtosStaticResolver_Create(TEST_DESTINATION_IPV4);
datagram = SolidSyslogFreeRtosDatagram_Create();

struct SolidSyslogUdpSenderConfig udpConfig = {
.Resolver = resolver,
Expand All @@ -790,7 +784,7 @@ static void InteractiveTask(void* argument)
* UDP endpoint callbacks because the BDD oracle (syslog-ng) listens on the
* same host:port for both transports — the syslog-ng config in
* Bdd/syslog-ng/syslog-ng.conf has a TCP listener on 5514 alongside UDP. */
tcpStream = SolidSyslogFreeRtosTcpStream_Create(&tcpStreamStorage);
tcpStream = SolidSyslogFreeRtosTcpStream_Create();
struct SolidSyslogStreamSenderConfig tcpConfig = {
.Resolver = resolver,
.Stream = tcpStream,
Expand Down Expand Up @@ -820,12 +814,12 @@ static void InteractiveTask(void* argument)
* emission in S08.04 slice 3 will add more). The buffer's Read side
* is the Service task; its Write side is whichever task calls
* SolidSyslog_Log. */
bufferMutex = SolidSyslogFreeRtosMutex_Create(&mutexStorage);
bufferMutex = SolidSyslogFreeRtosMutex_Create();
buffer = SolidSyslogCircularBuffer_Create(bufferMutex, bufferRing, sizeof(bufferRing));

/* Lifecycle mutex created up front so the Service task can take it
* from its very first iteration without a NULL check. */
lifecycleMutex = SolidSyslogFreeRtosMutex_Create(&lifecycleMutexStorage);
lifecycleMutex = SolidSyslogFreeRtosMutex_Create();

/* Default store is NullStore — flipped to FatFs/BlockStore by
* `set store file` via RebuildWithFileStore(). */
Expand Down
9 changes: 9 additions & 0 deletions Bdd/Targets/FreeRtos/solidsyslog_user_tunables.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,13 @@
* generated Bdd/features/steps/solidsyslog_tunables.py mirror). */
#define SOLIDSYSLOG_MAX_MESSAGE_SIZE 512

/* The BDD target creates two FreeRtosMutex instances: `bufferMutex` (gating
* the CircularBuffer producers against the Service task drain) and
* `lifecycleMutex` (serialising SolidSyslog_Service against the
* `set store file` rebuild path that destroys and re-creates SolidSyslog
* mid-run). The library default of 1 would silently fall the second Create
* back to NullMutex — Lock/Unlock would become no-ops and the rebuild path
* could race the Service task. */
#define SOLIDSYSLOG_FREE_RTOS_MUTEX_POOL_SIZE 2U

#endif /* SOLIDSYSLOG_USER_TUNABLES_H */
8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,15 +326,15 @@ live under `Core/Interface/`; platform-specific helpers (the `SolidSyslogPosix*`
| `SolidSyslogResolver.h` | Any code that needs to resolve a destination | `SolidSyslogResolver_Resolve(resolver, transport, host, port, *out)` |
| `SolidSyslogResolverDefinition.h` | Resolver implementors (extension point) | `SolidSyslogResolver` vtable struct (`Resolve`) |
| `SolidSyslogNullResolver.h` | Any code installing a no-op resolver slot (Resolve returns `false` so the caller's unresolved-host error path runs naturally) | `SolidSyslogNullResolver_Get` |
| `SolidSyslogFreeRtosStaticResolver.h` | System setup code on FreeRTOS targets pinned to a hardcoded IPv4 destination (no DNS) | `SolidSyslogFreeRtosStaticResolverStorage`, `SOLIDSYSLOG_FREERTOSSTATICRESOLVER_SIZE`, `SolidSyslogFreeRtosStaticResolver_Create(storage, ipv4Octets)`, `_Destroy(resolver)` (ignores host and transport at Resolve time; port is taken from each call) |
| `SolidSyslogFreeRtosStaticResolver.h` | System setup code on FreeRTOS targets pinned to a hardcoded IPv4 destination (no DNS) | `SolidSyslogFreeRtosStaticResolver_Create(ipv4Octets)`, `_Destroy(base)` (ignores host and transport at Resolve time; port is taken from each call). Instance struct lives in a library-internal static pool (E11). Pool-exhaustion fallback is the shared `SolidSyslogNullResolver`. |
| `SolidSyslogDatagram.h` | Sender implementors using datagram transport | `SolidSyslogDatagram_Open`, `_SendTo`, `_Close` |
| `SolidSyslogDatagramDefinition.h` | Datagram implementors (extension point) | `SolidSyslogDatagram` vtable struct (`Open`, `SendTo`, `Close`) |
| `SolidSyslogNullDatagram.h` | Any code installing a no-op datagram slot (Open/Close are no-ops, SendTo returns `SENT` to drop on the floor so the Store does not fill with undeliverables, MaxPayload returns the IPv6-safe default) | `SolidSyslogNullDatagram_Get` |
| `SolidSyslogFreeRtosDatagram.h` | System setup code on FreeRTOS targets using FreeRTOS-Plus-TCP for UDP | `SolidSyslogFreeRtosDatagramStorage`, `SOLIDSYSLOG_FREERTOSDATAGRAM_SIZE`, `SolidSyslogFreeRtosDatagram_Create(storage)`, `_Destroy(datagram)` (wraps `FreeRTOS_socket` / `FreeRTOS_sendto` / `FreeRTOS_closesocket`) |
| `SolidSyslogFreeRtosDatagram.h` | System setup code on FreeRTOS targets using FreeRTOS-Plus-TCP for UDP | `SolidSyslogFreeRtosDatagram_Create(void)`, `_Destroy(base)` (wraps `FreeRTOS_socket` / `FreeRTOS_sendto` / `FreeRTOS_closesocket`). Instance struct lives in a library-internal static pool (E11). Pool-exhaustion fallback is the shared `SolidSyslogNullDatagram`. |
| `SolidSyslogStream.h` | Sender implementors using stream transport | `SolidSyslogStream_Open`, `_Send`, `_Read`, `_Close`, `SolidSyslogSsize` |
| `SolidSyslogStreamDefinition.h` | Stream implementors (extension point) | `SolidSyslogStream` vtable struct (`Open`, `Send`, `Read`, `Close`) |
| `SolidSyslogNullStream.h` | Any code installing a no-op stream slot (Open/Close are no-ops, Send returns `true` to drop on the floor so the Store does not fill with undeliverables, Read returns `0` for would-block so the caller does not tear the connection down) | `SolidSyslogNullStream_Get` |
| `SolidSyslogFreeRtosTcpStream.h` | System setup code on FreeRTOS targets using FreeRTOS-Plus-TCP for TCP | `SolidSyslogFreeRtosTcpStreamStorage`, `SOLIDSYSLOG_FREERTOSTCPSTREAM_SIZE`, `SolidSyslogFreeRtosTcpStream_Create(storage)`, `_Destroy(stream)` (wraps `FreeRTOS_socket` / `FreeRTOS_connect` / `FreeRTOS_send` / `FreeRTOS_recv` / `FreeRTOS_closesocket`; bounded blocking connect via `SO_SNDTIMEO=200ms`, cleared post-connect so Send/Read are non-blocking) |
| `SolidSyslogFreeRtosTcpStream.h` | System setup code on FreeRTOS targets using FreeRTOS-Plus-TCP for TCP | `SolidSyslogFreeRtosTcpStream_Create(void)`, `_Destroy(base)` (wraps `FreeRTOS_socket` / `FreeRTOS_connect` / `FreeRTOS_send` / `FreeRTOS_recv` / `FreeRTOS_closesocket`; bounded blocking connect via `SO_SNDTIMEO=200ms`, cleared post-connect so Send/Read are non-blocking). Instance struct lives in a library-internal static pool (E11); default pool size 2 to support the future TLS-via-mbedTLS + plain-TCP pair (S08.07). Pool-exhaustion fallback is the shared `SolidSyslogNullStream`. |
| `SolidSyslogUdpSender.h` | System setup code using UDP transport | `SolidSyslogUdpSenderConfig` (resolver, datagram, endpoint, endpointVersion), `SolidSyslogUdpSender_Create(config)`, `_Destroy(sender)`. Instance struct lives in a library-internal static pool (E11); `_Destroy` takes the handle returned by `_Create`. Pool-exhaustion and bad-config fallback is the shared `SolidSyslogNullSender`. |
| `SolidSyslogPosixTcpStream.h` | System setup code on POSIX targets using non-blocking TCP with bounded connect/keepalive | `SolidSyslogPosixTcpStream_Create(void)`, `_Destroy(base)`. Instance struct lives in a library-internal static pool (E11); default pool size 2 to support the BDD-target plain-TCP + TLS-underlying-TCP pair. Pool-exhaustion fallback is the shared `SolidSyslogNullStream`. |
| `SolidSyslogStreamSender.h` | System setup code using octet-framed transport (RFC 6587) over any Stream — `SolidSyslogPosixTcpStream` (POSIX TCP), `SolidSyslogWinsockTcpStream` (Windows TCP), `SolidSyslogFreeRtosTcpStream` (FreeRTOS-Plus-TCP), `SolidSyslogTlsStream` (TLS; OpenSSL reference integration), or a caller-supplied Stream backend | `SolidSyslogStreamSenderConfig` (resolver, stream, endpoint, endpointVersion), `SolidSyslogStreamSender_Create(config)`, `_Destroy(base)`. Instance struct lives in a library-internal static pool (E11); `_Destroy` takes the handle returned by `_Create`. Pool exhaustion resolves to the shared `SolidSyslogNullSender`. |
Expand All @@ -350,7 +350,7 @@ live under `Core/Interface/`; platform-specific helpers (the `SolidSyslogPosix*`
| `SolidSyslogNullMutex.h` | System setup code (single-task, no synchronisation) | `SolidSyslogNullMutex_Get` |
| `SolidSyslogPosixMutex.h` | System setup code on POSIX targets needing thread-safe buffering | `SolidSyslogPosixMutex_Create(void)`, `_Destroy(base)` (wraps `pthread_mutex_t`). Instance struct lives in a library-internal static pool (E11). Pool-exhaustion fallback is the shared `SolidSyslogNullMutex`. |
| `SolidSyslogWindowsMutex.h` | System setup code on Windows targets needing thread-safe buffering | `SolidSyslogWindowsMutex_Create(void)`, `_Destroy(base)` (wraps `CRITICAL_SECTION`). Instance struct lives in a library-internal static pool (E11). Pool-exhaustion fallback is the shared `SolidSyslogNullMutex`. |
| `SolidSyslogFreeRtosMutex.h` | System setup code on FreeRTOS targets needing thread-safe buffering | `SolidSyslogFreeRtosMutexStorage`, `SOLIDSYSLOG_FREERTOSMUTEX_SIZE`, `SolidSyslogFreeRtosMutex_Create(storage)`, `_Destroy(mutex)` (wraps `xSemaphoreCreateMutexStatic` — caller's `StaticSemaphore_t` lives inside the injected storage; requires `configSUPPORT_STATIC_ALLOCATION=1`) |
| `SolidSyslogFreeRtosMutex.h` | System setup code on FreeRTOS targets needing thread-safe buffering | `SolidSyslogFreeRtosMutex_Create(void)`, `_Destroy(base)` (wraps `xSemaphoreCreateMutexStatic`; requires `configSUPPORT_STATIC_ALLOCATION=1`). Instance struct lives in a library-internal static pool (E11). Pool-exhaustion fallback is the shared `SolidSyslogNullMutex`. |
| `SolidSyslogStore.h` | Library internals consuming a store (Service algorithm) and integrator code querying capacity | `SolidSyslogStore_Write`, `_ReadNextUnsent`, `_MarkSent`, `_HasUnsent`, `_IsHalted`, `_GetTotalBytes`, `_GetUsedBytes` |
| `SolidSyslogStoreDefinition.h` | Store implementors (extension point) | `SolidSyslogStore` vtable struct (`Write`, `ReadNextUnsent`, `MarkSent`, `HasUnsent`, `IsHalted`, `GetTotalBytes`, `GetUsedBytes`) |
| `SolidSyslogNullStore.h` | System setup code (no store-and-forward) | `SolidSyslogNullStore_Get` |
Expand Down
85 changes: 85 additions & 0 deletions Core/Interface/SolidSyslogTunablesDefaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,4 +456,89 @@
#error "SOLIDSYSLOG_WINSOCK_TCP_STREAM_POOL_SIZE must be >= 1"
#endif

/*
* Number of SolidSyslogFreeRtosMutex instances the library's internal
* static pool can simultaneously hold. Each instance carries a
* StaticSemaphore_t — the kernel-primitive layout the adapter wraps
* via xSemaphoreCreateMutexStatic.
*
* Default 1 — almost all FreeRTOS integrators wire a single mutex
* into a CircularBuffer or other thread-safe primitive. Bump via
* SOLIDSYSLOG_USER_TUNABLES_FILE if more than one is genuinely
* needed.
*
* Floor: 1. Sub-floor values rejected at compile time.
*/
#ifndef SOLIDSYSLOG_FREE_RTOS_MUTEX_POOL_SIZE
/* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- macro form required for preprocessor visibility (floor #if) and C array-size const-expr. */
#define SOLIDSYSLOG_FREE_RTOS_MUTEX_POOL_SIZE 1U
#endif

#if SOLIDSYSLOG_FREE_RTOS_MUTEX_POOL_SIZE < 1
#error "SOLIDSYSLOG_FREE_RTOS_MUTEX_POOL_SIZE must be >= 1"
#endif

/*
* Number of SolidSyslogFreeRtosDatagram instances the library's
* internal static pool can simultaneously hold. Each instance carries
* a FreeRTOS-Plus-TCP Socket_t.
*
* Default 1 — almost all FreeRTOS integrators wire a single datagram
* into a UdpSender. Bump via SOLIDSYSLOG_USER_TUNABLES_FILE if more
* than one is genuinely needed.
*
* Floor: 1. Sub-floor values rejected at compile time.
*/
#ifndef SOLIDSYSLOG_FREE_RTOS_DATAGRAM_POOL_SIZE
/* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- macro form required for preprocessor visibility (floor #if) and C array-size const-expr. */
#define SOLIDSYSLOG_FREE_RTOS_DATAGRAM_POOL_SIZE 1U
#endif

#if SOLIDSYSLOG_FREE_RTOS_DATAGRAM_POOL_SIZE < 1
#error "SOLIDSYSLOG_FREE_RTOS_DATAGRAM_POOL_SIZE must be >= 1"
#endif

/*
* Number of SolidSyslogFreeRtosStaticResolver instances the library's
* internal static pool can simultaneously hold. Each instance carries
* the 4-byte IPv4 octets the integrator pins it to.
*
* Default 1 — the static resolver pairs with a single hardcoded
* destination; the typical FreeRTOS integrator wires one. Bump via
* SOLIDSYSLOG_USER_TUNABLES_FILE if more than one is needed.
*
* Floor: 1. Sub-floor values rejected at compile time.
*/
#ifndef SOLIDSYSLOG_FREE_RTOS_STATIC_RESOLVER_POOL_SIZE
/* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- macro form required for preprocessor visibility (floor #if) and C array-size const-expr. */
#define SOLIDSYSLOG_FREE_RTOS_STATIC_RESOLVER_POOL_SIZE 1U
#endif

#if SOLIDSYSLOG_FREE_RTOS_STATIC_RESOLVER_POOL_SIZE < 1
#error "SOLIDSYSLOG_FREE_RTOS_STATIC_RESOLVER_POOL_SIZE must be >= 1"
#endif

/*
* Number of SolidSyslogFreeRtosTcpStream instances the library's
* internal static pool can simultaneously hold. Each instance carries
* a FreeRTOS-Plus-TCP Socket_t for the bounded-blocking-connect
* non-blocking TCP transport.
*
* Default 2 — matches the POSIX and Windows TCP stream pool defaults
* so a future TLS-via-mbedTLS path (S08.07) wrapping an underlying
* FreeRtosTcpStream does not silently fall back to NullStream on the
* second Create. Plain-TCP-only integrators pay 8 bytes of extra
* static state; mbedTLS integrators are spared an override.
*
* Floor: 1. Sub-floor values rejected at compile time.
*/
#ifndef SOLIDSYSLOG_FREE_RTOS_TCP_STREAM_POOL_SIZE
/* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- macro form required for preprocessor visibility (floor #if) and C array-size const-expr. */
#define SOLIDSYSLOG_FREE_RTOS_TCP_STREAM_POOL_SIZE 2U
#endif

#if SOLIDSYSLOG_FREE_RTOS_TCP_STREAM_POOL_SIZE < 1
#error "SOLIDSYSLOG_FREE_RTOS_TCP_STREAM_POOL_SIZE must be >= 1"
#endif

#endif /* SOLIDSYSLOG_TUNABLES_DEFAULTS_H */
16 changes: 16 additions & 0 deletions Core/Source/SolidSyslogErrorMessages.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,21 @@
"SolidSyslogWinsockTcpStream_Create pool exhausted; returning fallback stream"
#define SOLIDSYSLOG_ERROR_MSG_WINSOCKTCPSTREAM_UNKNOWN_DESTROY \
"SolidSyslogWinsockTcpStream_Destroy called with a handle not issued by this pool"
#define SOLIDSYSLOG_ERROR_MSG_FREERTOSMUTEX_POOL_EXHAUSTED \
"SolidSyslogFreeRtosMutex_Create pool exhausted; returning fallback mutex"
#define SOLIDSYSLOG_ERROR_MSG_FREERTOSMUTEX_UNKNOWN_DESTROY \
"SolidSyslogFreeRtosMutex_Destroy called with a handle not issued by this pool"
#define SOLIDSYSLOG_ERROR_MSG_FREERTOSDATAGRAM_POOL_EXHAUSTED \
"SolidSyslogFreeRtosDatagram_Create pool exhausted; returning fallback datagram"
#define SOLIDSYSLOG_ERROR_MSG_FREERTOSDATAGRAM_UNKNOWN_DESTROY \
"SolidSyslogFreeRtosDatagram_Destroy called with a handle not issued by this pool"
#define SOLIDSYSLOG_ERROR_MSG_FREERTOSSTATICRESOLVER_POOL_EXHAUSTED \
"SolidSyslogFreeRtosStaticResolver_Create pool exhausted; returning fallback resolver"
#define SOLIDSYSLOG_ERROR_MSG_FREERTOSSTATICRESOLVER_UNKNOWN_DESTROY \
"SolidSyslogFreeRtosStaticResolver_Destroy called with a handle not issued by this pool"
#define SOLIDSYSLOG_ERROR_MSG_FREERTOSTCPSTREAM_POOL_EXHAUSTED \
"SolidSyslogFreeRtosTcpStream_Create pool exhausted; returning fallback stream"
#define SOLIDSYSLOG_ERROR_MSG_FREERTOSTCPSTREAM_UNKNOWN_DESTROY \
"SolidSyslogFreeRtosTcpStream_Destroy called with a handle not issued by this pool"

#endif /* SOLIDSYSLOGERRORMESSAGES_H */
Loading
Loading