From: Michael Marley Date: Sun, 10 Apr 2016 19:05:17 +0000 (-0400) Subject: input: tvhdhomerun: Handle the device changing IP addresses X-Git-Tag: v4.2.1~676 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=58966cdf8c3c1e7cf88d056b05c6cd2ab4160b52;p=thirdparty%2Ftvheadend.git input: tvhdhomerun: Handle the device changing IP addresses 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. --- diff --git a/src/input/mpegts/tvhdhomerun/tvhdhomerun.c b/src/input/mpegts/tvhdhomerun/tvhdhomerun.c index 48b946ac4..81534bcc2 100644 --- a/src/input/mpegts/tvhdhomerun/tvhdhomerun.c +++ b/src/input/mpegts/tvhdhomerun/tvhdhomerun.c @@ -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); diff --git a/src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c b/src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c index b9a741f88..5aa318e2a 100644 --- a/src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c +++ b/src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c @@ -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); } diff --git a/src/input/mpegts/tvhdhomerun/tvhdhomerun_private.h b/src/input/mpegts/tvhdhomerun/tvhdhomerun_private.h index a65a18cb4..93235f7e9 100644 --- a/src/input/mpegts/tvhdhomerun/tvhdhomerun_private.h +++ b/src/input/mpegts/tvhdhomerun/tvhdhomerun_private.h @@ -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;