]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
input: tvhdhomerun: Handle the device changing IP addresses
authorMichael Marley <michael@michaelmarley.com>
Sun, 10 Apr 2016 19:05:17 +0000 (15:05 -0400)
committerJaroslav Kysela <perex@perex.cz>
Mon, 11 Apr 2016 10:45:25 +0000 (12:45 +0200)
Previously the device detection loop would always ignore HDHomeRuns
with the same UID as devices that had already been detected.  This
would not detect if an HDHomeRun changed IPs for any reason (e.g.
APIPA, misconfigured DHCP server) while TVHeadend was running,
requiring a restart to resume functionality.  Instead, if
a newly detected device has the same UID as an previously-detected
one but a different IP address, destroy the old device and recreate
it with the new IP address.

src/input/mpegts/tvhdhomerun/tvhdhomerun.c
src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c
src/input/mpegts/tvhdhomerun/tvhdhomerun_private.h

index 48b946ac4f9c91950f3ee857387fbe1d36bf051c..81534bcc2beda22233a070b8e9ec446112f5fe98 100644 (file)
@@ -21,6 +21,7 @@
 #include "input.h"
 #include "htsbuf.h"
 #include "settings.h"
+#include "tcp.h"
 #include "tvhdhomerun.h"
 #include "tvhdhomerun_private.h"
 
@@ -85,8 +86,10 @@ tvhdhomerun_device_class_get_title( idnode_t *in, const char *lang )
 {
   static char buf[256];
   tvhdhomerun_device_t *hd = (tvhdhomerun_device_t *)in;
+  char ip[64];
+  tcp_get_str_from_ip((struct sockaddr *)&hd->hd_info.ip_address, ip, sizeof(ip));
   snprintf(buf, sizeof(buf),
-           "%s - %s", hd->hd_info.friendlyname, hd->hd_info.ip_address);
+           "%s - %s", hd->hd_info.friendlyname, ip);
   return buf;
 }
 
@@ -263,7 +266,6 @@ static void tvhdhomerun_device_create(struct hdhomerun_discover_device_t *dInfo)
   int j, save = 0;
   struct hdhomerun_device_t *hdhomerun_tuner;
   dvb_fe_type_t type = DVB_TYPE_C;
-  struct in_addr ip_addr;
 
   tvhdhomerun_device_calc_uuid(&uuid, dInfo->device_id);
 
@@ -318,8 +320,9 @@ static void tvhdhomerun_device_create(struct hdhomerun_discover_device_t *dInfo)
   char fName[128];
   snprintf(fName, 128, "HDHomeRun(%08X)",dInfo->device_id);
 
-  ip_addr.s_addr = htonl(dInfo->ip_addr);
-  hd->hd_info.ip_address = strdup(inet_ntoa(ip_addr));
+  memset(&hd->hd_info.ip_address, 0, sizeof(hd->hd_info.ip_address));
+  hd->hd_info.ip_address.ss_family = AF_INET;
+  ((struct sockaddr_in *)&hd->hd_info.ip_address)->sin_addr.s_addr = htonl(dInfo->ip_addr);
   hd->hd_info.uuid = strdup(uuid.hex);
   hd->hd_info.friendlyname = strdup(fName);
 
@@ -363,11 +366,32 @@ tvhdhomerun_device_discovery_thread( void *aux )
         struct hdhomerun_discover_device_t* cDev = &result_list[numDevices];
         if ( cDev->device_type == HDHOMERUN_DEVICE_TYPE_TUNER ) {
           pthread_mutex_lock(&global_lock);
-          if ( !tvhdhomerun_device_find(cDev->device_id) &&
-               tvheadend_is_running() ) {
-            tvhlog(LOG_INFO, "tvhdhomerun","Found HDHomerun device %08x with %d tuners",
-                   cDev->device_id, cDev->tuner_count);
-            tvhdhomerun_device_create(cDev);
+          tvhdhomerun_device_t *existing = tvhdhomerun_device_find(cDev->device_id);
+          if ( tvheadend_is_running() ) {
+            if ( !existing ) {
+              tvhlog(LOG_INFO, "tvhdhomerun","Found HDHomerun device %08x with %d tuners",
+                     cDev->device_id, cDev->tuner_count);
+              tvhdhomerun_device_create(cDev);
+            } else if ( ((struct sockaddr_in *)&existing->hd_info.ip_address)->sin_addr.s_addr !=
+                     htonl(cDev->ip_addr) ) {
+              struct sockaddr_storage detected_dev_addr;
+              memset(&detected_dev_addr, 0, sizeof(detected_dev_addr));
+              detected_dev_addr.ss_family = AF_INET;
+              ((struct sockaddr_in *)&detected_dev_addr)->sin_addr.s_addr = htonl(cDev->ip_addr);
+
+              char existing_ip[64];
+              tcp_get_str_from_ip((struct sockaddr *)&existing->hd_info.ip_address,
+                     existing_ip, sizeof(existing_ip));
+
+              char detected_ip[64];
+              tcp_get_str_from_ip((struct sockaddr *)&detected_dev_addr, detected_ip,
+                     sizeof(detected_ip));
+
+              tvhlog(LOG_INFO, "tvhdhomerun","HDHomerun device %08x switched IPs from %s to %s, updating",
+                     cDev->device_id, existing_ip, detected_ip);
+              tvhdhomerun_device_destroy(existing);
+              tvhdhomerun_device_create(cDev);
+            }
           }
           pthread_mutex_unlock(&global_lock);
         }
@@ -454,7 +478,6 @@ tvhdhomerun_device_destroy( tvhdhomerun_device_t *hd )
   }
 
 #define FREEM(x) free(hd->hd_info.x)
-  FREEM(ip_address);
   FREEM(friendlyname);
   FREEM(uuid);
   FREEM(deviceModel);
index b9a741f882da0a70cf04525a5a4030cc4ad95b5b..5aa318e2a17ececa69b9e3edfef4c43a4b7f636b 100644 (file)
@@ -21,6 +21,7 @@
 #include "tvheadend.h"
 #include "tvhpoll.h"
 #include "streaming.h"
+#include "tcp.h"
 #include "tvhdhomerun_private.h"
 
 static int
@@ -722,8 +723,10 @@ tvhdhomerun_frontend_create(tvhdhomerun_device_t *hd, struct hdhomerun_discover_
        strstr(hfe->mi_name, " Tuner ") &&
        strstr(hfe->mi_name, " #"))) {
     char lname[256];
+    char ip[64];
+    tcp_get_str_from_ip((struct sockaddr *)&hd->hd_info.ip_address, ip, sizeof(ip));
     snprintf(lname, sizeof(lname), "HDHomeRun %s Tuner #%i (%s)",
-             dvb_type2str(type), hfe->hf_tunerNumber, hd->hd_info.ip_address);
+             dvb_type2str(type), hfe->hf_tunerNumber, ip);
     free(hfe->mi_name);
     hfe->mi_name = strdup(lname);
   }
index a65a18cb4140d2df1bd2d4449b70658b9a47a30c..93235f7e965bb7c2ddaa7560020d268588628387 100644 (file)
@@ -35,7 +35,7 @@ static struct hdhomerun_debug_t* hdhomerun_debug_obj = 0;
 
 struct tvhdhomerun_device_info
 {
-  char *ip_address;         /* IP address */
+  struct sockaddr_storage ip_address;         /* IP address */
   char *friendlyname;
   char *deviceModel;
   char *uuid;