Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

udp-notifier mechanism #1445

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ HIREDIS_MODS = src/apps/common/hiredis_libevent2.c
USERDB_HEADERS = src/apps/relay/dbdrivers/dbdriver.h src/apps/relay/dbdrivers/dbd_sqlite.h src/apps/relay/dbdrivers/dbd_pgsql.h src/apps/relay/dbdrivers/dbd_mysql.h src/apps/relay/dbdrivers/dbd_mongo.h src/apps/relay/dbdrivers/dbd_redis.h
USERDB_MODS = src/apps/relay/dbdrivers/dbdriver.c src/apps/relay/dbdrivers/dbd_sqlite.c src/apps/relay/dbdrivers/dbd_pgsql.c src/apps/relay/dbdrivers/dbd_mysql.c src/apps/relay/dbdrivers/dbd_mongo.c src/apps/relay/dbdrivers/dbd_redis.c

SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/apps/relay/mainrelay.h src/apps/relay/turn_admin_server.h src/apps/relay/dtls_listener.h src/apps/relay/libtelnet.h src/apps/relay/prom_server.h ${HIREDIS_HEADERS} ${USERDB_HEADERS}
SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turn_admin_server.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c src/apps/relay/prom_server.c ${HIREDIS_MODS} ${USERDB_MODS}
NOTIFIER_HEADERS = src/apps/relay/ntfy_drivers/ntfy_driver.h src/apps/relay/ntfy_drivers/udp_subscriber.h
NOTIFIER_MODS = src/apps/relay/ntfy_drivers/ntfy_driver.c src/apps/relay/ntfy_drivers/udp_subscriber.c

SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/apps/relay/mainrelay.h src/apps/relay/turn_admin_server.h src/apps/relay/dtls_listener.h src/apps/relay/libtelnet.h src/apps/relay/prom_server.h ${HIREDIS_HEADERS} ${USERDB_HEADERS} ${NOTIFIER_HEADERS}
SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turn_admin_server.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c src/apps/relay/prom_server.c ${HIREDIS_MODS} ${USERDB_MODS} ${NOTIFIER_MODS}
SERVERAPP_DEPS = ${SERVERTURN_MODS} ${SERVERTURN_DEPS} ${SERVERAPP_MODS} ${SERVERAPP_HEADERS} ${COMMON_DEPS} ${IMPL_DEPS} lib/libturnclient.a

TURN_BUILD_RESULTS = bin/turnutils_oauth bin/turnutils_natdiscovery bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h sqlite_empty_db
Expand Down
7 changes: 4 additions & 3 deletions README.turnserver
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,7 @@ Flags:
name will be constructed as-is, without PID and date appendage.
This option can be used, for example, together with the logrotate tool.

--new-log-timestamp Enable full ISO-8601 timestamp in all logs.

--new-log-timestamp-format <format> Set timestamp format (in strftime(1) format)
--new-log-timestamp Enable timestamp in all logs.

Copy link
Contributor

@jonesmz jonesmz Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems like you may need to rebase against the latest master/main branch?

Unless your PR is intending to remove the --new-log-timestamp-format option?

--log-binding Log STUN binding request. It is now disabled by default to avoid DoS attacks.

Expand Down Expand Up @@ -612,6 +610,9 @@ Options with values:
--cli-max-output-sessions Maximum number of output sessions in ps CLI command.
This value can be changed on-the-fly in CLI. The default value is 256.

--udp-notifier Send notification messages to target device via UDP interface.
"host=<host> port=<port>"

--web-admin Enable Turn Web-admin support. By default it is disabled.

--web-admin-ip=<IP> Local system IP address to be used for Web-admin server endpoint. Default value is 127.0.0.1.
Expand Down
10 changes: 6 additions & 4 deletions examples/etc/turnserver.conf
Original file line number Diff line number Diff line change
Expand Up @@ -541,12 +541,9 @@
#
#simple-log

# Enable full ISO-8601 timestamp in all logs.
# Enable timestamp in all logs.
#new-log-timestamp

# Set timestamp format (in strftime(1) format). Depends on new-log-timestamp to be enabled.
#new-log-timestamp-format "%FT%T%z"

# Disabled by default binding logging in verbose log mode to avoid DoS attacks.
# Enable binding logging and UDP endpoint logs in verbose log mode.
#log-binding
Expand Down Expand Up @@ -770,6 +767,11 @@
#no-tlsv1_1
#no-tlsv1_2

# UDP notifier
# Send notification messages to target device via UDP interface
#
#udp-notifier "host=127.0.0.1 port=5555"

# Disable RFC5780 (NAT behavior discovery).
#
# Originally, if there are more than one listener address from the same
Expand Down
10 changes: 5 additions & 5 deletions man/man1/turnserver.1
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,7 @@ This option can be used, for example, together with the logrotate tool.
.TP
.B
\fB\-\-new\-log\-timestamp\fP
Enable full ISO\-8601 timestamp in all logs.
.TP
.B
\fB\-\-new\-log\-timestamp\-format\fP
<format> Set timestamp format (in \fBstrftime\fP(1) format)
Enable timestamp in all logs.
.TP
.B
\fB\-\-log\-binding\fP
Expand Down Expand Up @@ -878,6 +874,10 @@ Maximum number of output sessions in ps CLI command.
This value can be changed on\-the\-fly in CLI. The default value is 256.
.TP
.B
\fB\-\-udp\-notifier\fP
Send notification messages to target device via UDP interface.
"host=<host> port=<port>"
.PP
\fB\-\-web\-admin\fP
Enable Turn Web\-admin support. By default it is disabled.
.TP
Expand Down
13 changes: 6 additions & 7 deletions src/apps/common/ns_turn_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,7 @@ static int no_stdout_log = 0;
void set_no_stdout_log(int val) { no_stdout_log = val; }

#define MAX_LOG_TIMESTAMP_FORMAT_LEN 48
static char turn_log_timestamp_format[MAX_LOG_TIMESTAMP_FORMAT_LEN] = "%FT%T%z";

void set_turn_log_timestamp_format(char *new_format) {
strncpy(turn_log_timestamp_format, new_format, MAX_LOG_TIMESTAMP_FORMAT_LEN - 1);
}
static char turn_log_timestamp_format[MAX_LOG_TIMESTAMP_FORMAT_LEN] = "%Y-%m-%d %H:%M:%S";

int use_new_log_timestamp_format = 0;

Expand Down Expand Up @@ -550,8 +546,11 @@ void turn_log_func_default(char *file, int line, TURN_LOG_LEVEL level, const cha
char s[MAX_RTPPRINTF_BUFFER_SIZE + 1];
size_t so_far = 0;
if (use_new_log_timestamp_format) {
time_t now = time(NULL);
so_far += strftime(s, sizeof(s), turn_log_timestamp_format, localtime(&now));
struct timeval now;
if(gettimeofday(&now, NULL) == 0) {
so_far += strftime(s, sizeof(s), turn_log_timestamp_format, localtime(&now.tv_sec));
so_far += snprintf(s + so_far, sizeof(s) - (so_far+1), ",%ld", now.tv_usec);
}
} else {
so_far += snprintf(s, sizeof(s), "%lu: ", (unsigned long)log_time());
}
Expand Down
2 changes: 0 additions & 2 deletions src/apps/common/ns_turn_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ void set_simple_log(int val);

void set_syslog_facility(char *val);

void set_turn_log_timestamp_format(char *new_format);

void turn_log_func_default(char *file, int line, TURN_LOG_LEVEL level, const char *format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 4, 5)))
Expand Down
23 changes: 11 additions & 12 deletions src/apps/relay/mainrelay.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,9 @@ turn_params_t turn_params = {
0, /* no_auth_pings */
0, /* no_dynamic_ip_list */
0, /* no_dynamic_realms */

///// UDP NOTIFIER /////
0,
"",
0, /* log_binding */
0, /* no_stun_backward_compatibility */
0, /* response_origin_only_with_rfc5780 */
Expand Down Expand Up @@ -1217,9 +1219,7 @@ static char Usage[] =
" name will be constructed as-is, without PID and date appendage.\n"
" This option can be used, for example, together with the logrotate "
"tool.\n"
" --new-log-timestamp Enable full ISO-8601 timestamp in all logs.\n"
" --new-log-timestamp-format <format> Set timestamp format (in strftime(1) format). Depends on "
"--new-log-timestamp to be enabled.\n"
" --new-log-timestamp Enable timestamp in all logs.\n"
" --log-binding Log STUN binding request. It is now disabled by default to "
"avoid DoS attacks.\n"
" --stale-nonce[=<value>] Use extra security with nonce value having limited lifetime (default "
Expand Down Expand Up @@ -1308,6 +1308,7 @@ static char Usage[] =
" when we want to run server applications on the relay endpoints.\n"
" This option eliminates the IP permissions check on the packets\n"
" incoming to the relay endpoints.\n"
" --udp-notifier Send notification messages to target device via UDP interface.\n"
" --cli-max-output-sessions Maximum number of output sessions in ps CLI command.\n"
" This value can be changed on-the-fly in CLI. The default value is "
"256.\n"
Expand Down Expand Up @@ -1435,7 +1436,6 @@ enum EXTRA_OPTS {
SYSLOG_FACILITY_OPT,
SIMPLE_LOG_OPT,
NEW_LOG_TIMESTAMP_OPT,
NEW_LOG_TIMESTAMP_FORMAT_OPT,
AUX_SERVER_OPT,
UDP_SELF_BALANCE_OPT,
ALTERNATE_SERVER_OPT,
Expand Down Expand Up @@ -1483,6 +1483,7 @@ enum EXTRA_OPTS {
NO_HTTP_OPT,
SECRET_KEY_OPT,
ACME_REDIRECT_OPT,
UDP_NOTIFIER_OPT,
LOG_BINDING_OPT,
NO_RFC5780,
NO_STUN_BACKWARD_COMPATIBILITY_OPT,
Expand Down Expand Up @@ -1584,7 +1585,6 @@ static const struct myoption long_options[] = {
{"syslog", optional_argument, NULL, SYSLOG_OPT},
{"simple-log", optional_argument, NULL, SIMPLE_LOG_OPT},
{"new-log-timestamp", optional_argument, NULL, NEW_LOG_TIMESTAMP_OPT},
{"new-log-timestamp-format", required_argument, NULL, NEW_LOG_TIMESTAMP_FORMAT_OPT},
{"aux-server", required_argument, NULL, AUX_SERVER_OPT},
{"udp-self-balance", optional_argument, NULL, UDP_SELF_BALANCE_OPT},
{"alternate-server", required_argument, NULL, ALTERNATE_SERVER_OPT},
Expand Down Expand Up @@ -1626,6 +1626,7 @@ static const struct myoption long_options[] = {
{"keep-address-family", optional_argument, NULL, 'K'},
{"allocation-default-address-family", required_argument, NULL, 'A'},
{"acme-redirect", required_argument, NULL, ACME_REDIRECT_OPT},
{"udp-notifier", required_argument, NULL, UDP_NOTIFIER_OPT },
{"log-binding", optional_argument, NULL, LOG_BINDING_OPT},
{"no-rfc5780", optional_argument, NULL, NO_RFC5780},
{"no-stun-backward-compatibility", optional_argument, NULL, NO_STUN_BACKWARD_COMPATIBILITY_OPT},
Expand Down Expand Up @@ -2328,6 +2329,10 @@ static void set_option(int c, char *value) {
turn_params.rest_api_separator = *value;
}
break;
case UDP_NOTIFIER_OPT:
turn_params.udp_notifier = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the C99 "stdbool" header, and the true/false keywords (sometimes implemented as macros by C99) over '1' and '0' and 'int'.

STRCPY(turn_params.udp_notifier_params, value);
break;
case LOG_BINDING_OPT:
turn_params.log_binding = get_bool_value(value);
break;
Expand All @@ -2350,7 +2355,6 @@ static void set_option(int c, char *value) {
case SYSLOG_OPT:
case SIMPLE_LOG_OPT:
case NEW_LOG_TIMESTAMP_OPT:
case NEW_LOG_TIMESTAMP_FORMAT_OPT:
case SYSLOG_FACILITY_OPT:
case 'c':
case 'n':
Expand Down Expand Up @@ -2491,8 +2495,6 @@ static void read_config_file(int argc, char **argv, int pass) {
set_simple_log(get_bool_value(value));
} else if ((pass == 0) && (c == NEW_LOG_TIMESTAMP_OPT)) {
use_new_log_timestamp_format = 1;
} else if ((pass == 0) && (c == NEW_LOG_TIMESTAMP_FORMAT_OPT)) {
set_turn_log_timestamp_format(value);
} else if ((pass == 0) && (c == SYSLOG_FACILITY_OPT)) {
set_syslog_facility(value);
} else if ((pass == 1) && (c != 'u')) {
Expand Down Expand Up @@ -2982,9 +2984,6 @@ int main(int argc, char **argv) {
case NEW_LOG_TIMESTAMP_OPT:
use_new_log_timestamp_format = 1;
break;
case NEW_LOG_TIMESTAMP_FORMAT_OPT:
set_turn_log_timestamp_format(optarg);
break;
case SYSLOG_FACILITY_OPT:
set_syslog_facility(optarg);
break;
Expand Down
4 changes: 4 additions & 0 deletions src/apps/relay/mainrelay.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@ typedef struct _turn_params_ {
int no_auth_pings;
int no_dynamic_ip_list;
int no_dynamic_realms;

//// UDP Notifier ////
int udp_notifier;
char udp_notifier_params[1025];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1025 is a magic number.

Additionally, does this need to be a flat buffer of characters? can't it be parsed into a struct that has meaningful variable names for whatever the fields are?


vint log_binding;
vint no_stun_backward_compatibility;
Expand Down
130 changes: 130 additions & 0 deletions src/apps/relay/ntfy_drivers/ntfy_driver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include "ntfy_driver.h"
#include "../mainrelay.h"
#include "../../common/apputils.h"
#include "udp_subscriber.h"
#include "apps/relay/mainrelay.h"
typedef struct _turn_notifier_t{
turn_ntfy_subscriber_if_t** subscribers;
size_t subscriber_count;
}turn_notifier_t;


pthread_key_t notifier_key;
pthread_once_t notifier_key_once = PTHREAD_ONCE_INIT;

static void notifier_interface_remove(void*notifier_p);


static void make_notifier_key(void)
{
(void) pthread_key_create(&notifier_key, notifier_interface_remove);
}

static void subscriber_add(turn_notifier_t* notifier, turn_ntfy_subscriber_if_t* subscriber)
{
if(notifier && subscriber) {
notifier->subscribers = (turn_ntfy_subscriber_if_t**)realloc(notifier->subscribers,(sizeof(turn_ntfy_subscriber_if_t*)*(notifier->subscriber_count+1)));
notifier->subscribers[notifier->subscriber_count] = subscriber;
notifier->subscriber_count += 1;
}
}

static void subscribers_init(turn_notifier_t *notifier){

size_t i;

for(i=0; i<(notifier->subscriber_count); i++){
if(notifier->subscribers[i]->init) {
notifier->subscribers[i]->long_term_data = notifier->subscribers[i]->init();
}
}
}

static void subscribers_notify(turn_notifier_t *notifier, TURN_NTFY_LEVEL level, const char* string){

size_t i;

for(i=0; i<(notifier->subscriber_count); i++){
if(notifier->subscribers[i]->notify) {
notifier->subscribers[i]->notify(notifier->subscribers[i]->long_term_data, level, string);
}
}
}

static void subscribers_remove(turn_notifier_t *notifier){

size_t i;

for(i=0; i<(notifier->subscriber_count); i++){
if(notifier->subscribers[i]->remove) {
notifier->subscribers[i]->remove(notifier->subscribers[i]->long_term_data);
}
}
}

static turn_notifier_t* notifier_interface_get(void){

(void) pthread_once(&notifier_key_once, make_notifier_key);

turn_notifier_t *notifier = (turn_notifier_t *)pthread_getspecific(notifier_key);

if(!notifier){

turn_notifier_t* notifier=(turn_notifier_t*)malloc(sizeof(turn_notifier_t));
if(!notifier) return notifier;

bzero(notifier,sizeof(turn_notifier_t));

subscriber_add(notifier,udp_subscriber_inferface_get());

subscribers_init(notifier);

pthread_setspecific(notifier_key, notifier);
}
return notifier;
}

static void notifier_interface_remove(void*notifier_p){

turn_notifier_t *notifier = (turn_notifier_t *)notifier_p;

if(notifier){

subscribers_remove(notifier);

free(notifier);
}
}

int turn_ntfy_check(){

turn_notifier_t* notifier = notifier_interface_get();

if(notifier){
if(notifier->subscriber_count>0)
return 1;
}
return 0;
}

void turn_ntfy_func_default(TURN_NTFY_LEVEL level, const char* format, ...){

#define MAX_RTPPRINTF_BUFFER_SIZE (1024)
char string[MAX_RTPPRINTF_BUFFER_SIZE+1];
#undef MAX_RTPPRINTF_BUFFER_SIZE

va_list args;

turn_notifier_t* notifier = notifier_interface_get();

if(notifier){
va_start(args,format);

vsnprintf(string, sizeof(string)-1, format, args);
string[sizeof(string)-1]=0;

va_end(args);

subscribers_notify(notifier, level, string);
}
}