Building a Client
Relevant source files
The following files were used as context for generating this wiki page:
Building a client using librelp involves interacting with the Reliable Event Logging Protocol (RELP) engine to establish a reliable, command-response based connection with a server. The library is designed to be state-free at the global level, requiring the creation of an engine object to manage sessions, commands, and network I/O.
A RELP client follows a specific lifecycle: initializing the engine, configuring optional security parameters (like TLS), establishing a connection, transmitting messages (commands), and gracefully shutting down the session. The protocol ensures reliability through application-level acknowledgments for every command sent.
Sources: doc/relp.html:15-25, src/relp.h:118-124
Engine Initialization and Configuration
The first step in building a client is constructing the RELP engine and configuring its behavior. The engine serves as the container for all RELP objects and manages the dispatching of frames.
Key Engine API Functions
The engine must be initialized before any other library functions are called.
| Function | Purpose |
|---|---|
relpEngineConstruct | Allocates and initializes a new RELP engine instance. |
relpEngineSetDbgprint | Sets a callback for debug logging. |
relpEngineSetOnErr | Sets a callback for handling object-specific errors. |
relpEngineSetOnGenericErr | Sets a callback for errors not tied to a specific object. |
relpEngineSetEnableCmd | Enables specific commands (e.g., "syslog") for the engine. |
Sources: src/librelp.h:135-155, src/relp.c:166-177, tests/send.c:450-465
The diagram shows the mandatory sequence for preparing the RELP environment before a client can be instantiated.
Sources: src/relp.c:595-605, tests/send.c:450-470
Client Construction and Connection
Once the engine is ready, a client object (relpClt_t) is created. This object manages the specific connection to a remote host.
Connection Process
Connecting a client involves specifying the protocol family (IPv4/IPv6), the target host, and the port. If TLS is required, it must be enabled and configured before the relpCltConnect call.
- Construct Client: Call
relpEngineCltConstruct. - Optional Configuration: Set timeouts using
relpCltSetTimeoutor window sizes withrelpCltSetWindowSize. - Establish Connection: Call
relpCltConnect. This initiates the RELP "open" command handshake.
Sources: src/librelp.h:180-195, src/relpsess.c:647-660, tests/send.c:470-505
TLS Configuration
If security is required, the client can be configured with various authentication modes and certificates.
| Authentication Mode | Description |
|---|---|
eRelpAuthMode_None | No authentication (often used with anonymous DH). |
eRelpAuthMode_Fingerprint | Validates peer certificate fingerprint against a permitted list. |
eRelpAuthMode_Name | Validates peer certificate Common Name (CN). |
eRelpAuthMode_CertValid | Standard certificate validation. |
Sources: src/librelp.h:68-75, tests/send.c:475-490
Data Transmission (The Syslog Command)
Data in RELP is transmitted as commands. The most common client operation is sending syslog messages using the syslog command.
Reliability and Transaction Numbers (TXNR)
Every command is assigned a unique, monotonically increasing transaction number starting at 1. The server must respond with a rsp frame containing the same TXNR. The client maintains an "unacked" list to track outstanding commands.
This sequence illustrates the command-response reliability mechanism where the TXNR links requests to acknowledgments.
Sources: doc/relp.html:20-30, src/relpsess.c:380-395
Window Management
To optimize performance, RELP uses a window size (default 128). The client can send multiple commands without waiting for immediate responses, provided the number of unacknowledged frames does not exceed the window size. If the window is full, the client state transitions to eRelpSessState_WINDOW_FULL and must wait for server responses before sending more.
Sources: src/relp.h:150-155, src/relpsess.c:438-455, doc/relp.html:25-30
Error Handling and Recovery
RELP recovery logic is based on connection resets. If a session is broken (e.g., I/O error or timeout), the client flags the session as eRelpSessState_BROKEN.
Re-establishment Procedure
- Abort the existing TCP connection using
relpTcpAbortDestruct. - Reconnect to the server.
- Resend all unacknowledged frames from the internal unacked list, assigning them new TXNRs for the new session.
Sources: src/relpsess.c:600-630, doc/relp.html:35-45, tests/send.c:135-155
Shutdown and Cleanup
A graceful shutdown is required to ensure all data is acknowledged before closing the network socket.
Termination Steps
- Hint Bursts: If using burst mode, call
relpCltHintBurstEnd. - Close Command: Send the
closecommand. The client must not send further commands after this. - Await Response: Wait for the server's
rspto theclosecommand. - Destruction: Call
relpEngineCltDestructfollowed byrelpEngineDestruct.
Sources: src/relpsess.c:855-875, doc/relp.html:115-120, tests/send.c:510-520
Summary Table of Lifecycle Functions
| Stage | API Functions |
|---|---|
| Setup | relpEngineConstruct, relpEngineCltConstruct |
| Connecting | relpCltConnect |
| Sending | relpCltSendSyslog |
| Teardown | relpEngineCltDestruct, relpEngineDestruct |
Sources: src/librelp.h:135-210, tests/send.c:450-520
Conclusion
Building a client with librelp requires careful management of the engine and session states. By following the standard lifecycle of construction, connection with optional TLS, and command-response data transmission, developers can ensure that event data is delivered reliably with application-level verification. The built-in recovery mechanisms allow the client to handle network interruptions by resending unacknowledged data upon session re-establishment.
Sources: doc/relp.html:230-245, src/relpsess.c:600-615