ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
metrics.c
Go to the documentation of this file.
1
6#include <ascii-chat/network/consensus/metrics.h>
7#include <ascii-chat/common.h>
8#include <ascii-chat/util/endian.h>
9#include <ascii-chat/util/time.h>
10#include <ascii-chat/asciichat_errno.h>
11#include <string.h>
12#include <stdio.h>
13
25
29#define DEFAULT_BANDWIDTH_KBPS 50000
30
34#define DEFAULT_RTT_MS 25
35
39#define NUM_STUN_PROBES 10
40
49static uint8_t measure_stun_probe_success(void) {
50 // TODO: Implement actual STUN probing in future
51 // For now, return a reasonable default (90% success)
52 // In production, this would:
53 // 1. Send NUM_STUN_PROBES STUN Binding Request packets
54 // 2. Count successful responses
55 // 3. Return (successes * 100) / NUM_STUN_PROBES
56 return 90;
57}
58
72__attribute__((unused)) static uint8_t nat_type_to_tier(int nat_type) {
73 // ACIP_NAT_TYPE_* enum values:
74 // 0 = Open (OPEN = no NAT, essentially LAN)
75 // 1 = Full cone (best NAT)
76 // 2 = Address-restricted
77 // 3 = Port-restricted
78 // 4 = Symmetric (worst NAT)
79
80 if (nat_type < 0 || nat_type > 4) {
81 return 4; // Default to worst case
82 }
83 return (uint8_t)nat_type;
84}
85
86asciichat_error_t consensus_metrics_measure(const uint8_t my_id[16], participant_metrics_t *out_metrics) {
87 if (!my_id || !out_metrics) {
88 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters to consensus_metrics_measure");
89 }
90
91 // Initialize metrics structure
92 memset(out_metrics, 0, sizeof(*out_metrics));
93
94 // Copy participant ID
95 memcpy(out_metrics->participant_id, my_id, 16);
96
97 // NAT tier: Default to 1 (Public IP, no NAT needed)
98 // TODO: In production, query NAT detection module
99 out_metrics->nat_tier = 1;
100
101 // Upload bandwidth: Default 50 Mbps
102 out_metrics->upload_kbps = DEFAULT_BANDWIDTH_KBPS;
103
104 // RTT: Default 25ms (25,000,000 nanoseconds)
105 out_metrics->rtt_ns = DEFAULT_RTT_MS * NS_PER_MS;
106
107 // STUN probe success rate: Measure by sending probes
108 out_metrics->stun_probe_success_pct = measure_stun_probe_success();
109
110 // Public address and port: Placeholder values
111 snprintf(out_metrics->public_address, sizeof(out_metrics->public_address), "127.0.0.1");
112 out_metrics->public_port = 27224;
113
114 // Connection type: Default to direct
115 out_metrics->connection_type = 0; // Direct connection
116
117 // Measurement time: Current time in nanoseconds
118 out_metrics->measurement_time_ns = time_get_realtime_ns();
119
120 // Measurement window: 1 second in nanoseconds
121 out_metrics->measurement_window_ns = 1 * NS_PER_SEC;
122
123 return ASCIICHAT_OK;
124}
125
126asciichat_error_t consensus_metrics_to_wire(const participant_metrics_t *metrics, participant_metrics_t *out_wire) {
127 if (!metrics || !out_wire) {
128 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters to consensus_metrics_to_wire");
129 }
130
131 // Copy entire structure first
132 memcpy(out_wire, metrics, sizeof(*out_wire));
133
134 // Convert multi-byte fields to network byte order
135 out_wire->upload_kbps = endian_pack_u32(metrics->upload_kbps);
136 out_wire->rtt_ns = endian_pack_u32(metrics->rtt_ns);
137 out_wire->public_port = endian_pack_u16(metrics->public_port);
138 out_wire->measurement_time_ns = endian_pack_u64(metrics->measurement_time_ns);
139 out_wire->measurement_window_ns = endian_pack_u64(metrics->measurement_window_ns);
140
141 return ASCIICHAT_OK;
142}
143
144asciichat_error_t consensus_metrics_from_wire(const participant_metrics_t *wire_metrics,
145 participant_metrics_t *out_metrics) {
146 if (!wire_metrics || !out_metrics) {
147 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters to consensus_metrics_from_wire");
148 }
149
150 // Copy entire structure first
151 memcpy(out_metrics, wire_metrics, sizeof(*out_metrics));
152
153 // Convert multi-byte fields from network byte order
154 out_metrics->upload_kbps = endian_unpack_u32(wire_metrics->upload_kbps);
155 out_metrics->rtt_ns = endian_unpack_u32(wire_metrics->rtt_ns);
156 out_metrics->public_port = endian_unpack_u16(wire_metrics->public_port);
157 out_metrics->measurement_time_ns = endian_unpack_u64(wire_metrics->measurement_time_ns);
158 out_metrics->measurement_window_ns = endian_unpack_u64(wire_metrics->measurement_window_ns);
159
160 return ASCIICHAT_OK;
161}
162
164 if (!out_collection) {
165 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid output parameter");
166 }
167
168 consensus_metrics_collection_t *collection = SAFE_MALLOC(sizeof(*collection), consensus_metrics_collection_t *);
169 memset(collection, 0, sizeof(*collection));
170
171 collection->capacity = 10; // Start with capacity for 10 participants
172 collection->metrics = SAFE_MALLOC(collection->capacity * sizeof(participant_metrics_t), participant_metrics_t *);
173 collection->count = 0;
174
175 *out_collection = collection;
176 return ASCIICHAT_OK;
177}
178
180 const participant_metrics_t *metrics) {
181 if (!collection || !metrics) {
182 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters to collection_add");
183 }
184
185 // Resize if needed
186 if (collection->count >= collection->capacity) {
187 int new_capacity = collection->capacity * 2;
188 participant_metrics_t *new_metrics =
189 SAFE_MALLOC(new_capacity * sizeof(participant_metrics_t), participant_metrics_t *);
190
191 if (!new_metrics) {
192 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate metrics array");
193 }
194
195 // Copy existing metrics
196 if (collection->count > 0 && collection->metrics) {
197 memcpy(new_metrics, collection->metrics, collection->count * sizeof(participant_metrics_t));
198 SAFE_FREE(collection->metrics);
199 }
200
201 collection->metrics = new_metrics;
202 collection->capacity = new_capacity;
203 }
204
205 // Add new metrics
206 if (!collection->metrics) {
207 return SET_ERRNO(ERROR_MEMORY, "Collection metrics array is NULL");
208 }
209
210 memcpy(&collection->metrics[collection->count], metrics, sizeof(*metrics));
211 collection->count++;
212
213 return ASCIICHAT_OK;
214}
215
217 const participant_metrics_t **out_metrics, int *out_count) {
218 if (!collection || !out_metrics || !out_count) {
219 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters to collection_get");
220 }
221
222 *out_metrics = collection->metrics;
223 *out_count = collection->count;
224
225 return ASCIICHAT_OK;
226}
227
229 if (!collection) {
230 return;
231 }
232
233 if (collection->metrics) {
234 SAFE_FREE(collection->metrics);
235 }
236
237 SAFE_FREE(collection);
238}
asciichat_error_t consensus_metrics_from_wire(const participant_metrics_t *wire_metrics, participant_metrics_t *out_metrics)
Definition metrics.c:144
__attribute__((unused))
Definition metrics.c:72
asciichat_error_t consensus_metrics_to_wire(const participant_metrics_t *metrics, participant_metrics_t *out_wire)
Definition metrics.c:126
asciichat_error_t consensus_metrics_measure(const uint8_t my_id[16], participant_metrics_t *out_metrics)
Definition metrics.c:86
void consensus_metrics_collection_destroy(consensus_metrics_collection_t *collection)
Definition metrics.c:228
#define DEFAULT_RTT_MS
Definition metrics.c:34
asciichat_error_t consensus_metrics_collection_add(consensus_metrics_collection_t *collection, const participant_metrics_t *metrics)
Definition metrics.c:179
struct consensus_metrics_collection consensus_metrics_collection_t
Metrics collection structure for participant quality measurements.
#define DEFAULT_BANDWIDTH_KBPS
Definition metrics.c:29
asciichat_error_t consensus_metrics_collection_get(const consensus_metrics_collection_t *collection, const participant_metrics_t **out_metrics, int *out_count)
Definition metrics.c:216
asciichat_error_t consensus_metrics_collection_create(consensus_metrics_collection_t **out_collection)
Definition metrics.c:163
Metrics collection structure for participant quality measurements.
Definition metrics.c:20
participant_metrics_t * metrics
Array of participant metrics.
Definition metrics.c:21
int count
Number of participants.
Definition metrics.c:22
int capacity
Allocated capacity.
Definition metrics.c:23
uint64_t time_get_realtime_ns(void)
Definition util/time.c:59