Project

General

Profile

Feature #4617

SAT>IP: Support different PORT over NAT FORWARDING

Added by Mono Polimorph about 7 years ago. Updated about 7 years ago.

Status:
Fixed
Priority:
Normal
Category:
SAT>IP
Target version:
-
Start date:
2017-09-21
Due date:
% Done:

100%

Estimated time:

Description

Hi,

With the current implementation of the SAT>IP, when the server is over a NAT router it's required that the external port be the same as the internal port. This can be possible if you have control over the router. However, this is not always possible.

This patch resolves this problem. It enables the option for use a Custom External PORT. This concerns only to RTSP commands that use the server port (like do now the NAT external IP parameter already implemented).

Here the patch:

diff --git a/src/satip/rtsp.c b/src/satip/rtsp.c
index e194bcc..a4a99e3 100644
--- a/src/satip/rtsp.c
+++ b/src/satip/rtsp.c
@@ -81,6 +81,7 @@ static uint16_t stream_id;
 static char *rtsp_ip = NULL;
 static char *rtsp_nat_ip = NULL;
 static int rtsp_port = -1;
+static int rtsp_nat_port = -1;
 static int rtsp_descramble = 1;
 static int rtsp_rewrite_pmt = 0;
 static int rtsp_muxcnf = MUXCNF_AUTO;
@@ -252,6 +253,7 @@ static char *
 rtsp_check_urlbase(char *u)
 {
   char *p, *s;
+  int t;

   if (*u == '/' || strncmp(u, "stream=", 7) == 0)
     return u;
@@ -264,7 +266,8 @@ rtsp_check_urlbase(char *u)
     *p = '\0';
   if ((s = strchr(u, ':')) != NULL) {
     *s = '\0';
-    if (atoi(s + 1) != rtsp_port)
+    t = rtsp_nat_port ?: rtsp_port;
+    if (atoi(s + 1) != t)
       return NULL;
   } else {
 #if 0 /* VLC is broken */
@@ -1393,7 +1396,7 @@ static int
 rtsp_process_play(http_connection_t *hc, int cmd)
 {
   session_t *rs;
-  int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream;
+  int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, p, stream;
   char buf[256], *u = tvh_strdupa(hc->hc_url);
   http_arg_list_t args;

@@ -1452,8 +1455,9 @@ rtsp_process_play(http_connection_t *hc, int cmd)
     snprintf(buf, sizeof(buf), "%d", rs->stream);
     http_arg_set(&args, "com.ses.streamID", buf);
   } else {
-    if (rtsp_port != 554)
-      snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", rtsp_ip, rtsp_port, rs->stream);
+    p = rtsp_nat_port ?: rtsp_port;
+    if (p != 554)
+      snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", rtsp_ip, p, rs->stream);
     else
       snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", rtsp_ip, rs->stream);
     http_arg_set(&args, "RTP-Info", buf);
@@ -1683,7 +1687,7 @@ rtsp_close_sessions(void)
  */
 void satip_server_rtsp_init
   (const char *bindaddr, int port, int descramble, int rewrite_pmt, int muxcnf,
-   const char *nat_ip)
+   const char *nat_ip, int nat_port)
 {
   static tcp_server_ops_t ops = {
     .start  = rtsp_serve,
@@ -1716,6 +1720,7 @@ void satip_server_rtsp_init
   s = rtsp_nat_ip;
   rtsp_nat_ip = nat_ip ? strdup(nat_ip) : NULL;
   free(s);
+  rtsp_nat_port = nat_port;
   if (!rtsp_server)
     rtsp_server = tcp_server_create(LS_SATIPS, "SAT>IP RTSP", bindaddr, port, &ops, NULL);
   if (reg)
@@ -1738,6 +1743,7 @@ void satip_server_rtsp_done(void)
   pthread_mutex_lock(&global_lock);
   rtsp_server = NULL;
   rtsp_port = -1;
+  rtsp_nat_port = -1;
   free(rtsp_ip);
   free(rtsp_nat_ip);
   rtsp_ip = rtsp_nat_ip = NULL;
diff --git a/src/satip/server.c b/src/satip/server.c
index e6b5fdf..90b28fe 100644
--- a/src/satip/server.c
+++ b/src/satip/server.c
@@ -754,6 +754,16 @@ const idclass_t satip_server_class = {
       .group  = 1,
     },
     {
+      .type   = PT_INT,
+      .id     = "satip_nat_rtsp",
+      .name   = N_("External RTSP port (NAT)"),
+      .desc   = N_("Enter external PORT if behind Forwarding redirection." 
+                   "(0 = use the same local port)."),
+      .off    = offsetof(struct satip_server_conf, satip_nat_rtsp),
+      .opts   = PO_EXPERT,
+      .group  = 1,
+    },
+    {
       .type   = PT_BOOL,
       .id     = "satip_nom3u",
       .name   = N_("Disable X_SATIPM3U tag"),
@@ -868,6 +878,7 @@ static void satip_server_init_common(const char *prefix, int announce)
   char http_ip[128];
   int descramble, rewrite_pmt, muxcnf;
   char *nat_ip;
+  int nat_port;

   if (satip_server_rtsp_port <= 0)
     return;
@@ -890,13 +901,14 @@ static void satip_server_init_common(const char *prefix, int announce)
   rewrite_pmt = satip_server_conf.satip_rewrite_pmt;
   muxcnf = satip_server_conf.satip_muxcnf;
   nat_ip = strdup(satip_server_conf.satip_nat_ip ?: "");
+  nat_port = satip_server_conf.satip_nat_rtsp ?: satip_server_rtsp_port;

   if (announce)
     pthread_mutex_unlock(&global_lock);

   pthread_mutex_lock(&satip_server_reinit);

-  satip_server_rtsp_init(http_server_ip, satip_server_rtsp_port, descramble, rewrite_pmt, muxcnf, nat_ip);
+  satip_server_rtsp_init(http_server_ip, satip_server_rtsp_port, descramble, rewrite_pmt, muxcnf, nat_ip, nat_port);
   satip_server_info(prefix, descramble, muxcnf);

   if (announce)
diff --git a/src/satip/server.h b/src/satip/server.h
index 054e481..bb23271 100644
--- a/src/satip/server.h
+++ b/src/satip/server.h
@@ -62,6 +62,7 @@ struct satip_server_conf {
   int satip_atsc_t;
   int satip_atsc_c;
   char *satip_nat_ip;
+  int satip_nat_rtsp;
 };

 extern struct satip_server_conf satip_server_conf;
@@ -92,7 +93,7 @@ int satip_rtsp_delsys(int fe, int *findex, const char **ftype);

 void satip_server_rtsp_init(const char *bindaddr, int port,
                             int descramble, int rewrite_pmt, int muxcnf,
-                            const char *nat_ip);
+                            const char *nat_ip, int nat_port);
 void satip_server_rtsp_register(void);
 void satip_server_rtsp_done(void);

I hope you agree to commit it, as it completes the support for all NAT scenarios.
Attached is the patch file for easy apply. (I'm sorry, I can't produce a GitHub PR at time!)

Regards.


Files

SAT-IP-NAT-port-support.diff (4.83 KB) SAT-IP-NAT-port-support.diff Patch Mono Polimorph, 2017-09-21 13:27

History

#1

Updated by Mono Polimorph about 7 years ago

Hi Jaroslav,

Please, commit this patch,too . Very usefull! I'm using it right now.

#2

Updated by Mono Polimorph about 7 years ago

Still waiting for the acceptance of this patch. ;)

#3

Updated by Mono Polimorph about 7 years ago

I hope this patch will be accepted.
If there is something to change, please tell me what I have to do. ;)

#4

Updated by Jaroslav Kysela about 7 years ago

  • Status changed from New to Fixed
  • % Done changed from 0 to 100

Applied in changeset commit:tvheadend|f8f018e9a7e4407b888c334b751e833cc64f17d0.

#5

Updated by Mono Polimorph about 7 years ago

Thank you!

However, a slight difference in the implementation.

You overcome this part of the patch:

@@ -1393,7 +1396,7 @@ static int
 rtsp_process_play(http_connection_t *hc, int cmd)
 {
   session_t *rs;
-  int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream;
+  int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, p, stream;
   char buf[256], *u = tvh_strdupa(hc->hc_url);
   http_arg_list_t args;

@@ -1452,8 +1455,9 @@ rtsp_process_play(http_connection_t *hc, int cmd)
     snprintf(buf, sizeof(buf), "%d", rs->stream);
     http_arg_set(&args, "com.ses.streamID", buf);
   } else {
-    if (rtsp_port != 554)
-      snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", rtsp_ip, rtsp_port, rs->stream);
+    p = rtsp_nat_port ?: rtsp_port;
+    if (p != 554)
+      snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", rtsp_ip, p, rs->stream);
     else
       snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", rtsp_ip, rs->stream);
     http_arg_set(&args, "RTP-Info", buf);
@@ -1683,7 +1687,7 @@ rtsp_close_sessions(void)

If you don't catch this, the client can be confused: You indicate the real listening RTSP port, but the user connects to the NAT port.
Why you don't like this part of the patch?

Regards.

#6

Updated by Jaroslav Kysela about 7 years ago

I think that most clients does not parse this info and we use only the local IP address here (rtsp_ip not rtsp_nat_ip), too. The correct implementation should be to detect the "external" connection and masquearade everything for it, but this requires to specify the internal IP ranges from user (routed) and gather the IP networks bound to the local ethernet adapters.

#7

Updated by Mono Polimorph about 7 years ago

Jaroslav Kysela wrote:

I think that most clients does not parse this info and we use only the local IP address here (rtsp_ip not rtsp_nat_ip), too. The correct implementation should be to detect the "external" connection and masquearade everything for it, but this requires to specify the internal IP ranges from user (routed) and gather the IP networks bound to the local ethernet adapters.

Hi,

I don't understand it! This piece of code if for use the NAT port instead of the listening port. Equal as you use the NAT address, you need to use the NAT port!

rtsp_ip is the NAT address if you use NAT, and the local address if the NAT is disabled.
rtsp_port is all the time the listening port.
rtsp_nat_port is the NAT port if the NAT is enabled.

So you have all the required data in the function! You only need to use "rtsp_port" if NAT is disabled, and "rtsp_nat_port" if NAT is enabled.

The patch is fully tested. So please, commit also this part. Without it some clients will refuse to connect.
Thank you!

#8

Updated by Jaroslav Kysela about 7 years ago

Mono Polimorph wrote:

Jaroslav Kysela wrote:

I think that most clients does not parse this info and we use only the local IP address here (rtsp_ip not rtsp_nat_ip), too. The correct implementation should be to detect the "external" connection and masquearade everything for it, but this requires to specify the internal IP ranges from user (routed) and gather the IP networks bound to the local ethernet adapters.

Hi,

I don't understand it! This piece of code if for use the NAT port instead of the listening port. Equal as you use the NAT address, you need to use the NAT port!

rtsp_ip is the NAT address if you use NAT, and the local address if the NAT is disabled.

It's your mistake. rtsp_ip is the bind IP (local IP). Always.

#9

Updated by Mono Polimorph about 7 years ago

Jaroslav Kysela wrote:

It's your mistake. rtsp_ip is the bind IP (local IP). Always.

Ah! Ok, thank you for pointing it!

So, I'll rewrite the patch for use both the NAT IP & NAT PORT when advertizing.

Regards.

#10

Updated by Mono Polimorph about 7 years ago

Mono Polimorph wrote:

So, I'll rewrite the patch for use both the NAT IP & NAT PORT when advertizing.

Fixed in #4692

Also available in: Atom PDF