ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
consensus.h File Reference

Mode-agnostic ring consensus abstraction for session discovery. More...

Go to the source code of this file.

Data Structures

struct  session_consensus_callbacks_t
 Mode-specific hooks used by the session consensus adapter. More...

Typedefs

typedef asciichat_error_t(* session_consensus_send_packet_fn) (void *context, const uint8_t next_participant_id[SESSION_ID_SIZE], const uint8_t *packet, size_t packet_size)
 Callback: Send a consensus packet to the next ring participant.
typedef asciichat_error_t(* session_consensus_on_election_fn) (void *context, const uint8_t host_id[SESSION_ID_SIZE], const char host_address[ACIP_ADDRESS_SIZE], uint16_t host_port, const uint8_t backup_id[SESSION_ID_SIZE], const char backup_address[ACIP_ADDRESS_SIZE], uint16_t backup_port)
 Callback: Handle elected host result.
typedef asciichat_error_t(* session_consensus_get_metrics_fn) (void *context, const uint8_t my_id[SESSION_ID_SIZE], participant_metrics_t *out_metrics)
 Callback: Measure current participant's network metrics.
typedef asciichat_error_t(* session_consensus_election_fn) (void *context, const participant_metrics_t *metrics, int num_metrics, int *out_best_index, int *out_backup_index)
 Callback type for custom election algorithm.

Functions

asciichat_error_t session_consensus_create (const uint8_t my_id[SESSION_ID_SIZE], bool is_leader, const uint8_t participant_ids[MAX_SESSION_PARTICIPANTS][SESSION_ID_SIZE], int num_participants, const session_consensus_callbacks_t *callbacks, session_consensus_t **out_consensus)
 Create a new session consensus instance.
void session_consensus_destroy (session_consensus_t *consensus)
 Destroy consensus instance and free all resources.
asciichat_error_t session_consensus_process (session_consensus_t *consensus, uint32_t timeout_ms)
 Main consensus processing loop - call periodically.
asciichat_error_t session_consensus_set_topology (session_consensus_t *consensus, const uint8_t participant_ids[MAX_SESSION_PARTICIPANTS][SESSION_ID_SIZE], int num_participants)
 Update ring topology when participants change.
asciichat_error_t session_consensus_on_collection_start (session_consensus_t *consensus, uint32_t round_id, uint64_t deadline_ns)
 Handle incoming STATS_COLLECTION_START packet.
asciichat_error_t session_consensus_on_stats_update (session_consensus_t *consensus, const uint8_t sender_id[SESSION_ID_SIZE], const participant_metrics_t *metrics, uint8_t num_metrics)
 Handle incoming STATS_UPDATE packet (metrics relayed around ring).
asciichat_error_t session_consensus_on_election_result (session_consensus_t *consensus, const uint8_t host_id[SESSION_ID_SIZE], const char host_address[ACIP_ADDRESS_SIZE], uint16_t host_port, const uint8_t backup_id[SESSION_ID_SIZE], const char backup_address[ACIP_ADDRESS_SIZE], uint16_t backup_port)
 Handle incoming ELECTION_RESULT packet from leader.
asciichat_error_t session_consensus_get_elected_host (session_consensus_t *consensus, uint8_t out_host_id[SESSION_ID_SIZE], char out_host_address[ACIP_ADDRESS_SIZE], uint16_t *out_host_port, uint8_t out_backup_id[SESSION_ID_SIZE], char out_backup_address[ACIP_ADDRESS_SIZE], uint16_t *out_backup_port)
 Get the currently elected host.
bool session_consensus_is_ready (session_consensus_t *consensus)
 Check if consensus has completed at least one round.
int session_consensus_get_state (session_consensus_t *consensus)
 Get current consensus state.
uint64_t session_consensus_time_until_next_round (session_consensus_t *consensus)
 Get time until next consensus round in nanoseconds.
int session_consensus_get_metrics_count (session_consensus_t *consensus)
 Get count of metrics collected in current round.

Detailed Description

Mode-agnostic ring consensus abstraction for session discovery.

Provides a clean abstraction over the ring consensus protocol that any mode (server, client, acds, discovery) can use. The abstraction:

  • Wraps all consensus modules (state, coordinator, topology, election, metrics)
  • Uses callbacks to decouple consensus logic from transport/metrics specifics
  • Provides non-blocking periodic processing
  • Handles automatic packet generation and state transitions

Design Principles:

  1. Consensus algorithm is mode-agnostic - doesn't know about TCP/WebRTC/etc
  2. Modes provide callbacks for:
    • Sending packets to next participant
    • Measuring network metrics (NAT quality, bandwidth, etc)
    • Handling elected host results
  3. No tight coupling to specific transports or capture mechanisms
  4. Each mode can opt-in or opt-out independently

Definition in file consensus.h.

Typedef Documentation

◆ session_consensus_election_fn

typedef asciichat_error_t(* session_consensus_election_fn) (void *context, const participant_metrics_t *metrics, int num_metrics, int *out_best_index, int *out_backup_index)

Callback type for custom election algorithm.

If provided, consensus calls this instead of built-in election. Allows modes to implement custom host selection logic.

Parameters
contextOpaque pointer provided by caller during create
metricsArray of participant metrics
num_metricsCount of metrics
out_best_indexOutput: Index of best host (not ID)
out_backup_indexOutput: Index of backup host
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 120 of file consensus.h.

◆ session_consensus_get_metrics_fn

typedef asciichat_error_t(* session_consensus_get_metrics_fn) (void *context, const uint8_t my_id[SESSION_ID_SIZE], participant_metrics_t *out_metrics)

Callback: Measure current participant's network metrics.

Called by consensus to collect metrics for this participant. Should measure:

  • NAT tier (0=LAN, 1=Public, 2=UPnP, 3=STUN, 4=TURN)
  • Upload bandwidth (Kbps)
  • RTT to current host (nanoseconds)
  • STUN probe success rate (0-100%)
  • Public address and port
  • Connection type (Direct, UPnP, STUN, TURN)
Parameters
contextOpaque pointer provided by caller during create
my_id16-byte UUID of this participant
out_metricsOutput metrics structure (caller-allocated)
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 104 of file consensus.h.

◆ session_consensus_on_election_fn

typedef asciichat_error_t(* session_consensus_on_election_fn) (void *context, const uint8_t host_id[SESSION_ID_SIZE], const char host_address[ACIP_ADDRESS_SIZE], uint16_t host_port, const uint8_t backup_id[SESSION_ID_SIZE], const char backup_address[ACIP_ADDRESS_SIZE], uint16_t backup_port)

Callback: Handle elected host result.

Called by consensus when a new host election is complete and announced. The mode should:

  • Store the elected host and backup host info
  • Update connection targets if participant
  • Initiate host role if elected as new host
Parameters
contextOpaque pointer provided by caller during create
host_id16-byte UUID of elected host
host_addressAddress to connect to (hostname or IP)
host_portPort to connect to
backup_id16-byte UUID of backup host
backup_addressBackup address
backup_portBackup port
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 81 of file consensus.h.

◆ session_consensus_send_packet_fn

typedef asciichat_error_t(* session_consensus_send_packet_fn) (void *context, const uint8_t next_participant_id[SESSION_ID_SIZE], const uint8_t *packet, size_t packet_size)

Callback: Send a consensus packet to the next ring participant.

Called by consensus to send packets around the ring. The mode is responsible for serializing and transmitting to the appropriate transport.

Parameters
contextOpaque pointer provided by caller during create
next_participant_id16-byte UUID of next participant in ring
packetPacket data to send (including header)
packet_sizeSize of packet in bytes
Returns
ASCIICHAT_OK on success, error code if sending failed

Definition at line 59 of file consensus.h.

Function Documentation

◆ session_consensus_create()

asciichat_error_t session_consensus_create ( const uint8_t my_id[SESSION_ID_SIZE],
bool is_leader,
const uint8_t participant_ids[MAX_SESSION_PARTICIPANTS][SESSION_ID_SIZE],
int num_participants,
const session_consensus_callbacks_t * callbacks,
session_consensus_t ** out_consensus )

Create a new session consensus instance.

Initializes consensus for a participant in a session. The consensus will manage ring topology, metrics collection, and host election according to the configured ring parameters.

Parameters
my_id16-byte UUID of this participant
is_leaderWhether this participant should run elections (typically last in ring)
participant_idsArray of participant UUIDs (up to 128)
num_participantsCount of participants
callbacksCallback functions for mode integration
out_consensusOutput consensus handle (caller must destroy)
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 117 of file consensus.c.

120 {
121 if (!my_id || !callbacks || !out_consensus) {
122 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters: my_id=%p, callbacks=%p, out_consensus=%p", my_id,
123 callbacks, out_consensus);
124 }
125
126 if (!callbacks->send_packet || !callbacks->on_election || !callbacks->get_metrics) {
127 return SET_ERRNO(ERROR_INVALID_PARAM, "Required callbacks missing: send_packet=%p, on_election=%p, get_metrics=%p",
128 callbacks->send_packet, callbacks->on_election, callbacks->get_metrics);
129 }
130
131 if (num_participants < 1 || num_participants > MAX_SESSION_PARTICIPANTS) {
132 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid participant count: %d", num_participants);
133 }
134
135 // Allocate consensus handle
137 if (!consensus) {
138 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate session consensus");
139 }
140
141 // Copy identity
142 memcpy(consensus->my_id, my_id, SESSION_ID_SIZE);
143 consensus->is_leader = is_leader;
144
145 // Copy callbacks
146 consensus->send_packet = callbacks->send_packet;
147 consensus->on_election = callbacks->on_election;
148 consensus->get_metrics = callbacks->get_metrics;
149 consensus->election = callbacks->election; // May be NULL
150 consensus->context = callbacks->context;
151
152 // Create topology
153 asciichat_error_t err = consensus_topology_create(participant_ids, num_participants, my_id, &consensus->topology);
154 if (err != ASCIICHAT_OK) {
155 SAFE_FREE(consensus);
156 return err;
157 }
158
159 // Create coordinator
160 err = consensus_coordinator_create(my_id, consensus->topology, session_consensus_election_bridge, consensus,
161 &consensus->coordinator);
162 if (err != ASCIICHAT_OK) {
164 SAFE_FREE(consensus);
165 return err;
166 }
167
169
170 log_debug("Session consensus created: my_id=%.*s, is_leader=%d, participants=%d", 16, my_id, is_leader,
171 num_participants);
172
173 *out_consensus = consensus;
174 return ASCIICHAT_OK;
175}
#define SET_ERRNO(code,...)
struct session_consensus session_consensus_t
When code needs to work with session consensus, it keeps topology, coordinator, send_packet,...
asciichat_error_t consensus_coordinator_create(const uint8_t my_id[SESSION_ID_SIZE], const consensus_topology_t *topology, consensus_election_func_t election_func, void *election_context, consensus_coordinator_t **out_coordinator)
Initialize coordinator with given parameters.
Definition coordinator.c:56
void consensus_coordinator_set_metrics_provider(consensus_coordinator_t *coordinator, consensus_metrics_provider_fn provider, void *context)
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
#define MAX_SESSION_PARTICIPANTS
#define SESSION_ID_SIZE
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595
void * context
Opaque context passed to all callbacks.
Definition consensus.h:135
session_consensus_election_fn election
Custom election callback (optional, NULL = use default).
Definition consensus.h:134
session_consensus_on_election_fn on_election
Election result callback.
Definition consensus.h:132
session_consensus_get_metrics_fn get_metrics
Measure metrics callback.
Definition consensus.h:133
session_consensus_send_packet_fn send_packet
Send packet callback.
Definition consensus.h:131
consensus_topology_t * topology
Definition consensus.c:38
session_consensus_get_metrics_fn get_metrics
Definition consensus.c:44
session_consensus_on_election_fn on_election
Definition consensus.c:43
consensus_coordinator_t * coordinator
Definition consensus.c:39
session_consensus_send_packet_fn send_packet
Definition consensus.c:42
session_consensus_election_fn election
Definition consensus.c:45
uint8_t my_id[SESSION_ID_SIZE]
Definition consensus.c:49
void consensus_topology_destroy(consensus_topology_t *topology)
Destroy topology.
Definition topology.c:73
asciichat_error_t consensus_topology_create(const uint8_t participant_ids[MAX_SESSION_PARTICIPANTS][SESSION_ID_SIZE], int num_participants, const uint8_t my_id[SESSION_ID_SIZE], consensus_topology_t **out_topology)
Create new ring topology from participant list.
Definition topology.c:44

References ASCIICHAT_OK, consensus_coordinator_create(), consensus_coordinator_set_metrics_provider(), consensus_topology_create(), consensus_topology_destroy(), session_consensus::context, session_consensus_callbacks_t::context, session_consensus::coordinator, session_consensus::election, session_consensus_callbacks_t::election, ERROR_INVALID_PARAM, ERROR_MEMORY, session_consensus::get_metrics, session_consensus_callbacks_t::get_metrics, session_consensus::is_leader, log_debug, MAX_SESSION_PARTICIPANTS, session_consensus::my_id, session_consensus::on_election, session_consensus_callbacks_t::on_election, SAFE_CALLOC, SAFE_FREE, session_consensus::send_packet, session_consensus_callbacks_t::send_packet, SESSION_ID_SIZE, SET_ERRNO, and session_consensus::topology.

Referenced by consensus_create_for_discovery().

◆ session_consensus_destroy()

void session_consensus_destroy ( session_consensus_t * consensus)

Destroy consensus instance and free all resources.

Parameters
consensusConsensus handle (safe to pass NULL)

Definition at line 177 of file consensus.c.

177 {
178 if (!consensus) {
179 return;
180 }
181
182 if (consensus->coordinator) {
184 }
185
186 if (consensus->topology) {
188 }
189
190 SAFE_FREE(consensus);
191}
void consensus_coordinator_destroy(consensus_coordinator_t *coordinator)
Clean up coordinator resources.

References consensus_coordinator_destroy(), consensus_topology_destroy(), session_consensus::coordinator, SAFE_FREE, and session_consensus::topology.

◆ session_consensus_get_elected_host()

asciichat_error_t session_consensus_get_elected_host ( session_consensus_t * consensus,
uint8_t out_host_id[SESSION_ID_SIZE],
char out_host_address[ACIP_ADDRESS_SIZE],
uint16_t * out_host_port,
uint8_t out_backup_id[SESSION_ID_SIZE],
char out_backup_address[ACIP_ADDRESS_SIZE],
uint16_t * out_backup_port )

Get the currently elected host.

Returns the most recently elected host and backup. If no election has completed yet, returns the previous stored result if available, or error.

Parameters
consensusConsensus handle
out_host_idOutput: 16-byte UUID of host (caller provides buffer)
out_host_addressOutput: Host address (caller provides buffer, 64 bytes)
out_host_portOutput: Host port
out_backup_idOutput: 16-byte UUID of backup (caller provides buffer)
out_backup_addressOutput: Backup address (caller provides buffer, 64 bytes)
out_backup_portOutput: Backup port
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 274 of file consensus.c.

279 {
280 if (!consensus || !out_host_id || !out_host_address || !out_host_port || !out_backup_id || !out_backup_address ||
281 !out_backup_port) {
282 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
283 }
284
285 // Get from coordinator
286 asciichat_error_t err = consensus_coordinator_get_current_host(consensus->coordinator, out_host_id, out_backup_id);
287 if (err != ASCIICHAT_OK) {
288 return err;
289 }
290
291 // NOTE: The current API doesn't return addresses/ports. This is a limitation
292 // of the coordinator that should be addressed in a future enhancement.
293 // For now, return zeros and indicate this is a placeholder.
294 memset(out_host_address, 0, ACIP_ADDRESS_SIZE);
295 *out_host_port = 0;
296 memset(out_backup_address, 0, ACIP_ADDRESS_SIZE);
297 *out_backup_port = 0;
298
299 return ASCIICHAT_OK;
300}
#define ACIP_ADDRESS_SIZE
Definition acds_sizes.h:7
asciichat_error_t consensus_coordinator_get_current_host(const consensus_coordinator_t *coordinator, uint8_t out_host_id[SESSION_ID_SIZE], uint8_t out_backup_id[SESSION_ID_SIZE])
Get currently elected host.

References ACIP_ADDRESS_SIZE, ASCIICHAT_OK, consensus_coordinator_get_current_host(), session_consensus::coordinator, ERROR_INVALID_PARAM, SESSION_ID_SIZE, and SET_ERRNO.

◆ session_consensus_get_metrics_count()

int session_consensus_get_metrics_count ( session_consensus_t * consensus)

Get count of metrics collected in current round.

Useful for monitoring collection progress.

Parameters
consensusConsensus handle
Returns
Number of metrics collected, or -1 if invalid

Definition at line 331 of file consensus.c.

331 {
332 if (!consensus) {
333 return -1;
334 }
335
337}
int consensus_coordinator_get_metrics_count(const consensus_coordinator_t *coordinator)
Get count of metrics in current round.

References consensus_coordinator_get_metrics_count(), and session_consensus::coordinator.

◆ session_consensus_get_state()

int session_consensus_get_state ( session_consensus_t * consensus)

Get current consensus state.

Parameters
consensusConsensus handle
Returns
Current state from internal state machine

Definition at line 315 of file consensus.c.

315 {
316 if (!consensus) {
317 return -1;
318 }
319
320 return (int)consensus_coordinator_get_state(consensus->coordinator);
321}
consensus_state_machine_t consensus_coordinator_get_state(const consensus_coordinator_t *coordinator)
Get current coordinator state.

References consensus_coordinator_get_state(), and session_consensus::coordinator.

◆ session_consensus_is_ready()

bool session_consensus_is_ready ( session_consensus_t * consensus)

Check if consensus has completed at least one round.

Returns true if at least one complete consensus round has finished with a valid elected host and backup.

Parameters
consensusConsensus handle
Returns
true if consensus reached, false otherwise

Definition at line 302 of file consensus.c.

302 {
303 if (!consensus) {
304 return false;
305 }
306
307 // Check if we have a valid elected host
308 uint8_t host_id[SESSION_ID_SIZE];
309 uint8_t backup_id[SESSION_ID_SIZE];
310 asciichat_error_t err = consensus_coordinator_get_current_host(consensus->coordinator, host_id, backup_id);
311
312 return err == ASCIICHAT_OK;
313}
unsigned char uint8_t
Definition common.h:60

References ASCIICHAT_OK, consensus_coordinator_get_current_host(), session_consensus::coordinator, and SESSION_ID_SIZE.

◆ session_consensus_on_collection_start()

asciichat_error_t session_consensus_on_collection_start ( session_consensus_t * consensus,
uint32_t round_id,
uint64_t deadline_ns )

Handle incoming STATS_COLLECTION_START packet.

Consensus calls this when it receives a collection start from the previous ring participant. Should be called from packet handler in mode.

Parameters
consensusConsensus handle
round_idCollection round ID
deadline_nsUnix nanosecond deadline for collection
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 230 of file consensus.c.

231 {
232 if (!consensus) {
233 return SET_ERRNO(ERROR_INVALID_PARAM, "consensus is NULL");
234 }
235
236 return consensus_coordinator_on_collection_start(consensus->coordinator, round_id, deadline_ns);
237}
asciichat_error_t consensus_coordinator_on_collection_start(consensus_coordinator_t *coordinator, uint32_t round_id, uint64_t deadline_ns)
Handle STATS_COLLECTION_START packet.

References consensus_coordinator_on_collection_start(), session_consensus::coordinator, ERROR_INVALID_PARAM, and SET_ERRNO.

◆ session_consensus_on_election_result()

asciichat_error_t session_consensus_on_election_result ( session_consensus_t * consensus,
const uint8_t host_id[SESSION_ID_SIZE],
const char host_address[ACIP_ADDRESS_SIZE],
uint16_t host_port,
const uint8_t backup_id[SESSION_ID_SIZE],
const char backup_address[ACIP_ADDRESS_SIZE],
uint16_t backup_port )

Handle incoming ELECTION_RESULT packet from leader.

Consensus calls this when leader announces the elected host. Should be called from packet handler in mode.

Parameters
consensusConsensus handle
host_id16-byte UUID of elected host
host_addressAddress of elected host
host_portPort of elected host
backup_id16-byte UUID of backup host
backup_addressAddress of backup host
backup_portPort of backup host
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 249 of file consensus.c.

254 {
255 if (!consensus || !host_id || !backup_id) {
256 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
257 }
258
259 // First acknowledge the election in coordinator
260 asciichat_error_t err = consensus_coordinator_on_election_result(consensus->coordinator, host_id, backup_id);
261 if (err != ASCIICHAT_OK) {
262 return err;
263 }
264
265 // Then call the mode's election callback
266 if (consensus->on_election) {
267 return consensus->on_election(consensus->context, host_id, host_address, host_port, backup_id, backup_address,
268 backup_port);
269 }
270
271 return ASCIICHAT_OK;
272}
asciichat_error_t consensus_coordinator_on_election_result(consensus_coordinator_t *coordinator, const uint8_t host_id[SESSION_ID_SIZE], const uint8_t backup_id[SESSION_ID_SIZE])
Handle ELECTION_RESULT packet.

References ACIP_ADDRESS_SIZE, ASCIICHAT_OK, consensus_coordinator_on_election_result(), session_consensus::context, session_consensus::coordinator, ERROR_INVALID_PARAM, session_consensus::on_election, SESSION_ID_SIZE, and SET_ERRNO.

◆ session_consensus_on_stats_update()

asciichat_error_t session_consensus_on_stats_update ( session_consensus_t * consensus,
const uint8_t sender_id[SESSION_ID_SIZE],
const participant_metrics_t * metrics,
uint8_t num_metrics )

Handle incoming STATS_UPDATE packet (metrics relayed around ring).

Consensus calls this when it receives metrics from the previous participant. Should be called from packet handler in mode.

Parameters
consensusConsensus handle
sender_id16-byte UUID of who sent this update
metricsArray of metrics in this packet
num_metricsCount of metrics
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 239 of file consensus.c.

241 {
242 if (!consensus || !sender_id || !metrics) {
243 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
244 }
245
246 return consensus_coordinator_on_stats_update(consensus->coordinator, sender_id, metrics, num_metrics);
247}
asciichat_error_t consensus_coordinator_on_stats_update(consensus_coordinator_t *coordinator, const uint8_t sender_id[SESSION_ID_SIZE], const participant_metrics_t *metrics, uint8_t num_metrics)
Handle STATS_UPDATE packet.

References consensus_coordinator_on_stats_update(), session_consensus::coordinator, ERROR_INVALID_PARAM, SESSION_ID_SIZE, and SET_ERRNO.

◆ session_consensus_process()

asciichat_error_t session_consensus_process ( session_consensus_t * consensus,
uint32_t timeout_ms )

Main consensus processing loop - call periodically.

Handles:

  • Round scheduling (every 5 minutes)
  • Collection deadline enforcement (30 seconds)
  • Metrics measurement and relay around ring
  • Election computation (leader only)
  • Result broadcasting

Non-blocking: returns immediately if no action needed. Modes should call this regularly (at least once per second) to ensure timely round scheduling and deadline enforcement.

Parameters
consensusConsensus handle
timeout_msTimeout for this call in milliseconds (0 = non-blocking)
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 193 of file consensus.c.

193 {
194 if (!consensus) {
195 return SET_ERRNO(ERROR_INVALID_PARAM, "consensus is NULL");
196 }
197
198 // Call coordinator process
199 return consensus_coordinator_process(consensus->coordinator, timeout_ms);
200}
asciichat_error_t consensus_coordinator_process(consensus_coordinator_t *coordinator, uint32_t timeout_ms)
Main orchestration loop.

References consensus_coordinator_process(), session_consensus::coordinator, ERROR_INVALID_PARAM, and SET_ERRNO.

◆ session_consensus_set_topology()

asciichat_error_t session_consensus_set_topology ( session_consensus_t * consensus,
const uint8_t participant_ids[MAX_SESSION_PARTICIPANTS][SESSION_ID_SIZE],
int num_participants )

Update ring topology when participants change.

Called when the ring topology changes (participants join/leave). Updates the consensus topology and resets any in-progress round.

Parameters
consensusConsensus handle
participant_idsUpdated array of participant UUIDs
num_participantsNew count of participants
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 203 of file consensus.c.

205 {
206 if (!consensus || !participant_ids) {
207 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
208 }
209
210 if (num_participants < 1 || num_participants > MAX_SESSION_PARTICIPANTS) {
211 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid participant count: %d", num_participants);
212 }
213
214 // Validate the candidate before releasing the ring still borrowed by the
215 // coordinator. A rejected membership update must preserve the active round.
216 consensus_topology_t *replacement = NULL;
217 asciichat_error_t err = consensus_topology_create(participant_ids, num_participants, consensus->my_id, &replacement);
218 if (err != ASCIICHAT_OK)
219 return err;
220 err = consensus_coordinator_on_ring_members(consensus->coordinator, replacement);
221 if (err != ASCIICHAT_OK) {
222 consensus_topology_destroy(replacement);
223 return err;
224 }
226 consensus->topology = replacement;
227 return ASCIICHAT_OK;
228}
asciichat_error_t consensus_coordinator_on_ring_members(consensus_coordinator_t *coordinator, const consensus_topology_t *new_topology)
Update ring topology when participants change.
struct consensus_topology consensus_topology_t
Ring topology for consensus participants.

References ASCIICHAT_OK, consensus_coordinator_on_ring_members(), consensus_topology_create(), consensus_topology_destroy(), session_consensus::coordinator, ERROR_INVALID_PARAM, MAX_SESSION_PARTICIPANTS, session_consensus::my_id, SESSION_ID_SIZE, SET_ERRNO, and session_consensus::topology.

◆ session_consensus_time_until_next_round()

uint64_t session_consensus_time_until_next_round ( session_consensus_t * consensus)

Get time until next consensus round in nanoseconds.

Useful for scheduling when to call process() next.

Parameters
consensusConsensus handle
Returns
Nanoseconds until next round, or 0 if round is due now

Definition at line 323 of file consensus.c.

323 {
324 if (!consensus) {
325 return 0;
326 }
327
329}
uint64_t consensus_coordinator_time_until_next_round(const consensus_coordinator_t *coordinator)
Get time until next round.

References consensus_coordinator_time_until_next_round(), and session_consensus::coordinator.

Referenced by consensus_suggest_timeout_ms().