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
7 changes: 4 additions & 3 deletions Bdd/Targets/Common/BddTargetIps.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "BddTargetIps.h"
#include "SolidSyslogFormatter.h"
#include "SolidSyslogSdValue.h"

enum
{
Expand All @@ -23,7 +23,8 @@ size_t BddTargetIps_Count(void)
return sizeof(BDD_TARGET_IPS) / sizeof(BDD_TARGET_IPS[0]);
}

void BddTargetIps_At(struct SolidSyslogFormatter* formatter, size_t index)
void BddTargetIps_At(struct SolidSyslogSdValue* value, void* context, size_t index)
{
SolidSyslogFormatter_EscapedString(formatter, BDD_TARGET_IPS[index], BDD_TARGET_IP_MAX);
(void) context;
SolidSyslogSdValue_BoundedString(value, BDD_TARGET_IPS[index], BDD_TARGET_IP_MAX);
}
4 changes: 2 additions & 2 deletions Bdd/Targets/Common/BddTargetIps.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

EXTERN_C_BEGIN

struct SolidSyslogFormatter;
struct SolidSyslogSdValue;

size_t BddTargetIps_Count(void);
void BddTargetIps_At(struct SolidSyslogFormatter * formatter, size_t index);
void BddTargetIps_At(struct SolidSyslogSdValue * value, void* context, size_t index);

EXTERN_C_END

Expand Down
5 changes: 3 additions & 2 deletions Core/Interface/SolidSyslogOriginSd.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

EXTERN_C_BEGIN

struct SolidSyslogFormatter;
struct SolidSyslogSdValue;
struct SolidSyslogStructuredData;

typedef size_t (*SolidSyslogOriginIpCountFunction)(void);
typedef void (*SolidSyslogOriginIpAtFunction)(struct SolidSyslogFormatter* formatter, size_t index);
typedef void (*SolidSyslogOriginIpAtFunction)(struct SolidSyslogSdValue* value, void* context, size_t index);

struct SolidSyslogOriginSdConfig
{
Expand All @@ -20,6 +20,7 @@ EXTERN_C_BEGIN
const char* EnterpriseId;
SolidSyslogOriginIpCountFunction GetIpCount;
SolidSyslogOriginIpAtFunction GetIpAt;
void* IpContext;
};

struct SolidSyslogStructuredData* SolidSyslogOriginSd_Create(const struct SolidSyslogOriginSdConfig* config);
Expand Down
134 changes: 46 additions & 88 deletions Core/Source/SolidSyslogOriginSd.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,150 +3,108 @@
#include <stddef.h>

#include "SolidSyslogError.h"
#include "SolidSyslogFormatter.h"
#include "SolidSyslogNullSd.h"
#include "SolidSyslogOriginSdErrors.h"
#include "SolidSyslogOriginSdPrivate.h"
#include "SolidSyslogSdElementPrivate.h"
#include "SolidSyslogSdValue.h"
#include "SolidSyslogStructuredDataDefinition.h"

const struct SolidSyslogErrorSource OriginSdErrorSource = {"OriginSd"};

struct SolidSyslogFormatter;

static void OriginSd_Format(struct SolidSyslogStructuredData* base, struct SolidSyslogFormatter* formatter);

static inline struct SolidSyslogOriginSd* OriginSd_SelfFromBase(struct SolidSyslogStructuredData* base);
static inline void OriginSd_PreFormatStaticPrefix(
struct SolidSyslogOriginSd* self,
const struct SolidSyslogOriginSdConfig* config
);
static inline void OriginSd_EmitSoftware(
struct SolidSyslogFormatter* f,
const struct SolidSyslogOriginSdConfig* config
);
static inline void OriginSd_EmitSwVersion(
struct SolidSyslogFormatter* f,
const struct SolidSyslogOriginSdConfig* config
);
static inline void OriginSd_EmitEnterpriseId(
struct SolidSyslogFormatter* f,
const struct SolidSyslogOriginSdConfig* config
);
static inline void OriginSd_EmitIps(struct SolidSyslogFormatter* formatter, const struct SolidSyslogOriginSd* self);
static inline void OriginSd_EmitIp(
struct SolidSyslogFormatter* formatter,
const struct SolidSyslogOriginSd* self,
size_t index
);
static inline void OriginSd_EmitSoftware(struct SolidSyslogSdElement* element, const char* software);
static inline void OriginSd_EmitSwVersion(struct SolidSyslogSdElement* element, const char* swVersion);
static inline void OriginSd_EmitEnterpriseId(struct SolidSyslogSdElement* element, const char* enterpriseId);
static inline void OriginSd_EmitIps(struct SolidSyslogSdElement* element, const struct SolidSyslogOriginSd* self);

void OriginSd_Initialise(struct SolidSyslogStructuredData* base, const struct SolidSyslogOriginSdConfig* config)
{
struct SolidSyslogOriginSd* self = OriginSd_SelfFromBase(base);
self->Base.Format = OriginSd_Format;
self->Software = config->Software;
self->SwVersion = config->SwVersion;
self->EnterpriseId = config->EnterpriseId;
self->GetIpCount = config->GetIpCount;
self->GetIpAt = config->GetIpAt;
OriginSd_PreFormatStaticPrefix(self, config);
self->IpContext = config->IpContext;
}

void OriginSd_Cleanup(struct SolidSyslogStructuredData* base)
{
/* Overwrite the abstract base with the shared NullSd vtable so use-after-destroy
* is a safe no-op. Derived fields (incl. the pre-formatted static-prefix Formatter
* storage) are private to this TU; the next _Initialise rebuilds them. */
* is a safe no-op. Derived fields are private to this TU; the next _Initialise
* overwrites them. */
*base = *SolidSyslogNullSd_Get();
}

static void OriginSd_Format(struct SolidSyslogStructuredData* base, struct SolidSyslogFormatter* formatter)
{
struct SolidSyslogOriginSd* self = OriginSd_SelfFromBase(base);
struct SolidSyslogFormatter* preformat = SolidSyslogFormatter_FromStorage(self->FormattedStorage);

SolidSyslogFormatter_BoundedString(
formatter,
SolidSyslogFormatter_AsFormattedBuffer(preformat),
SolidSyslogFormatter_Length(preformat)
);
OriginSd_EmitIps(formatter, self);
SolidSyslogFormatter_AsciiCharacter(formatter, ']');
struct SolidSyslogSdElement element;

SolidSyslogSdElement_FromFormatter(&element, formatter);
SolidSyslogSdElement_Begin(&element, "origin", 0U);
OriginSd_EmitSoftware(&element, self->Software);
OriginSd_EmitSwVersion(&element, self->SwVersion);
OriginSd_EmitEnterpriseId(&element, self->EnterpriseId);
OriginSd_EmitIps(&element, self);
SolidSyslogSdElement_End(&element);
}

static inline struct SolidSyslogOriginSd* OriginSd_SelfFromBase(struct SolidSyslogStructuredData* base)
{
return (struct SolidSyslogOriginSd*) base;
}

static inline void OriginSd_PreFormatStaticPrefix(
struct SolidSyslogOriginSd* self,
const struct SolidSyslogOriginSdConfig* config
)
static inline void OriginSd_EmitSoftware(struct SolidSyslogSdElement* element, const char* software)
{
static const char sdPrefix[] = "[origin";
struct SolidSyslogFormatter* f = SolidSyslogFormatter_Create(self->FormattedStorage, ORIGIN_FORMATTED_MAX);

SolidSyslogFormatter_BoundedString(f, sdPrefix, sizeof(sdPrefix) - 1U);
OriginSd_EmitSoftware(f, config);
OriginSd_EmitSwVersion(f, config);
OriginSd_EmitEnterpriseId(f, config);
/* closing ']' deferred to OriginSd_Format() so per-message ip params can be spliced in */
}

static inline void OriginSd_EmitSoftware(struct SolidSyslogFormatter* f, const struct SolidSyslogOriginSdConfig* config)
{
if (config->Software != NULL)
if (software != NULL)
{
static const char softwareSd[] = " software=\"";
SolidSyslogFormatter_BoundedString(f, softwareSd, sizeof(softwareSd) - 1U);
SolidSyslogFormatter_EscapedString(f, config->Software, ORIGIN_SOFTWARE_MAX);
SolidSyslogFormatter_AsciiCharacter(f, '"');
SolidSyslogSdValue_BoundedString(
SolidSyslogSdElement_Param(element, "software"),
software,
ORIGIN_SOFTWARE_MAX
);
}
}

static inline void OriginSd_EmitSwVersion(
struct SolidSyslogFormatter* f,
const struct SolidSyslogOriginSdConfig* config
)
static inline void OriginSd_EmitSwVersion(struct SolidSyslogSdElement* element, const char* swVersion)
{
if (config->SwVersion != NULL)
if (swVersion != NULL)
{
static const char swVersionSd[] = " swVersion=\"";
SolidSyslogFormatter_BoundedString(f, swVersionSd, sizeof(swVersionSd) - 1U);
SolidSyslogFormatter_EscapedString(f, config->SwVersion, ORIGIN_SWVERSION_MAX);
SolidSyslogFormatter_AsciiCharacter(f, '"');
SolidSyslogSdValue_BoundedString(
SolidSyslogSdElement_Param(element, "swVersion"),
swVersion,
ORIGIN_SWVERSION_MAX
);
}
}

static inline void OriginSd_EmitEnterpriseId(
struct SolidSyslogFormatter* f,
const struct SolidSyslogOriginSdConfig* config
)
static inline void OriginSd_EmitEnterpriseId(struct SolidSyslogSdElement* element, const char* enterpriseId)
{
if (config->EnterpriseId != NULL)
if (enterpriseId != NULL)
{
static const char enterpriseIdSd[] = " enterpriseId=\"";
SolidSyslogFormatter_BoundedString(f, enterpriseIdSd, sizeof(enterpriseIdSd) - 1U);
SolidSyslogFormatter_EscapedString(f, config->EnterpriseId, ORIGIN_ENTERPRISE_ID_MAX);
SolidSyslogFormatter_AsciiCharacter(f, '"');
SolidSyslogSdValue_BoundedString(
SolidSyslogSdElement_Param(element, "enterpriseId"),
enterpriseId,
ORIGIN_ENTERPRISE_ID_MAX
);
}
}

static inline void OriginSd_EmitIps(struct SolidSyslogFormatter* formatter, const struct SolidSyslogOriginSd* self)
static inline void OriginSd_EmitIps(struct SolidSyslogSdElement* element, const struct SolidSyslogOriginSd* self)
{
if ((self->GetIpCount != NULL) && (self->GetIpAt != NULL))
{
size_t count = self->GetIpCount();
for (size_t i = 0; i < count; i++)
{
OriginSd_EmitIp(formatter, self, i);
self->GetIpAt(SolidSyslogSdElement_Param(element, "ip"), self->IpContext, i);
}
}
}

static inline void OriginSd_EmitIp(
struct SolidSyslogFormatter* formatter,
const struct SolidSyslogOriginSd* self,
size_t index
)
{
static const char ipSd[] = " ip=\"";
SolidSyslogFormatter_BoundedString(formatter, ipSd, sizeof(ipSd) - 1U);
self->GetIpAt(formatter, index);
SolidSyslogFormatter_AsciiCharacter(formatter, '"');
}
14 changes: 5 additions & 9 deletions Core/Source/SolidSyslogOriginSdPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <stdint.h>

#include "SolidSyslogError.h"
#include "SolidSyslogFormatter.h"
#include "SolidSyslogOriginSd.h"
#include "SolidSyslogOriginSdErrors.h"
#include "SolidSyslogPrival.h"
Expand All @@ -15,21 +14,18 @@ enum
ORIGIN_SOFTWARE_MAX = 48,
ORIGIN_SWVERSION_MAX = 32,
ORIGIN_ENTERPRISE_ID_MAX = 64,
ORIGIN_IP_MAX = 64,
ORIGIN_LITERAL_BYTES =
48, /* [origin software="" swVersion="" enterpriseId="" — closing ']' deferred to per-message OriginSd_Format */
ORIGIN_CONTENT_MAX = ORIGIN_LITERAL_BYTES + SOLIDSYSLOG_ESCAPED_MAX_SIZE(ORIGIN_SOFTWARE_MAX) +
SOLIDSYSLOG_ESCAPED_MAX_SIZE(ORIGIN_SWVERSION_MAX) +
SOLIDSYSLOG_ESCAPED_MAX_SIZE(ORIGIN_ENTERPRISE_ID_MAX),
ORIGIN_FORMATTED_MAX = ORIGIN_CONTENT_MAX + 1 /* null terminator */
ORIGIN_IP_MAX = 64
};

struct SolidSyslogOriginSd
{
struct SolidSyslogStructuredData Base;
const char* Software;
const char* SwVersion;
const char* EnterpriseId;
SolidSyslogOriginIpCountFunction GetIpCount;
SolidSyslogOriginIpAtFunction GetIpAt;
SolidSyslogFormatterStorage FormattedStorage[SOLIDSYSLOG_FORMATTER_STORAGE_SIZE(ORIGIN_FORMATTED_MAX)];
void* IpContext;
};

void OriginSd_Initialise(struct SolidSyslogStructuredData* base, const struct SolidSyslogOriginSdConfig* config);
Expand Down
34 changes: 34 additions & 0 deletions DEVLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14486,3 +14486,37 @@ MISRA rule — different category, doesn't set precedent.

### Open questions
- None outstanding.

## 2026-06-06 — S14.05: OriginSd onto the SD writer + #346 scratch removal

### Decisions
- **OriginSd migrated onto the E14 SD writer**, byte-identical (existing OriginSd tests
are the net), same shape as S14.03/S14.04: `SdElement_FromFormatter` +
`_Begin("origin",0U)` / `_Param` → `SolidSyslogSdValue_*` / `_End`. Static fields use
`SolidSyslogSdValue_BoundedString` with the existing `ORIGIN_*_MAX` decoded caps.
- **`GetIpAt` signature changed** to `void(struct SolidSyslogSdValue*, void* context,
size_t index)` with a paired `OriginSdConfig.IpContext`. It keeps its own typedef name
`SolidSyslogOriginIpAtFunction` (not the shared `SolidSyslogSdValueFunction` — it
carries the extra `index`). Routing `ip` through the param sink closes the `ip`
injection vector; with `language` (S14.04) that completes **#533**. New behaviour
(`void* context`) driven RED-first by `FormatPassesIpContextThrough`.
- **Took the #346 eliminate-the-scratch path.** The static fields emit straight into the
element at Format time; the `OriginSd` struct now **borrows** the three config strings
directly. `FormattedStorage` and the `ORIGIN_{LITERAL_BYTES,CONTENT_MAX,FORMATTED_MAX}`
sizing enums are deleted. No shared SD scratch buffer remains → concurrent-`Log`
reentrancy holds by construction. Behaviour change: the config strings are borrowed for
the SD's lifetime (were copied at `Create`) — fine for the literal/long-lived config
integrators pass.
- The shared `BddTargetIps_At` moved to `SolidSyslogSdValue_BoundedString`; renamed the
now-misnamed `WorstCaseFullyEscapedInputFitsPreFormattedStorage` test.
- Checks: debug green (1459 tests), OriginSd 38/38, BddTargetIps 2/2, BddTargetTests
66/66; clang-format applied; cppcheck-MISRA exit 0 (anchors moved: OriginSd.c 11.3
73→61, OriginSdPrivate.h 5.7 14→13). PR #555.

### Deferred
- SD vtable flip (S14.06), config header fields (S14.07). CLAUDE.md OriginSd
header-table row (still describes the removed pre-formatted storage) left for the
S14.08 wholesale table revision.

### Open questions
- None outstanding.
7 changes: 6 additions & 1 deletion Tests/Bdd/Targets/BddTargetIpsTest.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "BddTargetIps.h"
#include "SolidSyslogFormatter.h"
#include "SolidSyslogSdValue.h"
#include "SolidSyslogSdValuePrivate.h"
#include "CppUTest/TestHarness.h"

enum
Expand All @@ -12,10 +14,12 @@ TEST_GROUP(BddTargetIps)
{
SolidSyslogFormatterStorage storage[SOLIDSYSLOG_FORMATTER_STORAGE_SIZE(FORMATTER_BUFFER_SIZE)];
struct SolidSyslogFormatter* formatter = nullptr;
struct SolidSyslogSdValue value{};

void setup() override
{
formatter = SolidSyslogFormatter_Create(storage, FORMATTER_BUFFER_SIZE);
SolidSyslogSdValue_FromFormatter(&value, formatter);
}

[[nodiscard]] const char* formatted() const
Expand All @@ -33,6 +37,7 @@ TEST(BddTargetIps, CountIsOne)

TEST(BddTargetIps, AtZeroEmitsTheConfiguredIp)
{
BddTargetIps_At(formatter, 0);
BddTargetIps_At(&value, nullptr, 0);
SolidSyslogSdValue_Close(&value);
STRCMP_EQUAL("192.0.2.1", formatted());
}
Loading
Loading