mirror of
https://github.com/coturn/coturn.git
synced 2026-10-24 00:08:57 +03:00
## What Moves the `--multiplex-peer` demux table out of `ioa_engine_t` into its own module, `src/apps/relay/mp_peer_table.c/.h`, and gives it two properties it did not have: - **A per-allocation endpoint limit.** New `--multiplex-peer-max-peers` (default 256). Beyond it, CREATE_PERMISSION and CHANNEL_BIND are answered with 508 and SEND indications are dropped. The first rejection per allocation is logged once. - **A reverse index** (session → its endpoints), so `mp_deregister_permission_peers` and `mp_deregister_session_peers` cost that session's own endpoints instead of a full scan of the table shared by every session on the relay thread. ## Why The table is keyed by exact peer IP:port, but permissions are per peer IP, so a single permission covers all 65535 ports of that IP: every SEND indication naming a fresh port added an entry, with no cap and no backpressure. The table is per relay thread and shared, so one busy allocation grows a structure its co-tenants pay for — and every permission expiry and session teardown walked the whole thing. Ephemeral-port churn produces the same growth without anyone trying, so this is also a robustness issue for high-volume deployments. ## Behaviour changes - `--multiplex-peer-max-peers <n>` (1–65535, default 256). Config-file key works too. No effect unless `--multiplex-peer` is set. - An allocation exceeding the limit gets **508** on CREATE_PERMISSION / CHANNEL_BIND. 508 is what this mode already returns for its other capacity limitation (EVEN-PORT), so the code is not new to multiplex-peer clients. - Nothing changes below the limit; the default is far above normal use (a typical allocation registers two endpoints — its peer's RTP and RTCP ports). ## Performance Microbenchmark of the old vs new code paths (arm64, `-O2`, keys precomputed so only table work is timed): | table entries | demux lookup (per datagram) | re-register (per SEND) | permission expiry, 2-endpoint session | |---|---|---|---| | 400 | 99 → 96 ns | 190 → 103 ns | 2.5 µs → 0.068 µs | | 4,000 | 116 → 119 ns | 236 → 125 ns | 9.3 µs → 0.055 µs | | 50,000 | 129 → 133 ns | 270 → 147 ns | 98.7 µs → 0.24 µs | | 500,000 | 501 → 510 ns | 1002 → 510 ns | 986 µs → 1.2 µs | - Data plane is untouched — same map, same lookup; deltas are noise. - The SEND path is ~2× cheaper: the old code did `ur_addr_map_get` **and** `ur_addr_map_put`, and `put` re-scans the bucket. Registering an endpoint the session already owns now returns after the `get`. - Memory: +128 B per endpoint for the index copy, ~310 B per session with endpoints (index array starts at 2 slots because `ioa_addr` is 128 B and the common case is RTP + RTCP). Worst case per allocation is now ~66 KB at the default limit rather than unbounded. The per-thread bound is sessions × limit, so a hard ceiling still wants `--total-quota`. ## Tests - `tests/test_mp_peer_table.c` (new, 8 cases): idempotent re-registration, cross-session conflict, a 4096-port registration run capped at 64, the limit being per-session rather than global, slot reuse after release, per-IP and per-family deregistration, and a deterministic assertion — via a `deregister_ops` counter — that deregistration never touches 200 entries belonging to another session. - `examples/run_tests_multiplex_peer.sh`: server start/stop refactored into functions; adds a run under `--multiplex-peer-max-peers=4` (normal relaying unaffected) and one under `=1` asserting the client sees 508 and the server logs the limit. The second SKIPs where multiplex-peer is inactive (non-Linux). ## Validation - macOS: 18/18 ctest, all `examples/run_tests*.sh`, both fuzzing smoke targets, `make lint` clean. - Linux (Docker): 17/17 ctest; `run_tests.sh`, `run_tests_conf.sh`, `run_tests_mobile.sh`, `run_tests_multiplex_peer.sh`, `run_tests_rfc5780.sh`, `run_tests_stateless_nonce.sh` all green. - Packaged image: `make docker.image dockerfile=debian` + `make test.docker` — 19 Bats tests, 0 failures. ## Reviewer notes - `deregister_ops` is a counter on the table struct read only by the unit test; it is one increment inside a loop that already runs. - `mp_deregister_peer()` had no callers before this change and still has none; it is kept as the exact-key counterpart of the two bulk helpers. - Docs updated: `docs/multiplex-peer.md` (table layout, files-changed table, CLI examples) and `examples/etc/turnserver.conf`.
216 lines
12 KiB
Makefile
216 lines
12 KiB
Makefile
|
|
LIBEVENT_INCLUDE = -I${PREFIX}/include/ -I/usr/local/include/
|
|
|
|
INCFLAGS = -Isrc -Isrc/apps/common -Isrc/server -Isrc/client -Isrc/client++ ${LIBEVENT_INCLUDE}
|
|
|
|
CFLAGS += ${INCFLAGS}
|
|
|
|
MAKE_DEPS = Makefile
|
|
|
|
LIBCLIENTTURN_HEADERS = src/ns_turn_defs.h src/client++/TurnMsgLib.h src/client/ns_turn_ioaddr.h src/client/ns_turn_msg.h src/client/ns_turn_msg_defs.h src/client/ns_turn_msg_defs_experimental.h src/client/ns_turn_msg_addr.h
|
|
LIBCLIENTTURN_MODS = src/client/ns_turn_ioaddr.c src/client/ns_turn_msg_addr.c src/client/ns_turn_msg.c
|
|
LIBCLIENTTURN_DEPS = ${LIBCLIENTTURN_HEADERS} ${MAKE_DEPS}
|
|
LIBCLIENTTURN_OBJS = build/obj/ns_turn_ioaddr.o build/obj/ns_turn_msg_addr.o build/obj/ns_turn_msg.o
|
|
|
|
SERVERTURN_HEADERS = src/ns_turn_atomic.h src/server/ns_turn_allocation.h src/server/ns_turn_ioalib.h src/server/ns_turn_khash.h src/server/ns_turn_maps_rtcp.h src/server/ns_turn_maps.h src/server/ns_turn_server.h src/server/ns_turn_session.h src/server/ns_turn_ratelimit.h
|
|
SERVERTURN_DEPS = ${LIBCLIENTTURN_HEADERS} ${SERVERTURN_HEADERS} ${MAKE_DEPS}
|
|
SERVERTURN_MODS = ${LIBCLIENTTURN_MODS} src/server/ns_turn_allocation.c src/server/ns_turn_maps_rtcp.c src/server/ns_turn_maps.c src/server/ns_turn_server.c src/server/ns_turn_ratelimit.c
|
|
|
|
COMMON_HEADERS = src/apps/common/apputils.h src/apps/common/ns_turn_openssl.h src/apps/common/ns_turn_utils.h src/apps/common/stun_buffer.h
|
|
COMMON_MODS = src/apps/common/apputils.c src/apps/common/ns_turn_utils.c src/apps/common/stun_buffer.c
|
|
COMMON_DEPS = ${LIBCLIENTTURN_DEPS} ${COMMON_MODS} ${COMMON_HEADERS}
|
|
|
|
IMPL_HEADERS = src/apps/relay/ns_ioalib_impl.h src/apps/relay/ns_sm.h src/apps/relay/turn_ports.h src/apps/relay/mp_peer_table.h
|
|
IMPL_MODS = src/apps/relay/ns_ioalib_engine_impl.c src/apps/relay/mp_peer_table.c src/apps/relay/turn_ports.c src/apps/relay/http_server.c src/apps/relay/http_buffer.c src/apps/relay/acme.c
|
|
IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS}
|
|
|
|
HIREDIS_HEADERS = src/apps/relay/hiredis_libevent2.h
|
|
HIREDIS_MODS = src/apps/relay/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 src/apps/relay/dbdrivers/dbd_redis_conninfo.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 src/apps/relay/dbdrivers/dbd_redis_conninfo.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 src/prometheus/prom.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 src/prometheus/prom.c ${HIREDIS_MODS} ${USERDB_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
|
|
|
|
.PHONY: all test check unit-tests clean distclean sqlite_empty_db install deinstall uninstall reinstall
|
|
|
|
all: ${TURN_BUILD_RESULTS}
|
|
|
|
test: check
|
|
|
|
check: bin/turnutils_rfc5769check
|
|
bin/turnutils_rfc5769check
|
|
|
|
### Unit tests (Unity, configured via CMake — opt-in, requires cmake):
|
|
unit-tests:
|
|
${MKDIR} build/unit-tests
|
|
cd build/unit-tests && cmake -DBUILD_TESTING=ON ${CURDIR} && $(MAKE) check
|
|
|
|
# ns_turn_khash.h is a vendored 3rd-party header (khash); skip it.
|
|
format:
|
|
find . \( -iname "*.c" -o -iname "*.h" \) -not -name "ns_turn_khash.h" | xargs clang-format -i
|
|
|
|
lint:
|
|
find . \( -iname "*.c" -o -iname "*.h" \) -not -name "ns_turn_khash.h" | xargs clang-format --dry-run -Werror
|
|
|
|
include/turn/ns_turn_defs.h: src/ns_turn_defs.h
|
|
${RMCMD} include
|
|
${MKBUILDDIR} include/turn/client
|
|
cp -pf src/client/*.h include/turn/client/
|
|
cp -pf src/client++/*.h include/turn/client/
|
|
cp -pf src/ns_turn_defs.h include/turn/
|
|
|
|
bin/turnutils_uclient: ${COMMON_DEPS} src/apps/uclient/session.h lib/libturnclient.a src/apps/uclient/mainuclient.c src/apps/uclient/uclient.c src/apps/uclient/uclient.h src/apps/uclient/startuclient.c src/apps/uclient/startuclient.h src/server/ns_turn_ioalib.h
|
|
${MKBUILDDIR} bin
|
|
${CC} ${CPPFLAGS} ${CFLAGS} src/apps/uclient/uclient.c src/apps/uclient/startuclient.c src/apps/uclient/mainuclient.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
|
|
|
|
bin/turnutils_natdiscovery: ${COMMON_DEPS} lib/libturnclient.a src/apps/natdiscovery/natdiscovery.c src/server/ns_turn_ioalib.h
|
|
pwd
|
|
${MKBUILDDIR} bin
|
|
${CC} ${CPPFLAGS} ${CFLAGS} src/apps/natdiscovery/natdiscovery.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
|
|
|
|
bin/turnutils_oauth: ${COMMON_DEPS} lib/libturnclient.a src/apps/oauth/oauth.c src/server/ns_turn_ioalib.h
|
|
pwd
|
|
${MKBUILDDIR} bin
|
|
${CC} ${CPPFLAGS} ${CFLAGS} src/apps/oauth/oauth.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
|
|
|
|
bin/turnutils_stunclient: ${COMMON_DEPS} lib/libturnclient.a src/apps/stunclient/stunclient.c src/server/ns_turn_ioalib.h
|
|
pwd
|
|
${MKBUILDDIR} bin
|
|
${CC} ${CPPFLAGS} ${CFLAGS} src/apps/stunclient/stunclient.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
|
|
|
|
bin/turnutils_rfc5769check: ${COMMON_DEPS} lib/libturnclient.a src/apps/rfc5769/rfc5769check.c src/server/ns_turn_ioalib.h
|
|
pwd
|
|
${MKBUILDDIR} bin
|
|
${CC} ${CPPFLAGS} ${CFLAGS} src/apps/rfc5769/rfc5769check.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
|
|
|
|
bin/turnserver: ${SERVERAPP_DEPS} src/apps/relay/acme.h src/apps/relay/http_server.h
|
|
${MKBUILDDIR} bin
|
|
${RMCMD} bin/turnadmin
|
|
${CC} ${CPPFLAGS} ${CFLAGS} ${DBCFLAGS} ${IMPL_MODS} -Ilib ${SERVERAPP_MODS} ${COMMON_MODS} ${SERVERTURN_MODS} -o $@ ${DBLIBS} ${LDFLAGS}
|
|
cd bin; ln -s turnserver turnadmin
|
|
|
|
bin/turnutils_peer: ${COMMON_DEPS} ${LIBCLIENTTURN_MODS} ${LIBCLIENTTURN_DEPS} lib/libturnclient.a src/apps/peer/mainudpserver.c src/apps/peer/udpserver.h src/apps/peer/udpserver.c src/server/ns_turn_ioalib.h
|
|
${MKBUILDDIR} bin
|
|
${CC} ${CPPFLAGS} ${CFLAGS} src/apps/peer/mainudpserver.c src/apps/peer/udpserver.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
|
|
|
|
### Client Library:
|
|
|
|
lib/libturnclient.a: ${LIBCLIENTTURN_OBJS} ${LIBCLIENTTURN_DEPS}
|
|
${MKBUILDDIR} lib
|
|
${ARCHIVERCMD} $@ ${LIBCLIENTTURN_OBJS}
|
|
|
|
build/obj/ns_turn_ioaddr.o: src/client/ns_turn_ioaddr.c ${LIBCLIENTTURN_DEPS}
|
|
${MKBUILDDIR} build/obj
|
|
${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_ioaddr.c -o $@
|
|
|
|
build/obj/ns_turn_msg_addr.o: src/client/ns_turn_msg_addr.c ${LIBCLIENTTURN_DEPS}
|
|
${MKBUILDDIR} build/obj
|
|
${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_msg_addr.c -o $@
|
|
|
|
build/obj/ns_turn_msg.o: src/client/ns_turn_msg.c ${LIBCLIENTTURN_DEPS} src/apps/common/ns_turn_openssl.h src/apps/common/ns_turn_utils.h
|
|
${MKBUILDDIR} build/obj
|
|
${CC} ${CPPFLAGS} ${CFLAGS} -c src/client/ns_turn_msg.c -o $@
|
|
|
|
### Clean all:
|
|
|
|
clean:
|
|
${RMCMD} bin build lib obj *bak *~ */*~ */*/*~ */*/*/*~ *core */*core */*/*core include tmp sqlite
|
|
|
|
distclean: clean
|
|
${RMCMD} Makefile
|
|
|
|
### SQLite empty database:
|
|
sqlite_empty_db : sqlite/turndb
|
|
|
|
sqlite/turndb : turndb/schema.sql
|
|
${MKDIR} sqlite
|
|
${RMCMD} sqlite/turndb
|
|
${SQLITE_CMD} sqlite/turndb < turndb/schema.sql
|
|
|
|
### Install all:
|
|
|
|
install: all ${MAKE_DEPS}
|
|
${MKDIR} ${DESTDIR}${PREFIX}
|
|
${MKDIR} ${DESTDIR}${BINDIR}
|
|
${MKDIR} ${DESTDIR}${TURNDBDIR}
|
|
${MKDIR} ${DESTDIR}${MANPREFIX}/man/man1
|
|
${MKDIR} ${DESTDIR}${CONFDIR}
|
|
${MKDIR} ${DESTDIR}${LIBDIR}
|
|
${MKDIR} ${DESTDIR}${EXAMPLESDIR}
|
|
${MKDIR} ${DESTDIR}${DOCSDIR}
|
|
${MKDIR} ${DESTDIR}${SCHEMADIR}
|
|
${MKDIR} ${DESTDIR}${TURNINCLUDEDIR}
|
|
${INSTALL_PROGRAM} bin/turnserver ${DESTDIR}${BINDIR}
|
|
${INSTALL_PROGRAM} bin/turnadmin ${DESTDIR}${BINDIR}
|
|
${INSTALL_PROGRAM} bin/turnutils_uclient ${DESTDIR}${BINDIR}
|
|
${INSTALL_PROGRAM} bin/turnutils_peer ${DESTDIR}${BINDIR}
|
|
${INSTALL_PROGRAM} bin/turnutils_stunclient ${DESTDIR}${BINDIR}
|
|
${INSTALL_PROGRAM} bin/turnutils_oauth ${DESTDIR}${BINDIR}
|
|
${INSTALL_PROGRAM} bin/turnutils_natdiscovery ${DESTDIR}${BINDIR}
|
|
${INSTALL_MAN} man/man1/turnserver.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_MAN} man/man1/turnadmin.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_MAN} man/man1/turnutils.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_MAN} man/man1/turnutils_uclient.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_MAN} man/man1/turnutils_stunclient.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_MAN} man/man1/turnutils_oauth.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_MAN} man/man1/turnutils_natdiscovery.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_MAN} man/man1/turnutils_peer.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_MAN} man/man1/coturn.1 ${DESTDIR}${MANPREFIX}/man/man1/
|
|
${INSTALL_STATIC_LIB} lib/libturnclient.a ${DESTDIR}${LIBDIR}
|
|
${INSTALL_DATA} LICENSE ${DESTDIR}${DOCSDIR}
|
|
${INSTALL_DATA} README.turnserver ${DESTDIR}${DOCSDIR}
|
|
${INSTALL_DATA} README.turnadmin ${DESTDIR}${DOCSDIR}
|
|
${INSTALL_DATA} README.turnutils ${DESTDIR}${DOCSDIR}
|
|
${INSTALL_DATA} INSTALL ${DESTDIR}${DOCSDIR}
|
|
${INSTALL_DATA} postinstall.txt ${DESTDIR}${DOCSDIR}
|
|
${INSTALL_DATA} turndb/schema.sql ${DESTDIR}${SCHEMADIR}
|
|
${INSTALL_DATA} turndb/schema.mongo.sh ${DESTDIR}${SCHEMADIR}
|
|
${INSTALL_DATA} turndb/testredisdbsetup.sh ${DESTDIR}${SCHEMADIR}
|
|
${INSTALL_DATA} turndb/testmongosetup.sh ${DESTDIR}${SCHEMADIR}
|
|
${INSTALL_DATA} turndb/testsqldbsetup.sql ${DESTDIR}${SCHEMADIR}
|
|
${INSTALL_DATA} turndb/schema.userdb.redis ${DESTDIR}${SCHEMADIR}
|
|
${INSTALL_DATA} turndb/schema.stats.redis ${DESTDIR}${SCHEMADIR}
|
|
if [ -f sqlite/turndb ] ; then ${INSTALL_DATA} sqlite/turndb ${DESTDIR}${TURNDBDIR}/turndb; fi
|
|
${INSTALL_DATA} examples/etc/turnserver.conf ${DESTDIR}${CONFDIR}/turnserver.conf.default
|
|
${INSTALL_DIR} examples/etc ${DESTDIR}${EXAMPLESDIR}
|
|
${INSTALL_DIR} examples/scripts ${DESTDIR}${EXAMPLESDIR}
|
|
${RMCMD} ${DESTDIR}${EXAMPLESDIR}/scripts/rfc5769.sh
|
|
${INSTALL_DIR} include/turn/client ${DESTDIR}${TURNINCLUDEDIR}
|
|
${INSTALL_DATA} include/turn/ns_turn_defs.h ${DESTDIR}${TURNINCLUDEDIR}
|
|
${MORECMD} ${DESTDIR}${DOCSDIR}/postinstall.txt
|
|
|
|
deinstall: ${MAKE_DEPS}
|
|
${PKILL_PROGRAM} turnserver || ${ECHO_CMD} OK
|
|
${RMCMD} ${DESTDIR}${TURNDBDIR}/turndb
|
|
${RMCMD} ${DESTDIR}${DOCSDIR}
|
|
${RMCMD} ${DESTDIR}${SCHEMADIR}
|
|
${RMCMD} ${DESTDIR}${BINDIR}/turnserver
|
|
${RMCMD} ${DESTDIR}${BINDIR}/turnadmin
|
|
${RMCMD} ${DESTDIR}${BINDIR}/turnutils_peer
|
|
${RMCMD} ${DESTDIR}${BINDIR}/turnutils_uclient
|
|
${RMCMD} ${DESTDIR}${BINDIR}/turnutils_stunclient
|
|
${RMCMD} ${DESTDIR}${BINDIR}/turnutils_oauth
|
|
${RMCMD} ${DESTDIR}${BINDIR}/turnutils_natdiscovery
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnserver.1
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnadmin.1
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils.1
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_uclient.1
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_stunclient.1
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_oauth.1
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_natdiscovery.1
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/turnutils_peer.1
|
|
${RMCMD} ${DESTDIR}${MANPREFIX}/man/man1/coturn.1
|
|
${RMCMD} ${DESTDIR}${LIBDIR}/libturnclient.a
|
|
${RMCMD} ${DESTDIR}${EXAMPLESDIR}
|
|
${RMCMD} ${DESTDIR}${CONFDIR}/turnserver.conf.default
|
|
${RMCMD} ${DESTDIR}${TURNINCLUDEDIR}
|
|
|
|
uninstall: deinstall
|
|
|
|
reinstall: deinstall install
|