Skip to content

Commit b69dac9

Browse files
Arno500Flole998
authored andcommitted
iptv: allow to limit UDP ports for unicast inputs
1 parent eee5cda commit b69dac9

11 files changed

Lines changed: 95 additions & 37 deletions

File tree

src/config.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,9 +2199,13 @@ const idclass_t config_class = {
21992199
.number = 6,
22002200
},
22012201
{
2202-
.name = N_("Miscellaneous Settings"),
2202+
.name = N_("Ports settings"),
22032203
.number = 7,
22042204
},
2205+
{
2206+
.name = N_("Miscellaneous Settings"),
2207+
.number = 8,
2208+
},
22052209
{}
22062210
},
22072211
.ic_properties = (const property_t[]){
@@ -2647,14 +2651,36 @@ const idclass_t config_class = {
26472651
,
26482652
.group = 6
26492653
},
2654+
{
2655+
.type = PT_INT,
2656+
.id = "rtsp_udp_min_port",
2657+
.name = N_("RTSP UDP minimum port"),
2658+
.desc = N_("When using RTSP IPTV, this correspond to the "
2659+
"minimum port bind on the client (this server), "
2660+
"sent to the server. This is especially useful "
2661+
"when using firewalls and NAT or containers."),
2662+
.off = offsetof(config_t, rtsp_udp_min_port),
2663+
.opts = PO_EXPERT,
2664+
.group = 7,
2665+
},
2666+
{
2667+
.type = PT_INT,
2668+
.id = "rtsp_udp_max_port",
2669+
.name = N_("RTSP UDP maximum port"),
2670+
.desc = N_("Same as above, but for the maximum allowed "
2671+
"port. Note that each stream requires two ports."),
2672+
.off = offsetof(config_t, rtsp_udp_max_port),
2673+
.opts = PO_EXPERT,
2674+
.group = 7,
2675+
},
26502676
{
26512677
.type = PT_STR,
26522678
.id = "http_user_agent",
26532679
.name = N_("HTTP User Agent"),
26542680
.desc = N_("The user agent string for the build-in HTTP client."),
26552681
.off = offsetof(config_t, http_user_agent),
26562682
.opts = PO_HIDDEN | PO_EXPERT,
2657-
.group = 7,
2683+
.group = 8,
26582684
},
26592685
{
26602686
.type = PT_INT,
@@ -2663,7 +2689,7 @@ const idclass_t config_class = {
26632689
.desc = N_("Set the number of threads for IPTV to split load "
26642690
"across more CPUs."),
26652691
.off = offsetof(config_t, iptv_tpool_count),
2666-
.group = 7,
2692+
.group = 8,
26672693
},
26682694
{
26692695
.type = PT_INT,
@@ -2680,7 +2706,7 @@ const idclass_t config_class = {
26802706
.off = offsetof(config_t, dscp),
26812707
.list = config_class_dscp_list,
26822708
.opts = PO_EXPERT | PO_DOC_NLIST,
2683-
.group = 7,
2709+
.group = 8,
26842710
},
26852711
{
26862712
.type = PT_U32,
@@ -2690,7 +2716,7 @@ const idclass_t config_class = {
26902716
"there is a delay receiving CA keys. "),
26912717
.off = offsetof(config_t, descrambler_buffer),
26922718
.opts = PO_EXPERT,
2693-
.group = 7,
2719+
.group = 8,
26942720
},
26952721
{
26962722
.type = PT_BOOL,
@@ -2701,7 +2727,7 @@ const idclass_t config_class = {
27012727
"It may cause issues with some clients / players."),
27022728
.off = offsetof(config_t, parser_backlog),
27032729
.opts = PO_EXPERT,
2704-
.group = 7,
2730+
.group = 8,
27052731
},
27062732
{
27072733
.type = PT_STR,
@@ -2714,15 +2740,15 @@ const idclass_t config_class = {
27142740
.off = offsetof(config_t, muxconf_path),
27152741
.notify = config_muxconfpath_notify,
27162742
.opts = PO_ADVANCED,
2717-
.group = 7,
2743+
.group = 8,
27182744
},
27192745
{
27202746
.type = PT_BOOL,
27212747
.id = "hbbtv",
27222748
.name = N_("Parse HbbTV info"),
27232749
.desc = N_("Parse HbbTV information from services."),
27242750
.off = offsetof(config_t, hbbtv),
2725-
.group = 7,
2751+
.group = 8,
27262752
.def.i = 1,
27272753
},
27282754
{
@@ -2734,7 +2760,7 @@ const idclass_t config_class = {
27342760
"the system clock (normally only root)."),
27352761
.off = offsetof(config_t, tvhtime_update_enabled),
27362762
.opts = PO_EXPERT,
2737-
.group = 7,
2763+
.group = 8,
27382764
},
27392765
{
27402766
.type = PT_BOOL,
@@ -2746,7 +2772,7 @@ const idclass_t config_class = {
27462772
"performance is not that great."),
27472773
.off = offsetof(config_t, tvhtime_ntp_enabled),
27482774
.opts = PO_EXPERT,
2749-
.group = 7,
2775+
.group = 8,
27502776
},
27512777
{
27522778
.type = PT_U32,
@@ -2758,7 +2784,7 @@ const idclass_t config_class = {
27582784
"excessive oscillations on the system clock."),
27592785
.off = offsetof(config_t, tvhtime_tolerance),
27602786
.opts = PO_EXPERT,
2761-
.group = 7,
2787+
.group = 8,
27622788
},
27632789
#if ENABLE_VAAPI
27642790
{

src/config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ typedef struct config {
7575
char *hdhomerun_ip;
7676
char *local_ip;
7777
int local_port;
78+
int rtsp_udp_min_port;
79+
int rtsp_udp_max_port;
7880
uint32_t hdhomerun_server_tuner_count;
7981
char *hdhomerun_server_model_name;
8082
int hdhomerun_server_enable;

src/input/mpegts/iptv/iptv_rtcp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ rtcp_connect(rtcp_t * info, char *url, char *host, int port, char *interface, ch
385385

386386
if (info->connection == NULL) {
387387
rtcp_conn = udp_bind(LS_IPTV, nicename, NULL, 0, NULL, interface,
388-
IPTV_BUF_SIZE, 1024);
388+
IPTV_BUF_SIZE, 1024, 0);
389389
if (rtcp_conn == NULL || rtcp_conn == UDP_FATAL_ERROR) {
390390
tvhwarn(LS_IPTV, "%s - Unable to bind, RTCP won't be available",
391391
nicename);

src/input/mpegts/iptv/iptv_rtsp.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
#include "tvheadend.h"
21+
#include "config.h"
2122
#include "iptv_private.h"
2223
#include "iptv_rtcp.h"
2324
#include "http.h"
@@ -263,6 +264,8 @@ iptv_rtsp_start
263264
http_client_t *hc;
264265
udp_connection_t *rtp, *rtcp;
265266
int r;
267+
int rtp_port;
268+
int max_rtp_port;
266269

267270
if (!(hc = http_client_connect(im, RTSP_VERSION_1_0, u->scheme,
268271
u->host, u->port, NULL)))
@@ -272,15 +275,38 @@ iptv_rtsp_start
272275
hc->hc_rtsp_user = strdup(u->user);
273276
if (u->pass)
274277
hc->hc_rtsp_pass = strdup(u->pass);
278+
279+
rtp_port = config.rtsp_udp_min_port;
280+
max_rtp_port = config.rtsp_udp_max_port;
275281

276-
if (udp_bind_double(&rtp, &rtcp,
277-
LS_IPTV, "rtp", "rtcp",
278-
NULL, 0, NULL,
279-
128*1024, 16384, 4*1024, 4*1024) < 0) {
282+
if (!max_rtp_port) {
283+
rtp_port = 0;
284+
}
285+
286+
if (rtp_port > max_rtp_port)
287+
{
288+
tvherror(LS_IPTV, "UDP minimum port is set higher than the UDP maximum port");
280289
http_client_close(hc);
281290
return SM_CODE_TUNING_FAILED;
282291
}
283292

293+
while (udp_bind_double(&rtp, &rtcp,
294+
LS_IPTV, "rtp", "rtcp",
295+
NULL, rtp_port, NULL,
296+
128 * 1024, 16384, 4 * 1024, 4 * 1024, 1) < 0)
297+
{
298+
if (!rtp_port) {
299+
tvherror(LS_IPTV, "could not bind a random UDP port for RTP");
300+
http_client_close(hc);
301+
return SM_CODE_TUNING_FAILED;
302+
} else if (max_rtp_port && rtp_port >= max_rtp_port - 2) {
303+
tvherror(LS_IPTV, "all the UDP ports allocated are used, please reduce the number of simultaneous IPTV streams or increase the number of ports in the global settings");
304+
http_client_close(hc);
305+
return SM_CODE_TUNING_FAILED;
306+
}
307+
rtp_port += 2;
308+
}
309+
284310
hc->hc_hdr_received = iptv_rtsp_header;
285311
hc->hc_data_received = iptv_rtsp_data;
286312
hc->hc_handle_location = 1; /* allow redirects */

src/input/mpegts/iptv/iptv_udp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ iptv_udp_start
4242
/* Note: url->user is used for specifying multicast source address (SSM)
4343
here. The URL format is rtp://<srcaddr>@<grpaddr>:<port> */
4444
conn = udp_bind(LS_IPTV, im->mm_nicename, url->host, url->port, url->user,
45-
im->mm_iptv_interface, IPTV_BUF_SIZE, 4*1024);
45+
im->mm_iptv_interface, IPTV_BUF_SIZE, 4*1024, 0);
4646
if (conn == UDP_FATAL_ERROR)
4747
return SM_CODE_TUNING_FAILED;
4848
if (conn == NULL)

src/input/mpegts/satip/satip_frontend.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1729,7 +1729,7 @@ satip_frontend_input_thread ( void *aux )
17291729
if (udp_bind_double(&rtp, &rtcp,
17301730
LS_SATIP, "rtp", "rtcp",
17311731
satip_frontend_bindaddr(lfe), lfe->sf_udp_rtp_port,
1732-
NULL, SATIP_BUF_SIZE, 16384, 4*1024, 4*1024) < 0) {
1732+
NULL, SATIP_BUF_SIZE, 16384, 4*1024, 4*1024, 0) < 0) {
17331733
satip_frontend_tuning_error(lfe, tr);
17341734
goto done;
17351735
}

src/satip/rtsp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1562,7 +1562,7 @@ rtsp_process_play(http_connection_t *hc, int cmd)
15621562
LS_SATIPS, "rtsp", "rtcp",
15631563
(rtp_src_ip != NULL && rtp_src_ip[0] != '\0') ? rtp_src_ip : rtsp_ip, 0, NULL,
15641564
4*1024, 4*1024,
1565-
RTP_BUFSIZE, RTCP_BUFSIZE)) {
1565+
RTP_BUFSIZE, RTCP_BUFSIZE, 0)) {
15661566
errcode = HTTP_STATUS_INTERNAL;
15671567
goto error;
15681568
}

src/udp.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ udp_get_solip( void )
154154
udp_connection_t *
155155
udp_bind ( int subsystem, const char *name,
156156
const char *bindaddr, int port, const char *multicast_src,
157-
const char *ifname, int rxsize, int txsize )
157+
const char *ifname, int rxsize, int txsize, int bind_fail_allowed )
158158
{
159159
int fd, ifindex, reuse = 1;
160160
udp_connection_t *uc;
@@ -186,8 +186,8 @@ udp_bind ( int subsystem, const char *name,
186186

187187
uc->fd = fd;
188188

189-
/* Mark reuse address */
190-
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) {
189+
/* Mark reuse address, only wanted and required for Multicast in UDP (and TCP, but not here, then) */
190+
if (uc->multicast && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) {
191191
tvherror(subsystem, "%s - failed to reuse address for socket [%s]",
192192
name, strerror(errno));
193193
udp_close(uc);
@@ -207,9 +207,11 @@ udp_bind ( int subsystem, const char *name,
207207
/* Bind useful for receiver subsystem (not for udp streamer) */
208208
if (subsystem != LS_UDP) {
209209
if (bind(fd, (struct sockaddr *)&uc->ip, sizeof(struct sockaddr_in))) {
210-
inet_ntop(AF_INET, &IP_AS_V4(&uc->ip, addr), buf, sizeof(buf));
211-
tvherror(subsystem, "%s - cannot bind %s:%hu [e=%s]",
212-
name, buf, ntohs(IP_AS_V4(&uc->ip, port)), strerror(errno));
210+
if (!bind_fail_allowed) {
211+
inet_ntop(AF_INET, &IP_AS_V4(&uc->ip, addr), buf, sizeof(buf));
212+
tvherror(subsystem, "%s - cannot bind %s:%hu [e=%s]",
213+
name, buf, ntohs(IP_AS_V4(&uc->ip, port)), strerror(errno));
214+
}
213215
goto error;
214216
}
215217
}
@@ -280,9 +282,11 @@ udp_bind ( int subsystem, const char *name,
280282

281283
/* Bind */
282284
if (bind(fd, (struct sockaddr *)&uc->ip, sizeof(struct sockaddr_in6))) {
283-
inet_ntop(AF_INET6, &IP_AS_V6(&uc->ip, addr), buf, sizeof(buf));
284-
tvherror(subsystem, "%s - cannot bind %s:%hu [e=%s]",
285-
name, buf, ntohs(IP_AS_V6(&uc->ip, port)), strerror(errno));
285+
if (!bind_fail_allowed) {
286+
inet_ntop(AF_INET6, &IP_AS_V6(&uc->ip, addr), buf, sizeof(buf));
287+
tvherror(subsystem, "%s - cannot bind %s:%hu [e=%s]",
288+
name, buf, ntohs(IP_AS_V6(&uc->ip, port)), strerror(errno));
289+
}
286290
goto error;
287291
}
288292

@@ -334,21 +338,21 @@ udp_bind_double ( udp_connection_t **_u1, udp_connection_t **_u2,
334338
int subsystem, const char *name1,
335339
const char *name2, const char *host, int port,
336340
const char *ifname, int rxsize1, int rxsize2,
337-
int txsize1, int txsize2 )
341+
int txsize1, int txsize2, int bind_fail_allowed )
338342
{
339343
udp_connection_t *u1 = NULL, *u2 = NULL;
340344
udp_connection_t *ucs[10];
341345
int tst = 40, pos = 0, i, port2;
342346

343347
memset(&ucs, 0, sizeof(ucs));
344348
while (1) {
345-
u1 = udp_bind(subsystem, name1, host, port, NULL, ifname, rxsize1, txsize1);
349+
u1 = udp_bind(subsystem, name1, host, port, NULL, ifname, rxsize1, txsize1, bind_fail_allowed);
346350
if (u1 == NULL || u1 == UDP_FATAL_ERROR)
347351
goto fail;
348352
port2 = ntohs(IP_PORT(u1->ip));
349353
/* RTP port should be even, RTCP port should be odd */
350354
if ((port2 % 2) == 0) {
351-
u2 = udp_bind(subsystem, name2, host, port2 + 1, NULL, ifname, rxsize2, txsize2);
355+
u2 = udp_bind(subsystem, name2, host, port2 + 1, NULL, ifname, rxsize2, txsize2, bind_fail_allowed);
352356
if (u2 != NULL && u2 != UDP_FATAL_ERROR)
353357
break;
354358
}

src/udp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ typedef struct udp_connection {
4545
udp_connection_t *
4646
udp_bind ( int subsystem, const char *name,
4747
const char *bindaddr, int port, const char *multicast_src,
48-
const char *ifname, int rxsize, int txsize );
48+
const char *ifname, int rxsize, int txsize, int bind_fail_allowed );
4949
int
5050
udp_bind_double ( udp_connection_t **_u1, udp_connection_t **_u2,
5151
int subsystem, const char *name1,
5252
const char *name2, const char *host, int port,
5353
const char *ifname, int rxsize1, int rxsize2,
54-
int txsize1, int txsize2 );
54+
int txsize1, int txsize2, int bind_fail_allowed );
5555
udp_connection_t *
5656
udp_sendinit ( int subsystem, const char *name,
5757
const char *ifname, int txsize );

src/upnp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,11 @@ upnp_thread( void *aux )
130130

131131
multicast = udp_bind(LS_UPNP, "upnp_thread_multicast",
132132
"239.255.255.250", 1900, NULL,
133-
NULL, 32*1024, 32*1024);
133+
NULL, 32*1024, 32*1024, 0);
134134
if (multicast == NULL || multicast == UDP_FATAL_ERROR)
135135
goto error;
136136
unicast = udp_bind(LS_UPNP, "upnp_thread_unicast", bindaddr, 0, NULL,
137-
NULL, 32*1024, 32*1024);
137+
NULL, 32*1024, 32*1024, 0);
138138
if (unicast == NULL || unicast == UDP_FATAL_ERROR)
139139
goto error;
140140

0 commit comments

Comments
 (0)