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
28 changes: 16 additions & 12 deletions Bdd/Targets/Common/BddTargetStderrErrorHandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,42 @@
#include "SolidSyslogError.h"
#include "SolidSyslogPrival.h"

static void StderrErrorHandlerEx(
void* context,
enum SolidSyslogSeverity severity,
const struct SolidSyslogErrorSource* source,
uint8_t code
)
static void StderrErrorHandlerEx(void* context, const struct SolidSyslogErrorEvent* event)
{
(void) context;
const char* sourceName = "<unknown>";
const char* message = "<no translation>";
const struct SolidSyslogErrorSource* source = event->Source;
if (source != NULL)
{
sourceName = source->Name;
if (source->AsString != NULL)
{
message = source->AsString(code);
message = source->AsString((uint8_t) event->Detail);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
if (severity <= SOLIDSYSLOG_SEVERITY_ERROR)
if (event->Severity <= SOLIDSYSLOG_SEVERITY_ERROR)
{
(void) fprintf(stderr, "BDD-TARGET: FATAL: [%s/%u] %s\n", sourceName, (unsigned) code, message);
(void) fprintf(
stderr,
"BDD-TARGET: FATAL: [%s cat=%u detail=%ld] %s\n",
sourceName,
(unsigned) event->Category,
(long) event->Detail,
message
);
(void) fflush(stderr);
_Exit(3);
}
else
{
(void) fprintf(
stderr,
"[solidsyslog] severity=%d [%s/%u] %s\n",
(int) severity,
"[solidsyslog] severity=%d [%s cat=%u detail=%ld] %s\n",
(int) event->Severity,
sourceName,
(unsigned) code,
(unsigned) event->Category,
(long) event->Detail,
message
);
}
Expand Down
19 changes: 11 additions & 8 deletions Bdd/Targets/FreeRtos/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,25 +485,28 @@ static void GetAppName(struct SolidSyslogFormatter* formatter)
* tzKnown=0, isSynced=0. SolidSyslogConfig.Clock=NULL drops through to the
* library's NilClock; the resulting all-zero SolidSyslogTimestamp fails
* TimestampIsValid in Core/Source/SolidSyslog.c and emits "-" on the wire. */
static void ErrorHandlerEx(
void* context,
enum SolidSyslogSeverity severity,
const struct SolidSyslogErrorSource* source,
uint8_t code
)
static void ErrorHandlerEx(void* context, const struct SolidSyslogErrorEvent* event)
{
(void) context;
const char* sourceName = "<unknown>";
const char* message = "<no translation>";
const struct SolidSyslogErrorSource* source = event->Source;
if (source != NULL)
{
sourceName = source->Name;
if (source->AsString != NULL)
{
message = source->AsString(code);
message = source->AsString((uint8_t) event->Detail);
}
}
(void) printf("[solidsyslog] severity=%d [%s/%u] %s\n", (int) severity, sourceName, (unsigned) code, message);
(void) printf(
"[solidsyslog] severity=%d [%s cat=%u detail=%ld] %s\n",
(int) event->Severity,
sourceName,
(unsigned) event->Category,
(long) event->Detail,
message
);
}

static void GetTimeQuality(struct SolidSyslogTimeQuality* timeQuality)
Expand Down
19 changes: 11 additions & 8 deletions Bdd/Targets/FreeRtosLwip/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,25 +372,28 @@ static uint32_t GetEndpointVersion(void)
return endpointVersion;
}

static void ErrorHandlerEx(
void* context,
enum SolidSyslogSeverity severity,
const struct SolidSyslogErrorSource* source,
uint8_t code
)
static void ErrorHandlerEx(void* context, const struct SolidSyslogErrorEvent* event)
{
(void) context;
const char* sourceName = "<unknown>";
const char* message = "<no translation>";
const struct SolidSyslogErrorSource* source = event->Source;
if (source != NULL)
{
sourceName = source->Name;
if (source->AsString != NULL)
{
message = source->AsString(code);
message = source->AsString((uint8_t) event->Detail);
}
}
(void) printf("[solidsyslog] severity=%d [%s/%u] %s\n", (int) severity, sourceName, (unsigned) code, message);
(void) printf(
"[solidsyslog] severity=%d [%s cat=%u detail=%ld] %s\n",
(int) event->Severity,
sourceName,
(unsigned) event->Category,
(long) event->Detail,
message
);
}

static bool OnSet(const char* name, const char* value)
Expand Down
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,8 @@ live under `Core/Interface/`; platform-specific helpers (the `SolidSyslogPosix*`
| `SolidSyslog.h` | Application code that logs events | `SolidSyslogMessage`, `SolidSyslog_Log(handle, message)`, `SolidSyslog_Service(handle)`. `struct SolidSyslog` opaque. |
| `SolidSyslogConfig.h` | System setup code | `SolidSyslogConfig`, `SolidSyslog_Create(config) → handle`, `SolidSyslog_Destroy(handle)`. Instance struct lives in a library-internal static pool (E11; tunable `SOLIDSYSLOG_POOL_SIZE`, default `1U`). Pool-exhaustion fallback is a TU-private `NullInstance` wired to `SolidSyslogNull{Buffer,Sender,Store}_Get()` siblings — `_Log`/`_Service` against it dispatch through Null vtables and silently drop. |
| `SolidSyslogErrors.h` | Any code installing an error handler that wants to react to SolidSyslog-singleton events (pointer-identity match on `SolidSyslogErrorSource`, switch on `enum SolidSyslogErrors`) | `enum SolidSyslogErrors` (`SOLIDSYSLOG_ERROR_*` codes + `SOLIDSYSLOG_ERROR_MAX` bookend), `extern const struct SolidSyslogErrorSource SolidSyslogErrorSource`. Integrators ignore if not handling errors per source. |
| `SolidSyslogError.h` | Any code installing a handler to react to library-internal errors (NULL guards, send failures); also the library-internal call site for emitting them | `SolidSyslogErrorHandler` typedef, `SolidSyslog_SetErrorHandler(handler, context)`, `SolidSyslog_Error(severity, message)`. Default handler is a silent no-op; setting `handler = NULL` restores the default. Single global slot — intended for setup-time configuration, not synchronised with concurrent `Error` calls. |
| `SolidSyslogError.h` | Any code installing a handler to react to library-internal errors (NULL guards, send failures); also the library-internal call site for emitting them | `struct SolidSyslogErrorEvent` (`Severity`, `Source`, `uint16_t Category`, `int32_t Detail`), `SolidSyslogErrorHandler` typedef (`void(void* context, const struct SolidSyslogErrorEvent* event)`), `SolidSyslog_SetErrorHandler(handler, context)`, `SolidSyslog_Error(severity, source, category, detail)`. The handler reads three orthogonal axes off the event: `Source` (extensible identity, pointer-identity match), `Category` (portable reaction axis — see `SolidSyslogErrorCategory.h`), `Detail` (per-class `enum SolidSyslog<Class>Errors` value today, native `errno`/`X509_V_ERR_*` later). Default handler is a silent no-op; setting `handler = NULL` restores the default. Single global slot — intended for setup-time configuration, not synchronised with concurrent `Error` calls. |
| `SolidSyslogErrorCategory.h` | Any handler switching on the portable category axis; any emit site picking a category | Universal lifecycle category macros (`SOLIDSYSLOG_CAT_BAD_CONFIG` / `_BAD_ARGUMENT` / `_POOL_EXHAUSTED` / `_UNKNOWN_DESTROY`, all `uint16_t`) + per-role base ranges (`SOLIDSYSLOG_CAT_<ROLE>_BASE`, errno-domain style; a role occupies `[BASE, BASE + 0xFF]`, `0xC000+` reserved for integrator-defined roles). Category constants are `uint16_t` macros carrying their own cast so emit sites stay clean; the wire type is `uint16_t` (not an enum) so integrator classes can supply their own categories without being boxed into a library enum. Role-specific categories live in `SolidSyslog<Role>Categories.h` beside each `*Definition.h` (`SolidSyslogResolverCategories.h` → `_RESOLVER_RESOLVE_FAILED`; `SolidSyslogTlsStreamCategories.h` → `_TLSSTREAM_INIT_FAILED` / `_HANDSHAKE_FAILED`; `SolidSyslogSecurityPolicyCategories.h` → `_SECURITYPOLICY_KEY_UNAVAILABLE` / `_SEAL_FAILED` / `_OPEN_FAILED`; `SolidSyslogBufferCategories.h` → `_BUFFER_BACKEND_FAILED`). A category is defined only once a live emit site raises it. |
| `SolidSyslogConfigLock.h` | Setup code on systems where library-internal config-time critical sections (E11 pool `_Create`/`_Destroy` slot walks) may race across tasks or cores. Single-task setup needs nothing — defaults are no-ops. | `SolidSyslogConfigLockFunction` typedef (zero-arg `void(void)`), `SolidSyslog_SetConfigLock(lockFn, unlockFn)`, `SolidSyslog_LockConfig()`, `SolidSyslog_UnlockConfig()`. Pair API: both handlers installed together. `NULL` on either side restores that side's no-op default. Single global slot — intended for setup-time configuration, not synchronised with concurrent installs. Integrators wire `taskENTER_CRITICAL`/`taskEXIT_CRITICAL` (FreeRTOS), `pthread_mutex_lock`/`unlock` on a static `pthread_mutex_t` (POSIX), `EnterCriticalSection`/`LeaveCriticalSection` on a static `CRITICAL_SECTION` (Windows), or a spinlock pair. This is the only synchronisation primitive available to the Mutex and AtomicCounter pools for their own pool walks — chicken-and-egg eliminates their own injectables. |
| `SolidSyslogStringFunction.h` | Any code needing the string-callback typedef | `SolidSyslogStringFunction` (callback writes into a `SolidSyslogFormatter*`) — used by `SolidSyslogConfig` (hostname/appName/processId), `SolidSyslogMetaSdConfig` (language), `SolidSyslogOriginSdConfig` |
| `SolidSyslogFormatter.h` | Any code that formats into a bounded buffer | `SolidSyslogFormatter`, `SolidSyslogFormatterStorage`, `SOLIDSYSLOG_FORMATTER_STORAGE_SIZE`, `_Create`, `_FromStorage`, `_AsciiCharacter`, `_Bom`, `_BoundedString`, `_EscapedString`, `_PrintUsAsciiString`, `_Uint32`, `_TwoDigit`, `_FourDigit`, `_SixDigit`, `_AsFormattedBuffer`, `_Length` |
Expand Down
16 changes: 16 additions & 0 deletions Core/Interface/SolidSyslogBufferCategories.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef SOLIDSYSLOGBUFFERCATEGORIES_H
#define SOLIDSYSLOGBUFFERCATEGORIES_H

#include <stdint.h>

#include "SolidSyslogErrorCategory.h"

/*
* Portable Buffer-role error categories. Any Buffer implementation reuses
* these; a portable handler switch on event->Category reacts to a buffer
* backend failure identically regardless of the underlying mechanism
* (POSIX message queue, ring, ...).
*/
#define SOLIDSYSLOG_CAT_BUFFER_BACKEND_FAILED ((uint16_t) (SOLIDSYSLOG_CAT_BUFFER_BASE + 1U))

#endif /* SOLIDSYSLOGBUFFERCATEGORIES_H */
18 changes: 11 additions & 7 deletions Core/Interface/SolidSyslogError.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@ EXTERN_C_BEGIN
const char* (*AsString)(uint8_t code);
};

typedef void (*SolidSyslogErrorHandler)(
void* context,
enum SolidSyslogSeverity severity,
const struct SolidSyslogErrorSource* source,
uint8_t code
);
struct SolidSyslogErrorEvent
{
enum SolidSyslogSeverity Severity;
const struct SolidSyslogErrorSource* Source;
uint16_t Category;
int32_t Detail;
};

typedef void (*SolidSyslogErrorHandler)(void* context, const struct SolidSyslogErrorEvent* event);

void SolidSyslog_SetErrorHandler(SolidSyslogErrorHandler handler, void* context);
void SolidSyslog_Error(
enum SolidSyslogSeverity severity,
const struct SolidSyslogErrorSource* source,
uint8_t code
uint16_t category,
int32_t detail
);

EXTERN_C_END
Expand Down
38 changes: 38 additions & 0 deletions Core/Interface/SolidSyslogErrorCategory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef SOLIDSYSLOGERRORCATEGORY_H
#define SOLIDSYSLOGERRORCATEGORY_H

#include <stdint.h>

/*
* Portable error-category axis. Categories are library-owned constants
* organised errno-domain style: a low universal-lifecycle range, then one
* base per role family (declared beside that role's *Definition.h, off the
* bases below as BASE + n), then a reserved integrator range. 0xC000 and
* above is reserved for integrator-defined roles so custom backends never
* collide.
*
* The category constants carry their own (uint16_t) cast so emit sites stay
* clean — SolidSyslog_Error's category parameter is uint16_t (not an enum
* type), which is what lets integrator classes supply their own categories
* in the reserved range without being boxed into a library enum.
*/

/* Universal lifecycle categories, available to every source. */
#define SOLIDSYSLOG_CAT_BAD_CONFIG ((uint16_t) 0x0001U)
#define SOLIDSYSLOG_CAT_BAD_ARGUMENT ((uint16_t) 0x0002U)
#define SOLIDSYSLOG_CAT_POOL_EXHAUSTED ((uint16_t) 0x0003U)
#define SOLIDSYSLOG_CAT_UNKNOWN_DESTROY ((uint16_t) 0x0004U)

/*
* Per-role base ranges. A role occupies [BASE, BASE + 0xFF]. A base is listed
* here only once a role family carries a role-specific category; roles that
* emit only the universal categories above need none. (0x0100 Sender and
* 0x0300 Stream are intentionally unallocated — those roles emit only
* universal categories today.)
*/
#define SOLIDSYSLOG_CAT_RESOLVER_BASE ((uint16_t) 0x0200U)
#define SOLIDSYSLOG_CAT_TLSSTREAM_BASE ((uint16_t) 0x0400U)
#define SOLIDSYSLOG_CAT_SECURITYPOLICY_BASE ((uint16_t) 0x0500U)
#define SOLIDSYSLOG_CAT_BUFFER_BASE ((uint16_t) 0x0600U)

#endif /* SOLIDSYSLOGERRORCATEGORY_H */
15 changes: 15 additions & 0 deletions Core/Interface/SolidSyslogResolverCategories.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef SOLIDSYSLOGRESOLVERCATEGORIES_H
#define SOLIDSYSLOGRESOLVERCATEGORIES_H

#include <stdint.h>

#include "SolidSyslogErrorCategory.h"

/*
* Portable Resolver-role error categories. Any Resolver implementation
* reuses these; a portable handler switch on event->Category works
* identically across every resolver backend.
*/
#define SOLIDSYSLOG_CAT_RESOLVER_RESOLVE_FAILED ((uint16_t) (SOLIDSYSLOG_CAT_RESOLVER_BASE + 1U))

#endif /* SOLIDSYSLOGRESOLVERCATEGORIES_H */
19 changes: 19 additions & 0 deletions Core/Interface/SolidSyslogSecurityPolicyCategories.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef SOLIDSYSLOGSECURITYPOLICYCATEGORIES_H
#define SOLIDSYSLOGSECURITYPOLICYCATEGORIES_H

#include <stdint.h>

#include "SolidSyslogErrorCategory.h"

/*
* Portable SecurityPolicy-role error categories, shared by every integrity /
* confidentiality policy (HMAC, AES-GCM, OpenSSL, Mbed TLS, ...). Seal (write
* side) and open (read side) are kept distinct because "a stored record can no
* longer be read back" is a materially different operational signal from
* "a record could not be written".
*/
#define SOLIDSYSLOG_CAT_SECURITYPOLICY_KEY_UNAVAILABLE ((uint16_t) (SOLIDSYSLOG_CAT_SECURITYPOLICY_BASE + 1U))
#define SOLIDSYSLOG_CAT_SECURITYPOLICY_SEAL_FAILED ((uint16_t) (SOLIDSYSLOG_CAT_SECURITYPOLICY_BASE + 2U))
#define SOLIDSYSLOG_CAT_SECURITYPOLICY_OPEN_FAILED ((uint16_t) (SOLIDSYSLOG_CAT_SECURITYPOLICY_BASE + 3U))

#endif /* SOLIDSYSLOGSECURITYPOLICYCATEGORIES_H */
17 changes: 17 additions & 0 deletions Core/Interface/SolidSyslogTlsStreamCategories.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef SOLIDSYSLOGTLSSTREAMCATEGORIES_H
#define SOLIDSYSLOGTLSSTREAMCATEGORIES_H

#include <stdint.h>

#include "SolidSyslogErrorCategory.h"

/*
* Portable TLS-stream error categories, shared by every TLS backend (OpenSSL,
* Mbed TLS, or an integrator's own). A portable handler switch on
* event->Category reacts to a TLS init or handshake failure identically
* regardless of which TLS library produced it.
*/
#define SOLIDSYSLOG_CAT_TLSSTREAM_INIT_FAILED ((uint16_t) (SOLIDSYSLOG_CAT_TLSSTREAM_BASE + 1U))
#define SOLIDSYSLOG_CAT_TLSSTREAM_HANDSHAKE_FAILED ((uint16_t) (SOLIDSYSLOG_CAT_TLSSTREAM_BASE + 2U))

#endif /* SOLIDSYSLOGTLSSTREAMCATEGORIES_H */
22 changes: 15 additions & 7 deletions Core/Source/SolidSyslog.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "SolidSyslogBuffer.h"
#include "SolidSyslogConfig.h"
#include "SolidSyslogError.h"
#include "SolidSyslogErrorCategory.h"
#include "SolidSyslogErrors.h"
#include "SolidSyslogFormatter.h"
#include "SolidSyslogMessageFormatter.h"
Expand Down Expand Up @@ -85,7 +86,8 @@ static void SolidSyslog_InstallBuffer(struct SolidSyslog* self, struct SolidSysl
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_ERROR,
&SolidSyslogErrorSource,
(uint8_t) SOLIDSYSLOG_ERROR_CREATE_NULL_BUFFER
SOLIDSYSLOG_CAT_BAD_CONFIG,
(int32_t) SOLIDSYSLOG_ERROR_CREATE_NULL_BUFFER
);
}
else
Expand All @@ -101,7 +103,8 @@ static void SolidSyslog_InstallSender(struct SolidSyslog* self, struct SolidSysl
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_ERROR,
&SolidSyslogErrorSource,
(uint8_t) SOLIDSYSLOG_ERROR_CREATE_NULL_SENDER
SOLIDSYSLOG_CAT_BAD_CONFIG,
(int32_t) SOLIDSYSLOG_ERROR_CREATE_NULL_SENDER
);
}
else
Expand All @@ -117,7 +120,8 @@ static void SolidSyslog_InstallStore(struct SolidSyslog* self, struct SolidSyslo
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_ERROR,
&SolidSyslogErrorSource,
(uint8_t) SOLIDSYSLOG_ERROR_CREATE_NULL_STORE
SOLIDSYSLOG_CAT_BAD_CONFIG,
(int32_t) SOLIDSYSLOG_ERROR_CREATE_NULL_STORE
);
}
else
Expand Down Expand Up @@ -172,7 +176,8 @@ static void SolidSyslog_InstallStructuredData(
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_ERROR,
&SolidSyslogErrorSource,
(uint8_t) SOLIDSYSLOG_ERROR_CREATE_INCONSISTENT_SD
SOLIDSYSLOG_CAT_BAD_CONFIG,
(int32_t) SOLIDSYSLOG_ERROR_CREATE_INCONSISTENT_SD
);
}
else
Expand All @@ -189,7 +194,8 @@ void SolidSyslog_Service(struct SolidSyslog* handle)
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_ERROR,
&SolidSyslogErrorSource,
(uint8_t) SOLIDSYSLOG_ERROR_SERVICE_NULL_HANDLE
SOLIDSYSLOG_CAT_BAD_ARGUMENT,
(int32_t) SOLIDSYSLOG_ERROR_SERVICE_NULL_HANDLE
);
}
else if (SolidSyslog_IsServiceEnabled(handle))
Expand Down Expand Up @@ -255,15 +261,17 @@ void SolidSyslog_Log(struct SolidSyslog* handle, const struct SolidSyslogMessage
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_ERROR,
&SolidSyslogErrorSource,
(uint8_t) SOLIDSYSLOG_ERROR_LOG_NULL_HANDLE
SOLIDSYSLOG_CAT_BAD_ARGUMENT,
(int32_t) SOLIDSYSLOG_ERROR_LOG_NULL_HANDLE
);
}
else if (message == NULL)
{
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_ERROR,
&SolidSyslogErrorSource,
(uint8_t) SOLIDSYSLOG_ERROR_LOG_NULL_MESSAGE
SOLIDSYSLOG_CAT_BAD_ARGUMENT,
(int32_t) SOLIDSYSLOG_ERROR_LOG_NULL_MESSAGE
);
}
else
Expand Down
7 changes: 5 additions & 2 deletions Core/Source/SolidSyslogBlockStoreStatic.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "SolidSyslogBlockStoreErrors.h"
#include "SolidSyslogBlockStorePrivate.h"
#include "SolidSyslogError.h"
#include "SolidSyslogErrorCategory.h"
#include "SolidSyslogNullSecurityPolicy.h"
#include "SolidSyslogNullStore.h"
#include "SolidSyslogPoolAllocator.h"
Expand Down Expand Up @@ -67,7 +68,8 @@ struct SolidSyslogStore* SolidSyslogBlockStore_Create(const struct SolidSyslogBl
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_ERROR,
&BlockStoreErrorSource,
(uint8_t) BLOCKSTORE_ERROR_POOL_EXHAUSTED
SOLIDSYSLOG_CAT_POOL_EXHAUSTED,
(int32_t) BLOCKSTORE_ERROR_POOL_EXHAUSTED
);
}

Expand Down Expand Up @@ -138,7 +140,8 @@ void SolidSyslogBlockStore_Destroy(struct SolidSyslogStore* base)
SolidSyslog_Error(
SOLIDSYSLOG_SEVERITY_WARNING,
&BlockStoreErrorSource,
(uint8_t) BLOCKSTORE_ERROR_UNKNOWN_DESTROY
SOLIDSYSLOG_CAT_UNKNOWN_DESTROY,
(int32_t) BLOCKSTORE_ERROR_UNKNOWN_DESTROY
);
}
}
Expand Down
Loading
Loading