ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
nat.h File Reference

NAT quality detection for discovery mode host selection. More...

Go to the source code of this file.

Data Structures

struct  nat_quality_t
 NAT quality assessment result. More...
 

Functions

void nat_quality_init (nat_quality_t *quality)
 Initialize NAT quality structure with defaults.
 
asciichat_error_t nat_detect_quality (nat_quality_t *quality, const char *stun_server, uint16_t local_port)
 Detect NAT quality using all available methods.
 
asciichat_error_t nat_measure_bandwidth (nat_quality_t *quality, socket_t acds_socket)
 Measure upload bandwidth to ACDS server.
 
int nat_compare_quality (const nat_quality_t *ours, const nat_quality_t *theirs, bool we_are_initiator)
 Compare two NAT qualities and determine who should host.
 
void nat_quality_to_acip (const nat_quality_t *quality, const uint8_t session_id[16], const uint8_t participant_id[16], acip_nat_quality_t *out)
 Convert nat_quality_t to acip_nat_quality_t for network transmission.
 
void nat_quality_from_acip (const acip_nat_quality_t *acip, nat_quality_t *out)
 Convert acip_nat_quality_t to nat_quality_t.
 
const char * nat_type_to_string (acip_nat_type_t type)
 Get human-readable description of NAT type.
 
int nat_compute_tier (const nat_quality_t *quality)
 Compute NAT tier for host selection (0=best, 4=worst)
 

Detailed Description

NAT quality detection for discovery mode host selection.

Detects NAT characteristics to determine the best host candidate. Uses STUN, UPnP/NAT-PMP, and bandwidth measurements.

Definition in file nat.h.

Function Documentation

◆ nat_compare_quality()

int nat_compare_quality ( const nat_quality_t *  ours,
const nat_quality_t *  theirs,
bool  we_are_initiator 
)

Compare two NAT qualities and determine who should host.

Algorithm is deterministic - both sides get the same result. Uses NAT tier priority with bandwidth as tiebreaker.

Parameters
oursOur NAT quality
theirsPeer's NAT quality
we_are_initiatorTrue if we started the session
Returns
-1 = we host, 0 = equal (initiator wins), 1 = they host

Definition at line 54 of file nat.c.

54 {
55 if (!ours || !theirs) {
56 return we_are_initiator ? -1 : 1;
57 }
58
59 int our_tier = nat_compute_tier(ours);
60 int their_tier = nat_compute_tier(theirs);
61
62 // Check for bandwidth override: massive bandwidth advantage can override NAT tier
63 if (ours->upload_kbps > 0 && theirs->upload_kbps > 0) {
64 if (ours->upload_kbps >= theirs->upload_kbps * BANDWIDTH_OVERRIDE_RATIO) {
65 log_debug("NAT compare: we win by bandwidth override (%u vs %u kbps)", ours->upload_kbps, theirs->upload_kbps);
66 return -1;
67 }
68 if (theirs->upload_kbps >= ours->upload_kbps * BANDWIDTH_OVERRIDE_RATIO) {
69 log_debug("NAT compare: they win by bandwidth override (%u vs %u kbps)", theirs->upload_kbps, ours->upload_kbps);
70 return 1;
71 }
72 }
73
74 // Compare NAT tiers (lower = better)
75 if (our_tier < their_tier) {
76 log_debug("NAT compare: we win by tier (%d vs %d)", our_tier, their_tier);
77 return -1;
78 }
79 if (our_tier > their_tier) {
80 log_debug("NAT compare: they win by tier (%d vs %d)", our_tier, their_tier);
81 return 1;
82 }
83
84 // Same tier - bandwidth is tiebreaker
85 if (ours->upload_kbps > theirs->upload_kbps) {
86 log_debug("NAT compare: we win by bandwidth (%u vs %u kbps)", ours->upload_kbps, theirs->upload_kbps);
87 return -1;
88 }
89 if (ours->upload_kbps < theirs->upload_kbps) {
90 log_debug("NAT compare: they win by bandwidth (%u vs %u kbps)", theirs->upload_kbps, ours->upload_kbps);
91 return 1;
92 }
93
94 // Same bandwidth - latency is tiebreaker
95 if (ours->rtt_to_acds_ns < theirs->rtt_to_acds_ns) {
96 log_debug("NAT compare: we win by latency (%lu ns vs %lu ns)", ours->rtt_to_acds_ns, theirs->rtt_to_acds_ns);
97 return -1;
98 }
99 if (ours->rtt_to_acds_ns > theirs->rtt_to_acds_ns) {
100 log_debug("NAT compare: they win by latency (%lu ns vs %lu ns)", theirs->rtt_to_acds_ns, ours->rtt_to_acds_ns);
101 return 1;
102 }
103
104 // Everything equal - initiator hosts
105 log_debug("NAT compare: equal quality, initiator wins (we_are_initiator=%d)", we_are_initiator);
106 return we_are_initiator ? -1 : 1;
107}
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
int nat_compute_tier(const nat_quality_t *quality)
Compute NAT tier for host selection (0=best, 4=worst)
Definition nat.c:39
#define BANDWIDTH_OVERRIDE_RATIO
Definition nat.c:30
uint32_t upload_kbps
Upload bandwidth in Kbps.
Definition nat.h:39
uint64_t rtt_to_acds_ns
Latency to ACDS in nanoseconds.
Definition nat.h:41

References BANDWIDTH_OVERRIDE_RATIO, log_debug, nat_compute_tier(), nat_quality_t::rtt_to_acds_ns, and nat_quality_t::upload_kbps.

Referenced by negotiate_determine_result(), and negotiate_elect_future_host().

◆ nat_compute_tier()

int nat_compute_tier ( const nat_quality_t *  quality)

Compute NAT tier for host selection (0=best, 4=worst)

Parameters
qualityNAT quality
Returns
Tier value

Definition at line 39 of file nat.c.

39 {
40 if (!quality)
41 return 4;
42
43 if (quality->lan_reachable)
44 return 0; // LAN - best
45 if (quality->has_public_ip)
46 return 1; // Public IP
47 if (quality->upnp_available)
48 return 2; // UPnP mapping
49 if (quality->nat_type <= ACIP_NAT_TYPE_RESTRICTED)
50 return 3; // STUN hole-punchable
51 return 4; // TURN relay required
52}
@ ACIP_NAT_TYPE_RESTRICTED
Address-restricted cone NAT.
Definition acds.h:828
bool lan_reachable
Same subnet as peer.
Definition nat.h:33
acip_nat_type_t nat_type
NAT classification.
Definition nat.h:32
bool has_public_ip
STUN reflexive == local IP.
Definition nat.h:29
bool upnp_available
UPnP/NAT-PMP mapping succeeded.
Definition nat.h:30

References ACIP_NAT_TYPE_RESTRICTED, nat_quality_t::has_public_ip, nat_quality_t::lan_reachable, nat_quality_t::nat_type, and nat_quality_t::upnp_available.

Referenced by __attribute__(), discovery_session_process(), nat_compare_quality(), nat_detect_quality(), and negotiate_receive_peer_quality().

◆ nat_detect_quality()

asciichat_error_t nat_detect_quality ( nat_quality_t *  quality,
const char *  stun_server,
uint16_t  local_port 
)

Detect NAT quality using all available methods.

Runs STUN probe, UPnP check, and gathers ICE candidates in parallel. Results are stored in the provided nat_quality_t structure.

Parameters
qualityOutput structure for results
stun_serverSTUN server URL (e.g., "stun:stun.l.google.com:19302")
local_portLocal port to use for detection
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 293 of file nat.c.

293 {
294 if (!quality) {
295 return SET_ERRNO(ERROR_INVALID_PARAM, "quality is NULL");
296 }
297
298 nat_quality_init(quality);
299 log_info("Starting NAT quality detection (local_port=%u)", local_port);
300
301 // Try UPnP/NAT-PMP first
302 nat_upnp_context_t *upnp = NULL;
303 asciichat_error_t upnp_result = nat_upnp_open(local_port, "ascii-chat", &upnp);
304 if (upnp_result == ASCIICHAT_OK && upnp && nat_upnp_is_active(upnp)) {
305 quality->upnp_available = true;
306 quality->upnp_mapped_port = upnp->mapped_port;
307
308 char addr_buf[64];
309 if (nat_upnp_get_address(upnp, addr_buf, sizeof(addr_buf)) == ASCIICHAT_OK) {
310 // Parse IP:port
311 char *colon = strchr(addr_buf, ':');
312 if (colon) {
313 size_t ip_len = (size_t)(colon - addr_buf);
314 if (ip_len < sizeof(quality->public_address)) {
315 memcpy(quality->public_address, addr_buf, ip_len);
316 quality->public_address[ip_len] = '\0';
317 }
318 } else {
319 SAFE_STRNCPY(quality->public_address, addr_buf, sizeof(quality->public_address));
320 }
321 }
322
323 log_info("UPnP: mapped port %u, external IP %s", quality->upnp_mapped_port, quality->public_address);
324 quality->nat_type = ACIP_NAT_TYPE_FULL_CONE; // UPnP implies at least full-cone equivalent
325 } else {
326 log_debug("UPnP: not available or mapping failed");
327 }
328
329 // Try STUN probe if provided and UPnP didn't succeed
330 if (!quality->upnp_available && stun_server && stun_server[0]) {
331 asciichat_error_t stun_result = nat_stun_probe(quality, stun_server, local_port);
332 if (stun_result == ASCIICHAT_OK) {
333 // Successfully got reflexive address via STUN
334 quality->has_srflx_candidates = true;
335
336 // If reflexive address is not private range, we have public IP
337 // Private ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
338 if (quality->public_address[0] && strncmp(quality->public_address, "10.", 3) != 0 &&
339 strncmp(quality->public_address, "172.16.", 7) != 0 && strncmp(quality->public_address, "192.168.", 8) != 0) {
340 quality->has_public_ip = true;
341 quality->nat_type = ACIP_NAT_TYPE_OPEN;
342 } else {
343 // Reflexive address is still private - behind symmetric NAT
345 }
346 } else {
347 log_debug("STUN probe failed, falling back to symmetric NAT assumption");
348 }
349 }
350
351 // Set ICE candidate flags based on what we found
352 quality->has_host_candidates = true; // We always have local IP
353 quality->has_srflx_candidates = quality->upnp_available || quality->has_public_ip || quality->has_srflx_candidates;
354
355 // Check if TURN relay servers are available (configured via options or ACDS)
356 const options_t *opts = options_get();
357 const char *turn_servers = opts ? opts->turn_servers : NULL;
358 quality->has_relay_candidates = (turn_servers && turn_servers[0] != '\0');
359 if (quality->has_relay_candidates) {
360 log_debug("TURN relay servers configured: %s", turn_servers);
361 }
362
363 quality->detection_complete = true;
364 log_info("NAT detection complete: tier=%d, upnp=%d, has_public_ip=%d, nat_type=%s", nat_compute_tier(quality),
365 quality->upnp_available, quality->has_public_ip, nat_type_to_string(quality->nat_type));
366
367 if (upnp) {
368 // Keep UPnP mapping active for the session
369 // Don't close it here - caller is responsible for cleanup
370 }
371
372 return ASCIICHAT_OK;
373}
@ ACIP_NAT_TYPE_SYMMETRIC
Symmetric NAT (hardest, requires TURN)
Definition acds.h:830
@ ACIP_NAT_TYPE_FULL_CONE
Full cone NAT (easiest to traverse)
Definition acds.h:827
@ ACIP_NAT_TYPE_OPEN
No NAT (public IP)
Definition acds.h:826
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:414
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_INVALID_PARAM
#define log_info(...)
Log an INFO message.
Definition log/log.h:561
const options_t * options_get(void)
Get current options (lock-free read)
Definition rcu.c:496
void nat_quality_init(nat_quality_t *quality)
Initialize NAT quality structure with defaults.
Definition nat.c:32
const char * nat_type_to_string(acip_nat_type_t type)
Get human-readable description of NAT type.
Definition nat.c:526
bool detection_complete
All probes finished.
Definition nat.h:51
bool has_host_candidates
Local IP reachable.
Definition nat.h:46
bool has_srflx_candidates
STUN worked.
Definition nat.h:47
char public_address[64]
Public IP address.
Definition nat.h:35
bool has_relay_candidates
TURN available.
Definition nat.h:48
uint16_t upnp_mapped_port
Mapped external port (if upnp_available)
Definition nat.h:31
Handle to UPnP context.
Definition upnp.h:25
uint16_t mapped_port
External port that was mapped (may differ from internal)
Definition upnp.h:27
Consolidated options structure.
char turn_servers[256]
ACDS: Comma-separated list of TURN server URLs.
bool nat_upnp_is_active(const nat_upnp_context_t *ctx)
Check if port mapping is still active.
Definition upnp.c:291
asciichat_error_t nat_upnp_open(uint16_t internal_port, const char *description, nat_upnp_context_t **ctx)
Discover and open port via UPnP.
Definition upnp.c:236
asciichat_error_t nat_upnp_get_address(const nat_upnp_context_t *ctx, char *addr, size_t addr_len)
Get the public address (IP:port) for advertising to clients.
Definition upnp.c:310

References ACIP_NAT_TYPE_FULL_CONE, ACIP_NAT_TYPE_OPEN, ACIP_NAT_TYPE_SYMMETRIC, ASCIICHAT_OK, nat_quality_t::detection_complete, ERROR_INVALID_PARAM, nat_quality_t::has_host_candidates, nat_quality_t::has_public_ip, nat_quality_t::has_relay_candidates, nat_quality_t::has_srflx_candidates, log_debug, log_info, nat_upnp_context::mapped_port, nat_compute_tier(), nat_quality_init(), nat_quality_t::nat_type, nat_type_to_string(), nat_upnp_get_address(), nat_upnp_is_active(), nat_upnp_open(), options_get(), nat_quality_t::public_address, SAFE_STRNCPY, SET_ERRNO, options_state::turn_servers, nat_quality_t::upnp_available, and nat_quality_t::upnp_mapped_port.

Referenced by negotiate_start_detection().

◆ nat_measure_bandwidth()

asciichat_error_t nat_measure_bandwidth ( nat_quality_t *  quality,
socket_t  acds_socket 
)

Measure upload bandwidth to ACDS server.

Uploads a test payload and measures throughput.

Parameters
qualityStructure to update with bandwidth results
acds_socketConnected socket to ACDS
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 375 of file nat.c.

375 {
376 if (!quality) {
377 return SET_ERRNO(ERROR_INVALID_PARAM, "quality is NULL");
378 }
379 if (acds_socket == INVALID_SOCKET_VALUE) {
380 return SET_ERRNO(ERROR_INVALID_PARAM, "invalid socket");
381 }
382
383 // Prepare bandwidth test packet
384 acip_bandwidth_test_t test_msg = {0};
385 memset(test_msg.session_id, 0, sizeof(test_msg.session_id)); // Anonymous test
386 memset(test_msg.participant_id, 0, sizeof(test_msg.participant_id));
387 test_msg.test_size_bytes = 65536; // 64KB test payload
388 test_msg.client_send_time_ns = time_get_ns();
389
390 // Send BANDWIDTH_TEST packet
391 asciichat_error_t result = packet_send(acds_socket, PACKET_TYPE_ACIP_BANDWIDTH_TEST, &test_msg, sizeof(test_msg));
392 if (result != ASCIICHAT_OK) {
393 log_warn("Failed to send bandwidth test packet");
394 return result;
395 }
396
397 // Send test payload (64KB of data)
398 uint8_t *test_data = SAFE_MALLOC(test_msg.test_size_bytes, uint8_t *);
399 if (!test_data) {
400 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate bandwidth test payload");
401 }
402 memset(test_data, 0xAA, test_msg.test_size_bytes); // Fill with pattern
403
404 ssize_t sent = send(acds_socket, (const char *)test_data, test_msg.test_size_bytes, 0);
405 SAFE_FREE(test_data);
406
407 if (sent != (ssize_t)test_msg.test_size_bytes) {
408 log_warn("Failed to send bandwidth test payload: sent=%zd, expected=%u", sent, test_msg.test_size_bytes);
409 return SET_ERRNO(ERROR_NETWORK, "Bandwidth test payload send failed");
410 }
411
412 log_debug("Sent bandwidth test with %u bytes", test_msg.test_size_bytes);
413
414 // Set socket timeout for response (5 seconds)
415 if (socket_set_timeout(acds_socket, 5 * NS_PER_SEC_INT) != 0) {
416 log_warn("Failed to set socket timeout for bandwidth test");
417 return SET_ERRNO(ERROR_NETWORK, "Failed to set socket timeout");
418 }
419
420 // Wait for BANDWIDTH_RESULT response
421 packet_type_t response_type;
422 void *response_data = NULL;
423 size_t response_len = 0;
424
425 result = packet_receive(acds_socket, &response_type, &response_data, &response_len);
426
427 if (result != ASCIICHAT_OK) {
428 log_warn("Bandwidth test timeout or receive failed");
429 return SET_ERRNO(ERROR_NETWORK_TIMEOUT, "No bandwidth test response from ACDS");
430 }
431
432 if (response_type != PACKET_TYPE_ACIP_BANDWIDTH_RESULT) {
433 POOL_FREE(response_data, response_len);
434 log_warn("Unexpected packet type %d (expected BANDWIDTH_RESULT)", response_type);
435 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Wrong packet type in bandwidth test response");
436 }
437
438 if (response_len != sizeof(acip_bandwidth_result_t)) {
439 POOL_FREE(response_data, response_len);
440 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid bandwidth result size");
441 }
442
443 // Parse results
444 acip_bandwidth_result_t *results = (acip_bandwidth_result_t *)response_data;
445 quality->upload_kbps = results->measured_upload_kbps;
446 quality->download_kbps = results->measured_download_kbps;
447 quality->rtt_to_acds_ns = results->rtt_ns;
448 quality->jitter_ns = results->jitter_ns;
449 quality->packet_loss_pct = results->packet_loss_pct;
450
451 POOL_FREE(response_data, response_len);
452
453 log_debug("Bandwidth measurement: upload=%u kbps, download=%u kbps, rtt=%lu ns", quality->upload_kbps,
454 quality->download_kbps, quality->rtt_to_acds_ns);
455
456 return ASCIICHAT_OK;
457}
acip_bandwidth_test_t
Definition acds.h:1020
acip_bandwidth_result_t
Definition acds.h:1037
#define POOL_FREE(data, size)
#define SAFE_FREE(ptr)
Definition common.h:376
#define SAFE_MALLOC(size, cast)
Definition common.h:264
unsigned char uint8_t
Definition common.h:56
@ ERROR_NETWORK
Definition error_codes.h:77
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:81
@ ERROR_MEMORY
Definition error_codes.h:56
@ ERROR_NETWORK_TIMEOUT
Definition error_codes.h:80
#define log_warn(...)
Log a WARN message.
Definition log/log.h:574
uint64_t time_get_ns(void)
Get current monotonic time in nanoseconds.
Definition util/time.c:108
#define NS_PER_SEC_INT
Definition time.h:157
asciichat_error_t packet_receive(socket_t sockfd, packet_type_t *type, void **data, size_t *len)
Receive a packet with proper header validation and CRC32 checking.
Definition packet.c:352
asciichat_error_t packet_send(socket_t sockfd, packet_type_t type, const void *data, size_t len)
Send a packet with proper header and CRC32.
Definition packet.c:292
packet_type_t
Network protocol packet type enumeration.
Definition packet.h:286
@ PACKET_TYPE_ACIP_BANDWIDTH_TEST
Bandwidth test request (Client -> ACDS)
Definition packet.h:479
@ PACKET_TYPE_ACIP_BANDWIDTH_RESULT
Bandwidth test results (ACDS -> Client)
Definition packet.h:481
int socket_set_timeout(socket_t sock, uint64_t timeout_ns)
Set socket receive and send timeouts.
Definition socket.c:82
#define INVALID_SOCKET_VALUE
Invalid socket value (POSIX: -1)
Definition socket.h:278
uint32_t download_kbps
Download bandwidth in Kbps.
Definition nat.h:40
uint8_t packet_loss_pct
Packet loss percentage.
Definition nat.h:43
uint64_t jitter_ns
Packet timing variance in nanoseconds.
Definition nat.h:42

References acip_bandwidth_result_t, acip_bandwidth_test_t, ASCIICHAT_OK, nat_quality_t::download_kbps, ERROR_INVALID_PARAM, ERROR_MEMORY, ERROR_NETWORK, ERROR_NETWORK_PROTOCOL, ERROR_NETWORK_TIMEOUT, INVALID_SOCKET_VALUE, nat_quality_t::jitter_ns, log_debug, log_warn, NS_PER_SEC_INT, nat_quality_t::packet_loss_pct, packet_receive(), packet_send(), PACKET_TYPE_ACIP_BANDWIDTH_RESULT, PACKET_TYPE_ACIP_BANDWIDTH_TEST, POOL_FREE, nat_quality_t::rtt_to_acds_ns, SAFE_FREE, SAFE_MALLOC, SET_ERRNO, socket_set_timeout(), time_get_ns(), and nat_quality_t::upload_kbps.

◆ nat_quality_from_acip()

void nat_quality_from_acip ( const acip_nat_quality_t *  acip,
nat_quality_t *  out 
)

Convert acip_nat_quality_t to nat_quality_t.

Parameters
acipACIP message structure
outOutput local NAT quality structure

Definition at line 497 of file nat.c.

497 {
498 if (!acip || !out)
499 return;
500
501 nat_quality_init(out);
502
503 out->has_public_ip = acip->has_public_ip != 0;
504 out->upnp_available = acip->upnp_available != 0;
505 out->upnp_mapped_port = ((uint16_t)acip->upnp_mapped_port[0] << 8) | acip->upnp_mapped_port[1];
506 out->nat_type = (acip_nat_type_t)acip->stun_nat_type;
507 out->lan_reachable = acip->lan_reachable != 0;
508 out->stun_latency_ns = acip->stun_latency_ns;
509
510 out->upload_kbps = acip->upload_kbps;
511 out->download_kbps = acip->download_kbps;
512 out->rtt_to_acds_ns = acip->rtt_to_acds_ns;
513 out->jitter_ns = acip->jitter_ns;
514 out->packet_loss_pct = acip->packet_loss_pct;
515
516 SAFE_STRNCPY(out->public_address, acip->public_address, sizeof(out->public_address));
517 out->public_port = acip->public_port;
518
519 out->has_host_candidates = (acip->ice_candidate_types & 1) != 0;
520 out->has_srflx_candidates = (acip->ice_candidate_types & 2) != 0;
521 out->has_relay_candidates = (acip->ice_candidate_types & 4) != 0;
522
523 out->detection_complete = true;
524}
acip_nat_type_t
NAT type classification for host selection.
Definition acds.h:825
unsigned short uint16_t
Definition common.h:57
uint64_t stun_latency_ns
RTT to STUN server in nanoseconds.
Definition nat.h:34
uint16_t public_port
Public port.
Definition nat.h:36

References nat_quality_t::detection_complete, nat_quality_t::download_kbps, nat_quality_t::has_host_candidates, nat_quality_t::has_public_ip, nat_quality_t::has_relay_candidates, nat_quality_t::has_srflx_candidates, nat_quality_t::jitter_ns, nat_quality_t::lan_reachable, nat_quality_init(), nat_quality_t::nat_type, nat_quality_t::packet_loss_pct, nat_quality_t::public_address, nat_quality_t::public_port, nat_quality_t::rtt_to_acds_ns, SAFE_STRNCPY, nat_quality_t::stun_latency_ns, nat_quality_t::upload_kbps, nat_quality_t::upnp_available, and nat_quality_t::upnp_mapped_port.

Referenced by __attribute__(), negotiate_elect_future_host(), and negotiate_receive_peer_quality().

◆ nat_quality_init()

void nat_quality_init ( nat_quality_t *  quality)

Initialize NAT quality structure with defaults.

Parameters
qualityStructure to initialize

Definition at line 32 of file nat.c.

32 {
33 if (!quality)
34 return;
35 memset(quality, 0, sizeof(nat_quality_t));
36 quality->nat_type = ACIP_NAT_TYPE_SYMMETRIC; // Assume worst case
37}
NAT quality assessment result.
Definition nat.h:27

References ACIP_NAT_TYPE_SYMMETRIC, and nat_quality_t::nat_type.

Referenced by nat_detect_quality(), nat_quality_from_acip(), and negotiate_init().

◆ nat_quality_to_acip()

void nat_quality_to_acip ( const nat_quality_t *  quality,
const uint8_t  session_id[16],
const uint8_t  participant_id[16],
acip_nat_quality_t *  out 
)

Convert nat_quality_t to acip_nat_quality_t for network transmission.

Parameters
qualityLocal NAT quality
session_idSession UUID
participant_idParticipant UUID
outOutput ACIP message structure

Definition at line 459 of file nat.c.

460 {
461 if (!quality || !out)
462 return;
463
464 memset(out, 0, sizeof(acip_nat_quality_t));
465
466 if (session_id)
467 memcpy(out->session_id, session_id, 16);
468 if (participant_id)
469 memcpy(out->participant_id, participant_id, 16);
470
471 out->has_public_ip = quality->has_public_ip ? 1 : 0;
472 out->upnp_available = quality->upnp_available ? 1 : 0;
473 out->upnp_mapped_port[0] = (uint8_t)(quality->upnp_mapped_port >> 8);
474 out->upnp_mapped_port[1] = (uint8_t)(quality->upnp_mapped_port & 0xFF);
475 out->stun_nat_type = (uint8_t)quality->nat_type;
476 out->lan_reachable = quality->lan_reachable ? 1 : 0;
477 out->stun_latency_ns = quality->stun_latency_ns;
478
479 out->upload_kbps = quality->upload_kbps;
480 out->download_kbps = quality->download_kbps;
481 out->rtt_to_acds_ns = quality->rtt_to_acds_ns;
482 out->jitter_ns = quality->jitter_ns;
483 out->packet_loss_pct = quality->packet_loss_pct;
484
485 SAFE_STRNCPY(out->public_address, quality->public_address, sizeof(out->public_address));
486 out->public_port = quality->public_port;
487
488 out->ice_candidate_types = 0;
489 if (quality->has_host_candidates)
490 out->ice_candidate_types |= 1;
491 if (quality->has_srflx_candidates)
492 out->ice_candidate_types |= 2;
493 if (quality->has_relay_candidates)
494 out->ice_candidate_types |= 4;
495}
acip_nat_quality_t
Definition acds.h:891
uint8_t session_id[16]
uint8_t participant_id[16]

References acip_nat_quality_t, nat_quality_t::download_kbps, nat_quality_t::has_host_candidates, nat_quality_t::has_public_ip, nat_quality_t::has_relay_candidates, nat_quality_t::has_srflx_candidates, nat_quality_t::jitter_ns, nat_quality_t::lan_reachable, nat_quality_t::nat_type, nat_quality_t::packet_loss_pct, participant_id, nat_quality_t::public_address, nat_quality_t::public_port, nat_quality_t::rtt_to_acds_ns, SAFE_STRNCPY, session_id, nat_quality_t::stun_latency_ns, nat_quality_t::upload_kbps, nat_quality_t::upnp_available, and nat_quality_t::upnp_mapped_port.

◆ nat_type_to_string()

const char * nat_type_to_string ( acip_nat_type_t  type)

Get human-readable description of NAT type.

Parameters
typeNAT type
Returns
String description

Definition at line 526 of file nat.c.

526 {
527 switch (type) {
529 return "Open (Public IP)";
531 return "Full Cone";
533 return "Restricted Cone";
535 return "Port Restricted";
537 return "Symmetric";
538 default:
539 return "Unknown";
540 }
541}
@ ACIP_NAT_TYPE_PORT_RESTRICTED
Port-restricted cone NAT.
Definition acds.h:829

References ACIP_NAT_TYPE_FULL_CONE, ACIP_NAT_TYPE_OPEN, ACIP_NAT_TYPE_PORT_RESTRICTED, ACIP_NAT_TYPE_RESTRICTED, and ACIP_NAT_TYPE_SYMMETRIC.

Referenced by nat_detect_quality().