ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
election.c
Go to the documentation of this file.
1
6#include <ascii-chat/network/consensus/election.h>
7#include <ascii-chat/common.h>
8#include <ascii-chat/util/time.h>
9#include <ascii-chat/asciichat_errno.h>
10#include <string.h>
11#include <stdint.h>
12
13uint32_t consensus_election_compute_score(const participant_metrics_t *metrics) {
14 if (!metrics)
15 return 0;
16
17 // NAT tier: 0=LAN (best), 4=TURN (worst)
18 // (4 - tier) * 1000 makes LAN score 4000, TURN score 0
19 uint32_t nat_score = (4 - metrics->nat_tier) * 1000;
20
21 // Bandwidth: higher is better
22 // Divide by 10 to keep in reasonable scale (10Mbps = +1000)
23 uint32_t bw_score = metrics->upload_kbps / 10;
24
25 // Latency: lower is better
26 // (500ms - rtt_ns) means 0ns RTT = +500, 500ms = 0, high latency = negative (but capped at 0)
27 // 500ms = 500,000,000ns
28 uint32_t rtt_score = (metrics->rtt_ns < 500 * NS_PER_MS) ? (500 - (metrics->rtt_ns / NS_PER_MS)) : 0;
29
30 // STUN probe success: 0-100%
31 uint32_t probe_score = metrics->stun_probe_success_pct;
32
33 // Total score
34 uint32_t total = nat_score + bw_score + rtt_score + probe_score;
35 return total;
36}
37
38// Helper: find index of best and second-best
39static void find_best_two(const uint32_t *scores, int count, int *best, int *second) {
40 *best = 0;
41 *second = 1;
42
43 // Handle 1-participant case (shouldn't happen, but be safe)
44 if (count < 2) {
45 *second = 0;
46 return;
47 }
48
49 // Swap if second is better than first
50 if (scores[1] > scores[0]) {
51 int tmp = *best;
52 *best = *second;
53 *second = tmp;
54 }
55
56 // Find best and second-best
57 for (int i = 2; i < count; i++) {
58 if (scores[i] > scores[*best]) {
59 *second = *best;
60 *best = i;
61 } else if (scores[i] > scores[*second]) {
62 *second = i;
63 }
64 }
65}
66
67asciichat_error_t consensus_election_choose_hosts(const participant_metrics_t *metrics, int num_metrics,
68 int *out_best_index, int *out_backup_index) {
69 if (!metrics || !out_best_index || !out_backup_index || num_metrics < 1) {
70 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid election parameters");
71 }
72
73 // Compute scores for all participants
74 uint32_t *scores = SAFE_MALLOC(sizeof(uint32_t) * num_metrics, uint32_t *);
75
76 for (int i = 0; i < num_metrics; i++) {
77 scores[i] = consensus_election_compute_score(&metrics[i]);
78 }
79
80 // Find best and second-best
81 find_best_two(scores, num_metrics, out_best_index, out_backup_index);
82
83 SAFE_FREE(scores);
84 return ASCIICHAT_OK;
85}
86
87asciichat_error_t consensus_election_verify(const participant_metrics_t *metrics, int num_metrics,
88 const uint8_t announced_host_id[16], const uint8_t announced_backup_id[16],
89 bool *out_valid) {
90 if (!metrics || !announced_host_id || !announced_backup_id || !out_valid) {
91 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid verification parameters");
92 }
93
94 // Find which indices the announced IDs correspond to
95 int host_idx = -1, backup_idx = -1;
96
97 for (int i = 0; i < num_metrics; i++) {
98 if (memcmp(metrics[i].participant_id, announced_host_id, 16) == 0) {
99 host_idx = i;
100 }
101 if (memcmp(metrics[i].participant_id, announced_backup_id, 16) == 0) {
102 backup_idx = i;
103 }
104 }
105
106 // If we can't find announced IDs, result is invalid
107 if (host_idx < 0 || backup_idx < 0) {
108 *out_valid = false;
109 return ASCIICHAT_OK;
110 }
111
112 // Run our own election
113 int computed_host, computed_backup;
114 asciichat_error_t err = consensus_election_choose_hosts(metrics, num_metrics, &computed_host, &computed_backup);
115
116 if (err != ASCIICHAT_OK) {
117 return err;
118 }
119
120 // Check if computed result matches announced
121 *out_valid = (host_idx == computed_host && backup_idx == computed_backup);
122 return ASCIICHAT_OK;
123}
uint32_t consensus_election_compute_score(const participant_metrics_t *metrics)
Definition election.c:13
asciichat_error_t consensus_election_choose_hosts(const participant_metrics_t *metrics, int num_metrics, int *out_best_index, int *out_backup_index)
Definition election.c:67
asciichat_error_t consensus_election_verify(const participant_metrics_t *metrics, int num_metrics, const uint8_t announced_host_id[16], const uint8_t announced_backup_id[16], bool *out_valid)
Definition election.c:87
uint8_t participant_id[16]