Commit Graph
119 Commits
Author SHA1 Message Date
Pavel PunskyandClaude Opus 4.8 8c7d8fcb86 Enable --udp-recvmmsg by default on Linux (#1930)
## Summary

Flips the Linux default for `--udp-recvmmsg` from **off** to **on**.
Operators opt out with `--udp-recvmmsg=false` (or `=0`).

> **Stacked on #1929.** This depends on the recvmmsg-scoping change in
#1929 and is based on that branch, so the diff shows only the default-on
change. GitHub will auto-retarget the base to `master` once #1929
merges. Merge #1929 first.

## Why this is now safe

The original objection to default-on (recorded in
`docs/PerformanceIterationLog.md`) was the **per-session-relay-socket
prealloc tax**: `--udp-recvmmsg` applied the 16-buffer batch path to
every connected relay socket, which only ever carries one flow, so the
churn ate the listener-side win.

#1929 scoped recvmmsg to **shared fan-in sockets only**
(`udp_recvmmsg_eligible`: the client listener, plus the per-thread
shared relay socket under `--multiplex-peer`). Per-session relay sockets
now stay on the single-recv path regardless of the flag, so that tax is
gone. The one socket touched by default — the client listener — is a
genuine fan-in point:

- batches whenever client concurrency is non-trivial (measured
`avg_batch ≈ 16` under load), and
- costs little when idle (few packets ⇒ few prealloc cycles).

## What changed

- `mainrelay.c`: `turn_params.udp_recvmmsg` default `false → true`
(Linux only).
- Removed the now-dead `--multiplex-peer` auto-enable block and the
`udp_recvmmsg_set_explicitly` tracking it relied on; multiplex-peer gets
its recvmmsg window from the default. The opt-out flows through the
normal `get_bool_value` path.
- Help text, `man/man1/turnserver.1`, `examples/etc/turnserver.conf`,
`CLAUDE.md`, and `docs/PerformanceIterationLog.md` updated for the new
default + opt-out.

Per-session relay sockets and DTLS session sockets are unchanged.

## Validation

- **Format:** clang-format 15.0.7 clean.
- **macOS:** build + ctest 6/6 + `run_tests.sh` pass.
- **Linux (Docker, clean build):** ctest 5/5; `run_tests.sh`,
`run_tests_conf.sh`, `run_tests_multiplex_peer.sh` all pass (no FAIL).
- **Runtime proof (loopback, `--udp-recvmmsg-log`):**
- Default, no flag: recvmmsg active, `calls=13714 packets=219306
avg_batch=15.99`.
  - `--udp-recvmmsg=false`: zero recvmmsg activity — opt-out confirmed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 21:27:05 -07:00
Pavel PunskyandClaude Sonnet 4.6 e0c37a3aa0 Multiplexpeer (#1916)
## Summary

Adds **`--multiplex-peer`**, a non-standard relay mode that replaces the
per-allocation peer-side port bind with **one shared IPv4+IPv6 UDP
socket pair per relay thread**. Sessions are demultiplexed by exact peer
IP:port in a per-thread `mp_table`. This lifts the ~16 k allocation cap
that the default 49152-65535 relay port range imposes, and dramatically
reduces kernel-level UDP receive-buffer drops under high pps.

Design and trade-offs: [docs/multiplex-peer.md](docs/multiplex-peer.md).

## What changes

### Server (turnserver)

- **`--multiplex-peer`** (cross-platform) — enable the shared per-thread
relay sockets. Replaces the per-session port bind. Implies sendmmsg
batching on Linux and default-enables `--udp-recvmmsg` (override with
`--udp-recvmmsg=0`). Incompatible with EVEN-PORT — those Allocates are
rejected with 400.
- **`--multiplex-peer-port <port>`** (cross-platform, default 3480) —
base port; thread `i` binds `<base>+2i` (IPv4) and `<base>+2i+1` (IPv6).
A 4-thread server consumes 8 ports.
- **`--udp-gso`** (Linux-only CLI) — UDP-GSO (`UDP_SEGMENT` cmsg) on the
relay send path. Requires `--multiplex-peer` (which is what enables the
sendmmsg batching GSO piggybacks on); passing `--udp-gso` alone is a
silent no-op.
- **CLI surface tightened**: `--udp-recvmmsg`, `--udp-recvmmsg-log`,
`--udp-gso` and their fields are now `#if defined(__linux__)` — absent
from `--help`, rejected with `unrecognized option`, and the code paths
compile out on macOS/Windows.
- **Windows portability**: `SO_REUSEPORT` in `mp_open_socket` wrapped in
`#ifdef` (MSVC's Winsock doesn't define it; REUSEPORT was defensive
anyway because the per-thread port layout is unique by construction).
- **`--sock-buf-size` honoured at startup**: the shared multiplex-peer
relay socket now calls `set_ioa_socket_buf_size` in `mp_open_socket` so
the configured rcvbuf is in effect from the moment the socket exists,
not deferred to the first Allocate.

### turnutils_uclient (loadgen)

- **`--no-even-port`** — force `ep = -1` on Allocate. The default path
randomly attaches EVEN-PORT (with no-R bit) even under `-c`, which
`--multiplex-peer` strictly rejects with 400; this flag makes
alloc-flood runs against multiplex-peer deterministic.
- **Legacy `timer_handler` now wraps the per-tick send batch with
`uclient_send_batch_begin/_end`** — without this, runs with
`--sender-threads 0` (the default for `-m < 4`) silently fell through
every send to plain `send(2)`. strace A/B: 205 k `sendto` → 61 k
`sendmsg` (GSO) + 4 k `sendmmsg` + small `sendto` residual for control.

## Measured impact (3-droplet DigitalOcean, c-4 / 4 vCPU, 8 concurrent
UDP streams, 45 s)

| | baseline | `--udp-recvmmsg` | `--multiplex-peer` | `--multiplex-peer
--udp-gso` |
|---|---:|---:|---:|---:|
| Server NIC rx pps (UDP relay both legs) | 350 k | 334 k | 326 k | 294
k |
| Server `UdpInDatagrams` pps | 279 k | 292 k | 300 k | 294 k |
| **Server `UdpRcvbufErrors` pps** | **71 k** | 42 k | 26 k | **0.3 k
(−99.6 %)** |
| **`turnserver` process CPU** | **387 %** | 205 % | 283 % | **133 %
(−65 %)** |
| Server host idle | 22 % | 49 % | 41 % | **68 %** |

Same loadgen-side packet rate (~2 M pps reported by uclient `send_pps`
after the legacy-path batching fix). Iteration log:
[docs/PerformanceIterationLog.md](docs/PerformanceIterationLog.md).

## Test plan

- [x] `ctest --test-dir build` — 3/3 pass (test_ioaddr, test_stun_msg,
test_http_server) on macOS + Linux.
- [x] `examples/run_tests.sh` — 4 protocols + 4 threaded + load-gen
smoke on Linux; 4 protocols on macOS.
- [x] `examples/run_tests_conf.sh` — same coverage, conf-driven.
- [x] `examples/run_tests_multiplex_peer.sh` — UDP/TCP/TLS/DTLS via
`--multiplex-peer --multiplex-peer-port=35000` on macOS + Linux.
- [x] Flag matrix smoke on macOS: `--multiplex-peer`,
`--multiplex-peer-port=42000`, `--multiplex-peer --udp-gso` (no-op),
`uclient --no-even-port`, `uclient --listener-threads N --sender-threads
M` — all pass; `--udp-recvmmsg` / `--udp-gso` correctly rejected with
`unrecognized option`.
- [x] Flag matrix smoke on Linux (Docker): same + `--udp-recvmmsg`
accepted, `--multiplex-peer` auto-enables `--udp-recvmmsg`,
`--udp-recvmmsg=0` overrides the auto-enable.
- [x] Windows compile fix verified — `SO_REUSEPORT` no longer referenced
unconditionally.
- [x] 3-droplet perf matrix completed; per-hop UDP counters captured.

## Docs updated

- New: [docs/multiplex-peer.md](docs/multiplex-peer.md)
- [README.turnserver](README.turnserver): full entries for
`--multiplex-peer`, `--multiplex-peer-port`, `--udp-gso`; clarified
`--udp-recvmmsg` auto-enable semantics.
- [README.turnutils](README.turnutils): added `--no-even-port`, plus
previously-undocumented `--listener-threads` / `--sender-threads`
loadgen pool flags.
- [examples/etc/turnserver.conf](examples/etc/turnserver.conf):
commented `udp-recvmmsg`, `udp-recvmmsg-log`, `udp-gso`,
`multiplex-peer`, `multiplex-peer-port` keys with one-paragraph
descriptions and pointer to `docs/multiplex-peer.md`.
- Man pages regenerated via `./make-man.sh`.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 19:16:55 -07:00
nfuhler faff5bf106 examples/turnserver.conf: update description of cli option (#1909)
the previous description does not describe the correct default since
commit 9467af5
2026-05-10 21:12:56 -07:00
Pavel PunskyandClaude Sonnet 4.6 69aa0e4401 Keep only NEV_UDP_SOCKET_PER_THREAD network engine (#1849)
Remove the two engine implementations (NEV_UDP_SOCKET_PER_SESSION and
NEV_UDP_SOCKET_PER_ENDPOINT) and all the dispatch/selection logic around
them. NEV_UDP_SOCKET_PER_THREAD is now the sole, unconditional
implementation.

- mainrelay.h: removed _NET_ENG_VERSION enum, typedef, and
net_engine_version / net_engine_version_txt struct fields
- mainrelay.c: removed NE_TYPE_OPT CLI option, set_network_engine(),
per-endpoint branch in print_features(), and all remaining
net_engine_version references
- netengine.c: removed run_udp_listener_thread(),
setup_socket_per_endpoint_udp_listener_servers() (~190 lines),
setup_socket_per_session_udp_listener_servers() (~90 lines); simplified
setup_barriers(), setup_relay_server(), run_general_relay_thread(),
setup_general_relay_servers(), and setup_server() by eliminating all
engine-type conditionals
- turn_admin_server.c: replaced dynamic engine version lookups with
hardcoded values (3 / "UDP thread per CPU core") in CLI and HTTPS status
handlers

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:26:46 -07:00
Pavel Punsky 6e8dd731a7 Update config and Readme files about deprecated TLSv1/1.1 (#1848)
This commit only updates documentation - the change has been done in
#1693
2026-04-05 20:49:46 -07:00
Pavel Punsky 9467af5041 CLI interface is disabled by default (#1830)
cli interface is ON by default which creates a security risk (even
though requires a password) and recommended to be disabled.
Instead of just recommendation, this PR disables CLI by default and now
requires an explicit flag to enable it

If using old configuration or cli arguments to turnserver - it will log
an error message about `--no-cli` being deprecated while doing nothing
(already disabled). This log line will be removed in the future
2026-03-06 18:00:45 -08:00
Pavel Punsky 20d8e38297 Disable reason string in response messages to reduce amplification factor (#1829)
Disable the messages by default - they can be re-enabled using
`--include-reason-string` option

As a result of not sending reason string (which is optional by standard
and provide debugging information for the actual numeric error code)
response message size can be decreased by up to NNN bytes.
2026-03-06 17:59:21 -08:00
Pavel Punsky 59921981bb Implement configurable buffer sizes (#1780)
# Description

Replace the hardcoded buffer sizes inside coturn to make them
configurable for different use cases (low bitrate use cases can save
memory and high bitrate use case can avoid congestion) - based on #1089

Add this feature in both sides (listener and relay connections).

# Tests

For now it is only the automated CI tests.
Confirmed with debugger that buffer sizes are set according to the
arguments.
2025-12-25 14:06:28 -08:00
Copilot 99984fbccd Add configurable CPU count option for containerized environments (#1717)
This PR adds a new `--cpus` configuration option to address CPU
detection issues in virtualized and containerized environments where
`_SC_NPROCESSORS_CONF` and `_SC_NPROCESSORS_ONLN` return host CPU counts
instead of allocated container CPUs.

## Problem
In containerized deployments, coturn detects the host's CPU count (e.g.,
128 CPUs) instead of the container's allocated CPUs (e.g., 2 CPUs). This
causes the server to create excessive relay threads and database
connections, leading to resource exhaustion and performance issues.

## Solution
Added a new `cpus` configuration option that allows manual override of
CPU detection:

### Command Line Usage
```bash
turnserver --cpus 2
```

### Configuration File Usage
```ini
# Override system CPU count detection for containers
cpus=2
```

## Key Features
- **Backward Compatible**: No changes needed for existing deployments
- **Input Validation**: Values must be between 1 and 128 with proper
error handling
- **Comprehensive Documentation**: Updated man pages and example config
files
- **Both Interfaces**: Works via command line and configuration file

## Testing
The implementation has been thoroughly tested:

```bash
# Container with 2 allocated CPUs on 128-CPU host
$ turnserver --cpus 2
INFO: System cpu num is 128       # Host detection
INFO: System enable num is 128    # Host detection  
INFO: Configured cpu num is 2     # Override applied
INFO: Total General servers: 2    # Correct thread count
```

-  Command line option: `--cpus 8` creates 8 relay servers
-  Config file option: `cpus=6` creates 6 relay servers  
-  Error handling: Invalid values show appropriate errors
-  Default behavior: Without option, uses system detection
-  RFC5769 tests: All protocol tests still pass

## Files Modified
- `src/apps/relay/mainrelay.c` - Core implementation
- `src/apps/relay/mainrelay.h` - Added configuration flag
- `examples/etc/turnserver.conf` - Added documentation and example
- `man/man1/turnserver.1` - Updated man page

This change directly addresses the resource consumption issues in
containerized environments while maintaining full backward
compatibility.

Fixes #1628.
2025-07-10 15:37:02 +02:00
Pavel Punsky cc5e18fc89 Make older TLS versions optional (#1693)
TLSv1 and TLSv1.1 can be enabled using `--tlsv1` and `--tlsv1_1`
arguments accordingly
That assumes openssl version being used has these versions enabled
(which as of openssl-3.5 is not by default)
2025-05-30 09:20:14 -07:00
Pavel Punsky 14f84fa48c [BREAKING] Deprecate response-origin-only-with-rfc5780 (#1690)
Make this true - response-origin-only will only be enabled with rfc5780 option enabled
2025-05-28 16:37:20 -07:00
Pavel Punsky 4cc076d424 [BREAKING] Invert no-stun-backward-compatibility to be default on (#1689)
Deprecate `--no-stun-backward-compatibility` and set it to true by
default
Add new option `--stun-backward-compatibility`, off by default

Update example/recommended configuration files

This is a breaking change as passing `--no-stun-backward-compatibility`
will be rejected as invalid argument
2025-05-28 16:23:33 -07:00
Pavel Punsky 368355a06f Invert RFC5780 option to default off (#1688)
Invert `--no-rfc5780` option to be true by default
Make it `--rfc5780` to enable it
Update example/recommended configuration files

Passing `--no-rfc5780` will have no effect as this is the default
behavior now
2025-05-28 15:08:57 -07:00
Stefan Kieszkowski 24647a1e83 [Quick Fix] Fix Repeated Line in Example turnserver.conf (#1671)
The `#allocation-default-address-family="ipv4"` line is repeated twice
in the example config, changed the second one to be `"ipv6"` which I
assume it was intended to be.
2025-05-21 07:33:51 +02:00
Chai-ShiandBen Chang 268f811f9e Add prometheus setting suggestions on turn.conf in example folder (#1597)
I believe that many users, like myself, prefer to reference the
`turn.conf` file when deploying the TURN server with Docker, rather than
the `Readme.turnserver`. Additionally, I think it's important to
synchronize the Prometheus settings from the README into the` turn.conf`
file for better clarity. This way, users won't overlook any essential
options.

Co-authored-by: Ben Chang <ben_chang@htc.com>
2024-11-17 19:49:10 -08:00
Nikolayshcxandnmegdanov eb3af26867 Add support for raw public keys (Rfc 7250) (#1458)
Resolving #1456

---------

Co-authored-by: nmegdanov <nikolay.megdanov@softavail.com>
2024-04-19 17:12:48 +02:00
Wittmer, Christian b009624902 Update turnserver.conf Example about listening-ip (#1336)
Fixes #1294
2024-04-09 23:03:53 +02:00
Dave Lambley 20c8d86a34 Return a 400 response to HTTP requests (#1231)
For our deployment, it is useful if coturn returns a valid HTTP response to an HTTP request. To do this on the same port as STUN/TURN and without enabling the admin site, I have extended `read_client_connection()` to return a canned HTTP response, in response to an HTTP request, rather than immediately closing the connection.
2023-11-05 17:25:12 -08:00
Alexander Udovichenko 2a695ea855 Add warning and disable web admin if no-tls option used (#1256)
Fixes https://github.com/coturn/coturn/issues/1239

https to web ui freeze in browser if no_tls option used, because no tls
stuff initialized.
This PR add warning about this and comment aboute this in default config
2023-08-27 16:27:37 -07:00
czephyr 19744a4a39 added warnings for prometheus apt unavailability (#1184)
added some warnings that the prometheus implementation is unavailable
when installing through apt
coturn/coturn#1133
2023-08-20 13:17:37 -07:00
Hyorin Choi ab1292059f Update turnserver.conf (#1009)
Made some text proofreading
2022-10-26 22:53:32 +02:00
Pavel Punsky 41a8aa09ff Document dependency between new-log-timestamp-format and new-log-timestamp 2022-08-27 20:34:35 -07:00
Pavel Punsky 0cb8535de6 Update example turnserver.conf file to reflect that dh2066 is default 2022-08-14 15:20:59 -07:00
KORAY VATANSEVER 22af3ea567 Add syslog facility configuration 2021-07-07 15:56:30 +03:00
Mészáros Mihály 708b83ea78 RESPONSE_ORIGIN attribute only if rfc5780 is on 2021-06-05 22:10:31 +02:00
Mészáros Mihály 54ef051844 Disable stun backward compatibility 2021-06-05 22:10:31 +02:00
Mészáros Mihály e7ddfb4f4b Tidy in turnserver.conf rfc5780 option 2021-06-05 22:10:31 +02:00
Mészáros Mihály eda11698f0 Add option no-rfc5780
To avoid any amplifiaction STUN binding attacks.
2021-06-05 22:10:31 +02:00
Mészáros Mihály 27cd04194e Merge pull request #717 from marcoschum/patch-1
Update turnserver.conf
2021-03-23 09:35:42 +01:00
Mészáros Mihály 2204778ce1 Replace keep-address-family with allocation-default-address-family 2021-03-12 23:05:18 +01:00
marcoschum cfb03bb934 Update turnserver.conf
fixed typo mor --> more
2021-02-24 09:19:03 +01:00
Mészáros Mihály 104ab83f09 Automatically notify systemd if compiled 2021-01-10 20:57:43 +01:00
Mészáros Mihály a66e5cd286 Remove pid handling from systemd service files 2021-01-10 20:57:06 +01:00
Mészáros Mihály ef7916842d Add systemd notification support 2021-01-07 17:51:34 +00:00
Mészáros Mihály 14f1630ec6 Fix stale-nonce documentation Resolves #604 2021-01-05 10:25:10 +00:00
Mészáros Mihály 27b261eb58 Disable binding logging to avoid DoS attack
* Add new option log-binding
2021-01-05 09:55:55 +00:00
Mészáros Mihály d73a8e85d7 Add acme to config file 2020-12-18 08:05:19 +00:00
Mészáros Mihály b0fb4a9a0a Rename new timestamp options, and fix these cli handling 2020-12-08 11:51:25 +01:00
Mészáros Mihály 37b61993e5 Add new log options to config file 2020-12-08 11:10:15 +01:00
David Florness 2baacbf895 Delete trailing whitespace in example configuration files 2020-10-17 13:49:07 -04:00
Mészáros Mihály 388d939ed9 Change prometheus exporter port to 9641 2020-08-03 14:24:20 +02:00
Mészáros Mihály c9cd99e4f5 Disable prometheus by default 2020-08-03 10:25:56 +02:00
wolmi a5d1fbba57 Merge branch 'master' into prometheus 2020-06-29 09:33:20 +02:00
bpcurse 1a4b4cc63a Remove reference to SSLv3
Judging from the information provided here https://github.com/coturn/coturn/issues/220#issuecomment-371916988,
SSL isn't supported anymore so the reference should be removed from the config file.
2020-05-29 15:24:21 +02:00
Mészáros Mihály 113f13855a Fix missing DH2066 default update in config 2020-05-18 08:24:40 +02:00
Miquel Ortega 83cf9ea6c4 Merge branch 'prometheus' of github.com:wolmi/coturn into prometheus 2020-05-05 19:44:16 +02:00
Miquel Ortega fdfa4b8594 Added no-prometheus flag on example configuration 2020-05-05 19:32:25 +02:00
Mészáros Mihály 7d1c1e0f89 Add new test certs 2020-04-28 09:26:31 +00:00
Mészáros Mihály 991a82e104 Merge branch 'master' into master 2020-04-28 09:47:20 +02:00
Mészáros Mihály 1e4456ea92 Merge pull request #506 from dbrgn/rename-prod
Rename "prod" config option to "no-software-attribute"
2020-04-28 09:18:51 +02:00