From d5a7456e6a26adeba2842e2f5caed368e6544ae3 Mon Sep 17 00:00:00 2001 From: Pavel Punsky Date: Fri, 15 Aug 2025 08:23:06 -0700 Subject: [PATCH] Implement configurable buffer sizes --- README.turnserver | 8 +++++--- docker/coturn/turnserver.conf | 5 +++++ examples/etc/turnserver.conf | 5 +++++ src/apps/relay/dtls_listener.c | 10 +++++++--- src/apps/relay/mainrelay.c | 7 +++++++ src/apps/relay/mainrelay.h | 2 ++ src/apps/relay/netengine.c | 27 +++++++++++++------------- src/apps/relay/ns_ioalib_engine_impl.c | 11 +++++++---- src/apps/relay/tls_listener.c | 4 ++++ src/server/ns_turn_ioalib.h | 5 +++-- src/server/ns_turn_server.c | 13 ++++++++++++- src/server/ns_turn_server.h | 10 +++------- 12 files changed, 74 insertions(+), 33 deletions(-) diff --git a/README.turnserver b/README.turnserver index b58ff7dc..c22776be 100644 --- a/README.turnserver +++ b/README.turnserver @@ -419,6 +419,8 @@ Options with values: endpoints allocation. Default value is 65535, according to RFC 5766. +--sock-buf-size Set socket buffer size to a new value (in bytes). + -u, --user Long-term security mechanism credentials user account, in the column-separated form username:key. Multiple user accounts may be used in the command line. @@ -464,11 +466,11 @@ Options with values: that other mode is dynamic. Multiple shared secrets can be used (both in the database and in the "static" fashion). - --no-auth-pings Disable periodic health checks to 'dynamic' auth secret tables. +--no-auth-pings Disable periodic health checks to 'dynamic' auth secret tables. - --no-dynamic-ip-list Do not use dynamic allowed/denied peer ip list. +--no-dynamic-ip-list Do not use dynamic allowed/denied peer ip list. - --no-dynamic-realms Do not use dynamic realm assignment and options. +--no-dynamic-realms Do not use dynamic realm assignment and options. --server-name Server name used for the oAuth authentication purposes. diff --git a/docker/coturn/turnserver.conf b/docker/coturn/turnserver.conf index a42797fc..6c683766 100644 --- a/docker/coturn/turnserver.conf +++ b/docker/coturn/turnserver.conf @@ -157,6 +157,11 @@ tls-listening-port=5349 min-port=49152 max-port=65535 +# Socket buffer size (in bytes). +# (default value is 2097152) +# +#sock-buf-size=2097152 + # Uncomment to run TURN server in 'normal' 'moderate' verbose mode. # By default the verbose mode is off. #verbose diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 60f3d871..71bb3046 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -178,6 +178,11 @@ #min-port=49152 #max-port=65535 +# Socket buffer size (in bytes). +# (default value is 2097152) +# +#sock-buf-size=2097152 + # Uncomment to run TURN server in 'normal' 'moderate' verbose mode. # By default the verbose mode is off. #verbose diff --git a/src/apps/relay/dtls_listener.c b/src/apps/relay/dtls_listener.c index 5d7da07d..6911aa43 100644 --- a/src/apps/relay/dtls_listener.c +++ b/src/apps/relay/dtls_listener.c @@ -243,7 +243,10 @@ static ioa_socket_handle dtls_accept_client_connection(dtls_listener_relay_serve ioa_socket_handle ioas = create_ioa_socket_from_ssl(server->e, sock, ssl, DTLS_SOCKET, CLIENT_SOCKET, remote_addr, local_addr); + if (ioas) { + set_ioa_socket_buf_size(ioas, server->ts->sock_buf_size); + addr_cpy(&(server->sm.m.sm.nd.src_addr), remote_addr); server->sm.m.sm.nd.recv_ttl = TTL_IGNORE; server->sm.m.sm.nd.recv_tos = TOS_IGNORE; @@ -452,6 +455,7 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server, struct mes (char *)saddr, (char *)rsaddr); } s->e = ioa_eng; + set_ioa_socket_buf_size(s, ts->sock_buf_size); add_socket_to_map(s, amap); if (open_client_connection_session(ts, &(sm->m.sm)) < 0) { return -1; @@ -516,6 +520,7 @@ static int create_new_connected_udp_socket(dtls_listener_relay_server_type *serv addr_cpy(&(ret->remote_addr), &(server->sm.m.sm.nd.src_addr)); set_socket_options(ret); + set_ioa_socket_buf_size(ret, server->ts->sock_buf_size); ret->current_ttl = s->current_ttl; ret->default_ttl = s->default_ttl; @@ -757,7 +762,7 @@ static int create_server_socket(dtls_listener_relay_server_type *server, int rep server->udp_listen_s = create_ioa_socket_from_fd(server->e, udp_listen_fd, NULL, UDP_SOCKET, LISTENER_SOCKET, NULL, &(server->addr)); - set_sock_buf_size(udp_listen_fd, UR_SERVER_SOCK_BUF_SIZE); + set_ioa_socket_buf_size(server->udp_listen_s, server->ts->sock_buf_size); if (sock_bind_to_device(udp_listen_fd, (unsigned char *)server->ifname) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind listener socket to device %s\n", server->ifname); @@ -842,8 +847,7 @@ static int reopen_server_socket(dtls_listener_relay_server_type *server, evutil_ /* some UDP sessions may fail due to the race condition here */ set_socket_options(server->udp_listen_s); - - set_sock_buf_size(udp_listen_fd, UR_SERVER_SOCK_BUF_SIZE); + set_ioa_socket_buf_size(server->udp_listen_s, server->ts->sock_buf_size); if (sock_bind_to_device(udp_listen_fd, (unsigned char *)server->ifname) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind listener socket to device %s\n", server->ifname); diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 3185a7ed..367ca665 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -178,6 +178,7 @@ turn_params_t turn_params = { NULL, /*external_ip*/ DEFAULT_GENERAL_RELAY_SERVERS_NUMBER, /*general_relay_servers_number*/ 0, /*udp_relay_servers_number*/ + UR_SERVER_SOCK_BUF_SIZE, ////////////// Auth server ///////////////////////////////////// "", @@ -1037,6 +1038,7 @@ static char Usage[] = " --max-port Upper bound of the UDP port range for relay endpoints " "allocation.\n" " Default value is 65535, according to RFC 5766.\n" + "--sock-buf-size Size of the socket buffer for UDP sockets (in bytes).\n" " -v, --verbose 'Moderate' verbose mode.\n" " -V, --Verbose Extra verbose mode, very annoying (for debug purposes only).\n" " -o, --daemon Start process as daemon (detach from current shell).\n" @@ -1440,6 +1442,7 @@ enum EXTRA_OPTS { PKEY_PWD_OPT, MIN_PORT_OPT, MAX_PORT_OPT, + SOCK_BUF_SIZE_OPT, STALE_NONCE_OPT, MAX_ALLOCATE_LIFETIME_OPT, CHANNEL_LIFETIME_OPT, @@ -1546,6 +1549,7 @@ static const struct myoption long_options[] = { {"relay-threads", required_argument, NULL, 'm'}, {"min-port", required_argument, NULL, MIN_PORT_OPT}, {"max-port", required_argument, NULL, MAX_PORT_OPT}, + {"sock-buf-size", required_argument, NULL, SOCK_BUF_SIZE_OPT}, {"lt-cred-mech", optional_argument, NULL, 'a'}, {"no-auth", optional_argument, NULL, 'z'}, {"user", required_argument, NULL, 'u'}, @@ -2053,6 +2057,9 @@ static void set_option(int c, char *value) { case MAX_PORT_OPT: turn_params.max_port = atoi(value); break; + case SOCK_BUF_SIZE_OPT: + turn_params.sock_buf_size = atoi(value); + break; case SECURE_STUN_OPT: turn_params.secure_stun = get_bool_value(value); break; diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 96cf4bea..a4e1aef8 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -280,6 +280,8 @@ typedef struct _turn_params_ { turnserver_id general_relay_servers_number; turnserver_id udp_relay_servers_number; + int sock_buf_size; + ////////////// Auth server //////////////// char oauth_server_name[1025]; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 353012b5..cb152a4c 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1665,19 +1665,20 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int bufferevent_setcb(rs->auth_in_buf, relay_receive_auth_message, NULL, NULL, rs); bufferevent_enable(rs->auth_in_buf, EV_READ); - init_turn_server( - &(rs->server), rs->id, turn_params.verbose, rs->ioa_eng, turn_params.ct, turn_params.fingerprint, - DONT_FRAGMENT_SUPPORTED, start_user_check, check_new_allocation_quota, release_allocation_quota, - turn_params.external_ip, &turn_params.check_origin, &turn_params.no_tcp_relay, &turn_params.no_udp_relay, - &turn_params.stale_nonce, &turn_params.max_allocate_lifetime, &turn_params.channel_lifetime, - &turn_params.permission_lifetime, &turn_params.stun_only, &turn_params.no_stun, turn_params.software_attribute, - &turn_params.web_admin_listen_on_workers, &turn_params.alternate_servers_list, - &turn_params.tls_alternate_servers_list, &turn_params.aux_servers_list, turn_params.udp_self_balance, - &turn_params.no_multicast_peers, &turn_params.allow_loopback_peers, &turn_params.ip_whitelist, - &turn_params.ip_blacklist, send_socket_to_relay, &turn_params.secure_stun, &turn_params.mobility, - 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.stun_backward_compatibility, &turn_params.respond_http_unsupported); + init_turn_server(&(rs->server), rs->id, turn_params.verbose, rs->ioa_eng, turn_params.ct, turn_params.fingerprint, + DONT_FRAGMENT_SUPPORTED, start_user_check, check_new_allocation_quota, release_allocation_quota, + turn_params.external_ip, &turn_params.check_origin, &turn_params.no_tcp_relay, + &turn_params.no_udp_relay, &turn_params.stale_nonce, &turn_params.max_allocate_lifetime, + &turn_params.channel_lifetime, &turn_params.permission_lifetime, &turn_params.stun_only, + &turn_params.no_stun, turn_params.software_attribute, &turn_params.web_admin_listen_on_workers, + &turn_params.alternate_servers_list, &turn_params.tls_alternate_servers_list, + &turn_params.aux_servers_list, turn_params.udp_self_balance, &turn_params.no_multicast_peers, + &turn_params.allow_loopback_peers, &turn_params.ip_whitelist, &turn_params.ip_blacklist, + send_socket_to_relay, &turn_params.secure_stun, &turn_params.mobility, turn_params.server_relay, + send_turn_session_info, send_https_socket, turn_params.sock_buf_size, 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.stun_backward_compatibility, &turn_params.respond_http_unsupported); if (to_set_rfc5780) { set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 47d96e1f..fbee5b43 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -254,6 +254,13 @@ void set_do_not_use_df(ioa_socket_handle s) { set_socket_df(s->fd, s->family, 0); } +int set_ioa_socket_buf_size(ioa_socket_handle s, int sz) { + if (!s || sz <= 0) { + return 0; + } + return set_sock_buf_size(s->fd, sz); +} + /************** Buffer List ********************/ static int buffer_list_empty(stun_buffer_list *bufs) { @@ -920,7 +927,6 @@ ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int famil perror("UDP socket"); return NULL; } - set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); break; case TCP_SOCKET: fd = socket(family, RELAY_STREAM_SOCKET_TYPE, RELAY_STREAM_SOCKET_PROTOCOL); @@ -928,7 +934,6 @@ ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int famil perror("TCP socket"); return NULL; } - set_sock_buf_size(fd, UR_CLIENT_SOCK_BUF_SIZE); break; default: /* we do not support other sockets in the relay position */ @@ -997,7 +1002,6 @@ int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s, in size_t iip = 0; for (iip = 0; iip < e->relays_number; ++iip) { - ioa_addr relay_addr; const ioa_addr *ra = ioa_engine_get_relay_addr(e, client_s, address_family, err_code); if (ra) { @@ -1031,7 +1035,6 @@ int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s, in if (even_port < 0) { port = turnipports_allocate(tp, transport, &relay_addr); } else { - port = turnipports_allocate_even(tp, &relay_addr, even_port, out_reservation_token); if (port >= 0 && even_port > 0) { if (rtcp_s != NULL) { diff --git a/src/apps/relay/tls_listener.c b/src/apps/relay/tls_listener.c index 1f62479e..0d96791a 100644 --- a/src/apps/relay/tls_listener.c +++ b/src/apps/relay/tls_listener.c @@ -109,6 +109,8 @@ static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd, s server->sm.m.sm.can_resume = 1; server->sm.relay_server = server->relay_server; + set_ioa_socket_buf_size(ioas, server->relay_server->server.sock_buf_size); + const int rc = server->connect_cb(server->e, &(server->sm)); if (rc < 0) { @@ -166,6 +168,8 @@ static void sctp_server_input_handler(struct evconnlistener *l, evutil_socket_t server->sm.m.sm.can_resume = 1; server->sm.relay_server = server->relay_server; + set_ioa_socket_buf_size(ioas, server->relay_server->server.sock_buf_size); + int rc = server->connect_cb(server->e, &(server->sm)); if (rc < 0) { diff --git a/src/server/ns_turn_ioalib.h b/src/server/ns_turn_ioalib.h index 8c126b58..a9ad0dc2 100644 --- a/src/server/ns_turn_ioalib.h +++ b/src/server/ns_turn_ioalib.h @@ -260,8 +260,8 @@ void inc_ioa_socket_ref_counter(ioa_socket_handle s); /* Relay socket handling */ /* - * event_port == -1: no rtcp; - * event_port == 0: reserve rtcp; + * even_port == -1: no rtcp; + * even_port == 0: reserve rtcp; * even_port == +1: reserve and bind rtcp. */ int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s, int address_family, uint8_t transport, @@ -310,6 +310,7 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s); void detach_socket_net_data(ioa_socket_handle s); int set_df_on_ioa_socket(ioa_socket_handle s, int value); void set_do_not_use_df(ioa_socket_handle s); +int set_ioa_socket_buf_size(ioa_socket_handle s, int sz); int ioa_socket_tobeclosed(ioa_socket_handle s); void set_ioa_socket_tobeclosed(ioa_socket_handle s); void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 75216bf4..3395abb8 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2157,6 +2157,8 @@ static int tcp_start_connection_to_peer(turn_turnserver *server, ts_ur_super_ses return -1; } + set_ioa_socket_buf_size(tcs, server->sock_buf_size); + tc->state = TC_STATE_CLIENT_TO_PEER_CONNECTING; if (tc->peer_s != tcs) { IOA_CLOSE_SOCKET(tc->peer_s); @@ -2237,6 +2239,7 @@ static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg) { set_ioa_socket_session(s, ss); set_ioa_socket_sub_session(s, tc); + set_ioa_socket_buf_size(s, server->sock_buf_size); if (register_callback_on_ioa_socket(server->e, s, IOA_EV_READ, tcp_peer_input_handler, tc, 1) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP peer data input callback\n", __FUNCTION__); @@ -4372,6 +4375,13 @@ static int create_relay_connection(turn_turnserver *server, ts_ur_super_session } } + if (newelem->s) { + set_ioa_socket_buf_size(newelem->s, server->sock_buf_size); + } + if (rtcp_s) { + set_ioa_socket_buf_size(rtcp_s, server->sock_buf_size); + } + if (newelem->s == NULL) { IOA_CLOSE_SOCKET(rtcp_s); *err_code = 508; @@ -4904,7 +4914,7 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io ip_range_list_t *ip_whitelist, ip_range_list_t *ip_blacklist, send_socket_to_relay_cb send_socket_to_relay, bool *secure_stun, bool *mobility, 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, + int sock_buf_size, 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, bool *log_binding, bool *stun_backward_compatibility, bool *respond_http_unsupported) { @@ -4931,6 +4941,7 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io server->server_relay = server_relay; server->send_turn_session_info = send_turn_session_info; server->send_https_socket = send_https_socket; + server->sock_buf_size = sock_buf_size; server->oauth = oauth; if (oauth) { server->oauth_server_name = oauth_server_name; diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 861feb1d..f7091dff 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -35,13 +35,8 @@ #ifndef __TURN_SERVER__ #define __TURN_SERVER__ -#include "ns_turn_allocation.h" // for tcp_connection_id -#include "ns_turn_defs.h" // for vintp, uint8_t, size_t, uint64_t -#include "ns_turn_ioaddr.h" // for ioa_addr -#include "ns_turn_ioalib.h" // for ioa_net_data, ioa_engine_handle, ioa... -#include "ns_turn_maps.h" // for ur_map -#include "ns_turn_msg.h" // for turn_credential_type, band_limit_t #include "ns_turn_session.h" +#include "ns_turn_utils.h" #ifdef __cplusplus extern "C" { @@ -155,6 +150,7 @@ struct _turn_turnserver { bool *no_multicast_peers; send_turn_session_info_cb send_turn_session_info; send_https_socket_cb send_https_socket; + int sock_buf_size; /* RFC 6062 ==>> */ bool *no_udp_relay; @@ -226,7 +222,7 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io ip_range_list_t *ip_whitelist, ip_range_list_t *ip_blacklist, send_socket_to_relay_cb send_socket_to_relay, bool *secure_stun, bool *mobility, 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, + int sock_buf_size, 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, bool *log_binding, bool *stun_backward_compatibility, bool *respond_http_unsupported);