Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ set(COMMON_SOURCES
src/rtp2httpd.c
src/supervisor.c
src/configuration.c
src/access_log.c
src/http.c
src/http_fetch.c
src/service.c
Expand Down
2 changes: 2 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default defineConfig({
{ text: "FCC 快速换台配置", link: "/guide/fcc-setup" },
{ text: "公网访问建议", link: "/guide/public-access" },
{ text: "时间处理说明", link: "/guide/time-processing" },
{ text: "访问日志", link: "/guide/access-log" },
{ text: "视频快照配置", link: "/guide/video-snapshot" },
],
},
Expand Down Expand Up @@ -126,6 +127,7 @@ export default defineConfig({
{ text: "Fast Channel Change", link: "/en/guide/fcc-setup" },
{ text: "Public Access", link: "/en/guide/public-access" },
{ text: "Time Processing", link: "/en/guide/time-processing" },
{ text: "Access Logging", link: "/en/guide/access-log" },
{ text: "Video Snapshot", link: "/en/guide/video-snapshot" },
],
},
Expand Down
100 changes: 100 additions & 0 deletions docs/en/guide/access-log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Access Logging

rtp2httpd can write access logs for media requests. This is useful for auditing which channels clients access, identifying client sources behind a reverse proxy, and integrating with external logging systems.

## Enabling Access Logging

Access logging is disabled by default. Logs are written only after `access_log` is configured.

### Configuration File

```ini
[global]
access_log = /var/log/rtp2httpd/access.log
log_format = $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"
```

### Command Line

```bash
rtp2httpd --access-log /var/log/rtp2httpd/access.log \
--log-format '$client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"'
```

The OpenWrt LuCI page also supports configuring the access log path and format.

## Default Format

When `log_format` is unset or empty, this default format is used:

```text
$client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"
```

Example output:

```text
192.0.2.10:53124 [2026-06-25T20:10:12+08:00] "/CCTV-1" rtp "rtp://239.0.0.1:1234"
```

## Placeholders

`log_format` uses nginx-style `$variable` placeholders. The following placeholders are supported:

| Placeholder | Description |
| --- | --- |
| `$time_iso8601` | Local time in ISO 8601 format, for example `2026-06-25T20:10:12+08:00` |
| `$time_local` | Local time in nginx-style format, for example `25/Jun/2026:20:10:12 +0800` |
| `$msec` | Unix timestamp with millisecond precision, for example `1782389412.123` |
| `$client_addr` | Client address shown on the status page |
| `$remote_addr` | Client IP or address parsed from `$client_addr` |
| `$remote_port` | Client port parsed from `$client_addr`; outputs `-` when no port is available |
| `$worker_pid` | PID of the worker process handling the request |
| `$request` | Request method and Service URL, for example `GET /rtp/239.0.0.1:1234` |
| `$request_method` | HTTP request method, for example `GET` |
| `$service_url` | Service URL requested by the client |
| `$host` | HTTP `Host` header |
| `$http_user_agent` | HTTP `User-Agent` header |
| `$http_x_forwarded_for` | HTTP `X-Forwarded-For` header |
| `$service_type` | Service type: `rtp`, `rtsp`, or `http` |
| `$upstream_url` | Actual upstream URL |
| `$$` | Outputs a literal `$` |

Unknown placeholders are output as-is. Empty values are output as `-`. Quotes, backslashes, newlines, and control characters in log values are escaped. Each log line is limited to 8192 bytes.

## Client Address and X-Forwarded-For

`$client_addr` matches the client address shown on the status page.

After `xff` is enabled, if the request's `X-Forwarded-For` header is accepted, `$client_addr` uses the first address from `X-Forwarded-For`. In that case there is usually no client port, so `$remote_port` outputs `-`.

## Token Hiding

If the request URL contains the `r2h-token` query parameter, `$service_url` in the access log does not include that parameter. `$http_user_agent` also hides `R2HTOKEN/...` fragments to avoid leaking tokens through access logs.

## Using logrotate

rtp2httpd workers keep the access log file open. After rotating logs, send `SIGHUP` to the supervisor process so workers reopen the log file.

Example logrotate config:

```text
/var/log/rtp2httpd/access.log {
daily
rotate 7
missingok
notifempty
compress
create 0644 root root
sharedscripts
postrotate
for pid in $(pidof rtp2httpd); do
ppid="$(awk '/^PPid:/ { print $2 }' "/proc/$pid/status" 2>/dev/null)"
[ "$(cat "/proc/$ppid/comm" 2>/dev/null)" = "rtp2httpd" ] && continue
kill -HUP "$pid" 2>/dev/null || true
done
endscript
}
```

This skips worker child processes whose parent process is also `rtp2httpd`, and sends `SIGHUP` only to the supervisor.
12 changes: 12 additions & 0 deletions docs/en/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ Unix socket listen paths must be absolute and must not contain whitespace. At st

- `-v, --verbose` - Logging verbosity (0=FATAL, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
- `-q, --quiet` - Show only fatal errors
- `--access-log <path>` - Write access logs to the specified file (default: disabled)
- `--log-format <format>` - Access log format using nginx-style `$variable` placeholders. See [Access Logging](/en/guide/access-log)

### Security Control

Expand Down Expand Up @@ -120,6 +122,13 @@ Configuration file path: `/etc/rtp2httpd.conf`. Lines starting with `#` or `;` a
# Logging verbosity: 0=FATAL 1=ERROR 2=WARN 3=INFO 4=DEBUG
verbosity = 3

# Access log file path (empty or unset means disabled)
access_log = /var/log/rtp2httpd/access.log

# Access log format (optional, nginx-style $variables)
# Default: $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"
log_format = $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"

# Maximum concurrent clients
maxclients = 20

Expand Down Expand Up @@ -273,6 +282,8 @@ rtp://239.253.64.120:5140
rtp://239.253.64.121:5140
```

For how to enable access logging, configure placeholders, and use logrotate, see [Access Logging](/en/guide/access-log).

## Runtime Configuration Management

rtp2httpd supports configuration hot reload: after editing the configuration file, trigger a reload via signal or the status page to apply changes without restarting the entire process. rtp2httpd uses a supervisor + worker multi-process architecture. Signals must be sent to the **supervisor process** (the main `rtp2httpd` process, not worker child processes).
Expand Down Expand Up @@ -300,6 +311,7 @@ kill -USR1 12345
- If `[bind]` listen addresses change, the supervisor sends `SIGTERM` to all workers and respawns them to apply the new listen addresses
- If the `workers` count changes, the supervisor automatically adds or removes worker processes
- For other configuration changes, the supervisor forwards `SIGHUP` to each worker, which applies them at runtime
- Workers reopen the [access log](/en/guide/access-log) file during reload, which helps with logrotate
- If the config file fails to parse, the old configuration is kept and existing connections are not interrupted

> [!NOTE]
Expand Down
100 changes: 100 additions & 0 deletions docs/guide/access-log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# 访问日志

rtp2httpd 可以为媒体请求写入访问日志,便于审计客户端访问了哪些频道、排查反向代理后的客户端来源,以及对接外部日志系统。

## 启用访问日志

访问日志默认关闭。只有配置 `access_log` 后才会写入日志。

### 配置文件

```ini
[global]
access_log = /var/log/rtp2httpd/access.log
log_format = $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"
```

### 命令行

```bash
rtp2httpd --access-log /var/log/rtp2httpd/access.log \
--log-format '$client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"'
```

OpenWrt LuCI 页面中也可以配置访问日志路径和格式。

## 默认格式

`log_format` 未配置或为空时,使用以下默认格式:

```text
$client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"
```

示例输出:

```text
192.0.2.10:53124 [2026-06-25T20:10:12+08:00] "/CCTV-1" rtp "rtp://239.0.0.1:1234"
```

## 占位符

`log_format` 使用类似 nginx 的 `$变量` 形式。支持的占位符如下:

| 占位符 | 说明 |
| --- | --- |
| `$time_iso8601` | 本地时间,ISO 8601 格式,例如 `2026-06-25T20:10:12+08:00` |
| `$time_local` | 本地时间,nginx 风格格式,例如 `25/Jun/2026:20:10:12 +0800` |
| `$msec` | Unix 时间戳,精确到毫秒,例如 `1782389412.123` |
| `$client_addr` | 状态页面显示的客户端地址 |
| `$remote_addr` | 从 `$client_addr` 拆出的客户端 IP 或地址 |
| `$remote_port` | 从 `$client_addr` 拆出的客户端端口;没有端口时输出 `-` |
| `$worker_pid` | 处理该请求的 worker 进程 PID |
| `$request` | 请求方法和 Service URL,例如 `GET /rtp/239.0.0.1:1234` |
| `$request_method` | HTTP 请求方法,例如 `GET` |
| `$service_url` | 客户端访问的 Service URL |
| `$host` | HTTP `Host` 头 |
| `$http_user_agent` | HTTP `User-Agent` 头 |
| `$http_x_forwarded_for` | HTTP `X-Forwarded-For` 头 |
| `$service_type` | 服务类型:`rtp`、`rtsp` 或 `http` |
| `$upstream_url` | 实际上游 URL |
| `$$` | 输出字面量 `$` |

未知占位符会按原样输出。空值会输出为 `-`。日志值中的引号、反斜杠、换行和控制字符会被转义,单行日志最长 8192 字节。

## 客户端地址与 X-Forwarded-For

`$client_addr` 与状态页面显示的客户端地址一致。

启用 `xff` 后,如果请求中的 `X-Forwarded-For` 被接受,`$client_addr` 会使用 `X-Forwarded-For` 中的第一个地址。这种情况下通常没有客户端端口,因此 `$remote_port` 会输出 `-`。

## 令牌隐藏

如果请求 URL 中包含 `r2h-token` 查询参数,访问日志中的 `$service_url` 不会包含该参数。`$http_user_agent` 也会隐藏 `R2HTOKEN/...` 片段,避免令牌通过访问日志泄露。

## 配合 logrotate

rtp2httpd worker 会保持访问日志文件打开。轮转日志后,需要向 supervisor 进程发送 `SIGHUP`,让 worker 重新打开日志文件。

logrotate 配置示例:

```text
/var/log/rtp2httpd/access.log {
daily
rotate 7
missingok
notifempty
compress
create 0644 root root
sharedscripts
postrotate
for pid in $(pidof rtp2httpd); do
ppid="$(awk '/^PPid:/ { print $2 }' "/proc/$pid/status" 2>/dev/null)"
[ "$(cat "/proc/$ppid/comm" 2>/dev/null)" = "rtp2httpd" ] && continue
kill -HUP "$pid" 2>/dev/null || true
done
endscript
}
```

这里会跳过父进程同样是 `rtp2httpd` 的 worker 子进程,只向 supervisor 发送 `SIGHUP`。
12 changes: 12 additions & 0 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ Unix socket 监听路径必须是绝对路径,且路径中不能包含空白

- `-v, --verbose` - 日志详细程度 (0=FATAL, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
- `-q, --quiet` - 仅显示致命错误
- `--access-log <路径>` - 将访问日志写入指定文件 (默认: 禁用)
- `--log-format <格式>` - 访问日志格式,使用类似 nginx 的 `$变量` 占位符,详见 [访问日志](../guide/access-log.md)

### 安全控制

Expand Down Expand Up @@ -120,6 +122,13 @@ Unix socket 监听路径必须是绝对路径,且路径中不能包含空白
# 日志详细程度: 0=FATAL 1=ERROR 2=WARN 3=INFO 4=DEBUG
verbosity = 3

# 访问日志文件路径(留空或不配置时禁用)
access_log = /var/log/rtp2httpd/access.log

# 访问日志格式(可选,nginx 风格 $变量)
# 默认: $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"
log_format = $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"

# 最大并发客户端数
maxclients = 20

Expand Down Expand Up @@ -272,6 +281,8 @@ rtp://239.253.64.120:5140
rtp://239.253.64.121:5140
```

访问日志的启用方式、格式占位符和 logrotate 配置见 [访问日志](../guide/access-log.md)。

## 运行时配置管理

rtp2httpd 支持配置热重载:修改配置文件后,通过发送信号或状态页面触发重载,即可应用变更,无需重启整个进程。rtp2httpd 采用 supervisor + worker 多进程架构,信号应发送给 **supervisor 进程**(即主 `rtp2httpd` 进程,而非 worker 子进程)。
Expand Down Expand Up @@ -299,6 +310,7 @@ kill -USR1 12345
- 若 `[bind]` 监听地址发生变化,supervisor 会向所有工作进程发送 `SIGTERM` 并重新拉起,以应用新的监听地址
- 若 `workers` 数量发生变化,supervisor 会自动增减工作进程
- 其他配置变更会转发 `SIGHUP` 给各工作进程,由工作进程在运行时应用
- 工作进程会在重载时重新打开 [访问日志](../guide/access-log.md) 文件,便于配合 logrotate
- 若配置文件解析失败,保留旧配置,不会中断现有连接

> [!NOTE]
Expand Down
Loading
Loading