Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mamarley authored and perexg committed Apr 11, 2016
1 parent 37ed360 commit 58966cd
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 12 deletions.
43 changes: 33 additions & 10 deletions src/input/mpegts/tvhdhomerun/tvhdhomerun.c
Expand Up @@ -21,6 +21,7 @@
#include "input.h"
#include "htsbuf.h"
#include "settings.h"
#include "tcp.h"
#include "tvhdhomerun.h"
#include "tvhdhomerun_private.h"

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c
Expand Up @@ -21,6 +21,7 @@
#include "tvheadend.h"
#include "tvhpoll.h"
#include "streaming.h"
#include "tcp.h"
#include "tvhdhomerun_private.h"

static int
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion src/input/mpegts/tvhdhomerun/tvhdhomerun_private.h
Expand Up @@ -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;
Expand Down

0 comments on commit 58966cd

Please sign in to comment.