]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
SAT>IP: allow to specify the local bind IP address
authorJaroslav Kysela <perex@perex.cz>
Thu, 22 May 2014 13:00:52 +0000 (15:00 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 22 May 2014 14:02:53 +0000 (16:02 +0200)
src/descrambler/cwc.c
src/http.h
src/httpc.c
src/imagecache.c
src/input/mpegts/iptv/iptv_http.c
src/input/mpegts/satip/satip.c
src/input/mpegts/satip/satip_frontend.c
src/input/mpegts/satip/satip_private.h
src/tcp.c
src/tcp.h
src/udp.h

index 63e3bb5d612a4ef7b6683301e4977e508a1854ac..6213684c47d0c72dedbca44f11f3cfe11e176fbc 100755 (executable)
@@ -1169,7 +1169,7 @@ cwc_thread(void *aux)
 
     pthread_mutex_unlock(&cwc_mutex);
 
-    fd = tcp_connect(hostname, port, errbuf, sizeof(errbuf), 10);
+    fd = tcp_connect(hostname, port, NULL, errbuf, sizeof(errbuf), 10);
 
     pthread_mutex_lock(&cwc_mutex);
 
index 5ba944bf1e225c14aee4e27ad60177eba4af3cd8..a8c99b2122a3ce4cbeeb763b8dcdc8adf70d6757 100644 (file)
@@ -222,6 +222,7 @@ struct http_client {
   char        *hc_scheme;
   char        *hc_host;
   int          hc_port;
+  char        *hc_bindaddr;
   tvhpoll_t   *hc_efd;
   int          hc_pevents;
 
@@ -289,8 +290,8 @@ void http_client_init ( void );
 void http_client_done ( void );
 
 http_client_t*
-http_client_connect ( void *aux, http_ver_t ver,
-                      const char *scheme, const char *host, int port );
+http_client_connect ( void *aux, http_ver_t ver, const char *scheme,
+                      const char *host, int port, const char *bindaddr );
 void http_client_register ( http_client_t *hc );
 void http_client_close ( http_client_t *hc );
 
index a2bbdcdd904d60acef8294b870f8008e707666c7..8f9111ce979dd8fc7d3870a285d99ce548a25d56 100644 (file)
@@ -1164,7 +1164,7 @@ http_client_reconnect
   hc->hc_port    = port;
   if (port < 0)
     return -EINVAL;
-  hc->hc_fd      = tcp_connect(host, port, errbuf, sizeof(errbuf), -1);
+  hc->hc_fd      = tcp_connect(host, port, hc->hc_bindaddr, errbuf, sizeof(errbuf), -1);
   if (hc->hc_fd < 0) {
     tvhlog(LOG_ERR, "httpc", "Unable to connect to %s:%i - %s", host, port, errbuf);
     return -EINVAL;
@@ -1217,7 +1217,8 @@ err1:
 
 http_client_t *
 http_client_connect 
-  ( void *aux, http_ver_t ver, const char *scheme, const char *host, int port )
+  ( void *aux, http_ver_t ver, const char *scheme,
+    const char *host, int port, const char *bindaddr )
 {
   http_client_t *hc;
 
@@ -1226,6 +1227,7 @@ http_client_connect
   hc->hc_io_size = 1024;
   hc->hc_rtsp_stream_id = -1;
   hc->hc_verify_peer = -1;
+  hc->hc_bindaddr = bindaddr ? strdup(bindaddr) : NULL;
 
   TAILQ_INIT(&hc->hc_args);
   TAILQ_INIT(&hc->hc_wqueue);
@@ -1280,6 +1282,7 @@ http_client_close ( http_client_t *hc )
   free(hc->hc_data);
   free(hc->hc_host);
   free(hc->hc_scheme);
+  free(hc->hc_bindaddr);
   free(hc);
 }
 
index cf17f01d29a83ed6a26ef895bbafb52366e9406d..f9f40ef19bc5c833b35ed55d2db3038187966e5d 100644 (file)
@@ -166,7 +166,7 @@ imagecache_image_fetch ( imagecache_image_t *img )
   pthread_mutex_unlock(&global_lock);
 
   hc = http_client_connect(NULL, HTTP_VERSION_1_1, url.scheme,
-                           url.host, url.port);
+                           url.host, url.port, NULL);
   if (hc == NULL)
     goto error;
 
index 660ece7dd9b35cabfed9efce40561704e790b747..e61b9ad58fee2142f41ca5a0140b695ec33d6d3a 100644 (file)
@@ -68,7 +68,7 @@ iptv_http_start
   int r;
 
   if (!(hc = http_client_connect(im, HTTP_VERSION_1_1, u->scheme,
-                                 u->host, u->port)))
+                                 u->host, u->port, NULL)))
     return SM_CODE_TUNING_FAILED;
   hc->hc_hdr_received    = iptv_http_header;
   hc->hc_data_received   = iptv_http_data;
index 9193b236131591aa6398d23172acacf5e32a444c..37234d8f3f80bb44259617cc22b61f593844d6ec 100644 (file)
@@ -112,6 +112,13 @@ const idclass_t satip_device_class =
       .opts     = PO_ADVANCED,
       .off      = offsetof(satip_device_t, sd_pids0),
     },
+    {
+      .type     = PT_STR,
+      .id       = "bindaddr",
+      .name     = "Local bind IP address",
+      .opts     = PO_ADVANCED,
+      .off      = offsetof(satip_device_t, sd_bindaddr),
+    },
     {
       .type     = PT_STR,
       .id       = "addr",
@@ -227,7 +234,7 @@ const idclass_t satip_device_class =
     {
       .type     = PT_STR,
       .id       = "myaddr",
-      .name     = "Local IP Address",
+      .name     = "Local Discovery IP Address",
       .opts     = PO_RDONLY | PO_NOSAVE,
       .off      = offsetof(satip_device_t, sd_info.myaddr),
     },
@@ -455,6 +462,7 @@ satip_device_destroy( satip_device_t *sd )
   FREEM(presentation);
   FREEM(tunercfg);
 #undef FREEM
+  free(sd->sd_bindaddr);
 
   tvh_hardware_delete((tvh_hardware_t*)sd);
   free(sd);
@@ -573,10 +581,7 @@ satip_discovery_http_closed(http_client_t *hc, int errn)
     socklen_t addrlen = sizeof(ip);
     errbuf[0] = '\0';
     getsockname(hc->hc_fd, (struct sockaddr *)&ip, &addrlen);
-    if (ip.ss_family == AF_INET6)
-      inet_ntop(AF_INET6, &IP_AS_V6(ip, addr), errbuf, sizeof(errbuf));
-    else
-      inet_ntop(AF_INET, &IP_AS_V4(ip, addr), errbuf, sizeof(errbuf));
+    inet_ntop(ip.ss_family, IP_IN_ADDR(ip), errbuf, sizeof(errbuf));
     free(d->myaddr);
     d->myaddr = strdup(errbuf);
   }
@@ -703,7 +708,7 @@ satip_discovery_timerq_cb(void *aux)
     }
 
     d->http_client = http_client_connect(d, HTTP_VERSION_1_1, d->url.scheme,
-                                         d->url.host, d->url.port);
+                                         d->url.host, d->url.port, NULL);
     if (d->http_client == NULL)
       satip_discovery_destroy(d, 1);
     else {
@@ -803,7 +808,7 @@ satip_discovery_service_received
   /* Forward information to next layer */
 
   d = calloc(1, sizeof(satip_discovery_t));
-  if (inet_ntop(storage->ss_family, IP_IN_ADDR(conn->ip),
+  if (inet_ntop(conn->ip.ss_family, IP_IN_ADDR(conn->ip),
                 sockbuf, sizeof(sockbuf)) == NULL) {
     satip_discovery_destroy(d, 0);
     return;
index d85423b20ab9c0f838d5d1eaf0a86338b129cbfa..5b8990acd804670ef163c81d547cfded5385a613 100644 (file)
@@ -42,6 +42,15 @@ satip_frontend_find_by_number( satip_device_t *sd, int num )
   return NULL;
 }
 
+static char *
+satip_frontend_bindaddr( satip_frontend_t *lfe )
+{
+  char *bindaddr = lfe->sf_device->sd_bindaddr;
+  if (bindaddr == NULL || bindaddr[0] == '\0')
+    bindaddr = lfe->sf_device->sd_bindaddr;
+  return bindaddr;
+}
+
 /* **************************************************************************
  * Class definition
  * *************************************************************************/
@@ -962,7 +971,8 @@ satip_frontend_input_thread ( void *aux )
   pthread_mutex_unlock(&lfe->sf_device->sd_tune_mutex);
 
   rtsp = http_client_connect(lfe, RTSP_VERSION_1_0, "rstp",
-                             lfe->sf_device->sd_info.addr, 554);
+                             lfe->sf_device->sd_info.addr, 554,
+                             satip_frontend_bindaddr(lfe));
   if (rtsp == NULL)
     return NULL;
 
@@ -1245,7 +1255,7 @@ satip_frontend_tune0
 
   if (udp_bind_double(&lfe->sf_rtp, &lfe->sf_rtcp,
                       "satip", "rtp", "rtpc",
-                      lfe->sf_device->sd_info.myaddr, lfe->sf_udp_rtp_port,
+                      satip_frontend_bindaddr(lfe), lfe->sf_udp_rtp_port,
                       NULL, SATIP_BUF_SIZE, 16384) < 0)
     return SM_CODE_TUNING_FAILED;
 
index 9972e7b8a36335b63eea3aa4d0b5bc265a35e30d..1fe5b78016e1ccb15a2184ff292edabe3ae59cab 100644 (file)
@@ -73,6 +73,7 @@ struct satip_device
   /*
    * RTSP
    */
+  char                      *sd_bindaddr;
   int                        sd_fullmux_ok;
   int                        sd_pids_max;
   int                        sd_pids_len;
index 0608abf2fa79848f9fef78c1e25bb5e4b776b75d..c530d686ee6437282539920c690b1d01b434e6db 100644 (file)
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -48,8 +48,8 @@ th_pipe_t tcp_server_pipe;
  *
  */
 int
-tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
-           int timeout)
+tcp_connect(const char *hostname, int port, const char *bindaddr,
+            char *errbuf, size_t errbufsize, int timeout)
 {
   int fd, r, res, err;
   struct addrinfo *ai;
@@ -78,7 +78,19 @@ tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
    */
   fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
 
-  if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6)) {
+  if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
+    if (bindaddr && bindaddr[0] != '\0') {
+      struct sockaddr_storage ip;
+      memset(&ip, 0, sizeof(ip));
+      ip.ss_family = ai->ai_family;
+      if (inet_pton(AF_INET, bindaddr, IP_IN_ADDR(ip)) <= 0 ||
+          bind(fd, (struct sockaddr *)&ip, IP_IN_ADDRLEN(ip)) < 0) {
+        snprintf(errbuf, errbufsize, "Cannot bind to IPv%s addr '%s'", bindaddr,
+                                     ai->ai_family == AF_INET6 ? "6" : "4");
+        return -1;
+      }
+    }
+  } else {
     snprintf(errbuf, errbufsize, "Invalid protocol family");
     freeaddrinfo(ai);
     return -1;
index 7006e4d235544e4dacb3a4ce905cb15ffeb71e9d..7c4b8ead0518a9a30368cd7c53025719ba2c0d55 100644 (file)
--- a/src/tcp.h
+++ b/src/tcp.h
 #include "htsbuf.h"
 #include "htsmsg.h"
 
+#define IP_AS_V4(storage, f) ((struct sockaddr_in *)&(storage))->sin_##f
+#define IP_AS_V6(storage, f) ((struct sockaddr_in6 *)&(storage))->sin6_##f
+#define IP_IN_ADDR(storage) \
+  ((storage).ss_family == AF_INET6 ? \
+      &((struct sockaddr_in6 *)&(storage))->sin6_addr : \
+      (void *)&((struct sockaddr_in  *)&(storage))->sin_addr)
+#define IP_IN_ADDRLEN(storage) \
+  ((storage).ss_family == AF_INET6 ? \
+      sizeof(struct sockaddr_in6) : \
+      sizeof(struct sockaddr_in))
+#define IP_PORT(storage) \
+  ((storage).ss_family == AF_INET6 ? \
+      ((struct sockaddr_in6 *)&(storage))->sin6_port : \
+      ((struct sockaddr_in  *)&(storage))->sin_port)
+
 typedef struct tcp_server_ops
 {
   void (*start)  (int fd, void **opaque,
@@ -37,8 +52,8 @@ extern int tcp_preferred_address_family;
 void tcp_server_init(int opt_ipv6);
 void tcp_server_done(void);
 
-int tcp_connect(const char *hostname, int port, char *errbuf,
-               size_t errbufsize, int timeout);
+int tcp_connect(const char *hostname, int port, const char *bindaddr,
+                char *errbuf, size_t errbufsize, int timeout);
 
 typedef void (tcp_server_callback_t)(int fd, void *opaque,
                                     struct sockaddr_storage *peer,
index c5fa2eef9a6cb677be5f9026c051a9f370f6c4b4..be6f062ce3c49e0c3c02afcc3ce24b717f3439ab 100644 (file)
--- a/src/udp.h
+++ b/src/udp.h
 
 #define UDP_FATAL_ERROR ((void *)-1)
 
-#define IP_AS_V4(storage, f) ((struct sockaddr_in *)&(storage))->sin_##f
-#define IP_AS_V6(storage, f) ((struct sockaddr_in6 *)&(storage))->sin6_##f
-#define IP_IN_ADDR(storage) \
-  ((storage).ss_family == AF_INET6 ? \
-      &((struct sockaddr_in6 *)&(storage))->sin6_addr : \
-      (void *)&((struct sockaddr_in  *)&(storage))->sin_addr)
-#define IP_PORT(storage) \
-  ((storage).ss_family == AF_INET6 ? \
-      ((struct sockaddr_in6 *)&(storage))->sin6_port : \
-      ((struct sockaddr_in  *)&(storage))->sin_port)
-
 typedef struct udp_connection {
   char *host;
   int port;