Scroll to navigation



lc_channel_nack_handler, lc_channel_nack_handler_thr, lc_channel_nack_add_log - outgoing message logging to handle NACK and replay requests


Librecast library (liblibrecast, -llibrecast)


#include <librecast/net.h>
int lc_channel_nack_handler(lc_channel_t *chan, int n_seconds);
int lc_channel_nack_handler_thr(lc_channel_t *chan, int n_seconds, void *(*nack_thread)(void *));
int lc_channel_nack_add_log(lc_channel_t *chan, const void *buf, size_t len, lc_seq_t seq);

Compile and link with -llibrecast.


lc_channel_nack_handler() sets up a per-channel buffer to keep a copy of outgoing messages sent via lc_msg_send() and also starts a new thread (called "nack thread") to handle any retransmission requests; the outgoing messages are kept for at least n_seconds seconds if there is sufficient free memory to do so. The nack thread listens for messages on a related channel, interprets them as NACK messages, and arranges for retransmission of the corresponding messages. The normal case is that these NACK messages are generated as a result of calling lc_channel_detect_gaps() on the receiver side. A call to lc_channel_free(3) will stop the nack thread if it's running.

lc_channel_nack_handler_thr() is similar to lc_channel_nack_handler() except that it specifies a different function to use for the nack thread; it will be called in a new thread with an opened channel and socket where it can receive NACK messages, and another channel it can use to resend packets; currently, there is no alternative thread to use, and this function is only used by the library's tests; however a different nack thread could be provided in future for example to deal with the special case of messages sent from static data, which can be resent without storing recent messages in a memory buffer.

lc_channel_nack_add_log() adds a message to the internal memory buffer, making it available for retransmission as a result of a NACK; it is not normally necessary to call this function if all messages are sent using lc_msg_send() however an application which defines its own message format will need to call lc_channel_nack_add_log() with a copy of each message as it goes on the wire, as well as the sequence number it contains, as the library will have no way to find this information in the applicatin's own message format. The application needs to call lc_channel_nack_handler() before using lc_channel_nack_add_log() otherwise the call will not log anything: this could be useful if message logging and NACK request handling is optional, so the application can conditionally call lc_channel_nack_handler() during initialisation, but then unconditionally call lc_channel_nack_add_log() for each message it sends.


lc_channel_nack_handler() and lc_channel_nack_handler_thr() return 0 on success, and -1 to indicate an error, setting the global variable errno to an appropriate code, most likely ENOMEM to indicate that there was insufficient memory to set up the required data structures.

The lc_channel_nack_add_log() function returns 0 on success and -1 to indicate that there was no memory to store the message in its internal buffers, setting errno to the value ENOMEM


lc_channel_nack_handler() and lc_channel_nack_handler_thr() can fail with any of the errors the malloc() library function can produce, as well as any errors produces by the lc_channel_sidehash() or lc_socket_new() functions.

lc_channel_nack_add_log() can fail with any of the errors the malloc() library function can produce.


Program source

lc_ctx_t *lctx;
lc_channel_t *chan;
lctx = lc_ctx_new();
chan = lc_channel_new(lctx, "channel name");
if (lc_channel_nack_handler(chan, 10) == -1) {
	/* handle this error */
/* your program goes here, likely calling lc_msg_send(chan, ...) */


lc_channel_detect_gaps(3), lc_channel_free(3), lc_msg_send(3)

2022-10-29 LIBRECAST