diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 5a9005bae..cd9d996ef 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -455,6 +455,8 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, struct mes s->e = ioa_eng; add_socket_to_map(s, amap); if (open_client_connection_session(ts, &(sm->m.sm)) < 0) { + // Signal change to add session limit + IOA_CLOSE_SOCKET(s); return -1; } } diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 269d64c5f..0f6516b8d 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -229,7 +229,9 @@ turn_params_t turn_params = { 0, /* log_binding */ 0, /* no_stun_backward_compatibility */ 0, /* response_origin_only_with_rfc5780 */ - 0 /* respond_http_unsupported */ + 0, /* respond_http_unsupported */ + // Signal change to add session limit + 0, /* session_limit */ }; //////////////// OpenSSL Init ////////////////////// @@ -1429,7 +1431,9 @@ enum EXTRA_OPTS { NO_STUN_BACKWARD_COMPATIBILITY_OPT, RESPONSE_ORIGIN_ONLY_WITH_RFC5780_OPT, RESPOND_HTTP_UNSUPPORTED_OPT, - VERSION_OPT + VERSION_OPT, + // Signal change to add session limit + SESSION_LIMIT_OPT }; struct myoption { @@ -1574,6 +1578,8 @@ static const struct myoption long_options[] = { {"respond-http-unsupported", optional_argument, NULL, RESPOND_HTTP_UNSUPPORTED_OPT}, {"version", optional_argument, NULL, VERSION_OPT}, {"syslog-facility", required_argument, NULL, SYSLOG_FACILITY_OPT}, + // Signal change to add session limit + {"session-limit", required_argument, NULL, SESSION_LIMIT_OPT}, {NULL, no_argument, NULL, 0}}; static const struct myoption admin_long_options[] = { @@ -2270,6 +2276,10 @@ static void set_option(int c, char *value) { case RESPOND_HTTP_UNSUPPORTED_OPT: turn_params.respond_http_unsupported = get_bool_value(value); break; + // Signal change to add session limit + case SESSION_LIMIT_OPT: + turn_params.session_limit = atoi(value); + break; /* these options have been already taken care of before: */ case 'l': diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index f08e1c67f..f7ea17555 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -331,6 +331,8 @@ typedef struct _turn_params_ { vint no_stun_backward_compatibility; vint response_origin_only_with_rfc5780; vint respond_http_unsupported; + // Signal change to add session limit + int session_limit; } turn_params_t; extern turn_params_t turn_params; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index f2380b402..f2e04cfac 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1681,7 +1681,9 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int turn_params.server_relay, send_turn_session_info, send_https_socket, allocate_bps, turn_params.oauth, turn_params.oauth_server_name, turn_params.acme_redirect, turn_params.allocation_default_address_family, &turn_params.log_binding, &turn_params.no_stun_backward_compatibility, - &turn_params.response_origin_only_with_rfc5780, &turn_params.respond_http_unsupported); + &turn_params.response_origin_only_with_rfc5780, &turn_params.respond_http_unsupported, + // Signal change to add session limit + turn_params.session_limit); if (to_set_rfc5780) { set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); diff --git a/src/apps/relay/prom_server.c b/src/apps/relay/prom_server.c index 2b44be238..23f85a15e 100644 --- a/src/apps/relay/prom_server.c +++ b/src/apps/relay/prom_server.c @@ -44,6 +44,9 @@ prom_counter_t *turn_rtt_client[8]; prom_counter_t *turn_rtt_peer[8]; prom_counter_t *turn_rtt_combined[8]; prom_counter_t *turn_with_no_ping_rcvp; +prom_counter_t *turn_allocation_response; +prom_gauge_t *turn_session_limit; +prom_counter_t *turn_sessions_overlimit; void start_prometheus_server(void) { if (turn_params.prometheus == 0) { @@ -194,6 +197,16 @@ void start_prometheus_server(void) { turn_with_no_ping_rcvp = prom_collector_registry_must_register_metric(prom_counter_new( "turn_with_no_ping_rcvp", "Count of packets received for TURN where no ICE ping has been observed", 0, NULL)); + const char *response_labels[] = {"response_code"}; + turn_allocation_response = prom_collector_registry_must_register_metric(prom_counter_new( + "turn_allocation_response", "Count of allocation responses sent (by error code)", 1, response_labels)); + + turn_session_limit = prom_collector_registry_must_register_metric( + prom_gauge_new("turn_session_limit", "Current number of additional sessions allowed", 0, NULL)); + + turn_sessions_overlimit = prom_collector_registry_must_register_metric(prom_counter_new( + "turn_sessions_overlimit", "Count of sessions deined because it would be over the limit", 0, NULL)); + promhttp_set_active_collector_registry(NULL); // some flags appeared first in microhttpd v0.9.53 @@ -322,7 +335,7 @@ int is_ipv6_enabled(void) { return ret; } -// Signal change to add rtt metrics +// Signal change to add metrics void prom_observe_rtt(prom_counter_t *counter[8], int microseconds, const char *protocolgroup) { const char *label[] = {protocolgroup}; if (microseconds <= 25000) { @@ -367,6 +380,28 @@ void prom_observe_rtt_combined(int microseconds, const char *protocolgroup) { } } +void prom_inc_allocation_response(int err_code) { + if (turn_params.prometheus == 1) { + char label[80]; + if (snprintf(label, sizeof(label), "%d", err_code) < (int)sizeof(label)) { + const char *labels[] = {label}; + prom_counter_add(turn_allocation_response, 1, labels); + } + } +} + +void prom_set_session_limit(int limit) { + if (turn_params.prometheus == 1) { + prom_gauge_set(turn_session_limit, limit, NULL); + } +} + +void prom_inc_sessions_overlimit(void) { + if (turn_params.prometheus == 1) { + prom_counter_add(turn_sessions_overlimit, 1, NULL); + } +} + #else void start_prometheus_server(void) { diff --git a/src/apps/relay/prom_server.h b/src/apps/relay/prom_server.h index 215b93cfb..7b66ddb22 100644 --- a/src/apps/relay/prom_server.h +++ b/src/apps/relay/prom_server.h @@ -58,6 +58,9 @@ extern prom_counter_t *turn_rtt_client[8]; extern prom_counter_t *turn_rtt_peer[8]; extern prom_counter_t *turn_rtt_combined[8]; extern prom_counter_t *turn_with_no_ping_rcvp; +extern prom_counter_t *turn_total_allocations; +extern prom_counter_t *turn_session_limit; +extern prom_counter_t *turn_sessions_overlimit; #define TURN_ALLOC_STR_MAX_SIZE (20) @@ -88,6 +91,9 @@ void prom_observe_rtt(prom_counter_t *counter[8], int microseconds, const char * void prom_observe_rtt_client(int microseconds, const char *protocolgroup); void prom_observe_rtt_peer(int microseconds, const char *protocolgroup); void prom_observe_rtt_combined(int microseconds, const char *protocolgroup); +void prom_inc_allocation_response(int err_code); +void prom_set_session_limit(int limit); +void prom_inc_sessions_overlimit(void); #else diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 9e70233c8..ce739ea62 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -1443,6 +1443,9 @@ static int handle_turn_allocate(turn_turnserver *server, ts_ur_super_session *ss } } + // Signal change to add metrics + prom_inc_allocation_response(*err_code); + return 0; } @@ -4172,12 +4175,24 @@ static int write_to_peerchannel(ts_ur_super_session *ss, uint16_t chnum, ioa_net static void client_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume); static void peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_data *data, void *arg, int can_resume); +// Signal change to add session limit +static TURN_MUTEX_DECLARE(session_limit_mutex); +static int session_limit; + /////////////// Client actions ///////////////// int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, int force, const char *reason) { FUNCSTART; + // Signal change to add session limit + if (session_limit != -1) { + TURN_MUTEX_LOCK(&session_limit_mutex); + ++session_limit; + prom_set_session_limit(session_limit); + TURN_MUTEX_UNLOCK(&session_limit_mutex); + } + if (!ss) return -1; @@ -4757,6 +4772,19 @@ int open_client_connection_session(turn_turnserver *server, struct socket_messag if (!(sm->s)) return -1; + // Signal change to add session limit + if (session_limit != -1) { + TURN_MUTEX_LOCK(&session_limit_mutex); + if (session_limit == 0) { + TURN_MUTEX_UNLOCK(&session_limit_mutex); + prom_inc_sessions_overlimit(); + return -1; + } + --session_limit; + prom_set_session_limit(session_limit); + TURN_MUTEX_UNLOCK(&session_limit_mutex); + } + ts_ur_super_session *ss = create_new_ss(server); ss->client_socket = sm->s; @@ -4955,11 +4983,24 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io allocate_bps_cb allocate_bps_func, int oauth, const char *oauth_server_name, const char *acme_redirect, ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family, vintp log_binding, vintp no_stun_backward_compatibility, vintp response_origin_only_with_rfc5780, - vintp respond_http_unsupported) { + vintp respond_http_unsupported, + // Signal change to add session limit + int configured_session_limit) { if (!server) return; + // Signal change to add session limit + if (id == 0) { + if (configured_session_limit) { + TURN_MUTEX_INIT(&session_limit_mutex); + session_limit = configured_session_limit; + } else { + session_limit = -1; + } + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "turn server session_limit = %d\n", session_limit); + } + memset(server, 0, sizeof(turn_turnserver)); server->e = e; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index d12af3074..08233e778 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -229,7 +229,9 @@ void init_turn_server( int server_relay, send_turn_session_info_cb send_turn_session_info, send_https_socket_cb send_https_socket, allocate_bps_cb allocate_bps_func, int oauth, const char *oauth_server_name, const char *acme_redirect, ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family, vintp log_binding, - vintp no_stun_backward_compatibility, vintp response_origin_only_with_rfc5780, vintp respond_http_unsupported); + vintp no_stun_backward_compatibility, vintp response_origin_only_with_rfc5780, vintp respond_http_unsupported, + // Signal change to add session limit + int configured_session_limit); ioa_engine_handle turn_server_get_engine(turn_turnserver *s);