Skip to content
Closed
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
19 changes: 18 additions & 1 deletion docs/en/guide/url-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ When `r2h-token` (HTTP request authentication token) is configured, all URLs mus
## Multicast RTP to HTTP Unicast Stream

```url
http://server:port/rtp/multicast_address:port[?fcc=FCC_server:port][&fcc-type=protocol_type][&fec=FEC_port]
http://server:port/rtp/multicast_address:port[?fcc=FCC_server:port][&fcc-type=protocol_type][&fec=FEC_port][&r2h-ifname=network_interface][&r2h-ifname-fcc=fcc_network_interface]
```

**Examples**:
Expand All @@ -22,6 +22,8 @@ http://192.168.1.1:5140/rtp/239.253.64.120:5140
http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970
http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:8027&fcc-type=huawei
http://192.168.1.1:5140/rtp/239.81.0.195:4056?fec=4055
http://192.168.1.1:5140/rtp/239.253.64.120:5140?r2h-ifname=eth1
http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970&r2h-ifname=eth0&r2h-ifname-fcc=eth1
```

### Parameters
Expand All @@ -33,13 +35,17 @@ http://192.168.1.1:5140/rtp/239.81.0.195:4056?fec=4055
- `telecom`: Telecom/ZTE/Fiberhome FCC protocol (default)
- `huawei`: Huawei FCC protocol
- **fec** (optional): FEC (Forward Error Correction) port number, used to receive FEC redundant packets for packet loss recovery
- **r2h-ifname** (optional): Specify the network interface name to receive multicast streams (e.g., `eth0`, `eth1`). Takes priority over the global `upstream-interface-multicast` configuration
- **r2h-ifname-fcc** (optional): Specify the network interface name for FCC. Only effective when using FCC, takes priority over the global `upstream-interface-fcc` configuration

### Use Cases

- Convert IPTV operator multicast streams to HTTP unicast streams
- Share IPTV streams across multiple devices on LAN
- Enable millisecond-level channel switching with FCC
- Improve playback stability with FEC packet loss recovery
- Use the `r2h-ifname` parameter to route different channels through different network interfaces (suitable for multi-NIC environments, such as receiving multicast streams from different operators on different interfaces)
- Use the `r2h-ifname-fcc` parameter to specify a separate network interface for FCC (separate multicast reception from FCC communication in multi-NIC environments)

## RTSP to HTTP

Expand All @@ -61,8 +67,15 @@ http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?tvdr=20240101120000GM

# Custom time-shift parameter name + time offset
http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?seek=20240101120000&r2h-seek-name=seek&r2h-seek-offset=3600

# Specify network interface
http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?r2h-ifname=eth1
```

### Parameters

- **r2h-ifname** (optional): Specify the network interface name for RTSP connections. Takes priority over the global `upstream-interface-rtsp` configuration

### Use Cases

- Convert IPTV RTSP unicast streams to HTTP streams
Expand Down Expand Up @@ -94,13 +107,17 @@ http://192.168.1.1:5140/http/upstream.example.com:8080/live/stream.m3u8

# Proxy HTTP request (port omitted, defaults to 80)
http://192.168.1.1:5140/http/api.example.com/video?auth=xxx&quality=hd

# Specify network interface
http://192.168.1.1:5140/http/upstream.example.com:8080/live/stream.m3u8?r2h-ifname=eth1
```

### Parameters

- **upstream_server**: Target HTTP server address
- **port** (optional): Target server port, defaults to 80
- **path**: Request path, including query parameters
- **r2h-ifname** (optional): Specify the network interface name for HTTP connections. Takes priority over the global `upstream-interface-http` configuration

### Use Cases

Expand Down
19 changes: 18 additions & 1 deletion docs/guide/url-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ rtp2httpd 支持多种流媒体协议,通过不同的 URL 前缀进行区分
## 组播 RTP 转 HTTP 单播流

```url
http://服务器地址:端口/rtp/组播地址:端口[?fcc=FCC服务器:端口][&fcc-type=协议类型][&fec=FEC端口]
http://服务器地址:端口/rtp/组播地址:端口[?fcc=FCC服务器:端口][&fcc-type=协议类型][&fec=FEC端口][&r2h-ifname=网络接口][&r2h-ifname-fcc=FCC网络接口]
```

**示例**:
Expand All @@ -22,6 +22,8 @@ http://192.168.1.1:5140/rtp/239.253.64.120:5140
http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970
http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:8027&fcc-type=huawei
http://192.168.1.1:5140/rtp/239.81.0.195:4056?fec=4055
http://192.168.1.1:5140/rtp/239.253.64.120:5140?r2h-ifname=eth1
http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970&r2h-ifname=eth0&r2h-ifname-fcc=eth1
```

### 参数说明
Expand All @@ -33,13 +35,17 @@ http://192.168.1.1:5140/rtp/239.81.0.195:4056?fec=4055
- `telecom`:电信/中兴/烽火 FCC 协议(默认)
- `huawei`:华为 FCC 协议
- **fec**(可选):FEC 前向纠错端口号,用于接收 FEC 冗余数据包来恢复丢包
- **r2h-ifname**(可选):指定用于接收组播流的网络接口名称(如 `eth0`, `eth1` 等)。优先级高于全局配置 `upstream-interface-multicast`
- **r2h-ifname-fcc**(可选):指定用于 FCC 的网络接口名称。仅在使用 FCC 时有效,优先级高于全局配置 `upstream-interface-fcc`

### 使用场景

- 将运营商 IPTV 组播流转换为 HTTP 单播流
- 在局域网内多设备共享 IPTV 流
- 配合 FCC 实现毫秒级换台
- 配合 FEC 实现丢包恢复,提高播放稳定性
- 通过 `r2h-ifname` 参数指定不同频道使用不同网络接口(适用于多网卡环境,如不同接口接收不同运营商的组播流)
- 使用 `r2h-ifname-fcc` 参数为 FCC 指定独立的网络接口(在多网卡环境下分离组播接收和 FCC 通信)

## RTSP 转 HTTP

Expand All @@ -61,8 +67,15 @@ http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?tvdr=20240101120000GM

# 自定义时移参数名 + 时间偏移
http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?seek=20240101120000&r2h-seek-name=seek&r2h-seek-offset=3600

# 指定网络接口
http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?r2h-ifname=eth1
```

### 参数说明

- **r2h-ifname**(可选):指定用于 RTSP 连接的网络接口名称。优先级高于全局配置 `upstream-interface-rtsp`

### 使用场景

- 将 IPTV RTSP 单播流转换为 HTTP 流
Expand Down Expand Up @@ -94,13 +107,17 @@ http://192.168.1.1:5140/http/upstream.example.com:8080/live/stream.m3u8

# 代理 HTTP 请求(省略端口,默认 80)
http://192.168.1.1:5140/http/api.example.com/video?auth=xxx&quality=hd

# 指定网络接口
http://192.168.1.1:5140/http/upstream.example.com:8080/live/stream.m3u8?r2h-ifname=eth1
```

### 参数说明

- **上游服务器**:目标 HTTP 服务器地址
- **端口**(可选):目标服务器端口,默认 80
- **路径**:请求路径,包括查询参数
- **r2h-ifname**(可选):指定用于 HTTP 连接的网络接口名称。优先级高于全局配置 `upstream-interface-http`

### 使用场景

Expand Down
7 changes: 6 additions & 1 deletion src/fcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,12 @@ int fcc_initialize_and_request(stream_context_t *ctx) {
config.udp_rcvbuf_size, strerror(errno));
}

upstream_if = get_upstream_interface_for_fcc();
/* Use per-service FCC interface if specified, otherwise use global config */
if (service->ifname_fcc && service->ifname_fcc[0] != '\0') {
upstream_if = service->ifname_fcc;
} else {
upstream_if = get_upstream_interface_for_fcc();
}
bind_to_upstream_interface(fcc->fcc_sock, upstream_if);

/* Bind to configured or ephemeral port */
Expand Down
9 changes: 7 additions & 2 deletions src/http_proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ void http_proxy_set_request_headers(http_proxy_session_t *session,
}
}

int http_proxy_connect(http_proxy_session_t *session) {
int http_proxy_connect(http_proxy_session_t *session, service_t *service) {
struct sockaddr_in server_addr;
struct hostent *he;
int connect_result;
Expand Down Expand Up @@ -294,7 +294,12 @@ int http_proxy_connect(http_proxy_session_t *session) {
}

/* Bind to upstream interface if configured */
upstream_if = get_upstream_interface_for_http();
/* Use per-service interface if specified, otherwise use global config */
if (service && service->ifname && service->ifname[0] != '\0') {
upstream_if = service->ifname;
} else {
upstream_if = get_upstream_interface_for_http();
}
Comment on lines +297 to +302
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http_proxy_connect() now dereferences service->ifname, but http_proxy.c only sees service_t as a forward declaration via http_proxy.h. This will not compile (incomplete type) unless you include service.h in http_proxy.c (or otherwise provide the full service_t definition) before accessing its fields.

Copilot uses AI. Check for mistakes.
bind_to_upstream_interface(session->socket, upstream_if);

/* Connect to server (non-blocking) */
Expand Down
6 changes: 4 additions & 2 deletions src/http_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
#include <stdint.h>
#include <sys/types.h>

/* Forward declaration */
/* Forward declarations */
struct connection_s;
typedef struct service_s service_t;

/* ========== HTTP PROXY BUFFER SIZE CONFIGURATION ========== */

Expand Down Expand Up @@ -163,9 +164,10 @@ void http_proxy_set_request_headers(http_proxy_session_t *session,
/**
* Connect to upstream HTTP server (non-blocking)
* @param session HTTP proxy session (must have epoll_fd set)
* @param service Service structure containing interface configuration (can be NULL)
* @return 0 on success (connection in progress), -1 on error
*/
int http_proxy_connect(http_proxy_session_t *session);
int http_proxy_connect(http_proxy_session_t *session, service_t *service);

/**
* Handle socket events (readable/writable) for async I/O state machine
Expand Down
16 changes: 13 additions & 3 deletions src/multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,13 @@ static int prepare_mcast_group_req(service_t *service, struct group_req *gr,
return -1;
}

upstream_if = get_upstream_interface_for_multicast();
/* Use per-service interface if specified, otherwise use global config */
if (service->ifname && service->ifname[0] != '\0') {
upstream_if = service->ifname;
} else {
upstream_if = get_upstream_interface_for_multicast();
}

if (upstream_if && upstream_if[0] != '\0') {
gr->gr_interface = if_nametoindex(upstream_if);
}
Expand Down Expand Up @@ -240,8 +246,12 @@ static int join_mcast_group(service_t *service, int is_fec) {
strerror(errno));
}

/* Determine which interface to use */
upstream_if = get_upstream_interface_for_multicast();
/* Use per-service interface if specified, otherwise use global config */
if (service->ifname && service->ifname[0] != '\0') {
upstream_if = service->ifname;
} else {
upstream_if = get_upstream_interface_for_multicast();
}
bind_to_upstream_interface(sock, upstream_if);

/* Prepare bind address with appropriate port */
Expand Down
Binary file added src/rtp2httpd
Binary file not shown.
14 changes: 12 additions & 2 deletions src/rtsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,12 @@ int rtsp_connect(rtsp_session_t *session) {
return -1;
}

upstream_if = get_upstream_interface_for_rtsp();
/* Use per-service interface if specified, otherwise use global config */
if (session->service && session->service->ifname && session->service->ifname[0] != '\0') {
upstream_if = session->service->ifname;
} else {
upstream_if = get_upstream_interface_for_rtsp();
}
bind_to_upstream_interface(session->socket, upstream_if);

/* Connect to server (non-blocking) */
Expand Down Expand Up @@ -2449,7 +2454,12 @@ static int rtsp_setup_udp_sockets(rtsp_session_t *session) {

logger(LOG_DEBUG, "RTSP: Setting up UDP sockets");

upstream_if = get_upstream_interface_for_rtsp();
/* Use per-service interface if specified, otherwise use global config */
if (session->service && session->service->ifname && session->service->ifname[0] != '\0') {
upstream_if = session->service->ifname;
} else {
upstream_if = get_upstream_interface_for_rtsp();
}

session->local_rtp_port = 0;
session->local_rtcp_port = 0;
Expand Down
4 changes: 4 additions & 0 deletions src/rtsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

#include "stun.h"

/* Forward declarations */
typedef struct service_s service_t;

#define RTSP_DISABLE_TCP_TRANSPORT 0 /* To debug UDP transport, set to 1 */

/* ========== RTSP BUFFER SIZE CONFIGURATION ========== */
Expand Down Expand Up @@ -111,6 +114,7 @@ typedef struct {
int socket; /* TCP socket to RTSP server */
int epoll_fd; /* Epoll file descriptor for socket registration */
struct connection_s *conn; /* Connection pointer for fdmap registration */
service_t *service; /* Service pointer for accessing per-service configuration */
rtsp_state_t state; /* Current RTSP state */
int status_index; /* Index in status_shared->clients array for state updates
*/
Expand Down
Loading
Loading