Compare commits

..

34 Commits
462 ... main

Author SHA1 Message Date
tyranron
e825110d38
Update Alpine to 3.21.1 version in Docker image
Some checks failed
Docker / build (arm32v7, alpine) (push) Has been cancelled
Docker / build (arm32v7, debian) (push) Has been cancelled
Docker / build (arm64v8, alpine) (push) Has been cancelled
Docker / build (arm64v8, debian) (push) Has been cancelled
Docker / build (i386, alpine) (push) Has been cancelled
Docker / build (i386, debian) (push) Has been cancelled
Docker / build (ppc64le, alpine) (push) Has been cancelled
Docker / build (ppc64le, debian) (push) Has been cancelled
Docker / build (s390x, alpine) (push) Has been cancelled
Docker / build (s390x, debian) (push) Has been cancelled
Docker / test (amd64, alpine) (push) Has been cancelled
Docker / test (amd64, debian) (push) Has been cancelled
Docker / test (arm32v6, alpine) (push) Has been cancelled
Docker / test (arm32v6, debian) (push) Has been cancelled
Docker / test (arm32v7, alpine) (push) Has been cancelled
Docker / test (arm32v7, debian) (push) Has been cancelled
Docker / test (arm64v8, alpine) (push) Has been cancelled
Docker / test (arm64v8, debian) (push) Has been cancelled
Docker / test (i386, alpine) (push) Has been cancelled
Docker / test (i386, debian) (push) Has been cancelled
Docker / test (ppc64le, alpine) (push) Has been cancelled
Docker / test (ppc64le, debian) (push) Has been cancelled
Docker / test (s390x, debian) (push) Has been cancelled
Docker / push (alpine, docker.io) (push) Has been cancelled
Docker / push (alpine, ghcr.io) (push) Has been cancelled
Docker / push (alpine, quay.io) (push) Has been cancelled
Docker / push (debian, docker.io) (push) Has been cancelled
Docker / push (debian, ghcr.io) (push) Has been cancelled
Docker / push (debian, quay.io) (push) Has been cancelled
Docker / release (GitHub) (push) Has been cancelled
2025-01-08 13:02:43 +02:00
guoyingbo
22aae5d0d0
Windows '_WTA' bug (#1624)
Every time the '_WTA' is called, its initial value is null, so the
function returns directly.


c98bb93514/src/apps/common/apputils.c (L905-L908)

c98bb93514/src/apps/common/apputils.c (L939-L941)

c98bb93514/src/apps/common/apputils.c (L960-L962)

c98bb93514/src/apps/common/apputils.c (L981-L983)
2025-01-04 17:50:29 -08:00
Pavel Punsky
c98bb93514
Fix cmake issues detecting mongo and libsystemd on macOS (#1621)
- libsystemd does not exist on macOS - ignore it and reduce warnings
during cmake step
- mongo-c has cmake file on macOS - reusing the same code path and
reduce warnings
2024-12-27 14:52:44 -08:00
Pavel Punsky
58f1b8926c
Fix hiredis detection by cmake (#1620)
See #1618 for details

This fix allows proper hiredis detection on macOS when building with
cmake
2024-12-27 11:36:58 -08:00
tyranron
326b983ece
Update Debian "bookworm" to 20241223 snapshot in Docker image 2024-12-25 11:08:34 +02:00
Pavel Punsky
89a5600be1
Drop TLS version support detection (#1617)
With requiring openssl version at least 1.1.1 all versions of TLS (up to
and including 1.3) and DTLS 1.2 are supported
With that, no detection or ability to disable a version will be provided
2024-12-19 17:10:49 -08:00
Pavel Punsky
20da9cd09a
Cleanup ALPN_SUPPORTED define usage (#1616)
As of openssl 1.1.1 ALPN is supported - no need for all the ifdefs anymore
2024-12-19 16:41:45 -08:00
Pavel Punsky
9f779a64d0
Fix warnings type conversion (#1615) 2024-12-19 09:05:37 -08:00
Alex Gustafsson
790cc6f79e
Add parameter for specifying prometheus path (#1602)
Add a `--prometheus-path` parameter which allows users to specify at
what
path the metrics should be exposed.

This simplifies serving metrics on a specific path behind some
restrictive reverse proxies that expect the upstream server to serve
URLs with paths matching the requested path.

Co-authored-by: Pavel Punsky <eakraly@users.noreply.github.com>
2024-12-18 14:50:38 -08:00
Pavel Punsky
3370eaf12d
Do not build with Ubuntu 18, use 24 (#1613)
Re-delete file that was undeleted accidentally
2024-12-15 17:37:03 -08:00
Michael Jones
c9878469fc
[BREAKING] Remove support for openssl older than 1.1.1 (#1397)
Openssl 1.1.1 is end-of-life in September 2023.
This PR removes support for versions of openssl OLDER than 1.1.1
1.1.1 should still be usable after this change is merged.

I don't see any value in supporting 1.1.1, but didn't see a reason to
purge support for 1.1.1 when there are so few checks for >= 3.0.

Note that this does also remove CI support for Ubuntu 16.04. The
official version of OpenSSL from Ubuntu for this release is listed here:
https://launchpad.net/ubuntu/+source/openssl as 1.0.2g

Since no newer releases of coturn will be backported by Canonical to
Ubuntu 16.04, anyone using Coturn on this operating system will have to
download and compile it themselves. They may build their own version of
OpenSSL if they somehow cannot upgrade to a newer version of Ubuntu.

My position is that these users should prefer to upgrade to a newer
operating system than worry about chasing newer releases of Coturn.

Co-authored-by: Pavel Punsky <eakraly@users.noreply.github.com>
2024-12-13 13:06:24 -08:00
Pavel Punsky
ea280f9431
[BREAKING] Cleanup deprecated options (#1599)
Following configuration options deleted:
- `--secret-ts-exp-time`
- `--prod` - disables SOFTWARE_ATTRIBUTE in messages. Now it is default.
To enable SOFTWARE_ATTRIBUTE use `--software-attribute`
- `--no-sslv2`, `--no-sslv3` - old versions of SSL are not supported and
it is not possible to enable them

These are breaking changes - if the CLI command has any of those
arguments it will cause turnserver to terminate and notify about unknown
argument
2024-12-13 09:31:06 -08:00
Pavel Punsky
94fcfadce1
[BREAKING] Reverse SOFTWARE_ATTRIBUTE_OPT to avoid inverse logic (#1598)
As part of looking at #1588 , I figured that sending `SOFTWARE`
attribute is also part of a problem as it increases messages sent out by
coturn and thus increasing amplification factor. For 4.6.2, the
additional size is 24 bytes (4 bytes attribute header, and 20 bytes for
"Coturn-4.6.2 'Gorst'")

If we are to use an example from #1588, "A 62 byte request will be met
with Coturn’s 401 Unauthorized response which is 150 bytes, a factor of
~2.42." - without SOFTWARE the response will be 126 bytes which reduces
amplification factor to ~2.

As I observed with multiple providers using coturn - some of the are
sending it. Meaning, they do not set `--no-software-attribute` - most
probably due to lack of clarity about this setting.

I believe sending SOFTWARE_ATTRIBUTE should be off by default which is
hinted in the RFC
(https://datatracker.ietf.org/doc/html/rfc8489#section-16.1.2)

Detailed changes:
- Extract setting the attribute into a function to avoid code
duplication
- This option is now not reloadable
- The option is now called `software_attribute` because inverse logic
creates multiple double-not in the code which makes it harder to read.
- `no-software_attribute` is still functional but marked as deprecated
in documentation

Test Plan:
- Run local tests with different cli arguments (new and deprecated) and
confirm SOFTWARE attribute is off by default, and added when arguments
say so
2024-12-13 09:28:45 -08:00
tyranron
a6b052c570
Upgrade Docker image to 4.6.3 Coturn version
Some checks failed
Docker / build (arm32v7, alpine) (push) Has been cancelled
Docker / build (arm32v7, debian) (push) Has been cancelled
Docker / build (arm64v8, alpine) (push) Has been cancelled
Docker / build (arm64v8, debian) (push) Has been cancelled
Docker / build (i386, alpine) (push) Has been cancelled
Docker / build (i386, debian) (push) Has been cancelled
Docker / build (ppc64le, alpine) (push) Has been cancelled
Docker / build (ppc64le, debian) (push) Has been cancelled
Docker / build (s390x, alpine) (push) Has been cancelled
Docker / build (s390x, debian) (push) Has been cancelled
Docker / test (amd64, alpine) (push) Has been cancelled
Docker / test (amd64, debian) (push) Has been cancelled
Docker / test (arm32v6, alpine) (push) Has been cancelled
Docker / test (arm32v6, debian) (push) Has been cancelled
Docker / test (arm32v7, alpine) (push) Has been cancelled
Docker / test (arm32v7, debian) (push) Has been cancelled
Docker / test (arm64v8, alpine) (push) Has been cancelled
Docker / test (arm64v8, debian) (push) Has been cancelled
Docker / test (i386, alpine) (push) Has been cancelled
Docker / test (i386, debian) (push) Has been cancelled
Docker / test (ppc64le, alpine) (push) Has been cancelled
Docker / test (ppc64le, debian) (push) Has been cancelled
Docker / test (s390x, debian) (push) Has been cancelled
Docker / push (alpine, docker.io) (push) Has been cancelled
Docker / push (alpine, ghcr.io) (push) Has been cancelled
Docker / push (alpine, quay.io) (push) Has been cancelled
Docker / push (debian, docker.io) (push) Has been cancelled
Docker / push (debian, ghcr.io) (push) Has been cancelled
Docker / push (debian, quay.io) (push) Has been cancelled
Docker / release (GitHub) (push) Has been cancelled
2024-12-11 19:33:47 +01:00
Kai Ren
adae3dda3e
Refactor CI workflows and fix failures due to Node.js 20 (#1610, actions/checkout#1809) 2024-12-11 19:27:05 +01:00
Pavel Punsky
b6e53ca4c9
Update version to 4.6.3 (#1609)
Some checks failed
AmazonLinux2023 / builds (amazonlinux:2023) (push) Has been cancelled
AmazonLinux2 / builds (amazonlinux:2) (push) Has been cancelled
Lint / build (push) Has been cancelled
clang-tidy / clang-tidy (Release) (push) Has been cancelled
CMake / build (push) Has been cancelled
CodeQL / CodeQL Analyze (push) Has been cancelled
compiler-sanitizers / compiler-sanitizers (address,pointer-compare,pointer-subtract) (push) Has been cancelled
compiler-sanitizers / compiler-sanitizers (thread) (push) Has been cancelled
MacOS / builds (macos-12) (push) Has been cancelled
MacOS / builds (macos-13) (push) Has been cancelled
MacOS / builds (macos-14) (push) Has been cancelled
mingw / build (OFF, Debug, windows-latest) (push) Has been cancelled
mingw / build (OFF, Release, windows-latest) (push) Has been cancelled
msvc-analyzer / msvc-analyzer (OFF, Release, x64, v143) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (OFF, Debug, Win32, v142, windows-latest, x86-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (OFF, Debug, x64, v143, windows-latest, x64-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (OFF, Release, Win32, v142, windows-latest, x86-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (OFF, Release, x64, v143, windows-latest, x64-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (ON, Debug, Win32, v142, windows-latest, x86-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (ON, Debug, x64, v143, windows-latest, x64-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (ON, Release, Win32, v142, windows-latest, x86-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (ON, Release, x64, v143, windows-latest, x64-windows) (push) Has been cancelled
Ubuntu / builds (ubuntu:16.04) (push) Has been cancelled
Ubuntu / builds (ubuntu:18.04) (push) Has been cancelled
Ubuntu / builds (ubuntu:20.04) (push) Has been cancelled
Ubuntu / builds (ubuntu:22.04) (push) Has been cancelled
preparing for new tag 4.6.3

---------

Co-authored-by: tyranron <tyranron@gmail.com>
2024-12-11 10:13:38 -08:00
Pavel Punsky
329cda4715
Fix cmake and prometheus test build jobs (#1608)
Some actions do not build with prometheus - adding prometheus tests
fails the jobs
cmake build tests did not run due to different target folder (while
reporting success) - now the bin folder is detected
2024-12-10 19:38:39 -08:00
Alex Gustafsson
d63704c72d
Implement custom prometheus http handler (#1591)
Implement a custom prometheus http handler in order to:

1. Support listening on a specified address as opposed to any
2. Remove the requirement on the unmaintained promhttp library

This feature comes with one limitation: if an IPv4 address is used, the
server will not listen on the IPv6-mapped address, even if IPv6 is
available. That is, dual-stacking does not work.

Solves: #1475

---------

Co-authored-by: Pavel Punsky <eakraly@users.noreply.github.com>
2024-12-10 10:28:43 -08:00
tyranron
8f9c87075b
Upgrade Alpine to 3.21 version in Docker image
Some checks failed
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (OFF, Release, Win32, v142, windows-latest, x86-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (OFF, Release, x64, v143, windows-latest, x64-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (ON, Debug, Win32, v142, windows-latest, x86-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (ON, Debug, x64, v143, windows-latest, x64-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (ON, Release, Win32, v142, windows-latest, x86-windows) (push) Has been cancelled
msvc / ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}} (ON, Release, x64, v143, windows-latest, x64-windows) (push) Has been cancelled
Ubuntu / builds (ubuntu:16.04) (push) Has been cancelled
Ubuntu / builds (ubuntu:18.04) (push) Has been cancelled
Ubuntu / builds (ubuntu:20.04) (push) Has been cancelled
Ubuntu / builds (ubuntu:22.04) (push) Has been cancelled
Docker CI / test (amd64, alpine) (push) Has been cancelled
Docker CI / test (amd64, debian) (push) Has been cancelled
Docker CI / test (arm32v6, alpine) (push) Has been cancelled
Docker CI / test (arm32v6, debian) (push) Has been cancelled
Docker CI / test (arm32v7, alpine) (push) Has been cancelled
Docker CI / test (arm32v7, debian) (push) Has been cancelled
Docker CI / test (arm64v8, alpine) (push) Has been cancelled
Docker CI / test (arm64v8, debian) (push) Has been cancelled
Docker CI / test (i386, alpine) (push) Has been cancelled
Docker CI / test (i386, debian) (push) Has been cancelled
Docker CI / test (ppc64le, alpine) (push) Has been cancelled
Docker CI / test (ppc64le, debian) (push) Has been cancelled
Docker CI / test (s390x, debian) (push) Has been cancelled
Docker CI / push (alpine, docker.io) (push) Has been cancelled
Docker CI / push (alpine, ghcr.io) (push) Has been cancelled
Docker CI / push (alpine, quay.io) (push) Has been cancelled
Docker CI / push (debian, docker.io) (push) Has been cancelled
Docker CI / push (debian, ghcr.io) (push) Has been cancelled
Docker CI / push (debian, quay.io) (push) Has been cancelled
Docker CI / release (GitHub) (push) Has been cancelled
2024-12-06 19:10:33 +01:00
tyranron
817bbd1bea
Update Debian "bookworm" to 20241202 snapshot in Docker image 2024-12-05 12:28:33 +01:00
Robert Silén
f6004a1c18
Add MariaDB support to README.md (#1601)
Suggesting to add MariaDB to README - any reason not to?
2024-11-21 14:13:36 -08:00
maddy
c4a954a7fc
Allow authenticating with a username to redis (#1488)
Add ability to authenticate to redis with a password (and optionally username for redis 6.0)

Tested by building and using with redis on old and new versionss
2024-11-18 16:51:02 -08:00
hariprasadt
e5ffe6e0a3
Easy installation of coturn on AWS (#1581)
https://github.com/coturn/coturn/issues/1576

Co-authored-by: Pavel Punsky <eakraly@users.noreply.github.com>
2024-11-18 09:00:08 -08:00
Chai-Shi
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
Pavel Punsky
4c2a2d568f
Install openssl-1.1.1 on amazonlinux:2 instead of openssl-1.0.1 (#1595)
In preparation to deprecation of openssl below version 1.1.1 switch to
using openssl-1.1.1 on amazonlinux:2 (where 1.0.2 is the default)

Fixes build issue for #1397
2024-11-14 16:59:31 -08:00
tyranron
f8c5695827
Update Debian "bookworm" to 20241111 snapshot in Docker image 2024-11-13 12:17:07 +01:00
Scott Godin
edcdfc8b02
Add new Drain feature (#1529)
Add new Drain feature

-when coturn server is in drain mode
  -current allocations will continue to work as usual
  -new allocations will be rejected with a 403 (Forbidden) response
  -when all allocations go away, then coturn will shutdown
-Enable drain mode with either
  -signaling SIGUSR1
  -turn_admin_server "drain" CLI command

This contribution is from Wire. https://wire.com/
2024-10-27 18:56:58 -07:00
tyranron
8e3a03d2da
Update Debian "bookworm" to 20241016 snapshot in Docker image 2024-10-21 10:47:11 +02:00
Michael Jones
af4c44a818
Additional refactoring of ns_turn_allocation.* to address security scanner concerns (#1514)
You can see the list here:
https://github.com/coturn/coturn/security/code-scanning

In this case, i'm attempting to address:

ns_turn_allocation.c:725 -- Dereferencing NULL pointer. 'ub->bufs'
contains the same NULL value as 'realloc()' did.
ns_turn_allocation.c:724 -- 'realloc' might return null pointer:
assigning null pointer to 'ub->bufs', which is passed as an argument to
'realloc', will cause the original memory block to be leaked.
ns_turn_allocation.c:604 -- Dereferencing NULL pointer. 'a->tcs.elems'
contains the same NULL value as 'realloc()' did.
    ns_turn_allocation.c:582 -- Dereferencing NULL pointer 'tc'.
ns_turn_allocation.c:603 -- 'realloc' might return null pointer:
assigning null pointer to 'a->tcs.elems', which is passed as an argument
to 'realloc', will cause the original memory block to be leaked.
    ns_turn_allocation.c:525 -- Using uninitialized memory '*chi'.
    ns_turn_allocation.c:229 -- Using uninitialized memory '*slot'.

---------

Co-authored-by: Pavel Punsky <eakraly@users.noreply.github.com>
2024-10-18 20:54:47 -07:00
redraincatching
08480ce137
fixed linting error in mainrelay.c (#1558)
fixed a formatting problem causing issues with `clang-format` in the
linting action
see
[here](https://github.com/redraincatching/coturn/actions/runs/10262259860)
for an example
2024-10-04 10:29:22 -07:00
eakraly
86a8f659fb
Fix rpm version scripts (#1556)
Fix #1521
2024-10-04 10:28:11 -07:00
Sven Tennie
cbb04aa9a2
Delete dead code (#1563)
`stun_port` isn't read after setting it. Thus, we can remove it.
2024-10-04 10:27:31 -07:00
Mészáros Mihály
e78d8f4fae
Fix cli auth (#1578)
Fix to avoid accept all password except the right cli_password

Co-authored-by: Mészáros Mihály <misi@eper.majd.eu>
2024-10-04 10:26:17 -07:00
tyranron
775d8fbf70
Update Debian "bookworm" to 20240926 snapshot in Docker image 2024-09-30 16:17:57 +03:00
67 changed files with 1733 additions and 2270 deletions

View File

@ -14,7 +14,7 @@ runs:
- name: check if sudo is set
shell: bash
run: |
if [ ${{inputs.SUDO}} = true ]
if [ ${{ inputs.SUDO }} = true ]
then
AS_ROOT="sudo"
else
@ -24,12 +24,12 @@ runs:
- name: apt update
shell: bash
run: ${{env.AS_ROOT}} apt update
run: ${{ env.AS_ROOT }} apt update
- name: install build tools
shell: bash
run: |
${{env.AS_ROOT}} apt install -y \
${{ env.AS_ROOT }} apt install -y \
build-essential \
clang \
clang-tidy \
@ -42,7 +42,7 @@ runs:
- name: install coturn dependencies
shell: bash
run: |
${{env.AS_ROOT}} apt install -y \
${{ env.AS_ROOT }} apt install -y \
libevent-dev \
libssl-dev \
libpq-dev \
@ -57,5 +57,5 @@ runs:
shell: bash
run: |
wget https://github.com/digitalocean/prometheus-client-c/releases/download/v0.1.3/libprom-dev-0.1.3-Linux.deb
wget https://github.com/digitalocean/prometheus-client-c/releases/download/v0.1.3/libpromhttp-dev-0.1.3-Linux.deb
${{env.AS_ROOT}} apt install -y ./libprom-dev-0.1.3-Linux.deb ./libpromhttp-dev-0.1.3-Linux.deb
${{ env.AS_ROOT }} apt install -y ./libprom-dev-0.1.3-Linux.deb
working-directory: /tmp/

View File

@ -1,46 +0,0 @@
name: AmazonLinux
on:
push:
pull_request:
types: [ opened, reopened, synchronize ]
# make GHA actions use node16 to use ancient container images
# See https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/
# Unclear how long this will work though
env:
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
jobs:
builds:
strategy:
fail-fast: false
matrix:
# amazonlinux 2 is end-of-life 2025-06
os: [ 'amazonlinux:2', 'amazonlinux:2023' ]
runs-on: ubuntu-latest
container: ${{ matrix.os }}
steps:
- name: Install Dependencies
run: |
yum install -y gcc make gzip tar openssl-devel libevent-devel
# Delay checkout until after dependencies have been installed. Amazon linux is very minimal and lacks basic stuff by default.
# use v3 of checkout until the weird container, nodejs, glibc issue is fixed
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Configure
run: ./configure
- name: Compile
run: make
- name: Unit Test
run: make check
- name: Integration Test
working-directory: examples
run: ./run_tests.sh && ./run_tests_conf.sh

View File

@ -1,47 +0,0 @@
name: clang-tidy
on:
push:
pull_request:
types: [ opened, reopened, synchronize ]
jobs:
clang-tidy:
runs-on: ubuntu-latest
strategy:
matrix:
config: [Release]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: install dependencies
uses: ./.github/workflows/actions/ubuntu-build-deps
with:
SUDO: true
- name: Configure
run: |
cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=${{ matrix.config }} -DCMAKE_EXPORT_COMPILE_COMMANDS=true
- name: Compile
run: |
cmake --build build --parallel --config ${{ matrix.config }}
# Implicitly requires build/compile_commands.json to exist
- name: Run Clang Tidy
run: |
wget https://raw.githubusercontent.com/llvm/llvm-project/llvmorg-14.0.6/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
chmod +x run-clang-tidy.py
./run-clang-tidy.py -j $(nproc) -p build
# Implicitly requires build/compile_commands.json to exist
- name: Run IWYU
run: |
wget https://raw.githubusercontent.com/include-what-you-use/include-what-you-use/clang_14/iwyu_tool.py
chmod +x iwyu_tool.py
# iwyu_tool.py returns non-zero if any executions returned nonzero. Which... happens to be useless unless the project is already IWYU clean.
./iwyu_tool.py -j $(nproc) -p build -- -Xiwyu --mapping_file=${GITHUB_WORKSPACE}/iwyu-ubuntu.imp | grep -v "has correct" | uniq || exit 0

105
.github/workflows/clang.yml vendored Normal file
View File

@ -0,0 +1,105 @@
name: Clang
on:
push:
branches: ["master"]
tags: ["4.*"]
pull_request:
branches: ["master"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
uses: ./.github/workflows/actions/ubuntu-build-deps
with:
SUDO: true
- name: Install `clang-format-15`
run: sudo apt install -y clang-format-15
- name: Prepare `clang-format`
run: |
set -e
if which clang-format-15 2>&1 >/dev/null
then
sudo cp $(which clang-format-15) $(which clang-format)
fi
clang-format --version
- run: ./configure
- run: make lint
sanitize:
runs-on: ubuntu-latest
strategy:
matrix:
sanitizer:
- address,pointer-compare,pointer-subtract
- thread
env:
CFLAGS: -fno-omit-frame-pointer -fstack-protector-all -fsanitize=${{ matrix.sanitizer }},bounds,enum -fsanitize-address-use-after-scope -fsanitize-address-use-after-return=always -fsanitize-recover=address -fsanitize-memory-track-origins=2
CC: clang
ASAN_OPTIONS: strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:detect_leaks=0:detect_invalid_pointer_pairs=1:halt_on_error=0
steps:
- uses: actions/checkout@v4
- name: Install dependencies
uses: ./.github/workflows/actions/ubuntu-build-deps
with:
SUDO: true
- run: ./configure
- run: make -j $(nproc)
- run: make check
- run: ./run_tests.sh
working-directory: examples/
- run: ./run_tests_conf.sh
working-directory: examples/
- run: ./run_tests_prom.sh
working-directory: examples/
tidy:
runs-on: ubuntu-latest
strategy:
matrix:
config: ["Release"]
steps:
- uses: actions/checkout@v4
- name: Install dependencies
uses: ./.github/workflows/actions/ubuntu-build-deps
with:
SUDO: true
- name: Configure
run: cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=${{ matrix.config }}
-DCMAKE_EXPORT_COMPILE_COMMANDS=true
- name: Compile
run: cmake --build build --parallel --config ${{ matrix.config }}
# Implicitly requires `build/compile_commands.json` to exist
- name: Run `clang-tidy`
run: |
set -e
wget https://raw.githubusercontent.com/llvm/llvm-project/llvmorg-14.0.6/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
chmod +x run-clang-tidy.py
./run-clang-tidy.py -j $(nproc) -p build
# Implicitly requires `build/compile_commands.json` to exist
- name: Run IWYU
run: |
set -e
wget https://raw.githubusercontent.com/include-what-you-use/include-what-you-use/clang_14/iwyu_tool.py
chmod +x iwyu_tool.py
# iwyu_tool.py returns non-zero if any executions returned nonzero. Which... happens to be useless unless the project is already IWYU clean.
./iwyu_tool.py -j $(nproc) -p build -- -Xiwyu --mapping_file=${GITHUB_WORKSPACE}/iwyu-ubuntu.imp | grep -v "has correct" | uniq || exit 0

View File

@ -2,40 +2,46 @@ name: CMake
on:
push:
branches: ["master"]
tags: ["4.*"]
pull_request:
types: [ opened, reopened, synchronize ]
branches: ["master"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
BUILD_TYPE: Release
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
wget \
libevent-dev \
libssl-dev \
libpq-dev libmariadb-dev libsqlite3-dev \
libhiredis-dev \
libmongoc-dev \
libmicrohttpd-dev
- uses: actions/checkout@v4
- name: Prometheus support
run: |
wget https://github.com/digitalocean/prometheus-client-c/releases/download/v0.1.3/libprom-dev-0.1.3-Linux.deb && \
wget https://github.com/digitalocean/prometheus-client-c/releases/download/v0.1.3/libpromhttp-dev-0.1.3-Linux.deb && \
sudo apt install ./libprom-dev-0.1.3-Linux.deb ./libpromhttp-dev-0.1.3-Linux.deb && \
rm ./libprom-dev-0.1.3-Linux.deb ./libpromhttp-dev-0.1.3-Linux.deb
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: apps tests
run: cd examples && ./run_tests.sh && ./run_tests_conf.sh
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libevent-dev \
libssl-dev \
libpq-dev libmariadb-dev libsqlite3-dev \
libhiredis-dev \
libmongoc-dev \
libmicrohttpd-dev \
wget
- uses: actions/checkout@v4
- name: Prometheus support
run: |
wget https://github.com/digitalocean/prometheus-client-c/releases/download/v0.1.3/libprom-dev-0.1.3-Linux.deb && \
sudo apt install ./libprom-dev-0.1.3-Linux.deb && \
rm ./libprom-dev-0.1.3-Linux.deb
- name: Configure
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- run: ./run_tests.sh
working-directory: examples/
- run: ./run_tests_conf.sh
working-directory: examples/

View File

@ -1,42 +1,43 @@
name: "CodeQL"
name: CodeQL
on:
push:
branches: ["master"]
tags: ["4.*"]
pull_request:
types: [ opened, reopened, synchronize ]
branches: ["master"]
schedule:
- cron: '6 13 * * 4'
- cron: "6 13 * * 4"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
BUILD_TYPE: Release
jobs:
analyze:
name: CodeQL Analyze
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
- name: Install Dependencies
uses: ./.github/workflows/actions/ubuntu-build-deps
with:
SUDO: true
- name: Install dependencies
uses: ./.github/workflows/actions/ubuntu-build-deps
with:
SUDO: true
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: cpp
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: cpp
- name: Configure
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Configure
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

View File

@ -1,47 +0,0 @@
name: compiler-sanitizers
on:
push:
pull_request:
types: [ opened, reopened, synchronize ]
jobs:
compiler-sanitizers:
runs-on: ubuntu-latest
strategy:
matrix:
sanitizer: [ 'address,pointer-compare,pointer-subtract', 'thread' ]
env:
CFLAGS: "-fno-omit-frame-pointer -fstack-protector-all -fsanitize=${{matrix.sanitizer}},bounds,enum -fsanitize-address-use-after-scope -fsanitize-address-use-after-return=always -fsanitize-recover=address -fsanitize-memory-track-origins=2"
CC: "clang"
ASAN_OPTIONS: "strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:detect_leaks=0:detect_invalid_pointer_pairs=1:halt_on_error=0"
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: install dependencies
uses: ./.github/workflows/actions/ubuntu-build-deps
with:
SUDO: true
- name: Configure
run: |
./configure
- name: Compile
run: |
make -j $(nproc)
- name: Check
run: |
make check
- name: Test
run: |
cd examples
./run_tests.sh && ./run_tests_conf.sh

View File

@ -1,4 +1,4 @@
name: Docker CI
name: Docker
on:
push:

View File

@ -1,35 +0,0 @@
name: Lint
on:
push:
pull_request:
types: [ opened, reopened, synchronize ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Dependencies
uses: ./.github/workflows/actions/ubuntu-build-deps
with:
SUDO: true
- name: Install clang-format-15
run: sudo apt install -y clang-format-15
- name: Configure
run: ./configure
- name: lint
run: |
if which clang-format-15 2>&1 >/dev/null
then
sudo cp $(which clang-format-15) $(which clang-format)
fi
clang-format --version
make lint

70
.github/workflows/linux.yml vendored Normal file
View File

@ -0,0 +1,70 @@
name: Linux
on:
push:
branches: ["master"]
tags: ["4.*"]
pull_request:
branches: ["master"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: build + test
strategy:
fail-fast: false
matrix:
os:
- amazonlinux:2023
- ubuntu:20.04
- ubuntu:22.04
- ubuntu:24.04
runs-on: ubuntu-latest
container:
image: ${{ matrix.os }}
volumes:
- ${{ contains('amazonlinux:2 ubuntu:16.04 ubuntu:18.04', matrix.os) && '/node20217:/node20217:rw,rshared' || ' ' }}
- ${{ contains('amazonlinux:2 ubuntu:16.04 ubuntu:18.04', matrix.os) && '/node20217:/__e/node20:ro,rshared' || ' ' }}
steps:
- name: Install `yum` dependencies
run: yum install -y gcc make gzip tar openssl-devel libevent-devel wget which
if: ${{ contains(matrix.os, 'amazonlinux') }}
- name: Install Node.js 20 built against glibc 2.17 for GitHub Actions
run: |
set -ex
which apt \
&& apt update \
&& apt install -y wget xz-utils
which yum \
&& yum install -y wget xz
wget https://unofficial-builds.nodejs.org/download/release/v20.9.0/node-v20.9.0-linux-x64-glibc-217.tar.xz
tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217
ldd /__e/node20/bin/node
working-directory: /tmp/
if: ${{ contains('amazonlinux:2 ubuntu:16.04 ubuntu:18.04', matrix.os) }}
- uses: actions/checkout@v4
- name: Install `apt` dependencies
# Set env variable or otherwise `tzdata` package requires interaction.
env:
DEBIAN_FRONTEND: noninteractive
uses: ./.github/workflows/actions/ubuntu-build-deps
if: ${{ contains(matrix.os, 'ubuntu') }}
- run: ./configure
- run: make
- run: make check
- run: ./run_tests.sh
working-directory: examples/
- run: ./run_tests_conf.sh
working-directory: examples/
- run: ./run_tests_prom.sh
working-directory: examples/
if: ${{ contains(matrix.os, 'ubuntu') }}

View File

@ -1,59 +1,85 @@
name: MacOS
name: macOS
on:
push:
branches: ["master"]
tags: ["4.*"]
pull_request:
types: [ opened, reopened, synchronize ]
branches: ["master"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
builds:
build:
name: build + test
strategy:
fail-fast: false
matrix:
os: [ 'macos-12', 'macos-13', 'macos-14' ]
runs-on: ${{ matrix.os }}
ver: ["13", "14", "15"]
runs-on: macos-${{ matrix.ver }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
- name: Brew - Relink Python
run: |
# Unlink and re-link to prevent errors when github mac runner images
# install python outside of brew, for example:
- name: Relink `python` package in `brew`
# Unlink and re-link to prevent errors when GitHub `macos` runner images
# install `python` outside of `brew`, for example:
# https://github.com/orgs/Homebrew/discussions/3895
# https://github.com/actions/setup-python/issues/577
# https://github.com/actions/runner-images/issues/6459
# https://github.com/actions/runner-images/issues/6507
# https://github.com/actions/runner-images/issues/2322
brew list -1 | grep python | while read formula; do brew unlink $formula; brew link --overwrite $formula; done
run: brew list -1
| grep python
| while read formula; do brew unlink $formula; brew link --overwrite $formula; done
- name: Brew - Update pkg listings
run: |
brew update
- run: brew update
- run: brew install wget pkg-config libevent openssl@1.1 sqlite hiredis mongo-c-driver libmicrohttpd
- name: Brew - Install Dependencies
run: |
brew install \
wget \
pkg-config \
libevent \
openssl@1.1 \
sqlite \
hiredis \
mongo-c-driver \
libmicrohttpd
- run: ./configure
env:
PKG_CONFIG_PATH: "${{ env.PKG_CONFIG_PATH }}:/usr/local/opt/openssl@1.1/lib/pkgconfig"
- run: make
- name: Configure
run: PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opt/openssl@1.1/lib/pkgconfig ./configure
- run: make check
- name: Compile
run: make
- run: ./run_tests.sh
working-directory: examples/
- run: ./run_tests_conf.sh
working-directory: examples/
- name: Unit Test
run: make check
build-cmake:
name: build + test cmake
strategy:
fail-fast: false
matrix:
ver: ["15"]
runs-on: macos-${{ matrix.ver }}
steps:
- uses: actions/checkout@v4
- name: Integration Test
working-directory: examples
run: ./run_tests.sh && ./run_tests_conf.sh
- name: Relink `python` package in `brew`
# Unlink and re-link to prevent errors when GitHub `macos` runner images
# install `python` outside of `brew`, for example:
# https://github.com/orgs/Homebrew/discussions/3895
# https://github.com/actions/setup-python/issues/577
# https://github.com/actions/runner-images/issues/6459
# https://github.com/actions/runner-images/issues/6507
# https://github.com/actions/runner-images/issues/2322
run: brew list -1
| grep python
| while read formula; do brew unlink $formula; brew link --overwrite $formula; done
- run: brew update
- run: brew install wget pkg-config libevent openssl@1.1 sqlite hiredis mongo-c-driver libmicrohttpd
- name: Configure
run: cmake -B ${{github.workspace}}/build
- name: Build
run: cmake --build ${{github.workspace}}/build
- run: ./run_tests.sh
working-directory: examples/
- run: ./run_tests_conf.sh
working-directory: examples/

View File

@ -1,129 +1,120 @@
name: mingw
name: MinGW
on:
push:
branches: ["master"]
tags: ["4.*"]
pull_request:
types: [ opened, reopened, synchronize ]
branches: ["master"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: build
strategy:
fail-fast: false
matrix:
os: [windows-latest]
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: [Release, Debug]
BUILD_SHARED_LIBS: [OFF]
os: ["windows"]
# Customize the CMake build type here (`Release`, `Debug`, `RelWithDebInfo`, etc.)
BUILD_TYPE: ["Release", "Debug"]
BUILD_SHARED_LIBS: ["OFF"]
defaults:
run:
shell: cmd
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.os }}-latest
env:
BUILD_TYPE: ${{ matrix.BUILD_TYPE }}
SOURCE_DIR: ${{github.workspace}}\.cache\source
TOOSL_DIR: ${{github.workspace}}\.cache\tools
INSTALL_DIR: ${{github.workspace}}\.cache\install_mingw_2022_02_15
SOURCE_DIR: ${{ github.workspace }}\.cache\source
TOOSL_DIR: ${{ github.workspace }}\.cache\tools
INSTALL_DIR: ${{ github.workspace }}\.cache\install_mingw_2022_02_15
steps:
- uses: actions/checkout@v4
#with:
#fetch-depth: 0
- uses: actions/checkout@v4
- name: pacman
env:
PATH: C:\msys64\usr\bin
run: |
C:\msys64\usr\bin\pacman.exe -S --noconfirm ^
mingw-w64-x86_64-cmake ^
mingw-w64-x86_64-make ^
mingw-w64-x86_64-nsis ^
mingw-w64-x86_64-gcc ^
mingw-w64-x86_64-zlib ^
mingw-w64-x86_64-openssl ^
mingw-w64-x86_64-libevent ^
mingw-w64-x86_64-sqlite3 ^
mingw-w64-x86_64-hiredis ^
mingw-w64-x86_64-postgresql ^
mingw-w64-x86_64-libmicrohttpd ^
git base-devel
- name: Install dependencies
run: |
C:\msys64\usr\bin\pacman.exe -S --noconfirm ^
mingw-w64-x86_64-cmake ^
mingw-w64-x86_64-make ^
mingw-w64-x86_64-nsis ^
mingw-w64-x86_64-gcc ^
mingw-w64-x86_64-zlib ^
mingw-w64-x86_64-openssl ^
mingw-w64-x86_64-libevent ^
mingw-w64-x86_64-sqlite3 ^
mingw-w64-x86_64-hiredis ^
mingw-w64-x86_64-postgresql ^
mingw-w64-x86_64-libmicrohttpd ^
git base-devel
env:
PATH: C:\msys64\usr\bin
- name: make_directory
run: |
cmake -E make_directory ${{env.SOURCE_DIR}}
cmake -E make_directory ${{env.TOOSL_DIR}}
cmake -E make_directory ${{env.INSTALL_DIR}}
- name: Create directories
run: |
cmake -E make_directory ${{ env.SOURCE_DIR }}
cmake -E make_directory ${{ env.TOOSL_DIR }}
cmake -E make_directory ${{ env.INSTALL_DIR }}
- name: Cache installed
uses: actions/cache@v4
id: cache-installed
with:
path: |
${{env.INSTALL_DIR}}
key: coturn-cache-installed-mingw
- name: Cache installed
uses: actions/cache@v4
id: cache-installed
with:
path: ${{ env.INSTALL_DIR }}
key: coturn-cache-installed-mingw
- name: build prometheus
if: false
working-directory: ${{env.SOURCE_DIR}}
env:
MSYSTEM: MINGW64
PATH: C:\msys64\mingw64\bin;C:\msys64\usr\bin
run: |
cd ${{env.SOURCE_DIR}}
git clone https://github.com/digitalocean/prometheus-client-c.git
cd prometheus-client-c/prom
mkdir build
cd build
cmake .. -G"MinGW Makefiles" ^
-DBUILD_SHARED_LIBS=${{matrix.BUILD_SHARED_LIBS}} ^
-DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} ^
-DCMAKE_INSTALL_PREFIX=${{env.INSTALL_DIR}}
cmake --build . --config ${{matrix.BUILD_TYPE}}
cmake --build . --config ${{matrix.BUILD_TYPE}} --target install
cd ${{env.SOURCE_DIR}}/prometheus-client-c/promhttp
mkdir build
cd build
cmake .. -G"MinGW Makefiles" ^
-DBUILD_SHARED_LIBS=${{matrix.BUILD_SHARED_LIBS}} ^
-DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} ^
-DCMAKE_INSTALL_PREFIX=${{env.INSTALL_DIR}}
cmake --build . --config ${{matrix.BUILD_TYPE}}
cmake --build . --config ${{matrix.BUILD_TYPE}} --target install
- name: Build Prometheus
run: |
cd ${{ env.SOURCE_DIR }}
git clone https://github.com/digitalocean/prometheus-client-c.git
cd prometheus-client-c/prom
mkdir build
cd build
cmake .. -G"MinGW Makefiles" ^
-DBUILD_SHARED_LIBS=${{ matrix.BUILD_SHARED_LIBS }} ^
-DCMAKE_BUILD_TYPE=${{ matrix.BUILD_TYPE }} ^
-DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }}
cmake --build . --config ${{ matrix.BUILD_TYPE }}
cmake --build . --config ${{ matrix.BUILD_TYPE }} --target install
env:
MSYSTEM: MINGW64
PATH: C:\msys64\mingw64\bin;C:\msys64\usr\bin
working-directory: ${{ env.SOURCE_DIR }}
if: ${{ false }}
- name: build coturn
working-directory: ${{github.workspace}}
env:
MSYSTEM: MINGW64
PATH: C:\msys64\mingw64\bin;C:\msys64\usr\bin
Prometheus_ROOT: ${{env.INSTALL_DIR}}
run: |
cmake -E make_directory build
cd build
cmake .. -G"MinGW Makefiles" ^
-DBUILD_SHARED_LIBS=${{matrix.BUILD_SHARED_LIBS}} ^
-DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} ^
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/build/install
cmake --build . --config ${{matrix.BUILD_TYPE}}
cmake --build . --config ${{matrix.BUILD_TYPE}} --target install
- name: Build Coturn
run: |
cmake -E make_directory build
cd build
cmake .. -G"MinGW Makefiles" ^
-DBUILD_SHARED_LIBS=${{ matrix.BUILD_SHARED_LIBS }} ^
-DCMAKE_BUILD_TYPE=${{ matrix.BUILD_TYPE }} ^
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/build/install
cmake --build . --config ${{ matrix.BUILD_TYPE }}
cmake --build . --config ${{ matrix.BUILD_TYPE }} --target install
env:
MSYSTEM: MINGW64
PATH: C:\msys64\mingw64\bin;C:\msys64\usr\bin
Prometheus_ROOT: ${{ env.INSTALL_DIR }}
working-directory: ${{ github.workspace }}
- name: Package
if: ${{ matrix.BUILD_TYPE == 'Release' }}
working-directory: ${{github.workspace}}\build
run: |
copy /Y ${{env.INSTALL_DIR}}\bin\*.dll install\bin
copy /Y ${{env.INSTALL_DIR}}\lib\*.dll install\bin
copy /Y ${{env.RUNVCPKG_VCPKG_ROOT}}\installed\${{env.RUNVCPKG_VCPKG_TRIPLET_OUT}}\bin\*.dll install\bin
7z a coturn_windows_mingw.zip ${{github.workspace}}\build\install\*
cmake --build . --config ${{matrix.BUILD_TYPE}} --target package
- name: Package
run: |
copy /Y ${{ env.INSTALL_DIR }}\bin\*.dll install\bin
copy /Y ${{ env.INSTALL_DIR }}\lib\*.dll install\bin
copy /Y ${{ env.RUNVCPKG_VCPKG_ROOT }}\installed\${{ env.RUNVCPKG_VCPKG_TRIPLET_OUT }}\bin\*.dll install\bin
7z a coturn_windows_mingw.zip ${{ github.workspace }}\build\install\*
cmake --build . --config ${{ matrix.BUILD_TYPE }} --target package
working-directory: ${{ github.workspace }}\build
if: ${{ matrix.BUILD_TYPE == 'Release' }}
- name: update
if: ${{ matrix.BUILD_TYPE == 'Release' }}
uses: actions/upload-artifact@v4
with:
name: coturn_mingw_${{ matrix.os }}
path: |
${{github.workspace}}\build\coturn_windows_mingw.zip
${{github.workspace}}\build\coturn*.exe
${{github.workspace}}\build\coturn*.md5
- name: Update artifacts
uses: actions/upload-artifact@v4
with:
name: coturn_mingw_${{ matrix.os }}
path: |
${{ github.workspace }}\build\coturn_windows_mingw.zip
${{ github.workspace }}\build\coturn*.exe
${{ github.workspace }}\build\coturn*.md5
if: ${{ matrix.BUILD_TYPE == 'Release' }}

View File

@ -1,78 +0,0 @@
name: msvc-analyzer
on:
push:
pull_request:
types: [ opened, reopened, synchronize ]
jobs:
msvc-analyzer:
runs-on: windows-latest
permissions:
# required for all codeql to report detected outcomes
security-events: write
strategy:
matrix:
BUILD_TYPE: [Release]
BUILD_SHARED_LIBS: [OFF]
VCPKG_PLATFORM_TOOLSET: [v143]
CMAKE_GENERATOR_PLATFORM: [x64]
env:
SOURCE_DIR: ${{github.workspace}}\.cache\source
TOOLS_DIR: ${{github.workspace}}\.cache\tools
INSTALL_DIR: ${{github.workspace}}\.cache\install_msvc_x64-windows_${{matrix.BUILD_TYPE}}
VCPKGGITCOMMITID: 53bef8994c541b6561884a8395ea35715ece75db
VCPKG_PLATFORM_TOOLSET: ${{matrix.VCPKG_PLATFORM_TOOLSET}}
CMAKE_GENERATOR_PLATFORM: ${{matrix.CMAKE_GENERATOR_PLATFORM}}
defaults:
run:
shell: cmd
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: make directory
run: |
cmake -E make_directory ${{env.SOURCE_DIR}}
cmake -E make_directory ${{env.TOOLS_DIR}}
cmake -E make_directory ${{env.INSTALL_DIR}}
- name: run-vcpkg
uses: lukka/run-vcpkg@v11
with:
# If not using a submodule for vcpkg sources, this specifies which commit
# id must be checkout from a Git repo. It must not set if using a submodule
# for vcpkg.
vcpkgGitCommitId: '${{ env.VCPKGGITCOMMITID }}'
- name: Configure (MSVC)
run: |
cmake -B build ^
-A ${{matrix.CMAKE_GENERATOR_PLATFORM}} ^
-T ${{matrix.VCPKG_PLATFORM_TOOLSET}} ^
-DWITH_MYSQL=OFF ^
-DBUILD_SHARED_LIBS=${{matrix.BUILD_SHARED_LIBS}} ^
-DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} ^
-DCMAKE_TOOLCHAIN_FILE=${{env.VCPKG_ROOT}}/scripts/buildsystems/vcpkg.cmake
- name: Initialize MSVC Code Analysis
uses: microsoft/msvc-code-analysis-action@v0.1.1
# Provide a unique ID to access the sarif output path
id: run-analysis
with:
cmakeBuildDirectory: build
buildConfiguration: ${{ matrix.BUILD_TYPE }}
# Ruleset file that will determine what checks will be run
ruleset: NativeRecommendedRules.ruleset
# Upload SARIF file to GitHub Code Scanning Alerts
- name: Upload SARIF to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.run-analysis.outputs.sarif }}

View File

@ -1,96 +1,160 @@
name: msvc
name: MSVC
on:
push:
branches: ["master"]
tags: ["4.*"]
pull_request:
types: [ opened, reopened, synchronize ]
branches: ["master"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
VCPKGGITCOMMITID: 53bef8994c541b6561884a8395ea35715ece75db
jobs:
compile:
name: ${{matrix.os}}-vc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_TYPE}}-${{matrix.BUILD_SHARED_LIBS}}
code-analysis:
name: code analysis (windows-vc-${{ matrix.VCPKG_PLATFORM_TOOLSET }}-${{ matrix.CMAKE_GENERATOR_PLATFORM }}-${{ matrix.BUILD_TYPE }}-${{ matrix.BUILD_SHARED_LIBS }})
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
BUILD_TYPE: [Release, Debug]
BUILD_SHARED_LIBS: [OFF, ON]
CMAKE_GENERATOR_PLATFORM: [x64, Win32]
os: [windows-latest]
BUILD_TYPE: [Release]
BUILD_SHARED_LIBS: [OFF]
VCPKG_PLATFORM_TOOLSET: [v143]
CMAKE_GENERATOR_PLATFORM: [x64]
env:
SOURCE_DIR: ${{ github.workspace }}\.cache\source
TOOLS_DIR: ${{ github.workspace }}\.cache\tools
INSTALL_DIR: ${{ github.workspace }}\.cache\install_msvc_x64-windows_${{ matrix.BUILD_TYPE }}
VCPKG_PLATFORM_TOOLSET: ${{ matrix.VCPKG_PLATFORM_TOOLSET }}
CMAKE_GENERATOR_PLATFORM: ${{ matrix.CMAKE_GENERATOR_PLATFORM }}
defaults:
run:
shell: cmd
permissions:
security-events: write # required for all CodeQL to report detected outcomes
steps:
- uses: actions/checkout@v4
- name: Create directories
run: |
cmake -E make_directory ${{ env.SOURCE_DIR }}
cmake -E make_directory ${{ env.TOOLS_DIR }}
cmake -E make_directory ${{ env.INSTALL_DIR }}
- name: run-vcpkg
uses: lukka/run-vcpkg@v11
with:
# If not using a submodule for vcpkg sources, this specifies which commit
# id must be checkout from a Git repo. It must not set if using a submodule
# for vcpkg.
vcpkgGitCommitId: '${{ env.VCPKGGITCOMMITID }}'
- name: Configure
run: |
cmake -B build ^
-A ${{ matrix.CMAKE_GENERATOR_PLATFORM }} ^
-T ${{ matrix.VCPKG_PLATFORM_TOOLSET }} ^
-DWITH_MYSQL=OFF ^
-DBUILD_SHARED_LIBS=${{ matrix.BUILD_SHARED_LIBS }} ^
-DCMAKE_BUILD_TYPE=${{ matrix.BUILD_TYPE }} ^
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
- name: Initialize MSVC Code Analysis
uses: microsoft/msvc-code-analysis-action@v0.1.1
# Provide a unique ID to access the SARIF output path.
id: run-analysis
with:
cmakeBuildDirectory: build
buildConfiguration: ${{ matrix.BUILD_TYPE }}
# Ruleset file that will determine what checks will be run.
ruleset: NativeRecommendedRules.ruleset
# Upload SARIF file to GitHub Code Scanning Alerts
- name: Upload SARIF to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.run-analysis.outputs.sarif }}
compile:
name: compile (${{ matrix.os }}-vc-${{ matrix.VCPKG_PLATFORM_TOOLSET }}-${{ matrix.CMAKE_GENERATOR_PLATFORM }}-${{ matrix.BUILD_TYPE }}-${{ matrix.BUILD_SHARED_LIBS }})
strategy:
fail-fast: false
matrix:
BUILD_TYPE: ["Release", "Debug"]
BUILD_SHARED_LIBS: ["OFF", "ON"]
CMAKE_GENERATOR_PLATFORM: ["x64", "Win32"]
os: ["windows"]
include:
# MSVC 2022
- triplet: x64-windows
VCPKG_PLATFORM_TOOLSET: v143
CMAKE_GENERATOR_PLATFORM: x64
- triplet: x86-windows
VCPKG_PLATFORM_TOOLSET: v143
CMAKE_GENERATOR_PLATFORM: Win32
# MSVC 2019
- triplet: x86-windows
VCPKG_PLATFORM_TOOLSET: v142
CMAKE_GENERATOR_PLATFORM: Win32
runs-on: ${{matrix.os}}
runs-on: ${{ matrix.os }}-latest
env:
SOURCE_DIR: ${{github.workspace}}\.cache\source
TOOLS_DIR: ${{github.workspace}}\.cache\tools
INSTALL_DIR: ${{github.workspace}}\.cache\install_msvc_${{matrix.triplet}}_${{matrix.BUILD_TYPE}}
VCPKGGITCOMMITID: 53bef8994c541b6561884a8395ea35715ece75db
VCPKG_PLATFORM_TOOLSET: ${{matrix.VCPKG_PLATFORM_TOOLSET}}
CMAKE_GENERATOR_PLATFORM: ${{matrix.CMAKE_GENERATOR_PLATFORM}}
SOURCE_DIR: ${{ github.workspace }}\.cache\source
TOOLS_DIR: ${{ github.workspace }}\.cache\tools
INSTALL_DIR: ${{ github.workspace }}\.cache\install_msvc_${{matrix.triplet}}_${{matrix.BUILD_TYPE}}
VCPKG_PLATFORM_TOOLSET: ${{ matrix.VCPKG_PLATFORM_TOOLSET }}
CMAKE_GENERATOR_PLATFORM: ${{ matrix.CMAKE_GENERATOR_PLATFORM }}
defaults:
run:
shell: cmd
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
- name: make directory
run: |
cmake -E make_directory ${{env.SOURCE_DIR}}
cmake -E make_directory ${{env.TOOLS_DIR}}
cmake -E make_directory ${{env.INSTALL_DIR}}
- name: Create directories
run: |
cmake -E make_directory ${{ env.SOURCE_DIR }}
cmake -E make_directory ${{ env.TOOLS_DIR }}
cmake -E make_directory ${{ env.INSTALL_DIR }}
- name: run-vcpkg
uses: lukka/run-vcpkg@v11
with:
# If not using a submodule for vcpkg sources, this specifies which commit
# id must be checkout from a Git repo. It must not set if using a submodule
# for vcpkg.
vcpkgGitCommitId: '${{ env.VCPKGGITCOMMITID }}'
- name: run-vcpkg
uses: lukka/run-vcpkg@v11
with:
# If not using a submodule for vcpkg sources, this specifies which commit
# id must be checkout from a Git repo. It must not set if using a submodule
# for vcpkg.
vcpkgGitCommitId: '${{ env.VCPKGGITCOMMITID }}'
- name: build coturn
run: |
cmake -E make_directory ${{github.workspace}}/build
cd ${{github.workspace}}/build
cmake ${{github.workspace}} ^
-A ${{matrix.CMAKE_GENERATOR_PLATFORM}} ^
-T ${{matrix.VCPKG_PLATFORM_TOOLSET}} ^
-DWITH_MYSQL=OFF ^
-DBUILD_SHARED_LIBS=${{matrix.BUILD_SHARED_LIBS}} ^
-DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} ^
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/build/install ^
-DCMAKE_TOOLCHAIN_FILE=${{env.VCPKG_ROOT}}/scripts/buildsystems/vcpkg.cmake
cmake --build . --config ${{matrix.BUILD_TYPE}}
cmake --build . --config ${{matrix.BUILD_TYPE}} --target install
- name: Build Coturn
run: |
cmake -E make_directory ${{ github.workspace }}/build
cd ${{ github.workspace }}/build
cmake ${{ github.workspace }} ^
-A ${{ matrix.CMAKE_GENERATOR_PLATFORM }} ^
-T ${{ matrix.VCPKG_PLATFORM_TOOLSET }} ^
-DWITH_MYSQL=OFF ^
-DBUILD_SHARED_LIBS=${{ matrix.BUILD_SHARED_LIBS }} ^
-DCMAKE_BUILD_TYPE=${{ matrix.BUILD_TYPE }} ^
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/build/install ^
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
cmake --build . --config ${{ matrix.BUILD_TYPE }}
cmake --build . --config ${{ matrix.BUILD_TYPE }} --target install
- name: Package
if: ${{ matrix.BUILD_TYPE == 'Release' }}
working-directory: ${{github.workspace}}\build
run: |
7z a coturn_windows_msvc.zip ${{github.workspace}}\build\install\*
cmake --build . --config ${{matrix.BUILD_TYPE}} --target package
- name: Package
run: |
7z a coturn_windows_msvc.zip ${{ github.workspace }}\build\install\*
cmake --build . --config ${{ matrix.BUILD_TYPE }} --target package
working-directory: ${{ github.workspace }}\build
if: ${{ matrix.BUILD_TYPE == 'Release' }}
- name: Update
if: ${{ matrix.BUILD_TYPE == 'Release' }}
uses: actions/upload-artifact@v4
with:
name: coturn_msvc-${{matrix.VCPKG_PLATFORM_TOOLSET}}-${{matrix.CMAKE_GENERATOR_PLATFORM}}-${{matrix.BUILD_SHARED_LIBS}}
path: |
${{github.workspace}}\build\coturn_windows_msvc.zip
${{github.workspace}}\build\coturn*.exe
${{github.workspace}}\build\coturn*.md5
- name: Update artifacts
uses: actions/upload-artifact@v4
with:
name: coturn_msvc-${{ matrix.VCPKG_PLATFORM_TOOLSET }}-${{ matrix.CMAKE_GENERATOR_PLATFORM }}-${{ matrix.BUILD_SHARED_LIBS }}
path: |
${{ github.workspace }}\build\coturn_windows_msvc.zip
${{ github.workspace }}\build\coturn*.exe
${{ github.workspace }}\build\coturn*.md5
if: ${{ matrix.BUILD_TYPE == 'Release' }}

View File

@ -1,36 +0,0 @@
name: Ubuntu
on:
push:
pull_request:
types: [ opened, reopened, synchronize ]
# make GHA actions use node16 to use ancient container images
# See https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/
# Unclear how long this will work though
env:
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
jobs:
builds:
strategy:
fail-fast: false
matrix:
os: [ 'ubuntu:16.04', 'ubuntu:18.04', 'ubuntu:20.04', 'ubuntu:22.04' ]
runs-on: ubuntu-latest
container: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Install dependencies
# Set env variable or otherwise tzdata package requires interaction
env:
DEBIAN_FRONTEND: noninteractive
uses: ./.github/workflows/actions/ubuntu-build-deps
- name: configure
run: ./configure
- name: make
run: make
- name: make check
run: make check
- name: apps tests
run: cd examples && ./run_tests.sh && ./run_tests_conf.sh

View File

@ -1,8 +1,11 @@
Thanks to the following contributors (in alphabetical order):
- Aaron Bird <25508292+Aaron-Bird@users.noreply.github.com>
- Alessandro Polidori <alessandro.polidori@nethesis.it>
- Alex Gustafsson <89969483+alexg-axis@users.noreply.github.com>
- Alexander N <a@a>
- Alexander Terczka <alex@mail.at>
- Alexander Udovichenko <udovichenko48@gmail.com>
- Antony Dovgal <tony@daylessday.org>
- Arjun <36335769+0x34d@users.noreply.github.com>
- Arne Georg Gisnås Gleditsch <argggh@appear.in>
@ -14,19 +17,24 @@ Thanks to the following contributors (in alphabetical order):
- Byron Clark <byron@theclarkfamily.name>
- Camden Narzt <c.narzt@me.com>
- Carsten Bock <carsten@ng-voice.com>
- Cédric DIJOUX <45537432+PrinceChoco@users.noreply.github.com>
- Cédric Krier <ced@b2ck.com>
- Chai-Shi <changchaishi@gmail.com>
- Corey Cole <coreyleoc@gmail.com>
- Cybermilitia <Cybermilitia@users.noreply.github.com>
- Daniil Meitis <30820460+dsmeytis@users.noreply.github.com>
- Daniil Meitis <daniil.meitis@viber.com>
- Danilo Bargen <mail@dbrgn.ch>
- Dave Lambley <dave@lambley.me.uk>
- Dave Lambley <github@davel.me.uk>
- David Florness <david@florness.com>
- David Smitmanis <davidsm@axis.com>
- David-dp- <David-dp-@users.noreply.github.com>
- Domenico Briganti <domenico.briganti@osys.it>
- Emil Ljungdahl <111423223+pando-emil@users.noreply.github.com>
- Erdem Duman <erdemduman23@gmail.com>
- Erik Moqvist <erik.moqvist@axis.com>
- Evgeny Khramtsov <xramtsov@gmail.com>
- Feral Interactive <noreply@feralinteractive.com>
- Gautier HUSSON <g.husson_git@liberasys.com>
- Giacomo Vacca <gvacca@subspace.com>
@ -34,12 +42,14 @@ Thanks to the following contributors (in alphabetical order):
- Greg Fodor <gfodor@gmail.com>
- Gregor Jasny <gjasny@googlemail.com>
- Gustavo Garcia <gustavogb@gmail.com>
- Gustavo Garcia <gustavogb@mail.com>
- Haseeb Abdul Qadir <haseebq@jumpdesktop.com>
- Hristo Venev <hristo@venev.name>
- Hui Kang <kangh@us.ibm.com>
- Hyorin Choi <17173216+hyorin@users.noreply.github.com>
- Ilya Kisleyko <osterik@gmail.com>
- James Huang <hng.jms@gmail.com>
- Jan Brasna <1784648+janbrasna@users.noreply.github.com>
- Jasper <jasper@jasperhugo.com>
- Jens Elkner <jel+coturn@cs.ovgu.de>
- Jens Elkner <jel+git@iks.cs.uni-magdeburg.de>
@ -49,6 +59,7 @@ Thanks to the following contributors (in alphabetical order):
- Johannes Weberhofer <jweberhofer@weberhofer.at>
- Jonathan GIBERT <Jonathan.GIBERT@iconsultants.fr>
- JooYoung <qkdlql@naver.com>
- Jorge <46056498+jorgectf@users.noreply.github.com>
- Juan Navarro <juan.navarro@gmx.es>
- KORAY VATANSEVER <koray.vatansever@turkcell.com.tr>
- KORAY VATANSEVER <ttkvatansever@TC08966777>
@ -67,14 +78,17 @@ Thanks to the following contributors (in alphabetical order):
- Mészáros Mihály <bakfitty@gmail.com>
- Mészáros Mihály <misi@majd.eu>
- Mészáros Mihály <misi@niif.hu>
- Michael Jones <jonesmz@users.noreply.github.com>
- Michal Biskup <eiver@eiver.pl>
- Miquel Ortega <miquel@syncrtc.com>
- Molly Miller <33266253+sysvinit@users.noreply.github.com>
- Molly Miller <molly.miller@wire.com>
- Mustafa Bingül <bnglmstf@gmail.com>
- NO NAME <45446340+linwenchen@users.noreply.github.com>
- NeoCat <neocat@neocat.jp>
- Nicolas Edet <nicedet@cisco.com>
- Nikolay Lanets <n.lanets@modxclub.ru>
- Nikolayshcx <77790944+Nikolayshcx@users.noreply.github.com>
- Oleg Moskalenko <mom040267@gmail.com>
- Orsiris de Jong <ozy@netpower.fr>
- Oskar Niburski <oskarniburski@gmail.com>
@ -90,8 +104,10 @@ Thanks to the following contributors (in alphabetical order):
- Prashanth Rajaram <prashanthr@users.noreply.github.com>
- RIORAO <lah.messagebox@gmail.com>
- Richard Garnier <richard@bitcraft.co.jp>
- Richard Russo <richard@signal.org>
- Robert Scheck <robert-scheck@users.noreply.github.com>
- Robert Scheck <robert@fedoraproject.org>
- Robert Silén <robert.silen@mariadb.org>
- Robert Tupelo-Schneck <schneck@cnri.reston.va.us>
- Rozhuk Ivan <rozhuk.im@gmail.com>
- Ruben Barkow-Kuder <rubo77@users.noreply.github.com>
@ -100,28 +116,41 @@ Thanks to the following contributors (in alphabetical order):
- Sandro Gauci <sandro@enablesecurity.com>
- Scott Godin <sgodin@sipspectrum.com>
- Sebastian Kemper <sebastian_ml@gmx.net>
- Sergey Radionov <RSATom@gmail.com>
- Sergey Safarov <s.safarov@gmail.com>
- Serhii Charykov <laammaar@gmail.com>
- Shu Muto <shu.mutow@gmail.com>
- Shu Muto <shu.mutow@nec.com>
- Stefan Junker <1181362+steveej@users.noreply.github.com>
- Stefan Sundin <git@stefansundin.com>
- Steffen Moser <public@steffen-moser.de>
- Steffen Moser <steffen.moser@uni-ulm.de>
- Subhra264 <chakrabortysubhradeep556@gmail.com>
- Sven Tennie <sven.tennie@gmail.com>
- Thibaut ACKERMANN <thib-ack@users.noreply.github.com>
- Thibaut Ackermann <thibaut.ackermann@al-enterprise.com>
- Thibaut Ackermann <thibaut.ackermann@alcatel-lucent.com>
- Tom Bevan <thehorrorthehorror@gmail.com>
- Wittmer, Christian <chris@computersalat.de>
- Wuelber Castillo <wuelber.castillo@gmail.com>
- Yoshiki Kadoshita <sublimer.me@gmail.com>
- Zebadiah Long <zeb@noblewhale.com>
- Zoey <zoey@z0ey.de>
- ashamedbit <muralianiruddhan@gmail.com>
- bpcurse <29312856+bpcurse@users.noreply.github.com>
- brevilo <brevilo@users.noreply.github.com>
- chanduthedev <chanduthedev@gmail.com>
- czephyr <alfredo.funicello@studenti.unimi.it>
- damencho <damencho@jitsi.org>
- ddeka2910 <60925700+ddeka2910@users.noreply.github.com>
- dominiquefournier <dominique@fournier38.fr>
- eakraly <eakraly@users.noreply.github.com>
- ggalperi <81175455+ggalperi@users.noreply.github.com>
- hariprasadt <hariprasad.t@samsung.com>
- huhaipeng <huhaipeng@corp.netease.com>
- islamoglus <islamogluselahaddin@gmail.com>
- korayvt <korayvt@users.noreply.github.com>
- maddy <maddy@kitty.garden>
- marcoschum <50410120+marcoschum@users.noreply.github.com>
- misi <bakfitty@gmail.com>
- mom040267 <mom040267@gmail.com>
@ -132,13 +161,16 @@ Thanks to the following contributors (in alphabetical order):
- ooookai <ooookai@users.noreply.github.com>
- r3g_5z <june@girlboss.ceo>
- raghumuppa <mupparthies@gmail.com>
- redraincatching <99604494+redraincatching@users.noreply.github.com>
- release-it <release-it@tawenda.com>
- rim <11380091+rozhuk-im@users.noreply.github.com>
- root <root@centot7.test.in.securom.me>
- seungbin-ko <seungbin.ko@navercorp.com>
- shuyin.wsy <shuyin.wsy@alibaba-inc.com>
- skystar-p <wogus150@naver.com>
- tyranron <tyranron@gmail.com>
- unicode-it <info@unicode-it.de>
- vuittont60 <81072379+vuittont60@users.noreply.github.com>
- wolmi <lenyos@gmail.com>
- xthursdayx <xthursdayx@mailbox.org>
- yohan <783b8c87@scimetis.net>

View File

@ -9,7 +9,7 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
# TODO: Modify this when the version is released
SET(BUILD_VERSION "4.6.2")
SET(BUILD_VERSION "4.6.3")
# Find Git Version Patch
IF(EXISTS "${CMAKE_SOURCE_DIR}/.git")

152
ChangeLog
View File

@ -1,3 +1,155 @@
Release 4.6.3
Changelist:
- Implement custom prometheus http handler (#1591) (Alex Gustafsson <89969483+alexg-axis@users.noreply.github.com>)
- Add MariaDB support to README.md (#1601) (Robert Silén <robert.silen@mariadb.org>)
- Allow authenticating with a username to redis (#1488) (maddy <maddy@kitty.garden>)
- Easy installation of coturn on AWS (#1581) (hariprasadt <hariprasad.t@samsung.com>)
- Add prometheus setting suggestions on turn.conf in example folder (#1597) (Chai-Shi <changchaishi@gmail.com>)
- Install openssl-1.1.1 on amazonlinux:2 instead of openssl-1.0.1 (#1595) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Add new Drain feature (#1529) (Scott Godin <sgodin@sipspectrum.com>)
- Additional refactoring of ns_turn_allocation.* to address security scanner concerns (#1514) (Michael Jones <jonesmz@users.noreply.github.com>)
- Fix linting error in mainrelay.c (#1558) (redraincatching <99604494+redraincatching@users.noreply.github.com>)
- Fix rpm version scripts (#1556) (eakraly <eakraly@users.noreply.github.com>)
- Delete dead code (#1563) (Sven Tennie <sven.tennie@gmail.com>)
- Fix cli auth (#1578) (Mészáros Mihály <misi@majd.eu>)
- Use bool, instead of int, for the functions in ns_turn_msg.c (#1553) (Michael Jones <jonesmz@users.noreply.github.com>)
- Reformat code (#1557) (Pavel Punsky <eakraly@users.noreply.github.com>)
- configure: data files shouldn't be executable (#1542) (Sergey Radionov <RSATom@gmail.com>)
- Update libtelnet (#1545) (Michael Jones <jonesmz@users.noreply.github.com>)
- Use calloc where appropriate, avoid memset when normal buffer initialization works (#1550) (Michael Jones <jonesmz@users.noreply.github.com>)
- Fix make lint (#1547) (Michael Jones <jonesmz@users.noreply.github.com>)
- Fix compiler warnings from continuous integration (#1555) (Michael Jones <jonesmz@users.noreply.github.com>)
- Fix nodejs/glibc problem with old container images. (#1548) (Michael Jones <jonesmz@users.noreply.github.com>)
- Windows: Only attempt to bind when the network interface is up (#1527) (David Smitmanis <davidsm@axis.com>)
- Memset user_db before reading conf file, not after (#1537) (Pavel Punsky <eakraly@users.noreply.github.com>)
- added support for amazon linux and renamed tests.yml (#1401) (redraincatching <99604494+redraincatching@users.noreply.github.com>)
- Check the result of malloc in send_message_to_redis (#1515) (Michael Jones <jonesmz@users.noreply.github.com>)
- Check the result of malloc in mongo_set_realm_option_one (#1516) (Michael Jones <jonesmz@users.noreply.github.com>)
- Simplify workflow for codeql (#1517) (Michael Jones <jonesmz@users.noreply.github.com>)
- Move the hiredis_libevent2 code from common to relay (#1509) (Michael Jones <jonesmz@users.noreply.github.com>)
- Include what you use (#1512) (Michael Jones <jonesmz@users.noreply.github.com>)
- Check the result of malloc in string_list_add (#1495) (Michael Jones <jonesmz@users.noreply.github.com>)
- Check the result of realloc and calloc in ch_map_get (#1497) (Michael Jones <jonesmz@users.noreply.github.com>)
- Address clang-tidy warnings in db files (#1405) (Michael Jones <jonesmz@users.noreply.github.com>)
- malloc now allocates space for string terminator (#1507) (redraincatching <99604494+redraincatching@users.noreply.github.com>)
- Use bool over int for the turnutils_uclient program (#1420) (Michael Jones <jonesmz@users.noreply.github.com>)
- Fix lint complaint about comment (#1506) (Michael Jones <jonesmz@users.noreply.github.com>)
- Run all of the CI except for Docker builds on any change (#1415) (Michael Jones <jonesmz@users.noreply.github.com>)
- Avoid read-past-end of string in get_bold_admin_title (#1499) (Michael Jones <jonesmz@users.noreply.github.com>)
- Check allocation results in add_static_user_account (#1501) (Michael Jones <jonesmz@users.noreply.github.com>)
- Address some build issues introduced by api changes (#1505) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Check the result of calloc in handle_logon_request (#1498) (Michael Jones <jonesmz@users.noreply.github.com>)
- Avoid writing potentially uninitialized data to aes_128 key file (#1500) (Michael Jones <jonesmz@users.noreply.github.com>)
- Use active CPU number instead of total number (#1469) (Pavel Punsky <eakraly@users.noreply.github.com>)
- defined a magic number for stun fingerprinting (#1489) (redraincatching <99604494+redraincatching@users.noreply.github.com>)
- Always run lint, regardless of branch (#1492) (Michael Jones <jonesmz@users.noreply.github.com>)
- avoid potential nullptr derefernence in udp_create_server_socket (#1496) (Michael Jones <jonesmz@users.noreply.github.com>)
- Change the various map functions to return bool instead of inconsistantly return 0, 1, or -1 (#1502) (Michael Jones <jonesmz@users.noreply.github.com>)
- Check the result of malloc in del_alt_server (#1503) (Michael Jones <jonesmz@users.noreply.github.com>)
- Avoid nullptr dereference of server variable in various functions (#1504) (Michael Jones <jonesmz@users.noreply.github.com>)
- Fix msvc analyzer error on goto label on rfc5769check (#1486) (Gustavo Garcia <gustavogb@gmail.com>)
- Fix buffer overflow in generate_enc_password with increase rsalt by 2 (#1463) (Stefan Junker <1181362+steveej@users.noreply.github.com>)
- Fix lint errors (Gustavo Garcia <gustavogb@gmail.com>)
- Add support for raw public keys (Rfc 7250) (#1458) (Nikolayshcx <77790944+Nikolayshcx@users.noreply.github.com>)
- Fix clang-format lint warnings (Gustavo Garcia <gustavogb@mail.com>)
- Fix const during free warning in rfc5769check app (Gustavo Garcia <gustavogb@mail.com>)
- Refactor: peer_input_handle (#1325) (Kang Lin <kl222@126.com>)
- workflow tidying (#1396) (redraincatching <99604494+redraincatching@users.noreply.github.com>)
- Update turnserver.conf Example about listening-ip (#1336) (Wittmer, Christian <chris@computersalat.de>)
- Fix Cmake find issue in libevent (#1466) (NO NAME <45446340+linwenchen@users.noreply.github.com>)
- CMake: Declare the variable nearby (#1387) (Kang Lin <kl222@126.com>)
- Print version only, no extra lines (#1441) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Fix memory leak in rfc5769check.c (#1410) (ashamedbit <muralianiruddhan@gmail.com>)
- Fix memory leak in netengine.c (#1411) (ashamedbit <muralianiruddhan@gmail.com>)
- Fix memory leak on http_server.c (#1412) (ashamedbit <muralianiruddhan@gmail.com>)
- ubuntu build dependencies extracted to composite actions (#1399) (redraincatching <99604494+redraincatching@users.noreply.github.com>)
- Delete unused variable (#1437) (Pavel Punsky <eakraly@users.noreply.github.com>)
- changed variables in stunclient.c to bool (C11) (#1421) (redraincatching <99604494+redraincatching@users.noreply.github.com>)
- added missing function prototype of turn_random_number() (#1428) (redraincatching <99604494+redraincatching@users.noreply.github.com>)
- Fix no-tls warning typo (#1426) (Jan Brasna <1784648+janbrasna@users.noreply.github.com>)
- Update SQLite.md (#1429) (dominiquefournier <dominique@fournier38.fr>)
- Adjust wording in cmake message when prometheous cannot be found. (#1418) (Michael Jones <jonesmz@users.noreply.github.com>)
- Add the InsertBraces command for clang-format to ensure that all conditionals always have braces (#1408) (Michael Jones <jonesmz@users.noreply.github.com>)
- Change minimal required cmake version to 3.16 (#1388) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Replace HeapAlloc with malloc (#1378) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Added sessionID to some log lines (#1334) (korayvt <korayvt@users.noreply.github.com>)
- Update FlowChart (#1377) (Kang Lin <kl222@126.com>)
- Add clang-tidy, include-what-you-use, and msvc-analyzer github actions (#1363) (Michael Jones <jonesmz@users.noreply.github.com>)
- Doc: add flowchart (#1328) (Kang Lin <kl222@126.com>)
- Missing session ID in coturn logs for denied IP - 1330 (#1332) (Cybermilitia <Cybermilitia@users.noreply.github.com>)
- Update lukka/run-vcpkg@11 (#1374) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Fix typos (#1345) (vuittont60 <81072379+vuittont60@users.noreply.github.com>)
- Fix mingw build (#1376) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Add github action that runs tests with compiler sanitizers (#1370) (Michael Jones <jonesmz@users.noreply.github.com>)
- Simplify macOS detection macros (#1372) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Fix potential null passed to function expecting nonnull (#1373) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Only set MHD_USE_DUAL_STACK if IPv6 is available (#1362) (Evgeny Khramtsov <xramtsov@gmail.com>)
- Remove unimplemented test folder reference from CMakeLists.txt (#1371) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Fix cmake find prometheus(fix #1304) (#1315) (Kang Lin <kl222@126.com>)
- Fix run cmake.yml in any github action (#1320) (Kang Lin <kl222@126.com>)
- Fix return correct error code for `create_relay_connection` in case of `RESERVATION-TOKEN` failure (#1319) (Subhra264 <chakrabortysubhradeep556@gmail.com>)
- Reduce ifdefs in code: TURN_NO_PROMETHEUS (#1116) (Pavel Punsky <eakraly@users.noreply.github.com>)
- strncpy doesn't return size_t (#1296) (Richard Russo <richard@signal.org>)
- Return a 400 response to HTTP requests (#1231) (Dave Lambley <dave@lambley.me.uk>)
- Fix missing strncpy in fix_stun_check_message_integrity_str (#1282) (Gustavo Garcia <gustavogb@gmail.com>)
- Fix ubuntu 16 build with GH action checkout version to v3 (#1281) (Gustavo Garcia <gustavogb@gmail.com>)
- Fix memleak in pgsql_reread_realms (#1278) (Pavel Punsky <eakraly@users.noreply.github.com>)
- Replace srand/rand with srandom/random (#1279) (Gustavo Garcia <gustavogb@gmail.com>)
- Fix memcpy len checks stun_is_challenge_response_str (#1280) (Gustavo Garcia <gustavogb@gmail.com>)
- Add warning and disable web admin if no-tls option used (#1256) (Alexander Udovichenko <udovichenko48@gmail.com>)
- Fix formatting to fix lint error (#1258) (Pavel Punsky <eakraly@users.noreply.github.com>)
- added warnings for prometheus apt unavailability (#1184) (czephyr <alfredo.funicello@studenti.unimi.it>)
- Update version in vcpkg.json (#1254) (Kang Lin <kl222@126.com>)
- Fix error of make command in Cygwin environment (#1236) (Aaron Bird <25508292+Aaron-Bird@users.noreply.github.com>)
- Fix recursive call in delete alternate server (#1250) (Cybermilitia <Cybermilitia@users.noreply.github.com>)
- Add CodeQL workflow (#1228) (Jorge <46056498+jorgectf@users.noreply.github.com>)
- Change printf() to TURN_LOG_FUNC() for --no-stdout-log (#1221) (Robert Scheck <robert-scheck@users.noreply.github.com>)
- Fix build with libressl 3.6+ (#1198) (rim <11380091+rozhuk-im@users.noreply.github.com>)
- Update turnserver.spec (#1192) (Mathieu Aubin <mathieu@zeroserieux.com>)
Contributors:
- Aaron Bird <25508292+Aaron-Bird@users.noreply.github.com>
- Alex Gustafsson <89969483+alexg-axis@users.noreply.github.com>
- Alexander Udovichenko <udovichenko48@gmail.com>
- Chai-Shi <changchaishi@gmail.com>
- Cybermilitia <Cybermilitia@users.noreply.github.com>
- Dave Lambley <dave@lambley.me.uk>
- David Smitmanis <davidsm@axis.com>
- Evgeny Khramtsov <xramtsov@gmail.com>
- Gustavo Garcia <gustavogb@gmail.com>
- Gustavo Garcia <gustavogb@mail.com>
- Jan Brasna <1784648+janbrasna@users.noreply.github.com>
- Jorge <46056498+jorgectf@users.noreply.github.com>
- Kang Lin <kl222@126.com>
- Mathieu Aubin <mathieu@zeroserieux.com>
- Mészáros Mihály <misi@majd.eu>
- Michael Jones <jonesmz@users.noreply.github.com>
- NO NAME <45446340+linwenchen@users.noreply.github.com>
- Nikolayshcx <77790944+Nikolayshcx@users.noreply.github.com>
- Pavel Punsky <eakraly@users.noreply.github.com>
- Richard Russo <richard@signal.org>
- Robert Scheck <robert-scheck@users.noreply.github.com>
- Robert Silén <robert.silen@mariadb.org>
- Scott Godin <sgodin@sipspectrum.com>
- Sergey Radionov <RSATom@gmail.com>
- Stefan Junker <1181362+steveej@users.noreply.github.com>
- Subhra264 <chakrabortysubhradeep556@gmail.com>
- Sven Tennie <sven.tennie@gmail.com>
- Wittmer, Christian <chris@computersalat.de>
- Zoey <zoey@z0ey.de>
- ashamedbit <muralianiruddhan@gmail.com>
- czephyr <alfredo.funicello@studenti.unimi.it>
- dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- dominiquefournier <dominique@fournier38.fr>
- eakraly <eakraly@users.noreply.github.com>
- hariprasadt <hariprasad.t@samsung.com>
- korayvt <korayvt@users.noreply.github.com>
- maddy <maddy@kitty.garden>
- redraincatching <99604494+redraincatching@users.noreply.github.com>
- rim <11380091+rozhuk-im@users.noreply.github.com>
- vuittont60 <81072379+vuittont60@users.noreply.github.com>
Release 4.6.2
Changelist:

View File

@ -35,7 +35,7 @@ coturn requires following dependencies to be installed first
Optional
- openssl (to support TLS and DTLS, authorized STUN and TURN)
- libmicrohttp and [prometheus-client-c](https://github.com/digitalocean/prometheus-client-c) (prometheus interface)
- MySQL (user database)
- MariaDB/MySQL (user database)
- [Hiredis](https://github.com/redis/hiredis) (user database, monitoring)
- SQLite (user database)
- PostgreSQL (user database)
@ -98,7 +98,7 @@ Relay protocols:
User databases (for user repository, with passwords or keys, if authentication is required):
* SQLite
* MySQL
* MariaDB/MySQL
* PostgreSQL
* Redis
* MongoDB

View File

@ -168,7 +168,10 @@ Flags:
-o, --daemon Run server as daemon.
--no-software-attribute Production mode: hide the software version.
--no-software-attribute DEPRECATED. See "--software-attribute".
--software-attribute Send SOFTWARE_ATTRIBUTE on messages that can have it. Disabled by default.
Equals to deprecated option "--no-software-attribute false".
-f, --fingerprint Use fingerprints in the TURN messages. If an incoming request
contains a fingerprint, then TURN server will always add

View File

@ -7,7 +7,7 @@
#
# Try to find prometheus
# Once done, this will define:
# Prometheus_FOUND - Prometheus (or all requested components of prom, promhttp, microhttpd) was found.
# Prometheus_FOUND - Prometheus (or all requested components of prom, microhttpd) was found.
# Prometheus_INCLUDE_DIRS - Libevent include directories
# Prometheus_LIBRARIES - libraries needed to use Prometheus
#
@ -16,9 +16,8 @@ include(FindPackageHandleStandardArgs)
find_package(PkgConfig)
pkg_check_modules(PC_prom QUIET prom)
pkg_check_modules(PC_promhttp QUIET promhttp)
pkg_check_modules(PC_microhttd QUIET microhttpd)
find_path(microhttpd_include_dir
NAMES microhttpd.h
HINTS ${Prometheus_DIR} ${Prometheus_ROOT} ${PC_microhttd_INCLUDE_DIRS} /usr
@ -47,28 +46,12 @@ find_library(
PATHS $ENV{Prometheus_DIR} $ENV{Prometheus_ROOT}
PATH_SUFFIXES lib ${CMAKE_INSTALL_LIBDIR})
find_path(promhttp_INCLUDE_DIR
NAMES promhttp.h
HINTS ${Prometheus_DIR} ${Prometheus_ROOT} ${PC_promhttp_INCLUDE_DIRS} /usr
PATHS $ENV{Prometheus_DIR} $ENV{Prometheus_ROOT}
PATH_SUFFIXES include
)
find_library(
promhttp_libs
NAMES promhttp
HINTS ${Prometheus_DIR} ${Prometheus_ROOT} ${PC_promhttp_LIBRARY_DIRS}
PATHS $ENV{Prometheus_DIR} $ENV{Prometheus_ROOT}
PATH_SUFFIXES lib ${CMAKE_INSTALL_LIBDIR})
find_package_handle_standard_args(Prometheus
REQUIRED_VARS prom_libs prom_INCLUDE_DIR
promhttp_libs promhttp_INCLUDE_DIR
microhttpd_include_dir microhttpd_libs
)
set(Prometheus_INCLUDE_DIRS
${prom_INCLUDE_DIR}
${promhttp_INCLUDE_DIR}
${microhttpd_include_dir})
set(Prometheus_LIBRARIES ${prom_libs} ${promhttp_libs} ${microhttpd_libs})
set(Prometheus_LIBRARIES ${prom_libs} ${microhttpd_libs})

26
configure vendored
View File

@ -848,30 +848,18 @@ if [ -z "${TURN_NO_PROMETHEUS}" ] ; then
ER=$?
if ! [ ${ER} -eq 0 ] ; then
${ECHO_CMD} "Prometheus lib found."
testlib promhttp
testlib microhttpd
ER=$?
if ! [ ${ER} -eq 0 ] ; then
${ECHO_CMD} "Prometheus http lib found."
testlib microhttpd
ER=$?
if ! [ ${ER} -eq 0 ] ; then
${ECHO_CMD} "Microhttpd lib found."
# Adjustments for Debian
# See: https://github.com/coturn/coturn/pull/754#issuecomment-824693226
if [ -f "/etc/debian_version" ] ; then
OSLIBS="${OSLIBS} -latomic"
fi
else
${ECHO_CMD}
${ECHO_CMD} "Warning: microhttpd development libraries are not installed properly in required location."
${ECHO_CMD} "Prometheus support will be disabled."
${ECHO_CMD} "See the docs/Prometheus.md file."
${ECHO_CMD}
OSCFLAGS="${OSCFLAGS} -DTURN_NO_PROMETHEUS"
${ECHO_CMD} "Microhttpd lib found."
# Adjustments for Debian
# See: https://github.com/coturn/coturn/pull/754#issuecomment-824693226
if [ -f "/etc/debian_version" ] ; then
OSLIBS="${OSLIBS} -latomic"
fi
else
${ECHO_CMD}
${ECHO_CMD} "Warning: Libpromhttp development libraries are not installed properly in required location."
${ECHO_CMD} "Warning: microhttpd development libraries are not installed properly in required location."
${ECHO_CMD} "Prometheus support will be disabled."
${ECHO_CMD} "See the docs/Prometheus.md file."
${ECHO_CMD}

View File

@ -4,6 +4,41 @@ Coturn TURN server Docker image changelog
## [4.6.3-r1] · 2025-01-08
[4.6.3-r1]: /../../tree/docker/4.6.3-r1
### Security updated
- [Alpine Linux] 3.21.1: <https://github.com/docker-library/official-images/commit/34b47f1f4bdef69e39ae335e55b0f07af3b4fa18>
- [Debian Linux] "bookworm" 20241223 (12.8): <https://github.com/docker-library/official-images/commit/b6ea0fc48d92a7f6ef631667e82600666be53181>
## [4.6.3-r0] · 2024-12-11
[4.6.3-r0]: /../../tree/docker/4.6.3-r0
### Upgraded
- [Coturn] 4.6.3: <https://github.com/coturn/coturn/blob/4.6.3/ChangeLog>
## [4.6.2-r13] · 2024-12-06
[4.6.2-r13]: /../../tree/docker/4.6.2-r13
### Upgraded
- [Alpine Linux] 3.21: <https://alpinelinux.org/posts/Alpine-3.21.0-released.html>
### Security updated
- [Debian Linux] "bookworm" 20241202 (12.8): <https://github.com/docker-library/official-images/commit/36ffb3d236c35c22922dfeca1844d7ad119b06f5>
## [4.6.2-r12] · 2024-09-09
[4.6.2-r12]: /../../tree/docker/4.6.2-r12

View File

@ -24,7 +24,7 @@ dockerify = $(strip $(if $(call eq,$(1),linux/arm32v6),linux/arm/v6,\
# Project parameters #
######################
COTURN_VER ?= 4.6.2
COTURN_VER ?= 4.6.3
COTURN_MIN_VER = $(strip $(shell echo $(COTURN_VER) | cut -d '.' -f1,2))
COTURN_MAJ_VER = $(strip $(shell echo $(COTURN_VER) | cut -d '.' -f1))
@ -34,7 +34,7 @@ ALPINE_VER := alpine$(strip $(shell grep -m1 'alpine_ver=' alpine/Dockerfile \
DEBIAN_VER := $(strip $(shell grep -m1 'debian_ver=' debian/Dockerfile \
| cut -d '=' -f2))
BUILD_REV ?= 12
BUILD_REV ?= 1
NAME := coturn
OWNER := $(or $(GITHUB_REPOSITORY_OWNER),coturn)

View File

@ -15,8 +15,8 @@ Coturn TURN server Docker image
## Supported tags and respective `Dockerfile` links
- [`4.6.2-r12`, `4.6.2-r12-debian`, `4.6.2`, `4.6.2-debian`, `4.6.2-bookworm`, `4.6`, `4.6-debian`, `4.6-bookworm`, `4`, `4-debian`, `4-bookworm`, `debian`, `bookworm`, `latest`][d1]
- [`4.6.2-r12-alpine`, `4.6.2-alpine`, `4.6.2-alpine3.20`, `4.6-alpine`, `4.6-alpine3.20`, `4-alpine`, `4-alpine3.20`, `alpine`, `alpine3.20`][d2]
- [`4.6.3-r1`, `4.6.3-r1-debian`, `4.6.3`, `4.6.3-debian`, `4.6.3-bookworm`, `4.6`, `4.6-debian`, `4.6-bookworm`, `4`, `4-debian`, `4-bookworm`, `debian`, `bookworm`, `latest`][d1]
- [`4.6.3-r1-alpine`, `4.6.3-alpine`, `4.6.3-alpine3.21`, `4.6-alpine`, `4.6-alpine3.21`, `4-alpine`, `4-alpine3.21`, `alpine`, `alpine3.21`][d2]

View File

@ -2,7 +2,7 @@
# Dockerfile of coturn/coturn:alpine Docker image.
#
ARG alpine_ver=3.20
ARG alpine_ver=3.21
@ -46,27 +46,13 @@ RUN mkdir -p /build/prom/build/ && cd /build/prom/build/ \
.. \
&& make
# Build libpromhttp.so from sources.
RUN mkdir -p /build/promhttp/build/ && cd /build/promhttp/build/ \
# Fix compiler warning: -Werror=incompatible-pointer-types
&& sed -i 's/\&promhttp_handler/(MHD_AccessHandlerCallback)\&promhttp_handler/' \
/build/promhttp/src/promhttp.c \
&& TEST=0 cmake -G "Unix Makefiles" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_SKIP_BUILD_RPATH=TRUE \
-DCMAKE_C_FLAGS="-g -O3" \
.. \
&& make VERBOSE=1
# Install prometheus-client-c.
RUN LIBS_DIR=/out/$(dirname $(find /usr/ -name libc.so)) \
&& mkdir -p $LIBS_DIR/ \
&& cp -rf /build/prom/build/libprom.so \
/build/promhttp/build/libpromhttp.so \
$LIBS_DIR/ \
&& mkdir -p /out/usr/include/ \
&& cp -rf /build/prom/include/* \
/build/promhttp/include/* \
/out/usr/include/ \
# Preserve license file.
&& mkdir -p /out/usr/share/licenses/prometheus-client-c/ \

View File

@ -46,27 +46,13 @@ RUN mkdir -p /build/prom/build/ && cd /build/prom/build/ \
.. \
&& make
# Build libpromhttp.so from sources.
RUN mkdir -p /build/promhttp/build/ && cd /build/promhttp/build/ \
# Fix compiler warning: -Werror=incompatible-pointer-types
&& sed -i 's/\&promhttp_handler/(MHD_AccessHandlerCallback)\&promhttp_handler/' \
/build/promhttp/src/promhttp.c \
&& TEST=0 cmake -G "Unix Makefiles" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_SKIP_BUILD_RPATH=TRUE \
-DCMAKE_C_FLAGS="-g -O3" \
.. \
&& make VERBOSE=1
# Install prometheus-client-c.
RUN LIBS_DIR=/out/$(dirname $(find /usr/ -name libc.so)) \
&& mkdir -p $LIBS_DIR/ \
&& cp -rf /build/prom/build/libprom.so \
/build/promhttp/build/libpromhttp.so \
$LIBS_DIR/ \
&& mkdir -p /out/usr/include/ \
&& cp -rf /build/prom/include/* \
/build/promhttp/include/* \
/out/usr/include/ \
# Preserve license file.
&& mkdir -p /out/usr/share/licenses/prometheus-client-c/ \

View File

@ -601,14 +601,14 @@ syslog
#
#stun-only
# Option to hide software version. Enhance security when used in production.
# Option to show software version - disabled by default.
# Revealing the specific software version of the agent through the
# SOFTWARE attribute might allow them to become more vulnerable to
# attacks against software that is known to contain security holes.
# Implementers SHOULD make usage of the SOFTWARE attribute a
# configurable option (https://tools.ietf.org/html/rfc5389#section-16.1.2)
# configurable option (https://datatracker.ietf.org/doc/html/rfc8489#section-16.1.2)
#
#no-software-attribute
#software-attribute
# Option to suppress STUN functionality, only TURN requests will be processed.
# Run as TURN server only, all STUN requests will be ignored.

View File

@ -213,6 +213,16 @@
#
#prometheus
# Enable labeling prometheus traffic metrics with client usernames.
# Labeling with client usernames is disabled by default, because this may cause memory
# leaks when using authentication with ephemeral usernames (e.g. TURN REST API).
#
#prometheus-username-labels
# Prometheus listener port (Default: 9641).
#
#prometheus-port=9641
# TURN REST API flag.
# (Time Limited Long Term Credential)
# Flag that sets a special authorization option that is based upon authentication secret.

View File

@ -1,14 +1,20 @@
#!/bin/bash
# Detect cmake build and adjust path
BINDIR="../bin"
if [ ! -f $BINDIR/turnserver ]; then
BINDIR="../build/bin"
fi
echo 'Running turnserver'
../bin/turnserver --use-auth-secret --static-auth-secret=secret --realm=north.gov --allow-loopback-peers --no-cli --cert ../examples/ca/turn_server_cert.pem --pkey ../examples/ca/turn_server_pkey.pem > /dev/null &
$BINDIR/turnserver --use-auth-secret --static-auth-secret=secret --realm=north.gov --allow-loopback-peers --no-cli --cert ../examples/ca/turn_server_cert.pem --pkey ../examples/ca/turn_server_pkey.pem > /dev/null &
echo 'Running peer client'
../bin/turnutils_peer -L 127.0.0.1 -L ::1 -L 0.0.0.0 > /dev/null &
$BINDIR/turnutils_peer -L 127.0.0.1 -L ::1 -L 0.0.0.0 > /dev/null &
sleep 2
echo 'Running turn client TCP'
../bin/turnutils_uclient -t -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
$BINDIR/turnutils_uclient -t -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
@ -17,7 +23,7 @@ else
fi
echo 'Running turn client TLS'
../bin/turnutils_uclient -t -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
$BINDIR/turnutils_uclient -t -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
@ -26,7 +32,7 @@ else
fi
echo 'Running turn client UDP'
../bin/turnutils_uclient -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
$BINDIR/turnutils_uclient -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
@ -35,7 +41,7 @@ else
fi
echo 'Running turn client DTLS'
../bin/turnutils_uclient -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
$BINDIR/turnutils_uclient -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else

View File

@ -1,22 +1,29 @@
#!/bin/bash
echo 'Create turnserver.conf file'
echo "use-auth-secret" > ../bin/turnserver.conf
echo "static-auth-secret=secret" >> ../bin/turnserver.conf
echo "realm=north.gov" >> ../bin/turnserver.conf
echo "allow-loopback-peers" >> ../bin/turnserver.conf
echo "no-cli" >> ../bin/turnserver.conf
echo "cert=../examples/ca/turn_server_cert.pem" >> ../bin/turnserver.conf
echo "pkey=../examples/ca/turn_server_pkey.pem" >> ../bin/turnserver.conf
# Detect cmake build and adjust path
BINDIR="../bin"
if [ ! -f $BINDIR/turnserver ]; then
BINDIR="../build/bin"
fi
echo "Creating $BINDIR/turnserver.conf file"
echo "use-auth-secret" > $BINDIR/turnserver.conf
echo "static-auth-secret=secret" >> $BINDIR/turnserver.conf
echo "realm=north.gov" >> $BINDIR/turnserver.conf
echo "allow-loopback-peers" >> $BINDIR/turnserver.conf
echo "no-cli" >> $BINDIR/turnserver.conf
echo "cert=../examples/ca/turn_server_cert.pem" >> $BINDIR/turnserver.conf
echo "pkey=../examples/ca/turn_server_pkey.pem" >> $BINDIR/turnserver.conf
echo 'Running turnserver'
../bin/turnserver -c ../bin/turnserver.conf > /dev/null &
$BINDIR/turnserver -c $BINDIR/turnserver.conf > /dev/null &
echo 'Running peer client'
../bin/turnutils_peer -L 127.0.0.1 -L ::1 -L 0.0.0.0 > /dev/null &
$BINDIR/turnutils_peer -L 127.0.0.1 -L ::1 -L 0.0.0.0 > /dev/null &
sleep 2
echo 'Running turn client TCP'
../bin/turnutils_uclient -t -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
$BINDIR/turnutils_uclient -t -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
@ -25,7 +32,7 @@ else
fi
echo 'Running turn client TLS'
../bin/turnutils_uclient -t -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
$BINDIR/turnutils_uclient -t -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
@ -34,7 +41,7 @@ else
fi
echo 'Running turn client UDP'
../bin/turnutils_uclient -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
$BINDIR/turnutils_uclient -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
@ -43,7 +50,7 @@ else
fi
echo 'Running turn client DTLS'
../bin/turnutils_uclient -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
$BINDIR/turnutils_uclient -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else

73
examples/run_tests_prom.sh Executable file
View File

@ -0,0 +1,73 @@
#!/bin/bash
# Detect cmake build and adjust path
BINDIR="../bin"
if [ ! -f $BINDIR/turnserver ]; then
BINDIR="../build/bin"
fi
function assert_prom_no_response() {
wget --quiet --output-document=/dev/null --tries=1 "$1"
status="$?"
if [ "$status" -eq 0 ]; then
echo FAIL
exit 1
else
echo OK
fi
}
function assert_prom_response() {
# Match something that looks like the expected body
wget --quiet --output-document=- --tries=1 "$1" | grep 'TYPE\|HELP\|counter\|gauge' >/dev/null
status="$?"
if [ "$status" -eq 0 ]; then
echo OK
else
echo FAIL
exit "$status"
fi
}
echo "Running without prometheus"
$BINDIR/turnserver /dev/null &
turnserver_pid="$!"
sleep 2
assert_prom_no_response "http://localhost:9641/metrics"
kill "$turnserver_pid"
echo "Running turnserver with prometheus, using defaults"
$BINDIR/turnserver --prometheus > /dev/null &
turnserver_pid="$!"
sleep 2
assert_prom_response "http://localhost:9641/metrics"
kill "$turnserver_pid"
echo "Running turnserver with prometheus, using custom address"
$BINDIR/turnserver --prometheus --prometheus-address="127.0.0.1" > /dev/null &
turnserver_pid="$!"
sleep 2
assert_prom_response "http://127.0.0.1:9641/metrics"
kill "$turnserver_pid"
echo "Running turnserver with prometheus, using custom port"
$BINDIR/turnserver --prometheus --prometheus-port="8080" > /dev/null &
turnserver_pid="$!"
sleep 2
assert_prom_response "http://localhost:8080/metrics"
kill "$turnserver_pid"
echo "Running turnserver with prometheus, using custom address and port"
$BINDIR/turnserver --prometheus --prometheus-address="127.0.0.1" --prometheus-port="8080" > /dev/null &
turnserver_pid="$!"
sleep 2
assert_prom_response "http://127.0.0.1:8080/metrics"
kill "$turnserver_pid"
echo "Running turnserver with prometheus, using custom path"
$BINDIR/turnserver --prometheus --prometheus-path="/coturn/metrics" > /dev/null &
turnserver_pid="$!"
sleep 2
assert_prom_response "http://localhost:9641/coturn/metrics"
kill "$turnserver_pid"

View File

@ -2,7 +2,7 @@
# Run it from the root of the coturn source tree
V=4.5.2
V=4.6.3
PACKDIR=`pwd`/../coturn-releases/
SRCDIR=`pwd`

View File

@ -2,7 +2,7 @@
# Common settings script.
TURNVERSION=4.5.2
TURNVERSION=4.6.3
BUILDDIR=~/rpmbuild
ARCH=`uname -p`

View File

@ -1,5 +1,5 @@
Name: turnserver
Version: 4.6.2
Version: 4.6.3
Release: 0%{dist}
Summary: Coturn TURN Server

View File

@ -0,0 +1,175 @@
#!/bin/bash
#####################################################################################
############## purpose : install coturn as a server ########
############## verification on aws : tested & verified on aws ec2 ########
############## platform : aws ec2 ########
############## aws ubuntu version : ubuntu 22.04 LTS ########
############## coturn base version : 4.6.3 ########
############## dependent tools : installs prometheus client as well ########
############## file permissions : chmod 777 install_coturn_on_aws_ec2.sh #####
############## run command : ./install_coturn_on_aws_ec2.sh ########
############## developer : hariprasad.t@samsung.com ########
#####################################################################################
coturn_package="https://github.com/coturn/coturn/archive/refs/tags/4.6.3.tar.gz"
coturn_version="4.6.3"
if [ "$#" -eq 0 ]
then
echo "coturn version is not supplied as argument, installing below version as default."
echo "default coturn package: $coturn_package"
else
coturn_package="https://github.com/coturn/coturn/archive/refs/tags/$1.tar.gz"
coturn_version="$1"
echo "installing coturn package: $coturn_package"
fi
echo "--------> this script installs coturn server version $1 on aws ec2 instance..."
echo "--------> create user turnserver..."
sudo adduser --gecos "" --disabled-password turnserver
echo "--------> updating packages..."
sudo DEBIAN_FRONTEND=noninteractive apt-get -y update
sudo DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
### install all dependent packages
echo "--------> installing dependent packages..."
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y gcc make openssl-dev build-essential pkg-config libsystemd-dev musl-dev sqlite
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y libssl-dev libsqlite3-dev libevent-dev libpq-dev libmysqlclient-dev libhiredis-dev libmicrohttpd-dev
### download prometheus client libraries
echo "--------> installing prometheus client..."
wget https://github.com/digitalocean/prometheus-client-c/releases/download/v0.1.3/libprom-dev-0.1.3-Linux.deb
wget https://github.com/digitalocean/prometheus-client-c/releases/download/v0.1.3/libpromhttp-dev-0.1.3-Linux.deb
sudo dpkg -i prometheus-client/libprom-dev-0.1.3-Linux.deb
sudo dpkg -i prometheus-client/libpromhttp-dev-0.1.3-Linux.deb
### download coturn source code
echo "--------> downloading coturn $coturn_package"
wget "$coturn_package"
tar -xf "$coturn_version.tar.gz"
cd "coturn-$coturn_version"
./configure
### compile & install coturn
make
echo "--------> installing coturn ..."
sudo make install
sudo bash -c "cat > /etc/default/coturn << EOL
TURNSERVER_ENABLED=1
EXTRA_OPTIONS=-v
EOL"
echo "--------> generating random key for realm..."
secret_key=$(bash -c 'openssl rand -hex 32')
### fetch ec2 public ip and private ip using metadata token (applicable for v2 version of metadata)
echo "--------> retrieving public & private ips of ec2 instance..."
aws_token=$(bash -c 'curl -s -X PUT "http://instance-data/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"')
public_ip=$(bash -c 'curl -s -H "X-aws-ec2-metadata-token:'$aws_token'" -X GET "http://instance-data/latest/meta-data/public-ipv4"')
private_ip=$(bash -c 'curl -s -H "X-aws-ec2-metadata-token:'$aws_token'" -X GET "http://instance-data/latest/meta-data/local-ipv4"')
echo "--------> public ip: $public_ip, private ip: $private_ip"
sudo bash -c "mv /etc/turnserver.conf /etc/turnserver.conf.original"
### create configuration file for coturn with basic expected parameters
### change below values as per your requirement.. like ports, username, password, etc.
echo "--------> applying new config changes..."
sudo bash -c "cat > /etc/turnserver.conf << EOL
listening-port=3478
tls-listening-port=5349
# allow only TLSv1.2+
no-tlsv1
no-tlsv1_1
userdb=/usr/local/var/db/turndb
no-cli
min-port=45000
max-port=65535
log-file=/var/log/turnserver/turnserver.log
verbose
fingerprint
realm=${secret_key}
lt-cred-mech
user=username:password
external-ip=${public_ip}/${private_ip}
new-log-timestamp
new-log-timestamp-format \"%FT%T%z\"
log-binding
prometheus
EOL"
### make coturn as auto recoverable by making it as a service
sudo bash -c "cat > /lib/systemd/system/coturn.service << EOL
[Unit]
Description=coTURN STUN Server
Documentation=man:coturn(1) man:turnadmin(1) man:turnserver(1)
After=network.target
[Service]
User=turnserver
Group=turnserver
Type=notify
EnvironmentFile=/etc/default/coturn
ExecStart=/usr/local/bin/turnserver -c /etc/turnserver.conf --pidfile=
Restart=on-failure
InaccessibleDirectories=/home
PrivateTmp=yes
LimitCORE=infinity
LimitNOFILE=1000000
LimitNPROC=60000
LimitRTPRIO=infinity
LimitRTTIME=7000000
[Install]
WantedBy=multi-user.target
EOL"
### memory based database configurations
sudo bash -c "sudo mkdir -p /var/lib/turn/turndb"
sudo bash -c "sudo chown turnserver:turnserver /var/lib/turn/turndb"
### apply log rotation policy to avoid "disk full" issues
echo "--------> setting log rotation policy..."
sudo bash -c "sudo mkdir -p /var/log/turnserver"
sudo bash -c "sudo chown turnserver:turnserver /var/log/turnserver"
sudo bash -c "cat > /etc/logrotate.d/coturn << EOL
/var/log/turnserver/*.log
{
rotate 7
daily
missingok
notifempty
compress
postrotate
/bin/systemctl kill -s HUP coturn.service
endscript
}
EOL"
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 3478/udp
sudo ufw allow 5349/tcp
#Running coTURN on privileged port 443
sudo bash -c "setcap cap_net_bind_service=+ep /usr/local/bin/turnserver"
sudo bash -c "sudo chown turnserver:turnserver /etc/default/coturn"
sudo bash -c "sudo chown turnserver:turnserver /etc/turnserver.conf"
echo "--------> starting coturn as a service..."
sudo systemctl enable coturn.service
sudo systemctl daemon-reload
sudo systemctl restart coturn.service
echo "--------> coturn is running successfully..."
####
echo "------ verification steps after installation -------"
echo "a. check with command: ps -eaf | grep turnserver"
echo "b. check with command: systemctl status coturn"
echo "c. check configuration: cat /etc/turnserver.conf"
echo "----------------------------------------------------"
####

View File

@ -537,40 +537,6 @@ const char *socket_type_name(SOCKET_TYPE st) {
return "UNKNOWN";
}
const char *duration_name(unsigned long duration) {
if (duration < 60) {
return "1min";
} else if (duration < 600) {
return "10mins";
} else if (duration < 86400) {
return "24hrs";
} else {
return "days";
}
}
const char *rate_name(unsigned long rate_kbps) {
if (rate_kbps < 1) {
return "1kbps";
} else if (rate_kbps < 50) {
return "50kbps";
} else if (rate_kbps < 2500) {
return "2500kbps";
} else {
return "10000kbps";
}
}
const char *addr_family_name(int addr_family) {
if (addr_family == AF_INET) {
return "ipv4";
} else if (addr_family == AF_INET6) {
return "ipv6";
} else {
return "other";
}
}
/////////////////// MTU /////////////////////////////////////////
int set_socket_df(evutil_socket_t fd, int family, int value) {
@ -937,7 +903,7 @@ char *dirname(char *path) {
* \return
*/
static char *_WTA(__in wchar_t *pszInBuf, __in int nInSize, __out char **pszOutBuf, __out int *pnOutSize) {
if (!pszInBuf || !pszOutBuf || !*pszOutBuf || !pnOutSize || nInSize <= 0) {
if (!pszInBuf || !pszOutBuf || !pnOutSize || nInSize <= 0) {
return NULL;
}
*pnOutSize = WideCharToMultiByte((UINT)0, (DWORD)0, pszInBuf, nInSize, NULL, 0, NULL, NULL);
@ -1172,7 +1138,7 @@ char *find_config_file(const char *config_file) {
size_t celen = strlen(c_execdir);
fnsz = sizeof(char) * (dirlen + cflen + celen + 10);
fn = (char *)malloc(fnsz + 1);
strncpy(fn, c_execdir, celen);
strncpy(fn, c_execdir, fnsz);
size_t fnlen = strlen(fn);
if (fnlen < fnsz) {
strncpy(fn + fnlen, "/", fnsz - fnlen);
@ -1366,7 +1332,7 @@ void build_base64_decoding_table(void) {
char *table = (char *)calloc(256, sizeof(char));
for (char i = 0; i < 64; i++) {
for (size_t i = 0; i < 64; i++) {
table[(unsigned char)encoding_table[i]] = i;
}
decoding_table = table;

View File

@ -55,85 +55,35 @@ extern "C" {
extern int IS_TURN_SERVER;
/* ALPN */
#define OPENSSL_FIRST_ALPN_VERSION (0x10002003L)
#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION
#define ALPN_SUPPORTED 1
#else
#define ALPN_SUPPORTED 0
#endif
/* TLS */
#if defined(TURN_NO_TLS)
#define TLS_SUPPORTED 0
#define TLSv1_1_SUPPORTED 0
#define TLSv1_2_SUPPORTED 0
#else
#define TLS_SUPPORTED 1
#if defined(SSL_OP_NO_TLSv1_1)
#define TLSv1_1_SUPPORTED 1
#else
#define TLSv1_1_SUPPORTED 0
#endif
#if defined(SSL_OP_NO_TLSv1_2)
#define TLSv1_2_SUPPORTED 1
#else
#define TLSv1_2_SUPPORTED 0
#endif
#if defined(SSL_OP_NO_TLSv1_3)
#define TLSv1_3_SUPPORTED 1
#else
#define TLSv1_3_SUPPORTED 0
#endif
#endif
#if defined(TURN_NO_DTLS) || (!defined(DTLS_CTRL_LISTEN) && (OPENSSL_VERSION_NUMBER < 0x10100000L))
#if defined(TURN_NO_DTLS)
#define DTLS_SUPPORTED 0
#define DTLSv1_2_SUPPORTED 0
#else
#define DTLS_SUPPORTED 1
#if defined(SSL_OP_NO_DTLSv1_2)
#define DTLSv1_2_SUPPORTED 1
#else
#define DTLSv1_2_SUPPORTED 0
#endif
#endif
#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION
#define SSL_SESSION_ECDH_AUTO_SUPPORTED 1
#else
#define SSL_SESSION_ECDH_AUTO_SUPPORTED 0
#endif
/////////// SSL //////////////////////////
// clang-format off
enum _TURN_TLS_TYPE {
TURN_TLS_NO = 0,
TURN_TLS_SSL23,
TURN_TLS_v1_0,
#if TLSv1_1_SUPPORTED
TURN_TLS_v1_1,
#if TLSv1_2_SUPPORTED
TURN_TLS_v1_2,
#endif
#endif
TURN_TLS_v1_3,
TURN_TLS_TOTAL
};
// clang-format on
typedef enum _TURN_TLS_TYPE TURN_TLS_TYPE;

View File

@ -75,7 +75,7 @@ else()
list(APPEND turnserver_DEFINED TURN_NO_MYSQL)
endif()
if(WIN32)
if(WIN32 OR APPLE)
find_package(mongoc-1.0)
if(mongoc-1.0_FOUND)
list(APPEND turnserver_LIBS mongo::mongoc_shared)
@ -87,24 +87,24 @@ if(WIN32)
else()
find_package(mongo)
if(mongo_FOUND)
list(APPEND turnserver_LIBS mongo)
list(APPEND SOURCE_FILES dbdrivers/dbd_mongo.c)
list(APPEND turnserver_LIBS mongo)
list(APPEND SOURCE_FILES dbdrivers/dbd_mongo.c)
list(APPEND HEADER_FILES dbdrivers/dbd_mongo.h)
else()
list(APPEND turnserver_DEFINED TURN_NO_MONGO)
list(APPEND turnserver_DEFINED TURN_NO_MONGO)
endif()
endif()
find_package(hiredis)
if(hiredis_FOUND)
list(APPEND turnserver_LIBS hiredis::hiredis)
pkg_check_modules(HIREDIS IMPORTED_TARGET hiredis)
if(HIREDIS_FOUND)
list(APPEND turnserver_LIBS PkgConfig::HIREDIS)
list(APPEND SOURCE_FILES hiredis_libevent2.c dbdrivers/dbd_redis.c)
list(APPEND HEADER_FILES hiredis_libevent2.h dbdrivers/dbd_redis.h)
else()
list(APPEND turnserver_DEFINED TURN_NO_HIREDIS)
endif()
if(UNIX)
if(UNIX AND (NOT APPLE))
find_package(libsystemd)
if(NOT libsystemd_FOUND)
list(APPEND turnserver_DEFINED TURN_NO_SYSTEMD)
@ -119,7 +119,7 @@ if(Prometheus_FOUND)
list(APPEND turnserver_include_dirs ${Prometheus_INCLUDE_DIRS})
else()
message(AUTHOR_WARNING "Could not find prometheus. Please install "
"prom, promhttp, microhttpd, and set Prometheus_ROOT. "
"prom, microhttpd, and set Prometheus_ROOT. "
"See docs/Prometheus.md")
list(APPEND turnserver_DEFINED TURN_NO_PROMETHEUS)
endif()

View File

@ -106,12 +106,8 @@ char *decryptPassword(char *in, const unsigned char *mykey) {
struct ctr_state state;
init_ctr(&state, iv);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
CRYPTO_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num,
(block128_f)AES_encrypt);
#else
AES_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num);
#endif
strcat(last, (char *)outdata);
out = (char *)malloc(sizeof(char) * (strlen(last) + 1)); // add 1 to allocate space for terminating '\0'

View File

@ -49,6 +49,7 @@ static void turnFreeRedisReply(void *reply) {
struct _Ryconninfo {
char *host;
char *dbname;
char *user;
char *password;
unsigned int connect_timeout;
unsigned int port;
@ -64,6 +65,9 @@ static void RyconninfoFree(Ryconninfo *co) {
if (co->dbname) {
free(co->dbname);
}
if (co->user) {
free(co->user);
}
if (co->password) {
free(co->password);
}
@ -117,13 +121,13 @@ static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) {
} else if (!strcmp(s, "database")) {
co->dbname = strdup(seq + 1);
} else if (!strcmp(s, "user")) {
;
co->user = strdup(seq + 1);
} else if (!strcmp(s, "uname")) {
;
co->user = strdup(seq + 1);
} else if (!strcmp(s, "name")) {
;
co->user = strdup(seq + 1);
} else if (!strcmp(s, "username")) {
;
co->user = strdup(seq + 1);
} else if (!strcmp(s, "password")) {
co->password = strdup(seq + 1);
} else if (!strcmp(s, "pwd")) {
@ -162,9 +166,6 @@ static Ryconninfo *RyconninfoParse(const char *userdb, char **errmsg) {
if (!(co->host)) {
co->host = strdup("127.0.0.1");
}
if (!(co->password)) {
co->password = strdup("");
}
}
return co;
@ -224,8 +225,12 @@ redis_context_handle get_redis_async_connection(struct event_base *base, redis_s
if (!rc) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB async connection\n");
} else {
if (co->password) {
turnFreeRedisReply(redisCommand(rc, "AUTH %s", co->password));
if (co->password && strlen(co->password)) {
if (co->user && strlen(co->user)) {
turnFreeRedisReply(redisCommand(rc, "AUTH %s %s", co->user, co->password));
} else {
turnFreeRedisReply(redisCommand(rc, "AUTH %s", co->password));
}
}
if (co->dbname) {
turnFreeRedisReply(redisCommand(rc, "select %s", co->dbname));
@ -267,7 +272,7 @@ redis_context_handle get_redis_async_connection(struct event_base *base, redis_s
}
}
ret = redisLibeventAttach(base, co->host, co->port, co->password, atoi(co->dbname));
ret = redisLibeventAttach(base, co->host, co->port, co->user, co->password, atoi(co->dbname));
if (!ret) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize Redis DB connection\n");
@ -347,8 +352,13 @@ static redisContext *get_redis_connection(void) {
}
redisFree(redisconnection);
redisconnection = NULL;
} else if (co->password) {
void *reply = redisCommand(redisconnection, "AUTH %s", co->password);
} else if (co->password && strlen(co->password)) {
void *reply;
if (co->user && strlen(co->user)) {
reply = redisCommand(redisconnection, "AUTH %s %s", co->user, co->password);
} else {
reply = redisCommand(redisconnection, "AUTH %s", co->password);
}
if (!reply) {
if (redisconnection->err && redisconnection->errstr[0]) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Redis: %s\n", redisconnection->errstr);

View File

@ -201,12 +201,7 @@ static int generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie
return 1;
}
static int verify_cookie(SSL *ssl,
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
const
#endif
unsigned char *cookie,
unsigned int cookie_len) {
static int verify_cookie(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len) {
unsigned int resultlength = 0;
unsigned char result[COOKIE_SECRET_LENGTH];
@ -284,14 +279,8 @@ static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_ty
SSL_set_bio(connecting_ssl, NULL, wbio);
SSL_set_options(connecting_ssl, SSL_OP_COOKIE_EXCHANGE
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
| SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
#endif
#else
#if defined(SSL_OP_NO_RENEGOTIATION)
| SSL_OP_NO_RENEGOTIATION
#endif
#endif
);
SSL_set_max_cert_list(connecting_ssl, 655350);
@ -459,8 +448,6 @@ 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;
}
}
@ -557,14 +544,8 @@ static int create_new_connected_udp_socket(dtls_listener_relay_server_type *serv
SSL_set_bio(connecting_ssl, NULL, wbio);
SSL_set_options(connecting_ssl, SSL_OP_COOKIE_EXCHANGE
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
| SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
#endif
#else
#if defined(SSL_OP_NO_RENEGOTIATION)
| SSL_OP_NO_RENEGOTIATION
#endif
#endif
);

View File

@ -50,6 +50,7 @@ struct redisLibeventEvents {
int rev_set, wev_set;
char *ip;
int port;
char *user;
char *pwd;
int db;
};
@ -212,7 +213,7 @@ void send_message_to_redis(redis_context_handle rch, const char *command, const
///////////////////////// Attach /////////////////////////////////
redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int port0, char *pwd, int db) {
redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int port0, char *user, char *pwd, int db) {
char ip[256];
if (ip0 && ip0[0]) {
@ -246,6 +247,9 @@ redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int
e->base = base;
e->ip = strdup(ip);
e->port = port;
if (user) {
e->user = strdup(user);
}
if (pwd) {
e->pwd = strdup(pwd);
}
@ -274,9 +278,15 @@ redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int
e->wev_set = 1;
// Authentication
if (redis_le_valid(e) && pwd) {
if (redisAsyncCommand(ac, NULL, e, "AUTH %s", pwd) != REDIS_OK) {
e->invalid = 1;
if (redis_le_valid(e) && pwd && strlen(pwd)) {
if (user && strlen(user)) {
if (redisAsyncCommand(ac, NULL, e, "AUTH %s %s", e->user, e->pwd) != REDIS_OK) {
e->invalid = 1;
}
} else {
if (redisAsyncCommand(ac, NULL, e, "AUTH %s", e->pwd) != REDIS_OK) {
e->invalid = 1;
}
}
}
@ -349,9 +359,15 @@ static void redis_reconnect(struct redisLibeventEvents *e) {
e->invalid = 0;
// Authentication
if (redis_le_valid(e) && e->pwd) {
if (redisAsyncCommand(ac, NULL, e, "AUTH %s", e->pwd) != REDIS_OK) {
e->invalid = 1;
if (redis_le_valid(e) && e->pwd && strlen(e->pwd)) {
if (e->user && strlen(e->user)) {
if (redisAsyncCommand(ac, NULL, e, "AUTH %s %s", e->user, e->pwd) != REDIS_OK) {
e->invalid = 1;
}
} else {
if (redisAsyncCommand(ac, NULL, e, "AUTH %s", e->pwd) != REDIS_OK) {
e->invalid = 1;
}
}
}

View File

@ -48,7 +48,7 @@ typedef void *redis_context_handle;
#if !defined(TURN_NO_HIREDIS)
redis_context_handle redisLibeventAttach(struct event_base *base, char *ip, int port, char *pwd, int db);
redis_context_handle redisLibeventAttach(struct event_base *base, char *ip, int port, char *user, char *pwd, int db);
void send_message_to_redis(redis_context_handle rch, const char *command, const char *key, const char *format, ...);

View File

@ -40,10 +40,6 @@
#define MAX_TRIES 3
#endif
#if (!defined OPENSSL_VERSION_1_1_1)
#define OPENSSL_VERSION_1_1_1 0x10101000L
#endif
////// TEMPORARY data //////////
static int use_lt_credentials = 0;
@ -55,14 +51,10 @@ static int use_tltc = 0;
////// ALPN //////////
#if ALPN_SUPPORTED
char STUN_ALPN[128] = "stun.nat-discovery";
char TURN_ALPN[128] = "stun.turn";
char HTTP_ALPN[128] = "http/1.1";
#endif
////// TURNDB //////////////
#if defined(Q)
@ -121,7 +113,7 @@ turn_params_t turn_params = {
//////////////// Common params ////////////////////
TURN_VERBOSE_NONE, /* verbose */
0, /* turn_daemon */
0, /* no_software_attribute */
false, /* software_attribute */
0, /* web_admin_listen_on_workers */
0, /* do_not_use_config_file */
@ -188,7 +180,8 @@ turn_params_t turn_params = {
{NULL, 0, {0, NULL}}, /*tls_alternate_servers_list*/
/////////////// stop server ////////////////
0, /*stop_turn_server*/
false, /*drain_turn_server*/
false, /*stop_turn_server*/
/////////////// MISC PARAMS ////////////////
0, /* stun_only */
@ -211,6 +204,8 @@ turn_params_t turn_params = {
0, /* user_quota */
0, /* prometheus disabled by default */
DEFAULT_PROM_SERVER_PORT, /* prometheus port */
"", /* prometheus address */
"/metrics", /* prometheus path */
0, /* prometheus username labelling disabled by default when prometheus is enabled */
///////////// Users DB //////////////
@ -230,9 +225,7 @@ turn_params_t turn_params = {
0, /* log_binding */
0, /* no_stun_backward_compatibility */
0, /* response_origin_only_with_rfc5780 */
0, /* respond_http_unsupported */
// Signal change to add session limit
0, /* session_limit */
0 /* respond_http_unsupported */
};
//////////////// OpenSSL Init //////////////////////
@ -264,6 +257,7 @@ static void read_config_file(int argc, char **argv, int pass);
static void reload_ssl_certs(evutil_socket_t sock, short events, void *args);
static void shutdown_handler(evutil_socket_t sock, short events, void *args);
static void drain_handler(evutil_socket_t sock, short events, void *args);
//////////////////////////////////////////////////
@ -1028,7 +1022,8 @@ static char Usage[] =
" -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"
" --no-software-attribute Production mode: hide the software version (formerly --prod).\n"
" --no-software-attribute DEPRECATED Production mode: hide the software version.\n"
" --software-attribute Enable sending software attribute (for debugging).\n"
" -f, --fingerprint Use fingerprints in the TURN messages.\n"
" -a, --lt-cred-mech Use the long-term credential mechanism.\n"
" -z, --no-auth Do not use any credential mechanism, allow anonymous access.\n"
@ -1138,6 +1133,8 @@ static char Usage[] =
"enabled it will listen on port 9641 under the path /metrics\n"
" also the path / on this port can be used as a health check\n"
" --prometheus-port <port> Prometheus metrics port (Default: 9641).\n"
" --prometheus-address <address> Prometheus listening address (Default: any).\n"
" --prometheus-path <path> Prometheus serve path (Default: /metrics).\n"
" --prometheus-username-labels When metrics are enabled, add labels with client usernames.\n"
#endif
" --use-auth-secret TURN REST API flag.\n"
@ -1436,6 +1433,8 @@ enum EXTRA_OPTS {
PERMISSION_LIFETIME_OPT,
PROMETHEUS_OPT,
PROMETHEUS_PORT_OPT,
PROMETHEUS_ADDRESS_OPT,
PROMETHEUS_PATH_OPT,
PROMETHEUS_ENABLE_USERNAMES_OPT,
AUTH_SECRET_OPT,
NO_AUTH_PINGS_OPT,
@ -1443,7 +1442,6 @@ enum EXTRA_OPTS {
NO_DYNAMIC_REALMS_OPT,
DEL_ALL_AUTH_SECRETS_OPT,
STATIC_AUTH_SECRET_VAL_OPT,
AUTH_SECRET_TS_EXP, /* deprecated */
NO_STDOUT_LOG_OPT,
SYSLOG_OPT,
SYSLOG_FACILITY_OPT,
@ -1482,8 +1480,6 @@ enum EXTRA_OPTS {
DH566_OPT,
DH1066_OPT,
NE_TYPE_OPT,
NO_SSLV2_OPT, /*deprecated*/
NO_SSLV3_OPT, /*deprecated*/
NO_TLSV1_OPT,
NO_TLSV1_1_OPT,
NO_TLSV1_2_OPT,
@ -1493,7 +1489,8 @@ enum EXTRA_OPTS {
ADMIN_USER_QUOTA_OPT,
SERVER_NAME_OPT,
OAUTH_OPT,
NO_SOFTWARE_ATTRIBUTE_OPT,
SOFTWARE_ATTRIBUTE_OPT,
DEPRECATED_NO_SOFTWARE_ATTRIBUTE_OPT,
NO_HTTP_OPT,
SECRET_KEY_OPT,
ACME_REDIRECT_OPT,
@ -1502,9 +1499,7 @@ enum EXTRA_OPTS {
NO_STUN_BACKWARD_COMPATIBILITY_OPT,
RESPONSE_ORIGIN_ONLY_WITH_RFC5780_OPT,
RESPOND_HTTP_UNSUPPORTED_OPT,
VERSION_OPT,
// Signal change to add session limit
SESSION_LIMIT_OPT
VERSION_OPT
};
struct myoption {
@ -1558,6 +1553,8 @@ static const struct myoption long_options[] = {
#if !defined(TURN_NO_PROMETHEUS)
{"prometheus", optional_argument, NULL, PROMETHEUS_OPT},
{"prometheus-port", optional_argument, NULL, PROMETHEUS_PORT_OPT},
{"prometheus-address", optional_argument, NULL, PROMETHEUS_ADDRESS_OPT},
{"prometheus-path", optional_argument, NULL, PROMETHEUS_PATH_OPT},
{"prometheus-username-labels", optional_argument, NULL, PROMETHEUS_ENABLE_USERNAMES_OPT},
#endif
{"use-auth-secret", optional_argument, NULL, AUTH_SECRET_OPT},
@ -1565,7 +1562,6 @@ static const struct myoption long_options[] = {
{"no-auth-pings", optional_argument, NULL, NO_AUTH_PINGS_OPT},
{"no-dynamic-ip-list", optional_argument, NULL, NO_DYNAMIC_IP_LIST_OPT},
{"no-dynamic-realms", optional_argument, NULL, NO_DYNAMIC_REALMS_OPT},
/* deprecated: */ {"secret-ts-exp-time", optional_argument, NULL, AUTH_SECRET_TS_EXP},
{"realm", required_argument, NULL, 'r'},
{"server-name", required_argument, NULL, SERVER_NAME_OPT},
{"oauth", optional_argument, NULL, OAUTH_OPT},
@ -1576,8 +1572,8 @@ static const struct myoption long_options[] = {
{"verbose", optional_argument, NULL, 'v'},
{"Verbose", optional_argument, NULL, 'V'},
{"daemon", optional_argument, NULL, 'o'},
/* deprecated: */ {"prod", optional_argument, NULL, NO_SOFTWARE_ATTRIBUTE_OPT},
{"no-software-attribute", optional_argument, NULL, NO_SOFTWARE_ATTRIBUTE_OPT},
/* deprecated: */ {"no-software-attribute", optional_argument, NULL, DEPRECATED_NO_SOFTWARE_ATTRIBUTE_OPT},
{"software-attribute", optional_argument, NULL, SOFTWARE_ATTRIBUTE_OPT},
{"fingerprint", optional_argument, NULL, 'f'},
{"check-origin-consistency", optional_argument, NULL, CHECK_ORIGIN_CONSISTENCY_OPT},
{"no-udp", optional_argument, NULL, NO_UDP_OPT},
@ -1634,8 +1630,6 @@ static const struct myoption long_options[] = {
{"dh566", optional_argument, NULL, DH566_OPT},
{"dh1066", optional_argument, NULL, DH1066_OPT},
{"ne", required_argument, NULL, NE_TYPE_OPT},
{"no-sslv2", optional_argument, NULL, NO_SSLV2_OPT}, /* deprecated */
{"no-sslv3", optional_argument, NULL, NO_SSLV3_OPT}, /* deprecated */
{"no-tlsv1", optional_argument, NULL, NO_TLSV1_OPT},
{"no-tlsv1_1", optional_argument, NULL, NO_TLSV1_1_OPT},
{"no-tlsv1_2", optional_argument, NULL, NO_TLSV1_2_OPT},
@ -1650,8 +1644,6 @@ 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[] = {
@ -1740,12 +1732,8 @@ void encrypt_aes_128(unsigned char *in, const unsigned char *mykey) {
struct ctr_state state;
init_ctr(&state, iv);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
CRYPTO_ctr128_encrypt(in, out, strlen((char *)in), &key, state.ivec, state.ecount, &state.num,
(block128_f)AES_encrypt);
#else
AES_ctr128_encrypt(in, out, strlen((char *)in), &key, state.ivec, state.ecount, &state.num);
#endif
totalSize += strlen((char *)in);
size = strlen((char *)in);
@ -1836,12 +1824,8 @@ void decrypt_aes_128(char *in, const unsigned char *mykey) {
struct ctr_state state;
init_ctr(&state, iv);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
CRYPTO_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num,
(block128_f)AES_encrypt);
#else
AES_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num);
#endif
strcat(last, (char *)outdata);
printf("%s\n", last);
@ -1920,12 +1904,6 @@ static void set_option(int c, char *value) {
turn_params.oauth = get_bool_value(value);
}
break;
case NO_SSLV2_OPT:
// deprecated
break;
case NO_SSLV3_OPT:
// deprecated
break;
case NO_TLSV1_OPT:
turn_params.no_tlsv1 = get_bool_value(value);
break;
@ -2170,8 +2148,11 @@ static void set_option(int c, char *value) {
anon_credentials = 1;
}
break;
case NO_SOFTWARE_ATTRIBUTE_OPT:
turn_params.no_software_attribute = get_bool_value(value);
case DEPRECATED_NO_SOFTWARE_ATTRIBUTE_OPT:
turn_params.software_attribute = !(bool)get_bool_value(value);
break;
case SOFTWARE_ATTRIBUTE_OPT:
turn_params.software_attribute = (bool)get_bool_value(value);
break;
case 'f':
turn_params.fingerprint = get_bool_value(value);
@ -2223,6 +2204,12 @@ static void set_option(int c, char *value) {
case PROMETHEUS_PORT_OPT:
turn_params.prometheus_port = atoi(value);
break;
case PROMETHEUS_ADDRESS_OPT:
STRCPY(turn_params.prometheus_address, value);
break;
case PROMETHEUS_PATH_OPT:
STRCPY(turn_params.prometheus_path, value);
break;
case PROMETHEUS_ENABLE_USERNAMES_OPT:
turn_params.prometheus_username_labels = 1;
break;
@ -2248,9 +2235,6 @@ static void set_option(int c, char *value) {
turn_params.ct = TURN_CREDENTIALS_LONG_TERM;
use_lt_credentials = 1;
break;
case AUTH_SECRET_TS_EXP:
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: Option --secret-ts-exp-time deprecated and has no effect.\n");
break;
case 'r':
set_default_realm_name(value);
break;
@ -2374,10 +2358,6 @@ 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':
@ -2829,29 +2809,17 @@ static void print_features(unsigned long mfn) {
#if !TLS_SUPPORTED
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS is not supported\n");
#elif TLSv1_3_SUPPORTED
#else
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS 1.3 supported\n");
#elif TLSv1_2_SUPPORTED
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS 1.2 supported\n");
#elif TLSv1_1_SUPPORTED
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS 1.1 supported\n");
#elif TLSv1_SUPPORTED
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS 1.0 supported\n");
#endif
#if !DTLS_SUPPORTED
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS is not supported\n");
#elif DTLSv1_2_SUPPORTED
#else
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS 1.2 supported\n");
#elif DTLS_SUPPORTED
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS supported\n");
#endif
#if ALPN_SUPPORTED
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TURN/STUN ALPN supported\n");
#else
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TURN/STUN ALPN is not supported\n");
#endif
if (ENC_ALG_NUM == 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Third-party authorization (oAuth) is not supported\n");
@ -3042,7 +3010,7 @@ int main(int argc, char **argv) {
return adminmain(argc, argv);
}
memset(&turn_params.default_users_db, 0, sizeof(default_users_db_t));
memset(&turn_params.default_users_db.ram_db, 0, sizeof(ram_users_db_t));
turn_params.default_users_db.ram_db.static_accounts = ur_string_map_create(free);
// Zero pass apply the log options.
@ -3354,6 +3322,8 @@ int main(int argc, char **argv) {
event_add(ev, NULL);
ev = evsignal_new(turn_params.listener.event_base, SIGINT, shutdown_handler, NULL);
event_add(ev, NULL);
ev = evsignal_new(turn_params.listener.event_base, SIGUSR1, drain_handler, NULL);
event_add(ev, NULL);
#endif
drop_privileges();
@ -3369,65 +3339,10 @@ int main(int argc, char **argv) {
////////// OpenSSL locking ////////////////////////////////////////
#if defined(OPENSSL_THREADS)
#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0
// array larger than anything that OpenSSL may need:
static TURN_MUTEX_DECLARE(mutex_buf[256]);
static int mutex_buf_initialized = 0;
void coturn_locking_function(int mode, int n, const char *file, int line);
void coturn_locking_function(int mode, int n, const char *file, int line) {
UNUSED_ARG(file);
UNUSED_ARG(line);
if (mutex_buf_initialized && (n < CRYPTO_num_locks())) {
if (mode & CRYPTO_LOCK) {
TURN_MUTEX_LOCK(&(mutex_buf[n]));
} else {
TURN_MUTEX_UNLOCK(&(mutex_buf[n]));
}
}
}
void coturn_id_function(CRYPTO_THREADID *ctid);
void coturn_id_function(CRYPTO_THREADID *ctid) {
UNUSED_ARG(ctid);
CRYPTO_THREADID_set_numeric(ctid, (unsigned long)pthread_self());
}
static int THREAD_setup(void) {
int i;
for (i = 0; i < CRYPTO_num_locks(); i++) {
TURN_MUTEX_INIT(&(mutex_buf[i]));
}
mutex_buf_initialized = 1;
CRYPTO_THREADID_set_callback(coturn_id_function);
CRYPTO_set_locking_callback(coturn_locking_function);
return 1;
}
int THREAD_cleanup(void) {
int i;
if (!mutex_buf_initialized) {
return 0;
}
CRYPTO_THREADID_set_callback(NULL);
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < CRYPTO_num_locks(); i++) {
TURN_MUTEX_DESTROY(&(mutex_buf[i]));
}
mutex_buf_initialized = 0;
return 1;
}
#else
static int THREAD_setup(void) { return 1; }
int THREAD_cleanup(void);
int THREAD_cleanup(void) { return 1; }
#endif /* OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0 */
#endif /* defined(OPENSSL_THREADS) */
static void adjust_key_file_name(char *fn, const char *file_title, int critical) {
@ -3503,16 +3418,7 @@ static DH *get_dh566(void) {
if ((dh = DH_new()) == NULL) {
return (NULL);
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
dh->p = BN_bin2bn(dh566_p, sizeof(dh566_p), NULL);
dh->g = BN_bin2bn(dh566_g, sizeof(dh566_g), NULL);
if ((dh->p == NULL) || (dh->g == NULL)) {
DH_free(dh);
return (NULL);
}
#else
DH_set0_pqg(dh, BN_bin2bn(dh566_p, sizeof(dh566_p), NULL), NULL, BN_bin2bn(dh566_g, sizeof(dh566_g), NULL));
#endif
return (dh);
}
@ -3540,16 +3446,7 @@ static DH *get_dh1066(void) {
if ((dh = DH_new()) == NULL) {
return (NULL);
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
dh->p = BN_bin2bn(dh1066_p, sizeof(dh1066_p), NULL);
dh->g = BN_bin2bn(dh1066_g, sizeof(dh1066_g), NULL);
if ((dh->p == NULL) || (dh->g == NULL)) {
DH_free(dh);
return (NULL);
}
#else
DH_set0_pqg(dh, BN_bin2bn(dh1066_p, sizeof(dh1066_p), NULL), NULL, BN_bin2bn(dh1066_g, sizeof(dh1066_g), NULL));
#endif
return (dh);
}
@ -3586,16 +3483,7 @@ static DH *get_dh2066(void) {
if ((dh = DH_new()) == NULL) {
return (NULL);
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
dh->p = BN_bin2bn(dh2066_p, sizeof(dh2066_p), NULL);
dh->g = BN_bin2bn(dh2066_g, sizeof(dh2066_g), NULL);
if ((dh->p == NULL) || (dh->g == NULL)) {
DH_free(dh);
return (NULL);
}
#else
DH_set0_pqg(dh, BN_bin2bn(dh2066_p, sizeof(dh2066_p), NULL), NULL, BN_bin2bn(dh2066_g, sizeof(dh2066_g), NULL));
#endif
return (dh);
}
@ -3607,8 +3495,6 @@ static int pem_password_func(char *buf, int size, int rwflag, void *password) {
return (strlen(buf));
}
#if ALPN_SUPPORTED
static int ServerALPNCallback(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
@ -3655,18 +3541,12 @@ static int ServerALPNCallback(SSL *ssl, const unsigned char **out, unsigned char
return SSL_TLSEXT_ERR_NOACK; //???
}
#endif
static void set_ctx(SSL_CTX **out, const char *protocol, const SSL_METHOD *method) {
SSL_CTX *ctx = SSL_CTX_new(method);
int err = 0;
int rc = 0;
#if ALPN_SUPPORTED
SSL_CTX_set_alpn_select_cb(ctx, ServerALPNCallback, NULL);
#endif
SSL_CTX_set_default_passwd_cb_userdata(ctx, turn_params.tls_password);
SSL_CTX_set_default_passwd_cb(ctx, pem_password_func);
if (!(turn_params.cipher_list[0])) {
@ -3679,10 +3559,7 @@ static void set_ctx(SSL_CTX **out, const char *protocol, const SSL_METHOD *metho
SSL_CTX_set_cipher_list(ctx, turn_params.cipher_list);
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
#if TLSv1_3_SUPPORTED
SSL_CTX_set_ciphersuites(ctx, turn_params.cipher_list);
#endif
if (!SSL_CTX_use_certificate_chain_file(ctx, turn_params.cert_file)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: no certificate found\n", protocol);
@ -3758,11 +3635,6 @@ static void set_ctx(SSL_CTX **out, const char *protocol, const SSL_METHOD *metho
}
if (set_auto_curve) {
#if SSL_SESSION_ECDH_AUTO_SUPPORTED
#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_CTX_set_ecdh_auto(ctx, 1);
#endif
#endif
set_auto_curve = 0;
}
}
@ -3915,22 +3787,6 @@ static void openssl_load_certificates(void) {
TURN_MUTEX_LOCK(&turn_params.tls_mutex);
if (!turn_params.no_tls) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
set_ctx(&turn_params.tls_ctx, "TLS", TLSv1_2_server_method()); /*openssl-1.0.2 version specific API */
if (turn_params.no_tlsv1) {
SSL_CTX_set_options(turn_params.tls_ctx, SSL_OP_NO_TLSv1);
}
#if TLSv1_1_SUPPORTED
if (turn_params.no_tlsv1_1) {
SSL_CTX_set_options(turn_params.tls_ctx, SSL_OP_NO_TLSv1_1);
}
#if TLSv1_2_SUPPORTED
if (turn_params.no_tlsv1_2) {
SSL_CTX_set_options(turn_params.tls_ctx, SSL_OP_NO_TLSv1_2);
}
#endif
#endif
#else // OPENSSL_VERSION_NUMBER < 0x10100000L
set_ctx(&turn_params.tls_ctx, "TLS", TLS_server_method());
if (turn_params.no_tlsv1) {
SSL_CTX_set_min_proto_version(turn_params.tls_ctx, TLS1_1_VERSION);
@ -3938,36 +3794,16 @@ static void openssl_load_certificates(void) {
if (turn_params.no_tlsv1_1) {
SSL_CTX_set_min_proto_version(turn_params.tls_ctx, TLS1_2_VERSION);
}
#if TLSv1_3_SUPPORTED
if (turn_params.no_tlsv1_2) {
SSL_CTX_set_min_proto_version(turn_params.tls_ctx, TLS1_3_VERSION);
}
#endif
#endif // OPENSSL_VERSION_NUMBER < 0x10100000L
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "TLS cipher suite: %s\n", turn_params.cipher_list);
}
if (!turn_params.no_dtls) {
#if !DTLS_SUPPORTED
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: DTLS is not supported.\n");
#elif OPENSSL_VERSION_NUMBER < 0x10000000L
TURN_LOG_FUNC(
TURN_LOG_LEVEL_WARNING,
"WARNING: TURN Server was compiled with rather old OpenSSL version, DTLS may not be working correctly.\n");
#else
#if OPENSSL_VERSION_NUMBER < 0x10100000L // before openssl-1.1.0 no version independent API
#if DTLSv1_2_SUPPORTED
set_ctx(&turn_params.dtls_ctx, "DTLS", DTLSv1_2_server_method()); // openssl-1.0.2
if (turn_params.no_tlsv1_2) {
SSL_CTX_set_options(turn_params.dtls_ctx, SSL_OP_NO_DTLSv1_2);
}
#else
set_ctx(&turn_params.dtls_ctx, "DTLS", DTLSv1_server_method()); // < openssl-1.0.2
#endif
if (turn_params.no_tlsv1 || turn_params.no_tlsv1_1) {
SSL_CTX_set_options(turn_params.dtls_ctx, SSL_OP_NO_DTLSv1);
}
#else // OPENSSL_VERSION_NUMBER < 0x10100000L
set_ctx(&turn_params.dtls_ctx, "DTLS", DTLS_server_method());
if (turn_params.no_tlsv1 || turn_params.no_tlsv1_1) {
SSL_CTX_set_min_proto_version(turn_params.dtls_ctx, DTLS1_2_VERSION);
@ -3975,7 +3811,6 @@ static void openssl_load_certificates(void) {
if (turn_params.no_tlsv1_2) {
SSL_CTX_set_max_proto_version(turn_params.dtls_ctx, DTLS1_VERSION);
}
#endif // OPENSSL_VERSION_NUMBER < 0x10100000L
setup_dtls_callbacks(turn_params.dtls_ctx);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS cipher suite: %s\n", turn_params.cipher_list);
#endif
@ -3997,7 +3832,15 @@ static void reload_ssl_certs(evutil_socket_t sock, short events, void *args) {
static void shutdown_handler(evutil_socket_t sock, short events, void *args) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Terminating on signal %d\n", sock);
turn_params.stop_turn_server = 1;
turn_params.stop_turn_server = true;
UNUSED_ARG(events);
UNUSED_ARG(args);
}
static void drain_handler(evutil_socket_t sock, short events, void *args) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Draining then terminating on signal %d\n", sock);
enable_drain_mode();
UNUSED_ARG(events);
UNUSED_ARG(args);

View File

@ -87,9 +87,7 @@
#include <openssl/pem.h>
#include <openssl/ssl.h>
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
#include <openssl/modes.h>
#endif
#if !defined(TURN_NO_SYSTEMD)
#include <systemd/sd-daemon.h>
@ -105,12 +103,10 @@ extern "C" {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#define DEFAULT_CIPHER_LIST OSSL_default_cipher_list()
#if TLSv1_3_SUPPORTED
#define DEFAULT_CIPHERSUITES OSSL_default_ciphersuites()
#endif
#else
#define DEFAULT_CIPHER_LIST "DEFAULT"
#if TLSv1_3_SUPPORTED && defined(TLS_DEFAULT_CIPHERSUITES)
#if defined(TLS_DEFAULT_CIPHERSUITES)
#define DEFAULT_CIPHERSUITES TLS_DEFAULT_CIPHERSUITES
#endif
#endif
@ -210,7 +206,7 @@ typedef struct _turn_params_ {
int verbose;
int turn_daemon;
int no_software_attribute;
bool software_attribute;
int web_admin_listen_on_workers;
int do_not_use_config_file;
@ -286,8 +282,9 @@ typedef struct _turn_params_ {
turn_server_addrs_list_t alternate_servers_list;
turn_server_addrs_list_t tls_alternate_servers_list;
/////////////// stop server ////////////////
int stop_turn_server;
/////////////// stop/drain server ////////////////
bool drain_turn_server;
bool stop_turn_server;
////////////// MISC PARAMS ////////////////
@ -311,6 +308,8 @@ typedef struct _turn_params_ {
vint user_quota;
int prometheus;
int prometheus_port;
char prometheus_address[INET6_ADDRSTRLEN];
char prometheus_path[1025];
int prometheus_username_labels;
/////// Users DB ///////////
@ -333,8 +332,6 @@ 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;
@ -379,6 +376,7 @@ void send_auth_message_to_auth_server(struct auth_message *am);
void init_listener(void);
void setup_server(void);
void run_listener_server(struct listener_server *ls);
void enable_drain_mode(void);
////////// BPS ////////////////

View File

@ -33,8 +33,7 @@
#include "ns_turn_ioalib.h"
//////////// Backward compatibility with OpenSSL 1.0.x //////////////
#if (OPENSSL_VERSION_NUMBER < 0x10100001L || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER <= 0x3040000fL))
#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER <= 0x3040000fL
#define SSL_CTX_up_ref(ctx) CRYPTO_add(&(ctx)->references, 1, CRYPTO_LOCK_SSL_CTX)
#endif
@ -45,10 +44,6 @@ static unsigned int barrier_count = 0;
static pthread_barrier_t barrier;
#endif
// Signal change to add rtt metrics
static pthread_barrier_t rtt_barrier;
////////////// Auth Server ////////////////
typedef unsigned char authserver_id;
@ -700,37 +695,6 @@ err:
return ret;
}
// Signal change to add rtt metrics
int send_cycle_rtt_map_to_relay(turnserver_id id) {
int ret = 0;
struct message_to_relay sm;
memset(&sm, 0, sizeof(struct message_to_relay));
sm.t = RMT_CYCLE_RTT_MAP;
struct relay_server *rs = get_relay_server(id);
if (!rs) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: can't find relay for turn_server_id: %d\n", __FUNCTION__, (int)id);
ret = -1;
goto err;
}
sm.relay_server = rs;
{
struct evbuffer *output = bufferevent_get_output(rs->out_buf);
if (output) {
evbuffer_add(output, &sm, sizeof(struct message_to_relay));
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Empty output buffer\n", __FUNCTION__);
ret = -1;
}
}
err:
return ret;
}
static int handle_relay_message(relay_server_handle rs, struct message_to_relay *sm) {
if (rs && sm) {
@ -811,18 +775,6 @@ static int handle_relay_message(relay_server_handle rs, struct message_to_relay
sm->m.sm.nd.nbh = NULL;
break;
}
// Signal change to add rtt metric
case RMT_CYCLE_RTT_MAP: {
rs->server.rtt_ms_mins = ur_map_create();
int br = 0;
do {
br = pthread_barrier_wait(&rtt_barrier);
if ((br < 0) && (br != PTHREAD_BARRIER_SERIAL_THREAD)) {
perror("rtt barrier wait (message)");
}
} while ((br < 0) && (br != PTHREAD_BARRIER_SERIAL_THREAD));
break;
}
default: {
perror("Weird buffer type\n");
}
@ -1652,6 +1604,11 @@ void run_listener_server(struct listener_server *ls) {
}
}
if (turn_params.drain_turn_server && global_allocation_count == 0) {
turn_params.stop_turn_server = true;
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Drain complete, shutting down now...\n");
}
run_events(ls->event_base, ls->ioa_eng);
rollover_logfile();
@ -1695,21 +1652,19 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int
bufferevent_enable(rs->auth_in_buf, EV_READ);
init_turn_server(
&(rs->server), rs->id, turn_params.verbose, rs->ioa_eng, turn_params.ct, 0, turn_params.fingerprint,
&(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.no_software_attribute, &turn_params.web_admin_listen_on_workers, &turn_params.alternate_servers_list,
&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.no_stun_backward_compatibility,
&turn_params.response_origin_only_with_rfc5780, &turn_params.respond_http_unsupported,
// Signal change to add session limit
turn_params.session_limit);
&turn_params.response_origin_only_with_rfc5780, &turn_params.respond_http_unsupported);
if (to_set_rfc5780) {
set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client);
@ -1948,62 +1903,18 @@ void setup_server(void) {
void init_listener(void) { memset(&turn_params.listener, 0, sizeof(struct listener_server)); }
///////////////////////////////
// Signal change to add rtt metrics
size_t cycle_rtt_ms_maps(ur_map **rtt_ms_maps, size_t len) {
if (len != 1 + ((turnserver_id)-1)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "cycle_rtt_ms_maps, length is %ld, must be %ld\n", len,
1L + ((turnserver_id)-1));
return 0;
}
size_t count = 0;
void enable_drain_mode(void) {
// Tell each turn_server we are draining
for (size_t i = 0; i < get_real_general_relay_servers_number(); i++) {
if (general_relay_servers[i] && general_relay_servers[i]->server.rtt_ms_mins) {
rtt_ms_maps[count] = general_relay_servers[i]->server.rtt_ms_mins;
++count;
if (general_relay_servers[i]) {
general_relay_servers[i]->server.is_draining = true;
}
}
for (size_t i = 0; i < get_real_udp_relay_servers_number(); i++) {
if (udp_relay_servers[i] && udp_relay_servers[i]->server.rtt_ms_mins) {
rtt_ms_maps[count] = udp_relay_servers[i]->server.rtt_ms_mins;
++count;
if (udp_relay_servers[i]) {
udp_relay_servers[i]->server.is_draining = true;
}
}
static size_t last_count = 0;
if (last_count != count) {
if (last_count) {
if (pthread_barrier_destroy(&rtt_barrier) != 0) {
perror("rtt barrier destroy");
return 0;
}
}
if (pthread_barrier_init(&rtt_barrier, NULL, count + 1) != 0) {
perror("rtt barrier init");
return 0;
}
last_count = count;
}
for (size_t i = 0; i < get_real_general_relay_servers_number(); i++) {
if (general_relay_servers[i] && general_relay_servers[i]->server.rtt_ms_mins) {
send_cycle_rtt_map_to_relay(i);
}
}
for (size_t i = 0; i < get_real_udp_relay_servers_number(); i++) {
if (udp_relay_servers[i] && udp_relay_servers[i]->server.rtt_ms_mins) {
send_cycle_rtt_map_to_relay(i + TURNSERVER_ID_BOUNDARY_BETWEEN_TCP_AND_UDP);
}
}
int br = 0;
do {
br = pthread_barrier_wait(&rtt_barrier);
if ((br < 0) && (br != PTHREAD_BARRIER_SERIAL_THREAD)) {
perror("rtt barrier wait");
}
} while ((br < 0) && (br != PTHREAD_BARRIER_SERIAL_THREAD));
return count;
turn_params.drain_turn_server = true;
}
///////////////////////////////

View File

@ -1371,30 +1371,9 @@ ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, ioa_socket_raw
}
static void ssl_info_callback(SSL *ssl, int where, int ret) {
UNUSED_ARG(ret);
UNUSED_ARG(ssl);
UNUSED_ARG(where);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
if (0 != (where & SSL_CB_HANDSHAKE_START)) {
ioa_socket_handle s = (ioa_socket_handle)SSL_get_app_data(ssl);
if (s) {
++(s->ssl_renegs);
}
} else if (0 != (where & SSL_CB_HANDSHAKE_DONE)) {
if (ssl->s3) {
ioa_socket_handle s = (ioa_socket_handle)SSL_get_app_data(ssl);
if (s) {
if (s->ssl_renegs > SSL_MAX_RENEG_NUMBER) {
ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
}
}
}
}
#endif
#endif
}
typedef void (*ssl_info_callback_t)(const SSL *ssl, int type, int val);
@ -1835,7 +1814,7 @@ int ssl_read(evutil_socket_t fd, SSL *ssl, ioa_network_buffer_handle nbh, int ve
BIO *rbio = BIO_new_mem_buf(buffer, old_buffer_len);
BIO_set_mem_eof_return(rbio, -1);
#if OPENSSL_VERSION_NUMBER < 0x10100000L || (defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER < 0x3040000fL)
#if defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER < 0x3040000fL
ssl->rbio = rbio;
#else
SSL_set0_rbio(ssl, rbio);
@ -1934,7 +1913,7 @@ int ssl_read(evutil_socket_t fd, SSL *ssl, ioa_network_buffer_handle nbh, int ve
if (ret > 0) {
ioa_network_buffer_add_offset_size(nbh, (uint16_t)buf_size, 0, (size_t)ret);
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L || (defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER < 0x3040000fL)
#if defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER < 0x3040000fL
ssl->rbio = NULL;
BIO_free(rbio);
#else
@ -3683,10 +3662,8 @@ void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh) {
}
#endif
{
// Signal change to add address family label
if (!refresh) {
prom_inc_allocation(get_ioa_socket_type(ss->client_socket),
get_ioa_socket_address_family(ss->client_socket), ss->protocolgroup);
prom_inc_allocation(get_ioa_socket_type(ss->client_socket));
}
}
}
@ -3694,7 +3671,7 @@ void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh) {
}
}
void turn_report_allocation_delete(void *a, SOCKET_TYPE socket_type, int family) {
void turn_report_allocation_delete(void *a, SOCKET_TYPE socket_type) {
if (a) {
ts_ur_super_session *ss = (ts_ur_super_session *)(((allocation *)a)->owner);
if (ss) {
@ -3743,33 +3720,27 @@ void turn_report_allocation_delete(void *a, SOCKET_TYPE socket_type, int family)
}
#endif
{
// Signal change to add metrics
if (ss->realm_options.name[0]) {
// Set prometheus traffic metrics
prom_set_finished_traffic(ss->realm_options.name, (const char *)ss->username,
(unsigned long)(ss->t_received_packets), (unsigned long)(ss->t_received_bytes),
(unsigned long)(ss->t_sent_packets), (unsigned long)(ss->t_sent_bytes),
(unsigned long)ss->t_before_ping_packets, false, ss->protocolgroup);
(unsigned long)(ss->t_sent_packets), (unsigned long)(ss->t_sent_bytes), false);
prom_set_finished_traffic(
ss->realm_options.name, (const char *)ss->username, (unsigned long)(ss->t_peer_received_packets),
(unsigned long)(ss->t_peer_received_bytes), (unsigned long)(ss->t_peer_sent_packets),
(unsigned long)(ss->t_peer_sent_bytes), 0, true, ss->protocolgroup);
(unsigned long)(ss->t_peer_sent_bytes), true);
} else {
// Set prometheus traffic metrics
prom_set_finished_traffic(NULL, (const char *)ss->username, (unsigned long)(ss->t_received_packets),
(unsigned long)(ss->t_received_bytes), (unsigned long)(ss->t_sent_packets),
(unsigned long)(ss->t_sent_bytes), (unsigned long)ss->t_before_ping_packets,
false, ss->protocolgroup);
(unsigned long)(ss->t_sent_bytes), false);
prom_set_finished_traffic(NULL, (const char *)ss->username, (unsigned long)(ss->t_peer_received_packets),
(unsigned long)(ss->t_peer_received_bytes),
(unsigned long)(ss->t_peer_sent_packets), (unsigned long)(ss->t_peer_sent_bytes),
0, true, ss->protocolgroup);
true);
}
turn_time_t ct = get_turn_server_time(server) - ss->start_time;
const uint32_t byte_to_kilobit = 125;
uint64_t sent_rate_kbps = ss->sent_rate / byte_to_kilobit;
prom_dec_allocation(socket_type, family, (unsigned long)ct, (unsigned long)sent_rate_kbps, ss->protocolgroup);
prom_dec_allocation(socket_type);
}
}
}

View File

@ -289,10 +289,6 @@ void *allocate_super_memory_engine_func(ioa_engine_handle e, size_t size, const
/////////////////////////////////////////////////
// Signal change to add rtt metrics
int send_cycle_rtt_map_to_relay(turnserver_id id);
size_t cycle_rtt_ms_maps(ur_map **rtt_ms_maps, size_t len);
#ifdef __cplusplus
}
#endif

View File

@ -9,8 +9,6 @@
#if !defined(TURN_NO_PROMETHEUS)
#define PROTOCOL_GROUP_LABEL "protocol-group"
prom_counter_t *stun_binding_request;
prom_counter_t *stun_binding_response;
prom_counter_t *stun_binding_error;
@ -35,19 +33,43 @@ prom_counter_t *turn_total_traffic_peer_rcvb;
prom_counter_t *turn_total_traffic_peer_sentp;
prom_counter_t *turn_total_traffic_peer_sentb;
prom_counter_t *turn_total_sessions;
prom_gauge_t *turn_total_allocations;
// Signal change to add metrics
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_counter_t *turn_create_permission_response;
prom_gauge_t *turn_session_limit;
prom_counter_t *turn_sessions_overlimit;
#if MHD_VERSION >= 0x00097002
#define MHD_RESULT enum MHD_Result
#else
#define MHD_RESULT int
#endif
MHD_RESULT promhttp_handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method,
const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) {
MHD_RESULT ret;
char *body = "not found";
enum MHD_ResponseMemoryMode mode = MHD_RESPMEM_PERSISTENT;
unsigned int status = MHD_HTTP_NOT_FOUND;
if (strcmp(method, "GET") != 0) {
status = MHD_HTTP_METHOD_NOT_ALLOWED;
body = "method not allowed";
} else if (strcmp(url, turn_params.prometheus_path) == 0) {
body = prom_collector_registry_bridge(PROM_COLLECTOR_REGISTRY_DEFAULT);
mode = MHD_RESPMEM_MUST_FREE;
status = MHD_HTTP_OK;
}
struct MHD_Response *response = MHD_create_response_from_buffer(strlen(body), body, mode);
if (response == NULL) {
if (mode == MHD_RESPMEM_MUST_FREE) {
free(body);
}
ret = MHD_NO;
} else {
ret = MHD_queue_response(connection, status, response);
MHD_destroy_response(response);
}
return ret;
}
void start_prometheus_server(void) {
if (turn_params.prometheus == 0) {
@ -56,9 +78,8 @@ void start_prometheus_server(void) {
}
prom_collector_registry_default_init();
// Signal change to add protocol-group label to metrics
const char *label[] = {"realm", PROTOCOL_GROUP_LABEL, PROTOCOL_GROUP_LABEL};
size_t nlabels = 2;
const char *label[] = {"realm", NULL};
size_t nlabels = 1;
if (turn_params.prometheus_username_labels) {
label[1] = "user";
@ -93,132 +114,33 @@ void start_prometheus_server(void) {
turn_traffic_peer_sentb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_peer_sentb", "Represents finished sessions peer sent bytes", nlabels, label));
const char *traffic_label[] = {PROTOCOL_GROUP_LABEL};
const size_t ntraffic_labels = 1;
// Create total finished traffic counter metrics
turn_total_traffic_rcvp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_rcvp", "Represents total finished sessions received packets",
ntraffic_labels, traffic_label));
turn_total_traffic_rcvb = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_rcvb", "Represents total finished sessions received bytes", ntraffic_labels, traffic_label));
turn_total_traffic_sentp = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_sentp", "Represents total finished sessions sent packets", ntraffic_labels, traffic_label));
turn_total_traffic_sentb = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_sentb", "Represents total finished sessions sent bytes", ntraffic_labels, traffic_label));
prom_counter_new("turn_total_traffic_rcvp", "Represents total finished sessions received packets", 0, NULL));
turn_total_traffic_rcvb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_rcvb", "Represents total finished sessions received bytes", 0, NULL));
turn_total_traffic_sentp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_sentp", "Represents total finished sessions sent packets", 0, NULL));
turn_total_traffic_sentb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_sentb", "Represents total finished sessions sent bytes", 0, NULL));
// Create total finished sessions traffic for peers counter metrics
turn_total_traffic_peer_rcvp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_peer_rcvp", "Represents total finished sessions peer received packets",
ntraffic_labels, traffic_label));
turn_total_traffic_peer_rcvb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_peer_rcvb", "Represents total finished sessions peer received bytes",
ntraffic_labels, traffic_label));
turn_total_traffic_peer_sentp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_peer_sentp", "Represents total finished sessions peer sent packets",
ntraffic_labels, traffic_label));
turn_total_traffic_peer_rcvp = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_peer_rcvp", "Represents total finished sessions peer received packets", 0, NULL));
turn_total_traffic_peer_rcvb = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_peer_rcvb", "Represents total finished sessions peer received bytes", 0, NULL));
turn_total_traffic_peer_sentp = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_peer_sentp", "Represents total finished sessions peer sent packets", 0, NULL));
turn_total_traffic_peer_sentb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_peer_sentb", "Represents total finished sessions peer sent bytes",
ntraffic_labels, traffic_label));
// Signal change to add protocol-group metric label
// Create total completed session counter metric
const char *total_sessions_labels[] = {"duration", "sent_rate", PROTOCOL_GROUP_LABEL};
turn_total_sessions = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_sessions", "Represents total completed sessions", 3, total_sessions_labels));
prom_counter_new("turn_total_traffic_peer_sentb", "Represents total finished sessions peer sent bytes", 0, NULL));
// Create total allocations number gauge metric
const char *total_allocations_labels[] = {"type", "client_addr_family", PROTOCOL_GROUP_LABEL};
const char *typeLabel[] = {"type"};
turn_total_allocations = prom_collector_registry_must_register_metric(
prom_gauge_new("turn_total_allocations", "Represents current allocations number", 3, total_allocations_labels));
// Signal change to add metrics
// Create round trip time pseudo-histogram metrics
// values must be kept in sync with observation function below
const char *rtt_labels[] = {PROTOCOL_GROUP_LABEL};
const size_t nrtt_labels = 1;
turn_rtt_client[0] = prom_collector_registry_must_register_metric(
prom_counter_new("turn_rtt_client_le_25ms", "Represents measured round trip time of client with channel",
nrtt_labels, rtt_labels));
turn_rtt_client[1] = prom_collector_registry_must_register_metric(
prom_counter_new("turn_rtt_client_le_50ms", "Represents measured round trip time of client with channel",
nrtt_labels, rtt_labels));
turn_rtt_client[2] = prom_collector_registry_must_register_metric(
prom_counter_new("turn_rtt_client_le_100ms", "Represents measured round trip time of client with channel",
nrtt_labels, rtt_labels));
turn_rtt_client[3] = prom_collector_registry_must_register_metric(
prom_counter_new("turn_rtt_client_le_200ms", "Represents measured round trip time of client with channel",
nrtt_labels, rtt_labels));
turn_rtt_client[4] = prom_collector_registry_must_register_metric(
prom_counter_new("turn_rtt_client_le_400ms", "Represents measured round trip time of client with channel",
nrtt_labels, rtt_labels));
turn_rtt_client[5] = prom_collector_registry_must_register_metric(
prom_counter_new("turn_rtt_client_le_800ms", "Represents measured round trip time of client with channel",
nrtt_labels, rtt_labels));
turn_rtt_client[6] = prom_collector_registry_must_register_metric(
prom_counter_new("turn_rtt_client_le_1500ms", "Represents measured round trip time of client with channel",
nrtt_labels, rtt_labels));
turn_rtt_client[7] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_client_more", "Represents measured round trip time of client with channel", nrtt_labels, rtt_labels));
turn_rtt_peer[0] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_peer_le_25ms", "Represents measured round trip time of peer with channel", nrtt_labels, rtt_labels));
turn_rtt_peer[1] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_peer_le_50ms", "Represents measured round trip time of peer with channel", nrtt_labels, rtt_labels));
turn_rtt_peer[2] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_peer_le_100ms", "Represents measured round trip time of peer with channel", nrtt_labels, rtt_labels));
turn_rtt_peer[3] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_peer_le_200ms", "Represents measured round trip time of peer with channel", nrtt_labels, rtt_labels));
turn_rtt_peer[4] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_peer_le_400ms", "Represents measured round trip time of peer with channel", nrtt_labels, rtt_labels));
turn_rtt_peer[5] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_peer_le_800ms", "Represents measured round trip time of peer with channel", nrtt_labels, rtt_labels));
turn_rtt_peer[6] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_peer_le_1500ms", "Represents measured round trip time of peer with channel", nrtt_labels, rtt_labels));
turn_rtt_peer[7] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_peer_more", "Represents measured round trip time of peer with channel", nrtt_labels, rtt_labels));
turn_rtt_combined[0] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_combined_le_25ms", "Represents combined round trip time of channel", nrtt_labels, rtt_labels));
turn_rtt_combined[1] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_combined_le_50ms", "Represents combined round trip time of channel", nrtt_labels, rtt_labels));
turn_rtt_combined[2] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_combined_le_100ms", "Represents combined round trip time of channel", nrtt_labels, rtt_labels));
turn_rtt_combined[3] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_combined_le_200ms", "Represents combined round trip time of channel", nrtt_labels, rtt_labels));
turn_rtt_combined[4] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_combined_le_400ms", "Represents combined round trip time of channel", nrtt_labels, rtt_labels));
turn_rtt_combined[5] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_combined_le_800ms", "Represents combined round trip time of channel", nrtt_labels, rtt_labels));
turn_rtt_combined[6] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_combined_le_1500ms", "Represents combined round trip time of channel", nrtt_labels, rtt_labels));
turn_rtt_combined[7] = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_rtt_combined_more", "Represents combined round trip time of channel", nrtt_labels, rtt_labels));
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_create_permission_response = prom_collector_registry_must_register_metric(
prom_counter_new("turn_create_permission_response", "Count of create_permission 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);
prom_gauge_new("turn_total_allocations", "Represents current allocations number", 1, typeLabel));
// some flags appeared first in microhttpd v0.9.53
unsigned int flags = 0;
if (MHD_is_feature_supported(MHD_FEATURE_IPv6) && is_ipv6_enabled()) {
flags |= MHD_USE_DUAL_STACK;
}
#if MHD_VERSION >= 0x00095300
flags |= MHD_USE_ERROR_LOG;
#endif
@ -236,7 +158,36 @@ void start_prometheus_server(void) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "prometheus exporter server will start using SELECT. "
"The exporter might be unreachable on highly used servers\n");
}
struct MHD_Daemon *daemon = promhttp_start_daemon(flags, turn_params.prometheus_port, NULL, NULL);
ioa_addr server_addr;
addr_set_any(&server_addr);
if (turn_params.prometheus_address[0]) {
if (make_ioa_addr((const uint8_t *)turn_params.prometheus_address, turn_params.prometheus_port, &server_addr) < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "could not parse prometheus collector's server address\n");
return;
}
if (is_ipv6_enabled() && server_addr.ss.sa_family == AF_INET6) {
flags |= MHD_USE_IPv6;
}
} else {
if (MHD_is_feature_supported(MHD_FEATURE_IPv6) && is_ipv6_enabled()) {
flags |= MHD_USE_DUAL_STACK;
server_addr.ss.sa_family = AF_INET6;
server_addr.s6.sin6_port = htons((uint16_t)turn_params.prometheus_port);
} else {
server_addr.ss.sa_family = AF_INET;
server_addr.s4.sin_port = htons((uint16_t)turn_params.prometheus_port);
}
}
uint8_t addr[MAX_IOA_ADDR_STRING];
addr_to_string(&server_addr, addr);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "prometheus exporter server will listen on %s\n", addr);
struct MHD_Daemon *daemon =
MHD_start_daemon(flags, 0, NULL, NULL, &promhttp_handler, NULL, MHD_OPTION_LISTENING_ADDRESS_REUSE, 1,
MHD_OPTION_SOCK_ADDR, &server_addr, MHD_OPTION_END);
if (daemon == NULL) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "could not start prometheus collector\n");
return;
@ -247,62 +198,50 @@ void start_prometheus_server(void) {
return;
}
// Signal change to add metrics
void prom_set_finished_traffic(const char *realm, const char *user, unsigned long rsvp, unsigned long rsvb,
unsigned long sentp, unsigned long sentb, unsigned long without_pingp, bool peer,
const char *protocolgroup) {
unsigned long sentp, unsigned long sentb, bool peer) {
if (turn_params.prometheus == 1) {
// Signal change to add protocol-group label to metrics
const char *user_label[] = {realm, protocolgroup, protocolgroup};
const char *label[] = {realm, NULL};
if (turn_params.prometheus_username_labels) {
user_label[1] = user;
label[1] = user;
}
const char *traffic_label[] = {protocolgroup};
// end signal change
if (peer) {
prom_counter_add(turn_traffic_peer_rcvp, rsvp, user_label);
prom_counter_add(turn_traffic_peer_rcvb, rsvb, user_label);
prom_counter_add(turn_traffic_peer_sentp, sentp, user_label);
prom_counter_add(turn_traffic_peer_sentb, sentb, user_label);
prom_counter_add(turn_traffic_peer_rcvp, rsvp, label);
prom_counter_add(turn_traffic_peer_rcvb, rsvb, label);
prom_counter_add(turn_traffic_peer_sentp, sentp, label);
prom_counter_add(turn_traffic_peer_sentb, sentb, label);
prom_counter_add(turn_total_traffic_peer_rcvp, rsvp, traffic_label);
prom_counter_add(turn_total_traffic_peer_rcvb, rsvb, traffic_label);
prom_counter_add(turn_total_traffic_peer_sentp, sentp, traffic_label);
prom_counter_add(turn_total_traffic_peer_sentb, sentb, traffic_label);
prom_counter_add(turn_total_traffic_peer_rcvp, rsvp, NULL);
prom_counter_add(turn_total_traffic_peer_rcvb, rsvb, NULL);
prom_counter_add(turn_total_traffic_peer_sentp, sentp, NULL);
prom_counter_add(turn_total_traffic_peer_sentb, sentb, NULL);
} else {
prom_counter_add(turn_traffic_rcvp, rsvp, user_label);
prom_counter_add(turn_traffic_rcvb, rsvb, user_label);
prom_counter_add(turn_traffic_sentp, sentp, user_label);
prom_counter_add(turn_traffic_sentb, sentb, user_label);
prom_counter_add(turn_traffic_rcvp, rsvp, label);
prom_counter_add(turn_traffic_rcvb, rsvb, label);
prom_counter_add(turn_traffic_sentp, sentp, label);
prom_counter_add(turn_traffic_sentb, sentb, label);
prom_counter_add(turn_total_traffic_rcvp, rsvp, traffic_label);
prom_counter_add(turn_total_traffic_rcvb, rsvb, traffic_label);
prom_counter_add(turn_total_traffic_sentp, sentp, traffic_label);
prom_counter_add(turn_total_traffic_sentb, sentb, traffic_label);
}
// Signal change to add metrics
if (without_pingp) {
prom_counter_add(turn_with_no_ping_rcvp, without_pingp, NULL);
prom_counter_add(turn_total_traffic_rcvp, rsvp, NULL);
prom_counter_add(turn_total_traffic_rcvb, rsvb, NULL);
prom_counter_add(turn_total_traffic_sentp, sentp, NULL);
prom_counter_add(turn_total_traffic_sentb, sentb, NULL);
}
}
}
void prom_inc_allocation(SOCKET_TYPE type, int addr_family, const char *protocolgroup) {
void prom_inc_allocation(SOCKET_TYPE type) {
if (turn_params.prometheus == 1) {
const char *labels[] = {socket_type_name(type), addr_family_name(addr_family), protocolgroup};
prom_gauge_inc(turn_total_allocations, labels);
const char *label[] = {socket_type_name(type)};
prom_gauge_inc(turn_total_allocations, label);
}
}
void prom_dec_allocation(SOCKET_TYPE type, int addr_family, unsigned long duration, unsigned long sent_rate_kbps,
const char *protocolgroup) {
void prom_dec_allocation(SOCKET_TYPE type) {
if (turn_params.prometheus == 1) {
const char *labels[] = {socket_type_name(type), addr_family_name(addr_family), protocolgroup};
prom_gauge_dec(turn_total_allocations, labels);
const char *total_sessions_labels[] = {duration_name(duration), rate_name(sent_rate_kbps), protocolgroup};
prom_counter_add(turn_total_sessions, 1, total_sessions_labels);
const char *label[] = {socket_type_name(type)};
prom_gauge_dec(turn_total_allocations, label);
}
}
@ -340,83 +279,6 @@ int is_ipv6_enabled(void) {
return ret;
}
// 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) {
prom_counter_add(counter[0], 1, label);
}
if (microseconds <= 50000) {
prom_counter_add(counter[1], 1, label);
}
if (microseconds <= 100000) {
prom_counter_add(counter[2], 1, label);
}
if (microseconds <= 200000) {
prom_counter_add(counter[3], 1, label);
}
if (microseconds <= 400000) {
prom_counter_add(counter[4], 1, label);
}
if (microseconds <= 800000) {
prom_counter_add(counter[5], 1, label);
}
if (microseconds <= 1500000) {
prom_counter_add(counter[6], 1, label);
}
prom_counter_add(counter[7], 1, label);
}
void prom_observe_rtt_client(int microseconds, const char *protocolgroup) {
if (turn_params.prometheus == 1) {
prom_observe_rtt(turn_rtt_client, microseconds, protocolgroup);
}
}
void prom_observe_rtt_peer(int microseconds, const char *protocolgroup) {
if (turn_params.prometheus == 1) {
prom_observe_rtt(turn_rtt_peer, microseconds, protocolgroup);
}
}
void prom_observe_rtt_combined(int microseconds, const char *protocolgroup) {
if (turn_params.prometheus == 1) {
prom_observe_rtt(turn_rtt_combined, microseconds, 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_inc_create_permission_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_create_permission_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) {
@ -425,32 +287,18 @@ void start_prometheus_server(void) {
}
void prom_set_finished_traffic(const char *realm, const char *user, unsigned long rsvp, unsigned long rsvb,
unsigned long sentp, unsigned long sentb, unsigned long without_pingp, bool peer,
const char *protocolgroup) {
unsigned long sentp, unsigned long sentb, bool peer) {
UNUSED_ARG(realm);
UNUSED_ARG(user);
UNUSED_ARG(rsvp);
UNUSED_ARG(rsvb);
UNUSED_ARG(sentp);
UNUSED_ARG(sentb);
UNUSED_ARG(without_pingp);
UNUSED_ARG(peer);
UNUSED_ARG(protocolgroup);
}
void prom_inc_allocation(SOCKET_TYPE type, int addr_family, const char *protocolgroup) {
UNUSED_ARG(type);
UNUSED_ARG(addr_family);
UNUSED_ARG(protocolgroup);
}
void prom_inc_allocation(SOCKET_TYPE type) { UNUSED_ARG(type); }
void prom_dec_allocation(SOCKET_TYPE type, int addr_family, unsigned long duration, unsigned long sent_rate_kbps,
const char *protocolgroup) {
UNUSED_ARG(type);
UNUSED_ARG(addr_family);
UNUSED_ARG(duration);
UNUSED_ARG(sent_rate_kbps);
UNUSED_ARG(protocolgroup);
}
void prom_dec_allocation(SOCKET_TYPE type) { UNUSED_ARG(type); }
#endif /* TURN_NO_PROMETHEUS */

View File

@ -18,7 +18,6 @@ extern "C" {
#endif
#include <microhttpd.h>
#include <prom.h>
#include <promhttp.h>
#ifdef __cplusplus
}
#endif /* __clplusplus */
@ -53,32 +52,17 @@ extern prom_counter_t *turn_total_traffic_peer_sentb;
extern prom_gauge_t *turn_total_allocations_number;
// Signal change to add metrics
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)
#ifdef __cplusplus
extern "C" {
#endif
void start_prometheus_server(void);
// Signal change to add metrics
void prom_set_finished_traffic(const char *realm, const char *user, unsigned long rsvp, unsigned long rsvb,
unsigned long sentp, unsigned long sentb, unsigned long without_pingp, bool peer,
const char *protocolgroup);
unsigned long sentp, unsigned long sentb, bool peer);
void prom_inc_allocation(SOCKET_TYPE type, int addr_family, const char *protocolgroup);
// Signal change to add protocol-group label
void prom_dec_allocation(SOCKET_TYPE type, int addr_family, unsigned long duration, unsigned long sent_rate_kbps,
const char *protocolgroup);
void prom_inc_allocation(SOCKET_TYPE type);
void prom_dec_allocation(SOCKET_TYPE type);
int is_ipv6_enabled(void);
@ -86,28 +70,15 @@ void prom_inc_stun_binding_request(void);
void prom_inc_stun_binding_response(void);
void prom_inc_stun_binding_error(void);
// Signal change to add metrics
void prom_observe_rtt(prom_counter_t *counter[8], int microseconds, const char *protocolgroup);
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_inc_create_permission_response(int err_code);
void prom_set_session_limit(int limit);
void prom_inc_sessions_overlimit(void);
#else
void start_prometheus_server(void);
// Signal change to add metrics
void prom_set_finished_traffic(const char *realm, const char *user, unsigned long rsvp, unsigned long rsvb,
unsigned long sentp, unsigned long sentb, unsigned long without_pingp, bool peer,
const char *protocolgroup);
unsigned long sentp, unsigned long sentb, bool peer);
void prom_inc_allocation(SOCKET_TYPE type, int addr_family, const char *protocolgroup);
void prom_dec_allocation(SOCKET_TYPE type, int addr_family, unsigned long duration, unsigned long sent_rate_kbps,
const char *protocolgroup);
void prom_inc_allocation(SOCKET_TYPE type);
void prom_dec_allocation(SOCKET_TYPE type);
#endif /* TURN_NO_PROMETHEUS */

View File

@ -85,9 +85,6 @@
#include "tls_listener.h"
// Signal change to add rtt metrics
#include <fcntl.h>
#include <unistd.h>
///////////////////////////////
struct bufferevent;
@ -140,6 +137,9 @@ static const char *CLI_HELP_STR[] = {"",
"",
" quit, q, exit, bye - end CLI session",
"",
" drain - drain TURN Server, then shutdown",
" (wait for all allocations to go away, reject new)",
"",
" stop, shutdown, halt - shutdown TURN Server",
"",
" pc - print configuration",
@ -963,7 +963,7 @@ static int run_cli_input(struct cli_session *cs, const char *buf0, unsigned int
if (sl) {
cs->cmds += 1;
if (cli_password[0] && !(cs->auth_completed)) {
if (check_password_equal(cmd, cli_password)) {
if (!check_password_equal(cmd, cli_password)) {
if (cs->cmds >= CLI_PASSWORD_TRY_NUMBER) {
addr_debug_print(1, &(cs->addr), "CLI authentication error");
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "CLI authentication error\n");
@ -983,12 +983,18 @@ static int run_cli_input(struct cli_session *cs, const char *buf0, unsigned int
myprintf(cs, "%s\n", str);
close_cli_session(cs);
ret = -1;
} else if (strcmp(cmd, "drain") == 0) {
addr_debug_print(1, &(cs->addr), "Drain command received from CLI user");
const char *str = "TURN server is draining then shutting down";
myprintf(cs, "%s\n", str);
close_cli_session(cs);
enable_drain_mode();
} else if ((strcmp(cmd, "halt") == 0) || (strcmp(cmd, "shutdown") == 0) || (strcmp(cmd, "stop") == 0)) {
addr_debug_print(1, &(cs->addr), "Shutdown command received from CLI user");
const char *str = "TURN server is shutting down";
myprintf(cs, "%s\n", str);
close_cli_session(cs);
turn_params.stop_turn_server = 1;
turn_params.stop_turn_server = true;
sleep(10);
exit(0);
} else if ((strcmp(cmd, "?") == 0) || (strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
@ -1420,11 +1426,6 @@ void setup_admin_thread(void) {
}
adminserver.sessions = ur_map_create();
// Signal change to add rtt metrics
// run once a day
adminserver.rtt_ev =
set_ioa_timer(adminserver.e, 86400, 0, admin_server_rtt_timer_handler, NULL, 1, "admin_server_rtt_timer");
}
void admin_server_receive_message(struct bufferevent *bev, void *ptr) {
@ -1657,7 +1658,7 @@ static void https_finish_page(struct str_buffer *sb, ioa_socket_handle s, int cc
str_buffer_append(sb, "</body>\r\n</html>\r\n");
send_str_from_ioa_socket_tcp(s, "HTTP/1.1 200 OK\r\nServer: ");
if (!turn_params.no_software_attribute) {
if (turn_params.software_attribute) {
send_str_from_ioa_socket_tcp(s, TURN_SOFTWARE);
}
send_str_from_ioa_socket_tcp(s, "\r\n");
@ -3846,82 +3847,3 @@ void send_https_socket(ioa_socket_handle s) {
}
///////////////////////////////
// Signal change to add rtt metrics
ur_map *rtt_maps[1 + ((turnserver_id)-1)] = {0};
size_t rtt_maps_count = 0;
size_t rtt_map_current = 0;
FILE *rtt_file;
bool rtt_foreach(ur_map_key_type key, ur_map_value_type value) {
if (!value) {
return false;
}
ur_map_value_type min = value;
for (size_t i = rtt_map_current + 1; i < rtt_maps_count; ++i) {
if (ur_map_get(rtt_maps[i], key, &value)) {
ur_map_put(rtt_maps[i], key, 0);
if (value && value < min) {
min = value;
}
}
}
// value is stored as measured rtt in ms + 1
value -= 1;
char saddr[INET6_ADDRSTRLEN] = "\0";
if (key & (1L << 63)) {
struct sockaddr_in6 addr = {0};
addr.sin6_family = AF_INET6;
size_t i = 6;
while (i--) {
addr.sin6_addr.s6_addr[i] = key & 0xFF;
key >>= 8;
}
inet_ntop(AF_INET6, &addr.sin6_addr, saddr, sizeof(saddr));
fprintf(rtt_file, "%s/48,%ld\n", saddr, min);
} else {
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
key <<= 8;
addr.sin_addr.s_addr = htonl(key & 0xFFFFFFFF);
inet_ntop(AF_INET, &addr.sin_addr, saddr, sizeof(saddr));
fprintf(rtt_file, "%s/24,%ld\n", saddr, min);
}
return false;
}
void admin_server_rtt_timer_handler(ioa_engine *engine, void *arg) {
UNUSED_ARG(engine);
UNUSED_ARG(arg);
int fd = open("/var/tmp/rtt_dump.tmp", O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "error opening temporary file during rtt timer (%d)\n", errno);
return;
}
rtt_file = fdopen(fd, "w");
if (rtt_file == NULL) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "fdopen error during rtt timer\n");
close(fd);
return;
}
fprintf(rtt_file, "network,rtt_ms\n");
rtt_maps_count = cycle_rtt_ms_maps(rtt_maps, sizeof(rtt_maps) / sizeof(rtt_maps[0]));
for (rtt_map_current = 0; rtt_map_current < rtt_maps_count; ++rtt_map_current) {
ur_map_foreach(rtt_maps[rtt_map_current], rtt_foreach);
ur_map_free(&rtt_maps[rtt_map_current]);
}
if (fflush(rtt_file) != 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "fflush /var/tmp/rtt_dump.tmp failed, not relinking (%d)\n", errno);
} else {
if (rename("/var/tmp/rtt_dump.tmp", "/var/tmp/rtt_dump") == -1) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "could not rename rtt dump into /var/tmp/rtt_dump (%d)\n", errno);
}
}
fclose(rtt_file);
rtt_file = NULL;
}

View File

@ -73,8 +73,6 @@ struct admin_server {
struct bufferevent *https_out_buf;
ur_map *sessions;
pthread_t thr;
// Signal change to add rtt metrics
ioa_timer_handle rtt_ev;
};
///////////////////////////////////////////
@ -115,10 +113,6 @@ void https_admin_server_receive_message(struct bufferevent *bev, void *ptr);
int send_turn_session_info(struct turn_session_info *tsi);
void send_https_socket(ioa_socket_handle s);
// Signal change to add rtt metrics
bool rtt_foreach(ur_map_key_type, ur_map_value_type);
void admin_server_rtt_timer_handler(ioa_engine *, void *);
////////////////////////////////////////////
#ifdef __cplusplus

View File

@ -68,6 +68,13 @@ static TURN_MUTEX_DECLARE(o_to_realm_mutex);
static ur_string_map *o_to_realm = NULL;
static secrets_list_t realms_list;
#ifndef _MSC_VER
_Atomic
#else
volatile
#endif
size_t global_allocation_count = 0; // used for drain mode, to know when all allocations have gone away
static char userdb_type_unknown[] = "Unknown";
static char userdb_type_sqlite[] = "SQLite";
static char userdb_type_postgresql[] = "PostgreSQL";
@ -683,6 +690,15 @@ int check_new_allocation_quota(uint8_t *user, int oauth, uint8_t *realm) {
free(username);
ur_string_map_unlock(rp->status.alloc_counters);
}
#ifndef _MSC_VER
global_allocation_count++;
TURN_LOG_FUNC(TURN_LOG_LEVEL_DEBUG, "Global turn allocation count incremented, now %ld\n", global_allocation_count);
#else
size_t cur_count = (size_t)InterlockedIncrement((volatile LONG *)&global_allocation_count);
TURN_LOG_FUNC(TURN_LOG_LEVEL_DEBUG, "Global turn allocation count incremented, now %ld\n", cur_count);
#endif
return ret;
}
@ -709,6 +725,18 @@ void release_allocation_quota(uint8_t *user, int oauth, uint8_t *realm) {
ur_string_map_unlock(rp->status.alloc_counters);
free(username);
}
int log_level = TURN_LOG_LEVEL_DEBUG;
if (turn_params.drain_turn_server) {
log_level = TURN_LOG_LEVEL_INFO;
}
#ifndef _MSC_VER
global_allocation_count--;
TURN_LOG_FUNC(log_level, "Global turn allocation count decremented, now %ld\n", global_allocation_count);
#else
size_t cur_count = (size_t)InterlockedDecrement((volatile LONG *)&global_allocation_count);
TURN_LOG_FUNC(log_level, "Global turn allocation count decremented, now %ld\n", cur_count);
#endif
}
//////////////////////////////////

View File

@ -46,6 +46,14 @@
extern "C" {
#endif
#ifndef _MSC_VER
#include <stdatomic.h>
extern _Atomic
#else
extern volatile
#endif
size_t global_allocation_count;
//////////// REALM //////////////
struct _realm_status_t;

View File

@ -496,40 +496,16 @@ int main(int argc, char **argv) {
}
if (use_tcp) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#if TLSv1_2_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method());
#elif TLSv1_1_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method());
#else
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method());
#endif
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#else // OPENSSL_VERSION_NUMBER >= 0x10100000L
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLS_client_method());
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#endif
root_tls_ctx_num++;
} else {
#if !DTLS_SUPPORTED
fprintf(stderr, "ERROR: DTLS is not supported.\n");
exit(-1);
#else
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (OPENSSL_VERSION_NUMBER < 0x10000000L) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,
"WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n");
}
#if DTLSv1_2_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_2_client_method());
#else
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method());
#endif
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#else // OPENSSL_VERSION_NUMBER >= 0x10100000L
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLS_client_method());
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#endif
#endif
root_tls_ctx_num++;
}

View File

@ -55,10 +55,8 @@ static uint64_t current_reservation_token = 0;
static int allocate_rtcp = 0;
static const int never_allocate_rtcp = 0;
#if ALPN_SUPPORTED
static const unsigned char kALPNProtos[] = "\x08http/1.1\x09stun.turn\x12stun.nat-discovery";
static const size_t kALPNProtosLen = sizeof(kALPNProtos) - 1;
#endif
/////////////////////////////////////////
@ -96,9 +94,7 @@ static SSL *tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, bool *try_agai
ssl = SSL_new(root_tls_ctx[ctxtype]);
#if ALPN_SUPPORTED
SSL_set_alpn_protos(ssl, kALPNProtos, kALPNProtosLen);
#endif
if (use_tcp) {
SSL_set_fd(ssl, fd);

View File

@ -187,21 +187,12 @@ bool stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm,
if (shatype == SHATYPE_SHA256) {
#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
#if OPENSSL_VERSION_NUMBER < 0x10100000L
unsigned int keylen = 0;
EVP_MD_CTX ctx;
EVP_DigestInit(&ctx, EVP_sha256());
EVP_DigestUpdate(&ctx, str, strl);
EVP_DigestFinal(&ctx, key, &keylen);
EVP_MD_CTX_cleanup(&ctx);
#else
unsigned int keylen = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_DigestInit(ctx, EVP_sha256());
EVP_DigestUpdate(ctx, str, strl);
EVP_DigestFinal(ctx, key, &keylen);
EVP_MD_CTX_free(ctx);
#endif
ret = true;
#else
fprintf(stderr, "SHA256 is not supported\n");
@ -209,21 +200,12 @@ bool stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm,
#endif
} else if (shatype == SHATYPE_SHA384) {
#if !defined(OPENSSL_NO_SHA384) && defined(SHA384_DIGEST_LENGTH)
#if OPENSSL_VERSION_NUMBER < 0x10100000L
unsigned int keylen = 0;
EVP_MD_CTX ctx;
EVP_DigestInit(&ctx, EVP_sha384());
EVP_DigestUpdate(&ctx, str, strl);
EVP_DigestFinal(&ctx, key, &keylen);
EVP_MD_CTX_cleanup(&ctx);
#else
unsigned int keylen = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_DigestInit(ctx, EVP_sha384());
EVP_DigestUpdate(ctx, str, strl);
EVP_DigestFinal(ctx, key, &keylen);
EVP_MD_CTX_free(ctx);
#endif
ret = true;
#else
fprintf(stderr, "SHA384 is not supported\n");
@ -231,41 +213,19 @@ bool stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm,
#endif
} else if (shatype == SHATYPE_SHA512) {
#if !defined(OPENSSL_NO_SHA512) && defined(SHA512_DIGEST_LENGTH)
#if OPENSSL_VERSION_NUMBER < 0x10100000L
unsigned int keylen = 0;
EVP_MD_CTX ctx;
EVP_DigestInit(&ctx, EVP_sha512());
EVP_DigestUpdate(&ctx, str, strl);
EVP_DigestFinal(&ctx, key, &keylen);
EVP_MD_CTX_cleanup(&ctx);
#else
unsigned int keylen = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_DigestInit(ctx, EVP_sha512());
EVP_DigestUpdate(ctx, str, strl);
EVP_DigestFinal(ctx, key, &keylen);
EVP_MD_CTX_free(ctx);
#endif
ret = true;
#else
fprintf(stderr, "SHA512 is not supported\n");
ret = false;
#endif
} else {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
unsigned int keylen = 0;
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
#if defined EVP_MD_CTX_FLAG_NON_FIPS_ALLOW && !defined(LIBRESSL_VERSION_NUMBER)
if (FIPS_mode()) {
EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
}
#endif // defined EVP_MD_CTX_FLAG_NON_FIPS_ALLOW && !defined(LIBRESSL_VERSION_NUMBER)
EVP_DigestInit_ex(&ctx, EVP_md5(), NULL);
EVP_DigestUpdate(&ctx, str, strl);
EVP_DigestFinal(&ctx, key, &keylen);
EVP_MD_CTX_cleanup(&ctx);
#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
unsigned int keylen = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (EVP_default_properties_is_fips_enabled(NULL)) {
@ -275,7 +235,7 @@ bool stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm,
EVP_DigestUpdate(ctx, str, strl);
EVP_DigestFinal(ctx, key, &keylen);
EVP_MD_CTX_free(ctx);
#else // OPENSSL_VERSION_NUMBER >= 0x10100000L && OPENSSL_VERSION_NUMBER < 0x30000000L
#else // OPENSSL_VERSION_NUMBER < 0x30000000L
unsigned int keylen = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
#if defined EVP_MD_CTX_FLAG_NON_FIPS_ALLOW && !defined(LIBRESSL_VERSION_NUMBER)
@ -287,7 +247,7 @@ bool stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm,
EVP_DigestUpdate(ctx, str, strl);
EVP_DigestFinal(ctx, key, &keylen);
EVP_MD_CTX_free(ctx);
#endif // OPENSSL_VERSION_NUMBER < 0X10100000L
#endif // OPENSSL_VERSION_NUMBER >= 0X30000000L
ret = true;
}
@ -323,23 +283,6 @@ static void generate_enc_password(const char *pwd, char *result, const unsigned
result[3 + PWD_SALT_SIZE + PWD_SALT_SIZE] = '$';
unsigned char *out = (unsigned char *)(result + 3 + PWD_SALT_SIZE + PWD_SALT_SIZE + 1);
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX ctx;
#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
EVP_DigestInit(&ctx, EVP_sha256());
#else
EVP_DigestInit(&ctx, EVP_sha1());
#endif
EVP_DigestUpdate(&ctx, salt, PWD_SALT_SIZE);
EVP_DigestUpdate(&ctx, pwd, strlen(pwd));
{
unsigned char hash[129];
unsigned int keylen = 0;
EVP_DigestFinal(&ctx, hash, &keylen);
readable_string(hash, out, keylen);
}
EVP_MD_CTX_cleanup(&ctx);
#else
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
#if !defined(OPENSSL_NO_SHA256) && defined(SHA256_DIGEST_LENGTH)
EVP_DigestInit(ctx, EVP_sha256());
@ -355,7 +298,6 @@ static void generate_enc_password(const char *pwd, char *result, const unsigned
readable_string(hash, out, keylen);
}
EVP_MD_CTX_free(ctx);
#endif
}
}
@ -2312,12 +2254,7 @@ static bool encode_oauth_token_gcm(const uint8_t *server_name, encoded_oauth_tok
return false;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX *ctxp = &ctx;
#else
EVP_CIPHER_CTX *ctxp = EVP_CIPHER_CTX_new();
#endif
EVP_CIPHER_CTX_init(ctxp);
/* Initialize the encryption operation. */
@ -2367,11 +2304,7 @@ static bool encode_oauth_token_gcm(const uint8_t *server_name, encoded_oauth_tok
etoken->size = 2 + OAUTH_GCM_NONCE_SIZE + outl;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_CIPHER_CTX_cleanup(ctxp);
#else
EVP_CIPHER_CTX_free(ctxp);
#endif
return true;
}
@ -2411,12 +2344,7 @@ static bool decode_oauth_token_gcm(const uint8_t *server_name, const encoded_oau
return false;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX *ctxp = &ctx;
#else
EVP_CIPHER_CTX *ctxp = EVP_CIPHER_CTX_new();
#endif
EVP_CIPHER_CTX_init(ctxp);
/* Initialize the decryption operation. */
if (1 != EVP_DecryptInit_ex(ctxp, cipher, NULL, NULL, NULL)) {
@ -2459,21 +2387,13 @@ static bool decode_oauth_token_gcm(const uint8_t *server_name, const encoded_oau
int tmp_outl = 0;
if (EVP_DecryptFinal_ex(ctxp, decoded_field + outl, &tmp_outl) < 1) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_CIPHER_CTX_cleanup(ctxp);
#else
EVP_CIPHER_CTX_free(ctxp);
#endif
OAUTH_ERROR("%s: token integrity check failed\n", __FUNCTION__);
return false;
}
outl += tmp_outl;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_CIPHER_CTX_cleanup(ctxp);
#else
EVP_CIPHER_CTX_free(ctxp);
#endif
size_t len = 0;

View File

@ -48,9 +48,6 @@
#define STUN_MAX_SERVER_NAME_SIZE (1025)
#define STUN_MAX_PWD_SIZE (256)
#define AUTH_SECRET_SIZE STUN_MAX_PWD_SIZE
// Signal change to add group metric label
#define MAX_PROTOCOL_GROUP_SIZE (16)
#define DEFAULT_PROTOCOL_GROUP "00"
#define STUN_MAGIC_COOKIE (0x2112A442)

View File

@ -31,7 +31,7 @@
#ifndef __IOADEFS__
#define __IOADEFS__
#define TURN_SERVER_VERSION "4.6.2"
#define TURN_SERVER_VERSION "4.6.3"
#define TURN_SERVER_VERSION_NAME "Gorst"
#ifndef TURN_SERVER_BUILD_INFO
#define TURN_SERVER_BUILD_INFO ""

View File

@ -53,44 +53,39 @@ void init_allocation(void *owner, allocation *a, ur_map *tcp_connections) {
}
}
// Signal change to add address family label
void clear_allocation(allocation *a, SOCKET_TYPE socket_type, int family) {
if (a) {
if (a->is_valid) {
turn_report_allocation_delete(a, socket_type, family);
}
if (a->tcs.elems) {
size_t i;
size_t sz = a->tcs.sz;
for (i = 0; i < sz; ++i) {
tcp_connection *tc = a->tcs.elems[i];
if (tc) {
delete_tcp_connection(tc);
a->tcs.elems[i] = NULL;
}
}
free(a->tcs.elems);
a->tcs.elems = NULL;
}
a->tcs.sz = 0;
{
int i;
for (i = 0; i < ALLOC_PROTOCOLS_NUMBER; ++i) {
clear_ioa_socket_session_if(a->relay_sessions[i].s, a->owner);
clear_relay_endpoint_session_data(&(a->relay_sessions[i]));
IOA_EVENT_DEL(a->relay_sessions[i].lifetime_ev);
}
}
/* The order is important here: */
free_turn_permission_hashtable(&(a->addr_to_perm));
ch_map_clean(&(a->chns));
a->is_valid = 0;
void clear_allocation(allocation *a, SOCKET_TYPE socket_type) {
if (!a) {
return;
}
if (a->is_valid) {
turn_report_allocation_delete(a, socket_type);
}
if (a->tcs.elems) {
for (size_t i = 0; i < a->tcs.sz; ++i) {
tcp_connection *tc = a->tcs.elems[i];
if (tc) {
delete_tcp_connection(tc);
a->tcs.elems[i] = NULL;
}
}
free(a->tcs.elems);
a->tcs.elems = NULL;
}
a->tcs.sz = 0;
for (size_t i = 0; i < ALLOC_PROTOCOLS_NUMBER; ++i) {
clear_ioa_socket_session_if(a->relay_sessions[i].s, a->owner);
clear_relay_endpoint_session_data(&(a->relay_sessions[i]));
IOA_EVENT_DEL(a->relay_sessions[i].lifetime_ev);
}
/* The order is important here: */
free_turn_permission_hashtable(&(a->addr_to_perm));
ch_map_clean(&(a->chns));
a->is_valid = 0;
}
relay_endpoint_session *get_relay_session(allocation *a, int family) {
@ -121,27 +116,27 @@ ioa_socket_handle get_relay_socket(allocation *a, int family) {
}
void set_allocation_family_invalid(allocation *a, int family) {
if (a) {
size_t index = ALLOC_INDEX(family);
if (a->relay_sessions[index].s) {
if (a->tcs.elems) {
size_t i;
size_t sz = a->tcs.sz;
for (i = 0; i < sz; ++i) {
tcp_connection *tc = a->tcs.elems[i];
if (tc) {
if (tc->peer_s && (get_ioa_socket_address_family(tc->peer_s) == family)) {
delete_tcp_connection(tc);
a->tcs.elems[i] = NULL;
}
if (!a) {
return;
}
const size_t index = ALLOC_INDEX(family);
if (a->relay_sessions[index].s) {
if (a->tcs.elems) {
for (size_t i = 0; i < a->tcs.sz; ++i) {
tcp_connection *tc = a->tcs.elems[i];
if (tc) {
if (tc->peer_s && (get_ioa_socket_address_family(tc->peer_s) == family)) {
delete_tcp_connection(tc);
a->tcs.elems[i] = NULL;
}
}
}
clear_ioa_socket_session_if(a->relay_sessions[index].s, a->owner);
clear_relay_endpoint_session_data(&(a->relay_sessions[index]));
IOA_EVENT_DEL(a->relay_sessions[index].lifetime_ev);
}
clear_ioa_socket_session_if(a->relay_sessions[index].s, a->owner);
clear_relay_endpoint_session_data(&(a->relay_sessions[index]));
IOA_EVENT_DEL(a->relay_sessions[index].lifetime_ev);
}
}
@ -153,15 +148,14 @@ void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_h
}
}
int is_allocation_valid(const allocation *a) {
bool is_allocation_valid(const allocation *a) {
if (a) {
return a->is_valid;
} else {
return 0;
}
return false;
}
void set_allocation_valid(allocation *a, int value) {
void set_allocation_valid(allocation *a, bool value) {
if (a) {
a->is_valid = value;
}
@ -179,23 +173,24 @@ turn_permission_info *allocation_get_permission(allocation *a, const ioa_addr *a
static bool delete_channel_info_from_allocation_map(ur_map_key_type key, ur_map_value_type value);
void turn_permission_clean(turn_permission_info *tinfo) {
if (tinfo && tinfo->allocated) {
if (tinfo->verbose) {
char s[257] = "\0";
addr_to_string(&(tinfo->addr), (uint8_t *)s);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: peer %s deleted\n", tinfo->session_id, s);
}
if (!(tinfo->lifetime_ev)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) permission to be cleaned\n", __FUNCTION__);
}
IOA_EVENT_DEL(tinfo->lifetime_ev);
lm_map_foreach(&(tinfo->chns), (foreachcb_type)delete_channel_info_from_allocation_map);
lm_map_clean(&(tinfo->chns));
memset(tinfo, 0, sizeof(turn_permission_info));
if (!tinfo || !tinfo->allocated) {
return;
}
if (tinfo->verbose) {
char s[257] = "\0";
addr_to_string(&(tinfo->addr), (uint8_t *)s);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "session %018llu: peer %s deleted\n", tinfo->session_id, s);
}
if (!(tinfo->lifetime_ev)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) permission to be cleaned\n", __FUNCTION__);
}
IOA_EVENT_DEL(tinfo->lifetime_ev);
lm_map_foreach(&(tinfo->chns), (foreachcb_type)delete_channel_info_from_allocation_map);
lm_map_clean(&(tinfo->chns));
memset(tinfo, 0, sizeof(turn_permission_info));
}
static void init_turn_permission_hashtable(turn_permission_hashtable *map) {
@ -205,39 +200,36 @@ static void init_turn_permission_hashtable(turn_permission_hashtable *map) {
}
static void free_turn_permission_hashtable(turn_permission_hashtable *map) {
if (map) {
if (!map) {
return;
}
size_t i;
for (i = 0; i < TURN_PERMISSION_HASHTABLE_SIZE; ++i) {
for (size_t i = 0; i < TURN_PERMISSION_HASHTABLE_SIZE; ++i) {
turn_permission_array *parray = &(map->table[i]);
turn_permission_array *parray = &(map->table[i]);
{
size_t j;
for (j = 0; j < TURN_PERMISSION_ARRAY_SIZE; ++j) {
turn_permission_slot *slot = &(parray->main_slots[j]);
for (size_t j = 0; j < TURN_PERMISSION_ARRAY_SIZE; ++j) {
turn_permission_slot *slot = &(parray->main_slots[j]);
if (slot->info.allocated) {
turn_permission_clean(&(slot->info));
}
}
if (parray->extra_slots) {
for (size_t j = 0; j < parray->extra_sz; ++j) {
turn_permission_slot *slot = parray->extra_slots[j];
if (slot) {
if (slot->info.allocated) {
turn_permission_clean(&(slot->info));
}
free(slot);
parray->extra_slots[j] = NULL;
}
}
if (parray->extra_slots) {
size_t j;
for (j = 0; j < parray->extra_sz; ++j) {
turn_permission_slot *slot = parray->extra_slots[j];
if (slot) {
if (slot->info.allocated) {
turn_permission_clean(&(slot->info));
}
free(slot);
}
}
free(parray->extra_slots);
parray->extra_slots = NULL;
}
parray->extra_sz = 0;
free(parray->extra_slots);
parray->extra_slots = NULL;
}
parray->extra_sz = 0;
}
}
@ -249,21 +241,15 @@ static turn_permission_info *get_from_turn_permission_hashtable(turn_permission_
uint32_t index = addr_hash_no_port(addr) & (TURN_PERMISSION_HASHTABLE_SIZE - 1);
turn_permission_array *parray = &(map->table[index]);
{
size_t i;
for (i = 0; i < TURN_PERMISSION_ARRAY_SIZE; ++i) {
turn_permission_slot *slot = &(parray->main_slots[i]);
if (slot->info.allocated && addr_eq_no_port(&(slot->info.addr), addr)) {
return &(slot->info);
}
for (size_t i = 0; i < TURN_PERMISSION_ARRAY_SIZE; ++i) {
turn_permission_slot *slot = &(parray->main_slots[i]);
if (slot->info.allocated && addr_eq_no_port(&(slot->info.addr), addr)) {
return &(slot->info);
}
}
if (parray->extra_slots) {
size_t i;
size_t sz = parray->extra_sz;
for (i = 0; i < sz; ++i) {
for (size_t i = 0; i < parray->extra_sz; ++i) {
turn_permission_slot *slot = parray->extra_slots[i];
if (slot->info.allocated && addr_eq_no_port(&(slot->info.addr), addr)) {
return &(slot->info);
@ -302,38 +288,48 @@ static bool delete_channel_info_from_allocation_map(ur_map_key_type key, ur_map_
}
void turn_channel_delete(ch_info *chn) {
if (chn) {
int port = addr_get_port(&(chn->peer_addr));
if (port < 1) {
char s[129];
addr_to_string(&(chn->peer_addr), (uint8_t *)s);
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) channel to be cleaned: port is empty: %s\n",
__FUNCTION__, s);
}
{
turn_permission_info *tinfo = (turn_permission_info *)chn->owner;
if (tinfo) {
lm_map_del(&(tinfo->chns), (ur_map_key_type)port, NULL);
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (2) channel to be cleaned: permission is empty\n",
__FUNCTION__);
}
}
delete_channel_info_from_allocation_map((ur_map_key_type)port, (ur_map_value_type)chn);
if (!chn) {
return;
}
int port = addr_get_port(&(chn->peer_addr));
if (port < 1) {
char s[129];
addr_to_string(&(chn->peer_addr), (uint8_t *)s);
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (1) channel to be cleaned: port is empty: %s\n", __FUNCTION__,
s);
}
turn_permission_info *tinfo = (turn_permission_info *)chn->owner;
if (tinfo) {
lm_map_del(&(tinfo->chns), (ur_map_key_type)port, NULL);
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "!!! %s: strange (2) channel to be cleaned: permission is empty\n",
__FUNCTION__);
}
delete_channel_info_from_allocation_map((ur_map_key_type)port, (ur_map_value_type)chn);
}
ch_info *allocation_get_new_ch_info(allocation *a, uint16_t chnum, ioa_addr *peer_addr) {
if (!a) {
return NULL;
}
turn_permission_info *tinfo = get_from_turn_permission_hashtable(&(a->addr_to_perm), peer_addr);
if (!tinfo) {
tinfo = allocation_add_permission(a, peer_addr);
if (!tinfo) {
return NULL;
}
}
ch_info *chn = ch_map_get(&(a->chns), chnum, 1);
if (!chn) {
return NULL;
}
chn->allocated = 1;
chn->allocated = true;
chn->chnum = chnum;
chn->port = addr_get_port(peer_addr);
addr_cpy(&(chn->peer_addr), peer_addr);
@ -385,20 +381,34 @@ ch_info *get_turn_channel(turn_permission_info *tinfo, ioa_addr *addr) {
turn_permission_hashtable *allocation_get_turn_permission_hashtable(allocation *a) { return &(a->addr_to_perm); }
turn_permission_info *allocation_add_permission(allocation *a, const ioa_addr *addr) {
if (a && addr) {
if (!a || !addr) {
return NULL;
}
turn_permission_hashtable *map = &(a->addr_to_perm);
uint32_t hash = addr_hash_no_port(addr);
size_t fds = (size_t)(hash & (TURN_PERMISSION_HASHTABLE_SIZE - 1));
turn_permission_hashtable *map = &(a->addr_to_perm);
uint32_t hash = addr_hash_no_port(addr);
size_t fds = (size_t)(hash & (TURN_PERMISSION_HASHTABLE_SIZE - 1));
turn_permission_array *parray = &(map->table[fds]);
turn_permission_array *parray = &(map->table[fds]);
turn_permission_slot *slot = NULL;
turn_permission_slot *slot = NULL;
{
size_t i;
for (i = 0; i < TURN_PERMISSION_ARRAY_SIZE; ++i) {
slot = &(parray->main_slots[i]);
for (size_t i = 0; i < TURN_PERMISSION_ARRAY_SIZE; ++i) {
slot = &(parray->main_slots[i]);
if (!(slot->info.allocated)) {
break;
} else {
slot = NULL;
}
}
if (!slot) {
size_t old_sz = parray->extra_sz;
turn_permission_slot **slots = parray->extra_slots;
if (slots) {
for (size_t i = 0; i < old_sz; ++i) {
slot = slots[i];
if (!(slot->info.allocated)) {
break;
} else {
@ -408,168 +418,151 @@ turn_permission_info *allocation_add_permission(allocation *a, const ioa_addr *a
}
if (!slot) {
size_t old_sz = parray->extra_sz;
turn_permission_slot **slots = parray->extra_slots;
if (slots) {
size_t i;
for (i = 0; i < old_sz; ++i) {
slot = slots[i];
if (!(slot->info.allocated)) {
break;
} else {
slot = NULL;
}
}
size_t old_sz_mem = old_sz * sizeof(turn_permission_slot *);
turn_permission_slot **new_slots =
(turn_permission_slot **)realloc(parray->extra_slots, old_sz_mem + sizeof(turn_permission_slot *));
if (!new_slots) {
return NULL;
}
parray->extra_slots = new_slots;
slots = parray->extra_slots;
parray->extra_sz = old_sz + 1;
slot = (turn_permission_slot *)malloc(sizeof(turn_permission_slot));
if (!slot) {
size_t old_sz_mem = old_sz * sizeof(turn_permission_slot *);
parray->extra_slots =
(turn_permission_slot **)realloc(parray->extra_slots, old_sz_mem + sizeof(turn_permission_slot *));
slots = parray->extra_slots;
parray->extra_sz = old_sz + 1;
slots[old_sz] = (turn_permission_slot *)malloc(sizeof(turn_permission_slot));
slot = slots[old_sz];
return NULL;
}
slots[old_sz] = slot;
}
memset(slot, 0, sizeof(turn_permission_slot));
slot->info.allocated = 1;
turn_permission_info *elem = &(slot->info);
addr_cpy(&(elem->addr), addr);
elem->owner = a;
return elem;
} else {
return NULL;
}
memset(slot, 0, sizeof(turn_permission_slot));
slot->info.allocated = true;
turn_permission_info *elem = &(slot->info);
addr_cpy(&(elem->addr), addr);
elem->owner = a;
return elem;
}
ch_info *ch_map_get(ch_map *const map, const uint16_t chnum, const int new_chn) {
if (map) {
const size_t index = (size_t)(chnum & (CH_MAP_HASH_SIZE - 1));
ch_map_array *const a = &(map->table[index]);
if (!map) {
return NULL;
}
for (size_t i = 0; i < CH_MAP_ARRAY_SIZE; ++i) {
ch_info *const chi = &(a->main_chns[i]);
if (chi->allocated) {
if (!new_chn && (chi->chnum == chnum)) {
return chi;
}
} else if (new_chn) {
const size_t index = (size_t)(chnum & (CH_MAP_HASH_SIZE - 1));
ch_map_array *const a = &(map->table[index]);
for (size_t i = 0; i < CH_MAP_ARRAY_SIZE; ++i) {
ch_info *const chi = &(a->main_chns[i]);
if (chi->allocated) {
if (!new_chn && (chi->chnum == chnum)) {
return chi;
}
} else if (new_chn) {
return chi;
}
}
const size_t old_sz = a->extra_sz;
if (old_sz && a->extra_chns) {
for (size_t i = 0; i < old_sz; ++i) {
ch_info *const chi = a->extra_chns[i];
if (chi) {
if (chi->allocated) {
if (!new_chn && (chi->chnum == chnum)) {
return chi;
}
} else if (new_chn) {
const size_t old_sz = a->extra_sz;
if (old_sz && a->extra_chns) {
for (size_t i = 0; i < old_sz; ++i) {
ch_info *const chi = a->extra_chns[i];
if (chi) {
if (chi->allocated) {
if (!new_chn && (chi->chnum == chnum)) {
return chi;
}
} else if (new_chn) {
return chi;
}
}
}
}
if (new_chn) {
const size_t old_sz_mem = old_sz * sizeof(ch_info *);
ch_info **const pTmp = (ch_info **)realloc(a->extra_chns, old_sz_mem + sizeof(ch_info *));
if (!pTmp) {
return NULL;
}
a->extra_chns = pTmp;
a->extra_chns[old_sz] = (ch_info *)calloc(1, sizeof(ch_info));
if (!a->extra_chns[old_sz]) {
// if the realloc succeeds, but the calloc fails, we don't attempt to shrink the realloc back down
// by not recording the change to the size, we allow the next call to this function to realloc the
// block to presumably the same size it already is, which should be fine and not result in any leaks.
return NULL;
}
a->extra_sz += 1;
return a->extra_chns[old_sz];
if (new_chn) {
const size_t old_sz_mem = old_sz * sizeof(ch_info *);
ch_info **const pTmp = (ch_info **)realloc(a->extra_chns, old_sz_mem + sizeof(ch_info *));
if (!pTmp) {
return NULL;
}
a->extra_chns = pTmp;
a->extra_chns[old_sz] = (ch_info *)calloc(1, sizeof(ch_info));
if (!a->extra_chns[old_sz]) {
// if the realloc succeeds, but the calloc fails, we don't attempt to shrink the realloc back down
// by not recording the change to the size, we allow the next call to this function to realloc the
// block to presumably the same size it already is, which should be fine and not result in any leaks.
return NULL;
}
a->extra_sz += 1;
return a->extra_chns[old_sz];
}
return NULL;
}
void ch_map_clean(ch_map *map) {
if (map) {
size_t index;
for (index = 0; index < CH_MAP_HASH_SIZE; ++index) {
if (!map) {
return;
}
ch_map_array *a = &(map->table[index]);
for (size_t index = 0; index < CH_MAP_HASH_SIZE; ++index) {
ch_map_array *a = &(map->table[index]);
size_t i;
for (i = 0; i < CH_MAP_ARRAY_SIZE; ++i) {
ch_info *chi = &(a->main_chns[i]);
if (chi->allocated) {
ch_info_clean(chi);
}
for (size_t i = 0; i < CH_MAP_ARRAY_SIZE; ++i) {
ch_info *chi = &(a->main_chns[i]);
if (chi->allocated) {
ch_info_clean(chi);
}
if (a->extra_chns) {
size_t sz = a->extra_sz;
for (i = 0; i < sz; ++i) {
ch_info *chi = a->extra_chns[i];
if (chi) {
if (chi->allocated) {
ch_info_clean(chi);
}
free(chi);
a->extra_chns[i] = NULL;
}
}
free(a->extra_chns);
a->extra_chns = NULL;
}
a->extra_sz = 0;
}
if (a->extra_chns) {
for (size_t i = 0; i < a->extra_sz; ++i) {
ch_info *chi = a->extra_chns[i];
if (chi) {
if (chi->allocated) {
ch_info_clean(chi);
}
free(chi);
a->extra_chns[i] = NULL;
}
}
free(a->extra_chns);
a->extra_chns = NULL;
}
a->extra_sz = 0;
}
}
////////////////// TCP connections ///////////////////////////////
static void set_new_tc_id(uint8_t server_id, tcp_connection *tc) {
allocation *a = (allocation *)(tc->owner);
ur_map *map = a->tcp_connections;
uint32_t newid;
uint32_t sid = server_id;
sid = sid << 24;
const uint32_t sid = ((uint32_t)server_id) << 24;
allocation *const a = (allocation *)(tc->owner);
if (!a || !a->tcp_connections) {
return;
}
uint32_t newid = 0;
do {
newid = 0;
while (!newid) {
newid = (uint32_t)turn_random();
if (!newid) {
continue;
}
newid = newid & 0x00FFFFFF;
if (!newid) {
continue;
}
newid = newid | sid;
}
} while (ur_map_get(map, (ur_map_key_type)newid, NULL));
do {
newid = ((uint32_t)turn_random()) & 0x00FFFFFF;
} while (!newid);
newid = newid | sid;
} while (ur_map_get(a->tcp_connections, (ur_map_key_type)newid, NULL));
tc->id = newid;
ur_map_put(map, (ur_map_key_type)newid, (ur_map_value_type)tc);
ur_map_put(a->tcp_connections, (ur_map_key_type)newid, (ur_map_value_type)tc);
}
tcp_connection *create_tcp_connection(uint8_t server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr,
int *err_code) {
tcp_connection_list *tcl = &(a->tcs);
if (!tcl) {
return NULL;
}
if (tcl->elems) {
size_t i;
for (i = 0; i < tcl->sz; ++i) {
for (size_t i = 0; i < tcl->sz; ++i) {
tcp_connection *otc = tcl->elems[i];
if (otc) {
if (addr_eq(&(otc->peer_addr), peer_addr)) {
@ -579,21 +572,24 @@ tcp_connection *create_tcp_connection(uint8_t server_id, allocation *a, stun_tid
}
}
}
tcp_connection *tc = (tcp_connection *)calloc(1, sizeof(tcp_connection));
if (!tc) {
return NULL;
}
addr_cpy(&(tc->peer_addr), peer_addr);
if (tid) {
memcpy(&(tc->tid), tid, sizeof(stun_tid));
}
tc->owner = a;
int found = 0;
bool found = false;
if (a->tcs.elems) {
size_t i;
for (i = 0; i < tcl->sz; ++i) {
for (size_t i = 0; i < tcl->sz; ++i) {
tcp_connection *otc = tcl->elems[i];
if (!otc) {
tcl->elems[i] = tc;
found = 1;
found = true;
break;
}
}
@ -601,7 +597,11 @@ tcp_connection *create_tcp_connection(uint8_t server_id, allocation *a, stun_tid
if (!found) {
size_t old_sz_mem = a->tcs.sz * sizeof(tcp_connection *);
a->tcs.elems = (tcp_connection **)realloc(a->tcs.elems, old_sz_mem + sizeof(tcp_connection *));
tcp_connection **new_elems = realloc(a->tcs.elems, old_sz_mem + sizeof(tcp_connection *));
if (!new_elems) {
return NULL;
}
a->tcs.elems = new_elems;
a->tcs.elems[a->tcs.sz] = tc;
a->tcs.sz += 1;
tcl = &(a->tcs);
@ -612,38 +612,39 @@ tcp_connection *create_tcp_connection(uint8_t server_id, allocation *a, stun_tid
}
void delete_tcp_connection(tcp_connection *tc) {
if (tc) {
if (tc->done) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: check on already closed tcp data connection: %p\n", __FUNCTION__, tc);
return;
if (!tc) {
return;
}
if (tc->done) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s: check on already closed tcp data connection: %p\n", __FUNCTION__, tc);
return;
}
tc->done = true;
clear_unsent_buffer(&(tc->ub_to_client));
IOA_EVENT_DEL(tc->peer_conn_timeout);
IOA_EVENT_DEL(tc->conn_bind_timeout);
allocation *a = (allocation *)(tc->owner);
if (a) {
ur_map *map = a->tcp_connections;
if (map) {
ur_map_del(map, (ur_map_key_type)(tc->id), NULL);
}
tc->done = 1;
clear_unsent_buffer(&(tc->ub_to_client));
IOA_EVENT_DEL(tc->peer_conn_timeout);
IOA_EVENT_DEL(tc->conn_bind_timeout);
allocation *a = (allocation *)(tc->owner);
if (a) {
ur_map *map = a->tcp_connections;
if (map) {
ur_map_del(map, (ur_map_key_type)(tc->id), NULL);
}
tcp_connection_list *tcl = &(a->tcs);
if (tcl->elems) {
size_t i;
for (i = 0; i < tcl->sz; ++i) {
if (tcl->elems[i] == tc) {
tcl->elems[i] = NULL;
break;
}
tcp_connection_list *tcl = &(a->tcs);
if (tcl->elems) {
for (size_t i = 0; i < tcl->sz; ++i) {
if (tcl->elems[i] == tc) {
tcl->elems[i] = NULL;
break;
}
}
}
IOA_CLOSE_SOCKET(tc->client_s);
IOA_CLOSE_SOCKET(tc->peer_s);
free(tc);
}
IOA_CLOSE_SOCKET(tc->client_s);
IOA_CLOSE_SOCKET(tc->peer_s);
free(tc);
}
tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id) {
@ -671,9 +672,7 @@ tcp_connection *get_tcp_connection_by_peer(allocation *a, ioa_addr *peer_addr) {
if (a && peer_addr) {
tcp_connection_list *tcl = &(a->tcs);
if (tcl->elems) {
size_t i;
size_t sz = tcl->sz;
for (i = 0; i < sz; ++i) {
for (size_t i = 0; i < tcl->sz; ++i) {
tcp_connection *tc = tcl->elems[i];
if (tc) {
if (addr_eq(&(tc->peer_addr), peer_addr)) {
@ -686,16 +685,16 @@ tcp_connection *get_tcp_connection_by_peer(allocation *a, ioa_addr *peer_addr) {
return NULL;
}
int can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int server_relay) {
bool can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int server_relay) {
if (server_relay) {
return 1;
return true;
}
if (a && peer_addr) {
return (get_from_turn_permission_hashtable(&(a->addr_to_perm), peer_addr) != NULL);
return get_from_turn_permission_hashtable(&(a->addr_to_perm), peer_addr) != NULL;
}
return 0;
return false;
}
//////////////// Unsent buffers //////////////////////
@ -703,8 +702,7 @@ int can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int
void clear_unsent_buffer(unsent_buffer *ub) {
if (ub) {
if (ub->bufs) {
size_t sz;
for (sz = 0; sz < ub->sz; sz++) {
for (size_t sz = 0; sz < ub->sz; sz++) {
ioa_network_buffer_handle nbh = ub->bufs[sz];
if (nbh) {
ioa_network_buffer_delete(NULL, nbh);
@ -731,8 +729,7 @@ void add_unsent_buffer(unsent_buffer *ub, ioa_network_buffer_handle nbh) {
ioa_network_buffer_handle top_unsent_buffer(unsent_buffer *ub) {
ioa_network_buffer_handle ret = NULL;
if (ub && ub->bufs && ub->sz) {
size_t sz;
for (sz = 0; sz < ub->sz; ++sz) {
for (size_t sz = 0; sz < ub->sz; ++sz) {
if (ub->bufs[sz]) {
ret = ub->bufs[sz];
break;
@ -744,8 +741,7 @@ ioa_network_buffer_handle top_unsent_buffer(unsent_buffer *ub) {
void pop_unsent_buffer(unsent_buffer *ub) {
if (ub && ub->bufs && ub->sz) {
size_t sz;
for (sz = 0; sz < ub->sz; ++sz) {
for (size_t sz = 0; sz < ub->sz; ++sz) {
if (ub->bufs[sz]) {
ub->bufs[sz] = NULL;
break;

View File

@ -37,6 +37,8 @@
#include "ns_turn_maps.h"
#include "ns_turn_msg.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -92,7 +94,7 @@ struct _tcp_connection {
ioa_timer_handle conn_bind_timeout;
stun_tid tid;
void *owner; // a
int done;
bool done;
unsent_buffer ub_to_client;
};
@ -108,7 +110,7 @@ typedef struct _tcp_connection_list {
typedef struct _ch_info {
uint16_t chnum;
int allocated;
bool allocated;
uint16_t port;
ioa_addr peer_addr;
turn_time_t expiration_time;
@ -137,24 +139,15 @@ void ch_map_clean(ch_map *map);
////////////////////////////
// Signal change to add rtt metrics
typedef struct _turn_ice_ping_info {
stun_tid tid;
struct timespec ts;
int lastrttus;
} turn_ice_ping_info;
typedef struct _turn_permission_info {
int allocated;
bool allocated;
lm_map chns;
ioa_addr addr;
turn_time_t expiration_time;
ioa_timer_handle lifetime_ev;
void *owner; // a
int verbose;
bool verbose;
unsigned long long session_id;
// Signal change to add rtt metrics
turn_ice_ping_info pings[2]; // 0 measuring round trip to peer, 1 measuring round trip to client
} turn_permission_info;
typedef struct _turn_permission_slot {
@ -180,7 +173,7 @@ typedef struct _turn_permission_hashtable {
#define ALLOC_INDEX_ADDR(addr) ALLOC_INDEX(((addr)->ss).sa_family)
typedef struct _allocation {
int is_valid;
bool is_valid;
stun_tid tid;
turn_permission_hashtable addr_to_perm;
relay_endpoint_session relay_sessions[ALLOC_PROTOCOLS_NUMBER];
@ -201,13 +194,13 @@ void turn_channel_delete(ch_info *chn);
/////////// ALLOCATION ////////////
void init_allocation(void *owner, allocation *a, ur_map *tcp_connections);
void clear_allocation(allocation *a, SOCKET_TYPE socket_type, int family);
void clear_allocation(allocation *a, SOCKET_TYPE socket_type);
void turn_permission_clean(turn_permission_info *tinfo);
void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev, int family);
int is_allocation_valid(const allocation *a);
void set_allocation_valid(allocation *a, int value);
bool is_allocation_valid(const allocation *a);
void set_allocation_valid(allocation *a, bool value);
turn_permission_info *allocation_get_permission(allocation *a, const ioa_addr *addr);
turn_permission_hashtable *allocation_get_turn_permission_hashtable(allocation *a);
turn_permission_info *allocation_add_permission(allocation *a, const ioa_addr *addr);
@ -225,7 +218,7 @@ void set_allocation_family_invalid(allocation *a, int family);
tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_id id);
tcp_connection *get_tcp_connection_by_id(ur_map *map, tcp_connection_id id);
tcp_connection *get_tcp_connection_by_peer(allocation *a, ioa_addr *peer_addr);
int can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int server_relay);
bool can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int server_relay);
tcp_connection *create_tcp_connection(uint8_t server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr,
int *err_code);
void delete_tcp_connection(tcp_connection *tc);

View File

@ -219,7 +219,7 @@ typedef enum _STUN_PROMETHEUS_METRIC_TYPE STUN_PROMETHEUS_METRIC_TYPE;
void stun_report_binding(void *session, STUN_PROMETHEUS_METRIC_TYPE type);
void turn_report_allocation_set(void *a, turn_time_t lifetime, int refresh);
void turn_report_allocation_delete(void *a, SOCKET_TYPE socket_type, int family);
void turn_report_allocation_delete(void *a, SOCKET_TYPE socket_type);
void turn_report_session_usage(void *session, int force_invalid);
/*
@ -275,9 +275,6 @@ int is_stream_socket(int st);
int is_tcp_socket(int st);
int is_sctp_socket(int st);
const char *socket_type_name(SOCKET_TYPE st);
const char *duration_name(unsigned long duration);
const char *rate_name(unsigned long rate_kbps);
const char *addr_family_name(int family);
const char *get_ioa_socket_cipher(ioa_socket_handle s);
const char *get_ioa_socket_ssl_method(ioa_socket_handle s);
SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s);

View File

@ -31,8 +31,6 @@
#include "ns_turn_server.h"
#include "../apps/relay/ns_ioalib_impl.h"
// Signal change to add rtt metrics
#include "../apps/relay/prom_server.h"
#include "ns_turn_allocation.h"
#include "ns_turn_ioalib.h"
#include "ns_turn_msg_defs.h" // for STUN_ATTRIBUTE_NONCE
@ -77,13 +75,23 @@ static inline int get_family(int stun_family, ioa_engine_handle e, ioa_socket_ha
////////////////////////////////////////////////
const char *get_version(turn_turnserver *server) {
if (server && !*server->no_software_attribute) {
if (server && server->software_attribute) {
return (const char *)TURN_SOFTWARE;
} else {
return (const char *)"None";
}
}
static void maybe_add_software_attribute(turn_turnserver *server, ioa_network_buffer_handle nbh) {
if (server->software_attribute) {
const char *software = get_version(server);
size_t fsz = strlen(get_version(server));
size_t len = ioa_network_buffer_get_size(nbh);
stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, (const uint8_t *)software, fsz);
ioa_network_buffer_set_size(nbh, len);
}
}
#define MAX_NUMBER_OF_UNKNOWN_ATTRS (128)
int TURN_MAX_ALLOCATE_TIMEOUT = 60;
@ -187,8 +195,6 @@ static int inc_quota(ts_ur_super_session *ss, uint8_t *username) {
} else {
STRCPY(ss->username, username);
// Signal change to add protocol-group label to metrics
set_protocolgroup(ss);
ss->quota_used = 1;
}
@ -368,15 +374,6 @@ static int good_peer_addr(turn_turnserver *server, const char *realm, ioa_addr *
allocation *get_allocation_ss(ts_ur_super_session *ss) { return &(ss->alloc); }
void set_protocolgroup(ts_ur_super_session *ss) {
char *group = strrchr((char *)ss->username, '#');
if (group != NULL) {
strncpy(ss->protocolgroup, group, MAX_PROTOCOL_GROUP_SIZE);
} else {
strncpy(ss->protocolgroup, DEFAULT_PROTOCOL_GROUP, MAX_PROTOCOL_GROUP_SIZE);
}
}
static inline relay_endpoint_session *get_relay_session_ss(ts_ur_super_session *ss, int family) {
return get_relay_session(&(ss->alloc), family);
}
@ -816,12 +813,12 @@ static ts_ur_super_session *create_new_ss(turn_turnserver *server) {
return ss;
}
static void delete_ur_map_ss(void *p, SOCKET_TYPE socket_type, int family) {
static void delete_ur_map_ss(void *p, SOCKET_TYPE socket_type) {
if (p) {
ts_ur_super_session *ss = (ts_ur_super_session *)p;
delete_session_from_map(ss);
IOA_CLOSE_SOCKET(ss->client_socket);
clear_allocation(get_allocation_ss(ss), socket_type, family);
clear_allocation(get_allocation_ss(ss), socket_type);
IOA_EVENT_DEL(ss->to_be_allocated_timeout_ev);
free(p);
}
@ -829,8 +826,7 @@ static void delete_ur_map_ss(void *p, SOCKET_TYPE socket_type, int family) {
/////////// clean all /////////////////////
// Signal change to add address family label
static int turn_server_remove_all_from_ur_map_ss(ts_ur_super_session *ss, SOCKET_TYPE socket_type, int family) {
static int turn_server_remove_all_from_ur_map_ss(ts_ur_super_session *ss, SOCKET_TYPE socket_type) {
if (!ss) {
return 0;
} else {
@ -844,7 +840,7 @@ static int turn_server_remove_all_from_ur_map_ss(ts_ur_super_session *ss, SOCKET
if (get_relay_socket_ss(ss, AF_INET6)) {
clear_ioa_socket_session_if(get_relay_socket_ss(ss, AF_INET6), ss);
}
delete_ur_map_ss(ss, socket_type, family);
delete_ur_map_ss(ss, socket_type);
return ret;
}
}
@ -1302,6 +1298,13 @@ static int handle_turn_allocate(turn_turnserver *server, ts_ur_super_session *ss
}
}
if (server->is_draining) {
// Don't allow new allocations if we are draining
*err_code = 403; // 403 (Forbidden): RFC8656 - The request is valid, but the server is refusing to perform it,
// likely due to administrative restrictions....
*reason = (const uint8_t *)"Server is draining, then will shutdown, please try another server";
}
if (!(*err_code)) {
if (!af4 && !af6) {
switch (server->allocation_default_address_family) {
@ -1479,10 +1482,6 @@ static int handle_turn_allocate(turn_turnserver *server, ts_ur_super_session *ss
}
}
// Signal change to add metrics
#if !defined(TURN_NO_PROMETHEUS)
prom_inc_allocation_response(*err_code);
#endif
return 0;
}
@ -1493,8 +1492,6 @@ static void copy_auth_parameters(ts_ur_super_session *orig_ss, ts_ur_super_sessi
ss->nonce_expiration_time = orig_ss->nonce_expiration_time;
memcpy(&(ss->realm_options), &(orig_ss->realm_options), sizeof(ss->realm_options));
memcpy(ss->username, orig_ss->username, sizeof(ss->username));
// Signal change to add protocol-group label to metrics
memcpy(ss->protocolgroup, orig_ss->protocolgroup, sizeof(ss->protocolgroup));
ss->hmackey_set = orig_ss->hmackey_set;
memcpy(ss->hmackey, orig_ss->hmackey, sizeof(ss->hmackey));
ss->oauth = orig_ss->oauth;
@ -1781,13 +1778,7 @@ static int handle_turn_refresh(turn_turnserver *server, ts_ur_super_session *ss,
(uint8_t *)ss->s_mobile_id, strlen(ss->s_mobile_id));
ioa_network_buffer_set_size(nbh, len);
if (!(*server->no_software_attribute)) {
const uint8_t *field = (const uint8_t *)get_version(server);
size_t fsz = strlen(get_version(server));
size_t len = ioa_network_buffer_get_size(nbh);
stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
ioa_network_buffer_set_size(nbh, len);
}
maybe_add_software_attribute(server, nbh);
if (message_integrity) {
size_t len = ioa_network_buffer_get_size(nbh);
@ -2265,13 +2256,7 @@ static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg) {
ioa_network_buffer_set_size(nbh, len);
if (!(*server->no_software_attribute)) {
const uint8_t *field = (const uint8_t *)get_version(server);
size_t fsz = strlen(get_version(server));
size_t len = ioa_network_buffer_get_size(nbh);
stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
ioa_network_buffer_set_size(nbh, len);
}
maybe_add_software_attribute(server, nbh);
if ((server->fingerprint) || ss->enforce_fingerprints) {
size_t len = ioa_network_buffer_get_size(nbh);
@ -2543,13 +2528,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co
}
}
if (!(*server->no_software_attribute)) {
size_t fsz = strlen(get_version(server));
const uint8_t *field = (const uint8_t *)get_version(server);
size_t len = ioa_network_buffer_get_size(nbh);
stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
ioa_network_buffer_set_size(nbh, len);
}
maybe_add_software_attribute(server, nbh);
if (message_integrity && ss) {
size_t len = ioa_network_buffer_get_size(nbh);
@ -2957,106 +2936,6 @@ static int handle_turn_binding(turn_turnserver *server, ts_ur_super_session *ss,
return 0;
}
// Signal change to add metrics
/////////////// inspect relayed packets, they might be ICE binds ///////////////
static int inspect_binds(ts_ur_super_session *ss, turn_turnserver *server, ioa_net_data *in_buffer,
turn_permission_info *tinfo, int from_peer, int is_channel) {
if (!in_buffer || !tinfo || !(from_peer == 0 || from_peer == 1)) {
return 0;
}
size_t len = ioa_network_buffer_get_size(in_buffer->nbh);
uint8_t *buf = ioa_network_buffer_data(in_buffer->nbh);
if (stun_is_command_message_str(buf, len) && (stun_get_method_str(buf, len) == STUN_METHOD_BINDING)) {
if (stun_is_request_str(buf, len)) {
stun_tid tid;
stun_tid_from_message_str(buf, len, &tid);
// only process if this is the first received request
if (!stun_tid_equals(&tid, &tinfo->pings[from_peer].tid)) {
stun_tid_cpy(&tinfo->pings[from_peer].tid, &tid);
clock_gettime(CLOCK_MONOTONIC, &tinfo->pings[from_peer].ts);
}
} else if (stun_is_response_str(buf, len)) {
// invert from_peer, because we're processing replies
int from_client;
if (from_peer) {
from_client = 0;
} else {
from_client = 1;
}
if (tinfo->pings[from_client].ts.tv_sec == 0) {
return 0;
}
stun_tid tid;
stun_tid_from_message_str(buf, len, &tid);
if (stun_tid_equals(&tid, &tinfo->pings[from_client].tid)) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
if (now.tv_sec >= tinfo->pings[from_client].ts.tv_sec &&
now.tv_sec <= tinfo->pings[from_client].ts.tv_sec + 60) {
int diffus = (now.tv_sec - tinfo->pings[from_client].ts.tv_sec) * 1000000;
diffus += (now.tv_nsec - tinfo->pings[from_client].ts.tv_nsec) / 1000;
if (diffus > 0) {
tinfo->pings[from_client].lastrttus = diffus;
#if !defined(TURN_NO_PROMETHEUS)
if (is_channel) {
if (from_client) {
prom_observe_rtt_client(diffus, ss->protocolgroup);
} else {
prom_observe_rtt_peer(diffus, ss->protocolgroup);
}
if (tinfo->pings[from_peer].lastrttus > 0) {
prom_observe_rtt_combined(diffus + tinfo->pings[from_peer].lastrttus, ss->protocolgroup);
}
}
#endif
ur_map_key_type key = 0;
// add one to value to differentiate from zero
ur_map_value_type diffms = diffus / 1000 + 1;
if (in_buffer->src_addr.ss.sa_family == AF_INET) {
key = ntohl(((struct sockaddr_in *)&in_buffer->src_addr)->sin_addr.s_addr);
key >>= 8; // keep only the top 24 bits
} else if (in_buffer->src_addr.ss.sa_family == AF_INET6) {
// use the high 6 bytes (48 bits)
for (int i = 0; i < 6; ++i) {
key <<= 8;
key |= ((struct sockaddr_in6 *)&in_buffer->src_addr)->sin6_addr.s6_addr[i];
}
key |= (1L << 63);
}
// explicitly copy map pointer in case of concurrent access
ur_map *map = server->rtt_ms_mins;
ur_map_lock(map);
ur_map_value_type value = 0;
ur_map_get(map, key, &value);
if (value == 0 || diffms < value) {
ur_map_put(map, key, diffms);
}
ur_map_unlock(map);
}
}
// don't process retransmited responses
tinfo->pings[from_client].ts.tv_sec = 0;
}
}
} else {
if (tinfo->pings[0].lastrttus == 0 && tinfo->pings[1].lastrttus == 0) {
return 1;
}
}
return 0;
}
static int handle_turn_send(turn_turnserver *server, ts_ur_super_session *ss, int *err_code, const uint8_t **reason,
uint16_t *unknown_attrs, uint16_t *ua_num, ioa_net_data *in_buffer) {
@ -3142,11 +3021,6 @@ static int handle_turn_send(turn_turnserver *server, ts_ur_super_session *ss, in
len = 0;
ioa_network_buffer_set_size(nbh, len);
}
// Signal change to add rtt metrics
if (inspect_binds(ss, server, in_buffer, tinfo, 0, 0)) {
++(ss->t_before_ping_packets);
}
ioa_network_buffer_header_init(nbh);
int skip = 0;
send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss, peer_addr.ss.sa_family), &peer_addr, nbh,
@ -3314,11 +3188,6 @@ static int handle_turn_create_permission(turn_turnserver *server, ts_ur_super_se
}
}
// Signal change to add metrics
#if !defined(TURN_NO_PROMETHEUS)
prom_inc_create_permission_response(*err_code);
#endif
return ret;
}
@ -3541,8 +3410,6 @@ static int check_stun_auth(turn_turnserver *server, ts_ur_super_session *ss, stu
if (ss->oauth) {
ss->hmackey_set = 0;
STRCPY(ss->username, usname);
// Signal change to add protocol-group label to metrics
set_protocolgroup(ss);
} else {
if (method == STUN_METHOD_ALLOCATE) {
*err_code = 437;
@ -3555,8 +3422,6 @@ static int check_stun_auth(turn_turnserver *server, ts_ur_super_session *ss, stu
}
} else {
STRCPY(ss->username, usname);
// Signal change to add protocol-group label to metrics
set_protocolgroup(ss);
}
{
@ -3941,13 +3806,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss,
(unsigned long long)(ss->id));
}
if (!(*server->no_software_attribute)) {
const uint8_t *field = (const uint8_t *)get_version(server);
size_t fsz = strlen(get_version(server));
size_t len = ioa_network_buffer_get_size(nbh);
stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
ioa_network_buffer_set_size(nbh, len);
}
maybe_add_software_attribute(server, nbh);
send_turn_message_to(server, nbh, &response_origin, &response_destination);
stun_report_binding(ss, STUN_PROMETHEUS_METRIC_TYPE_RESPONSE);
@ -4047,13 +3906,7 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss,
*resp_constructed = 1;
}
if (!(*server->no_software_attribute)) {
const uint8_t *field = (const uint8_t *)get_version(server);
size_t fsz = strlen(get_version(server));
size_t len = ioa_network_buffer_get_size(nbh);
stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
ioa_network_buffer_set_size(nbh, len);
}
maybe_add_software_attribute(server, nbh);
if (message_integrity) {
size_t len = ioa_network_buffer_get_size(nbh);
@ -4229,13 +4082,6 @@ static int write_to_peerchannel(ts_ur_super_session *ss, uint16_t chnum, ioa_net
ioa_network_buffer_add_offset_size(in_buffer->nbh, STUN_CHANNEL_HEADER_LENGTH, 0,
ioa_network_buffer_get_size(in_buffer->nbh) - STUN_CHANNEL_HEADER_LENGTH);
// Signal change to add rtt metrics
turn_turnserver *server = (turn_turnserver *)ss->server;
turn_permission_info *tinfo = (turn_permission_info *)(chn->owner);
if (inspect_binds(ss, server, in_buffer, tinfo, 0, 1)) {
++(ss->t_before_ping_packets);
}
ioa_network_buffer_header_init(nbh);
int skip = 0;
@ -4258,32 +4104,17 @@ 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;
#if !defined(TURN_NO_PROMETHEUS)
prom_set_session_limit(session_limit);
#endif
TURN_MUTEX_UNLOCK(&session_limit_mutex);
}
if (!ss) {
return -1;
}
SOCKET_TYPE socket_type = get_ioa_socket_type(ss->client_socket);
int family = get_ioa_socket_address_family(ss->client_socket);
turn_report_session_usage(ss, 1);
dec_quota(ss);
@ -4348,7 +4179,7 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss,
}
}
turn_server_remove_all_from_ur_map_ss(ss, socket_type, family);
turn_server_remove_all_from_ur_map_ss(ss, socket_type);
FUNCEND;
@ -4458,7 +4289,7 @@ static void client_ss_allocation_timeout_handler(ioa_engine_handle e, void *arg)
turn_turnserver *server = (turn_turnserver *)(ss->server);
if (!server) {
clear_allocation(a, get_ioa_socket_type(ss->client_socket), get_ioa_socket_address_family(ss->client_socket));
clear_allocation(a, get_ioa_socket_type(ss->client_socket));
return;
}
@ -4871,23 +4702,6 @@ int open_client_connection_session(turn_turnserver *server, struct socket_messag
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);
#if !defined(TURN_NO_PROMETHEUS)
prom_inc_sessions_overlimit();
#endif
return -1;
}
--session_limit;
#if !defined(TURN_NO_PROMETHEUS)
prom_set_session_limit(session_limit);
#endif
TURN_MUTEX_UNLOCK(&session_limit_mutex);
}
ts_ur_super_session *ss = create_new_ss(server);
ss->client_socket = sm->s;
@ -4986,10 +4800,6 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_data
turn_permission_info *tinfo = allocation_get_permission(a, &(in_buffer->src_addr));
if (tinfo) {
chnum = get_turn_channel_number(tinfo, &(in_buffer->src_addr));
// Signal change to add rtt metrics
if (inspect_binds(ss, server, in_buffer, tinfo, 1, chnum != 0)) {
++(ss->t_before_ping_packets);
}
} else if (!(server->server_relay)) {
return;
}
@ -5025,13 +4835,7 @@ static void peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_data
stun_attr_add_addr_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &(in_buffer->src_addr));
ioa_network_buffer_set_size(nbh, len);
if (!(*server->no_software_attribute)) {
const uint8_t *field = (const uint8_t *)get_version(server);
size_t fsz = strlen(get_version(server));
size_t len = ioa_network_buffer_get_size(nbh);
stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
ioa_network_buffer_set_size(nbh, len);
}
maybe_add_software_attribute(server, nbh);
if ((server->fingerprint) || ss->enforce_fingerprints) {
size_t len = ioa_network_buffer_get_size(nbh);
@ -5082,11 +4886,11 @@ static void client_input_handler(ioa_socket_handle s, int event_type, ioa_net_da
///////////////////////////////////////////////////////////
void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, ioa_engine_handle e,
turn_credential_type ct, int stun_port, int fingerprint, dont_fragment_option_t dont_fragment,
turn_credential_type ct, int fingerprint, dont_fragment_option_t dont_fragment,
get_user_key_cb userkeycb, check_new_allocation_quota_cb chquotacb,
release_allocation_quota_cb raqcb, ioa_addr *external_ip, vintp check_origin, vintp no_tcp_relay,
vintp no_udp_relay, vintp stale_nonce, vintp max_allocate_lifetime, vintp channel_lifetime,
vintp permission_lifetime, vintp stun_only, vintp no_stun, vintp no_software_attribute,
vintp permission_lifetime, vintp stun_only, vintp no_stun, bool software_attribute,
vintp web_admin_listen_on_workers, turn_server_addrs_list_t *alternate_servers_list,
turn_server_addrs_list_t *tls_alternate_servers_list, turn_server_addrs_list_t *aux_servers_list,
int self_udp_balance, vintp no_multicast_peers, vintp allow_loopback_peers,
@ -5096,25 +4900,12 @@ 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,
// Signal change to add session limit
int configured_session_limit) {
vintp respond_http_unsupported) {
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;
@ -5160,7 +4951,7 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io
server->permission_lifetime = permission_lifetime;
server->stun_only = stun_only;
server->no_stun = no_stun;
server->no_software_attribute = no_software_attribute;
server->software_attribute = software_attribute;
server->web_admin_listen_on_workers = web_admin_listen_on_workers;
server->dont_fragment = dont_fragment;
@ -5169,9 +4960,6 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io
addr_cpy(&(server->external_ip), external_ip);
server->external_ip_set = 1;
}
if (stun_port < 1) {
stun_port = DEFAULT_STUN_PORT;
}
server->verbose = verbose;
@ -5194,8 +4982,7 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io
server->respond_http_unsupported = respond_http_unsupported;
// Signal change to add rtt metrics
server->rtt_ms_mins = ur_map_create();
server->is_draining = false;
}
ioa_engine_handle turn_server_get_engine(turn_turnserver *s) {

View File

@ -72,15 +72,7 @@ extern int TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY;
typedef uint8_t turnserver_id;
// Signal change to add rtt metrics
enum _MESSAGE_TO_RELAY_TYPE {
RMT_UNKNOWN = 0,
RMT_SOCKET,
RMT_CB_SOCKET,
RMT_MOBILE_SOCKET,
RMT_CANCEL_SESSION,
RMT_CYCLE_RTT_MAP
};
enum _MESSAGE_TO_RELAY_TYPE { RMT_UNKNOWN = 0, RMT_SOCKET, RMT_CB_SOCKET, RMT_MOBILE_SOCKET, RMT_CANCEL_SESSION };
typedef enum _MESSAGE_TO_RELAY_TYPE MESSAGE_TO_RELAY_TYPE;
///////// ALLOCATION DEFAULT ADDRESS FAMILY TYPES /////////////////////
@ -142,7 +134,7 @@ struct _turn_turnserver {
vintp permission_lifetime;
vintp stun_only;
vintp no_stun;
vintp no_software_attribute;
bool software_attribute;
vintp web_admin_listen_on_workers;
vintp secure_stun;
turn_credential_type ct;
@ -212,9 +204,8 @@ struct _turn_turnserver {
otherwise handling HTTP. */
vintp respond_http_unsupported;
// Signal change to add rtt metrics
/* measured round trip minimums per network */
ur_map *rtt_ms_mins;
/* Set to true on SIGUSR1 */
bool is_draining;
};
const char *get_version(turn_turnserver *server);
@ -222,11 +213,11 @@ const char *get_version(turn_turnserver *server);
///////////////////////////////////////////
void init_turn_server(
turn_turnserver *server, turnserver_id id, int verbose, ioa_engine_handle e, turn_credential_type ct, int stun_port,
turn_turnserver *server, turnserver_id id, int verbose, ioa_engine_handle e, turn_credential_type ct,
int fingerprint, dont_fragment_option_t dont_fragment, get_user_key_cb userkeycb,
check_new_allocation_quota_cb chquotacb, release_allocation_quota_cb raqcb, ioa_addr *external_addr,
vintp check_origin, vintp no_tcp_relay, vintp no_udp_relay, vintp stale_nonce, vintp max_allocate_lifetime,
vintp channel_lifetime, vintp permission_lifetime, vintp stun_only, vintp no_stun, vintp no_software_attribute,
vintp channel_lifetime, vintp permission_lifetime, vintp stun_only, vintp no_stun, bool software_attribute,
vintp web_admin_listen_on_workers, turn_server_addrs_list_t *alternate_servers_list,
turn_server_addrs_list_t *tls_alternate_servers_list, turn_server_addrs_list_t *aux_servers_list,
int self_udp_balance, vintp no_multicast_peers, vintp allow_loopback_peers, ip_range_list_t *ip_whitelist,
@ -234,9 +225,7 @@ 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,
// Signal change to add session limit
int configured_session_limit);
vintp no_stun_backward_compatibility, vintp response_origin_only_with_rfc5780, vintp respond_http_unsupported);
ioa_engine_handle turn_server_get_engine(turn_turnserver *s);

View File

@ -119,10 +119,6 @@ struct _ts_ur_super_session {
char s_mobile_id[33];
/* Bandwidth */
band_limit_t bps;
// Signal change to add metrics
uint64_t t_before_ping_packets;
// Signal change to add protocol-group label to metrics
char protocolgroup[MAX_PROTOCOL_GROUP_SIZE + 1];
};
////// Session info for statistics //////
@ -188,9 +184,6 @@ int turn_session_info_copy_from(struct turn_session_info *tsi, ts_ur_super_sessi
allocation *get_allocation_ss(ts_ur_super_session *ss);
// Signal change to add protocol-group label to metrics
void set_protocolgroup(ts_ur_super_session *ss);
///////////////////////////////////////////////////////
#ifdef __cplusplus

View File

@ -1,6 +1,6 @@
{
"name": "coturn",
"version-string": "4.6.2",
"version-string": "4.6.3",
"dependencies": [
{
"name": "pthreads",