ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
Stun

Functions

struct __attribute__ ((packed))
 STUN server configuration.
 
int stun_servers_parse (const char *csv_servers, const char *default_csv, stun_server_t *out_servers, int max_count)
 Parse comma-separated STUN server URLs into stun_server_t array.
 

Variables

 stun_server_t
 

STUN Protocol Constants

#define STUN_DEFAULT_PORT   3478
 Standard STUN port (RFC 5389)
 
#define STUN_TLS_DEFAULT_PORT   5349
 STUN over TLS port (RFC 5389)
 
#define STUN_MAX_URL_LEN   64
 Maximum STUN URL length.
 

Detailed Description

This module defines STUN server configuration structures for WebRTC connectivity. STUN servers help clients discover their public IP addresses and port mappings when behind NAT.

RFC 5389: Session Traversal Utilities for NAT (STUN) RFC 8489: Session Traversal Utilities for NAT (STUN) - updated

STUN SERVER ROLE:

USAGE IN ACDS:

Note
All structures are packed with attribute((packed)) for wire format
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026
Version
1.0

Macro Definition Documentation

◆ STUN_DEFAULT_PORT

#define STUN_DEFAULT_PORT   3478

#include <stun.h>

Standard STUN port (RFC 5389)

Definition at line 84 of file stun.h.

◆ STUN_MAX_URL_LEN

#define STUN_MAX_URL_LEN   64

#include <stun.h>

Maximum STUN URL length.

Definition at line 90 of file stun.h.

◆ STUN_TLS_DEFAULT_PORT

#define STUN_TLS_DEFAULT_PORT   5349

#include <stun.h>

STUN over TLS port (RFC 5389)

Definition at line 87 of file stun.h.

Function Documentation

◆ __attribute__()

struct __attribute__ ( (packed)  )

#include <stun.h>

STUN server configuration.

Used in ACDS SESSION_CREATED response to provide WebRTC connectivity information.

Protocol Format:

  • host_len: 1 byte (length of host string)
  • host: 64 bytes (null-terminated STUN URL)

URL Format Examples:

  • stun:discovery.ascii.chat:3478 (standard port)
  • stun:stun.l.google.com:19302 (Google public STUN)
  • stun:stun.example.com:5349 (custom port)

Wire Format (65 bytes total):

+----------+----------------------------------------+
| host_len | host[64] |
+----------+----------------------------------------+
| 1 byte | 64 bytes |
+----------+----------------------------------------+

< Length of host string (actual URL length)

< STUN server URL (e.g., "stun:discovery.ascii.chat:3478")

Definition at line 1 of file stun.h.

72 {
73 uint8_t host_len;
74 char host[64];
unsigned char uint8_t
Definition common.h:56
stun_server_t
Definition stun.h:75

◆ stun_servers_parse()

int stun_servers_parse ( const char *  csv_servers,
const char *  default_csv,
stun_server_t *  out_servers,
int  max_count 
)

#include <stun.h>

Parse comma-separated STUN server URLs into stun_server_t array.

Parses a comma-separated string of STUN server URLs (e.g., "stun:server1:3478,stun:server2:3478") into an array of stun_server_t structs. If the input string is empty or NULL, uses the default endpoints from the options system.

Example Input Formats:

  • Empty: "" (will use defaults from OPT_STUN_SERVERS_DEFAULT)
  • Single: "stun:stun.example.com:3478"
  • Multiple: "stun:server1:3478,stun:server2:19302,stun:server3:5349"
Parameters
csv_serversComma-separated STUN server URLs (can be empty)
default_csvDefault servers to use if csv_servers is empty
out_serversOutput array of stun_server_t structs (must be pre-allocated)
max_countMaximum number of servers to parse
Returns
Number of servers parsed (0-max_count), or -1 on error
Note
Each server URL is limited to STUN_MAX_URL_LEN (64) characters
Function gracefully stops at max_count or if a server exceeds max length

Parses a comma-separated string of STUN server URLs into stun_server_t structs. If the input string is empty or NULL, uses the provided default string.

Parameters
csv_serversComma-separated STUN server URLs (can be empty)
default_csvDefault servers to use if csv_servers is empty
out_serversOutput array of stun_server_t structs (must be pre-allocated)
max_countMaximum number of servers to parse
Returns
Number of servers parsed (0-max_count), or -1 on error

Definition at line 51 of file stun.c.

51 {
52 if (!out_servers || max_count <= 0) {
53 log_warn("stun_servers_parse: Invalid output array or max_count");
54 return -1;
55 }
56
57 // Use defaults if input is empty
58 const char *servers_to_parse = csv_servers;
59 if (!servers_to_parse || servers_to_parse[0] == '\0') {
60 servers_to_parse = default_csv;
61 }
62
63 if (!servers_to_parse || servers_to_parse[0] == '\0') {
64 log_warn("stun_servers_parse: No servers to parse and no defaults provided");
65 return 0;
66 }
67
68 // Get compiled regex (lazy initialization)
69 pcre2_code *regex = stun_entry_regex_get();
70
71 // If regex not available, fall back to manual parsing
72 if (!regex) {
73 log_warn("stun_servers_parse: PCRE2 regex not available, falling back to manual parsing");
74 // Fallback: manual character-by-character parsing (original implementation)
75 int count = 0;
76 const char *current = servers_to_parse;
77 const char *end;
78
79 while (count < max_count && *current != '\0') {
80 while (isspace(*current)) {
81 current++;
82 }
83 if (*current == '\0')
84 break;
85
86 end = strchr(current, ',');
87 if (!end) {
88 end = current + strlen(current);
89 }
90
91 while (end > current && isspace(*(end - 1))) {
92 end--;
93 }
94
95 size_t len = end - current;
96 if (len == 0) {
97 current = *end ? end + 1 : end;
98 continue;
99 }
100
101 if (len >= STUN_MAX_URL_LEN) {
102 log_warn("stun_servers_parse: STUN server URL too long (max %d): %.*s", STUN_MAX_URL_LEN, (int)len, current);
103 return -1;
104 }
105
106 out_servers[count].host_len = (uint8_t)len;
107 memcpy(out_servers[count].host, current, len);
108 out_servers[count].host[len] = '\0';
109 count++;
110
111 current = *end ? end + 1 : end;
112 }
113 return count;
114 }
115
116 // Parse using PCRE2 regex: match each trimmed entry
117 int count = 0;
118 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, NULL);
119 if (!match_data) {
120 log_warn("stun_servers_parse: Failed to allocate PCRE2 match data");
121 return -1;
122 }
123
124 size_t offset = 0;
125 int rc;
126
127 while (count < max_count) {
128 rc = pcre2_jit_match(regex, (PCRE2_SPTR8)servers_to_parse, strlen(servers_to_parse), offset, 0, match_data, NULL);
129
130 if (rc < 0) {
131 // No more matches (PCRE2_ERROR_NOMATCH or other error)
132 break;
133 }
134
135 // Extract the captured group (group 1)
136 size_t len;
137 const char *server_url = asciichat_pcre2_extract_group_ptr(match_data, 1, servers_to_parse, &len);
138
139 if (!server_url) {
140 break; // Group not matched
141 }
142
143 if (len >= STUN_MAX_URL_LEN) {
144 log_warn("stun_servers_parse: STUN server URL too long (max %d): %.*s", STUN_MAX_URL_LEN, (int)len, server_url);
145 pcre2_match_data_free(match_data);
146 return -1;
147 }
148
149 // Copy trimmed entry to output
150 out_servers[count].host_len = (uint8_t)len;
151 memcpy(out_servers[count].host, server_url, len);
152 out_servers[count].host[len] = '\0';
153
154 count++;
155
156 // Move offset to end of this match (need ovector for overall match end)
157 PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
158 offset = ovector[1];
159
160 // Skip comma if present
161 if (offset < strlen(servers_to_parse) && servers_to_parse[offset] == ',') {
162 offset++;
163 }
164 }
165
166 pcre2_match_data_free(match_data);
167 return count;
168}
#define log_warn(...)
Log a WARN message.
Definition log/log.h:574
#define STUN_MAX_URL_LEN
Maximum STUN URL length.
Definition stun.h:90
const char * asciichat_pcre2_extract_group_ptr(pcre2_match_data *match_data, int group_num, const char *subject, size_t *out_len)
Extract numbered capture group as pointer into subject (non-allocating)
Definition pcre2.c:339

References asciichat_pcre2_extract_group_ptr(), log_warn, and STUN_MAX_URL_LEN.

Variable Documentation

◆ stun_server_t

stun_server_t

#include <stun.h>

Definition at line 75 of file stun.h.