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

Deterministic host election algorithm. More...

Go to the source code of this file.

Functions

uint32_t consensus_election_compute_score (const participant_metrics_t *metrics)
 Compute deterministic score for a participant.
asciichat_error_t consensus_election_choose_hosts (const participant_metrics_t *metrics, int num_metrics, int *out_best_index, int *out_backup_index)
 Elect best and backup host from metrics.
asciichat_error_t consensus_election_verify (const participant_metrics_t *metrics, int num_metrics, const uint8_t announced_host_id[SESSION_ID_SIZE], const uint8_t announced_backup_id[SESSION_ID_SIZE], bool *out_valid)
 Verify election result matches expected scores.

Detailed Description

Deterministic host election algorithm.

Definition in file election.h.

Function Documentation

◆ consensus_election_choose_hosts()

asciichat_error_t consensus_election_choose_hosts ( const participant_metrics_t * metrics,
int num_metrics,
int * out_best_index,
int * out_backup_index )

Elect best and backup host from metrics.

Returns indices of best and second-best participants. Deterministic tie-breaking ensures identical result on all clients.

Definition at line 79 of file election.c.

80 {
81 if (!metrics || !out_best_index || !out_backup_index || num_metrics < 1) {
82 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid election parameters");
83 }
84
85 for (int i = 0; i < num_metrics; ++i) {
86 if (metrics[i].nat_tier > 4 || metrics[i].stun_probe_success_pct > 100)
87 return SET_ERRNO(ERROR_INVALID_PARAM, "Malformed participant metrics");
88 for (int j = 0; j < i; ++j)
89 if (!memcmp(metrics[i].participant_id, metrics[j].participant_id, SESSION_ID_SIZE))
90 return SET_ERRNO(ERROR_INVALID_PARAM, "Duplicate election participant");
91 }
92
93 // Compute scores for all participants
94 uint32_t *scores = SAFE_MALLOC(sizeof(uint32_t) * num_metrics, uint32_t *);
95
96 for (int i = 0; i < num_metrics; i++) {
97 scores[i] = consensus_election_compute_score(&metrics[i]);
98 }
99
100 // Find best and second-best
101 find_best_two(metrics, scores, num_metrics, out_best_index, out_backup_index);
102
103 SAFE_FREE(scores);
104 return ASCIICHAT_OK;
105}
#define SET_ERRNO(code,...)
uint32_t consensus_election_compute_score(const participant_metrics_t *metrics)
Compute deterministic score for a participant.
Definition election.c:14
unsigned int uint32_t
Definition common.h:62
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_MALLOC(size, cast)
Definition common.h:265
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
#define SESSION_ID_SIZE
uint8_t participant_id[SESSION_ID_SIZE]

References ASCIICHAT_OK, consensus_election_compute_score(), ERROR_INVALID_PARAM, participant_id, SAFE_FREE, SAFE_MALLOC, SESSION_ID_SIZE, and SET_ERRNO.

Referenced by consensus_election_verify(), consensus_handoff_tick(), and consensus_state_compute_election().

◆ consensus_election_compute_score()

uint32_t consensus_election_compute_score ( const participant_metrics_t * metrics)

Compute deterministic score for a participant.

Higher score = better host candidate

score = (4 - nat_tier) * 1000 // NAT tier: 0=best, 4=worst

  • (upload_kbps / 10) // Bandwidth bonus
  • (500 - rtt_ms) // Latency bonus
  • stun_probe_success_pct // Network stability

Definition at line 14 of file election.c.

14 {
15 if (!metrics || metrics->nat_tier > 4 || metrics->stun_probe_success_pct > 100)
16 return 0;
17
18 // NAT tier: 0=LAN (best), 4=TURN (worst)
19 // (4 - tier) * 1000 makes LAN score 4000, TURN score 0
20 uint32_t nat_score = (4 - metrics->nat_tier) * 1000;
21
22 // Bandwidth: higher is better
23 // Divide by 10 to keep in reasonable scale (10Mbps = +1000)
24 uint32_t bw_score = metrics->upload_kbps / 10;
25
26 // Latency: lower is better
27 // (500ms - rtt_ns) means 0ns RTT = +500, 500ms = 0, high latency = negative (but capped at 0)
28 // 500ms = 500,000,000ns
29 uint32_t rtt_score = (metrics->rtt_ns < 500 * NS_PER_MS) ? (500 - (metrics->rtt_ns / NS_PER_MS)) : 0;
30
31 // STUN probe success: 0-100%
32 uint32_t probe_score = metrics->stun_probe_success_pct;
33
34 // Total score
35 uint32_t total = nat_score + bw_score + rtt_score + probe_score;
36 return total;
37}
#define NS_PER_MS
Definition time.h:159

References NS_PER_MS.

Referenced by consensus_election_choose_hosts().

◆ consensus_election_verify()

asciichat_error_t consensus_election_verify ( const participant_metrics_t * metrics,
int num_metrics,
const uint8_t announced_host_id[SESSION_ID_SIZE],
const uint8_t announced_backup_id[SESSION_ID_SIZE],
bool * out_valid )

Verify election result matches expected scores.

Independent verification that leader's decision is correct. Used by all clients to validate election before accepting.

Definition at line 107 of file election.c.

109 {
110 if (!metrics || !announced_host_id || !announced_backup_id || !out_valid) {
111 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid verification parameters");
112 }
113
114 // Find which indices the announced IDs correspond to
115 int host_idx = -1, backup_idx = -1;
116
117 for (int i = 0; i < num_metrics; i++) {
118 if (memcmp(metrics[i].participant_id, announced_host_id, SESSION_ID_SIZE) == 0) {
119 host_idx = i;
120 }
121 if (memcmp(metrics[i].participant_id, announced_backup_id, SESSION_ID_SIZE) == 0) {
122 backup_idx = i;
123 }
124 }
125
126 // If we can't find announced IDs, result is invalid
127 if (host_idx < 0) {
128 *out_valid = false;
129 return ASCIICHAT_OK;
130 }
131
132 // Run our own election
133 int computed_host, computed_backup;
134 asciichat_error_t err = consensus_election_choose_hosts(metrics, num_metrics, &computed_host, &computed_backup);
135
136 if (err != ASCIICHAT_OK) {
137 return err;
138 }
139
140 // Check if computed result matches announced
141 uint8_t no_backup[SESSION_ID_SIZE] = {0};
142 *out_valid =
143 host_idx == computed_host && (computed_backup < 0 ? memcmp(announced_backup_id, no_backup, sizeof(no_backup)) == 0
144 : backup_idx == computed_backup);
145 return ASCIICHAT_OK;
146}
asciichat_error_t consensus_election_choose_hosts(const participant_metrics_t *metrics, int num_metrics, int *out_best_index, int *out_backup_index)
Elect best and backup host from metrics.
Definition election.c:79
unsigned char uint8_t
Definition common.h:60
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44

References ASCIICHAT_OK, consensus_election_choose_hosts(), ERROR_INVALID_PARAM, participant_id, SESSION_ID_SIZE, and SET_ERRNO.