51int stun_servers_parse(
const char *csv_servers,
const char *default_csv, stun_server_t *out_servers,
int max_count) {
52 if (!out_servers || max_count <= 0) {
53 log_warn(
"stun_servers_parse: Invalid output array or max_count");
58 const char *servers_to_parse = csv_servers;
59 if (!servers_to_parse || servers_to_parse[0] ==
'\0') {
60 servers_to_parse = default_csv;
63 if (!servers_to_parse || servers_to_parse[0] ==
'\0') {
64 log_warn(
"stun_servers_parse: No servers to parse and no defaults provided");
69 pcre2_code *regex = stun_entry_regex_get();
73 log_warn(
"stun_servers_parse: PCRE2 regex not available, falling back to manual parsing");
76 const char *current = servers_to_parse;
79 while (count < max_count && *current !=
'\0') {
80 while (isspace(*current)) {
86 end = strchr(current,
',');
88 end = current + strlen(current);
91 while (end > current && isspace(*(end - 1))) {
95 size_t len = end - current;
97 current = *end ? end + 1 : end;
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);
106 out_servers[count].host_len = (uint8_t)len;
107 memcpy(out_servers[count].host, current, len);
108 out_servers[count].host[len] =
'\0';
111 current = *end ? end + 1 : end;
118 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, NULL);
120 log_warn(
"stun_servers_parse: Failed to allocate PCRE2 match data");
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);
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);
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';
157 PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
161 if (offset < strlen(servers_to_parse) && servers_to_parse[offset] ==
',') {
166 pcre2_match_data_free(match_data);
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)
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.