release 20190607

This commit is contained in:
nickkelsey 2019-06-07 12:14:40 -07:00
parent 9719cbc7a5
commit a84eb45c43
5 changed files with 155 additions and 109 deletions

View file

@ -32,7 +32,7 @@ else
LDFLAGS += -lsocket LDFLAGS += -lsocket
endif endif
ifeq ($(OS),Darwin) ifeq ($(OS),Darwin)
CFLAGS += -arch i386 -arch x86_64 CFLAGS += -arch x86_64
LIBEXT := .dylib LIBEXT := .dylib
SHARED := -dynamiclib -install_name libhdhomerun$(LIBEXT) SHARED := -dynamiclib -install_name libhdhomerun$(LIBEXT)
endif endif

View file

@ -91,27 +91,37 @@ static int discover_print(char *target_ip_str)
} }
struct hdhomerun_discover_device_t result_list[64]; struct hdhomerun_discover_device_t result_list[64];
int count = hdhomerun_discover_find_devices_custom_v2(target_ip, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64); int result_count = hdhomerun_discover_find_devices_custom_v2(target_ip, HDHOMERUN_DEVICE_TYPE_WILDCARD, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64);
if (count < 0) { if (result_count < 0) {
fprintf(stderr, "error sending discover request\n"); fprintf(stderr, "error sending discover request\n");
return -1; return -1;
} }
if (count == 0) {
printf("no devices found\n");
return 0;
}
int index; struct hdhomerun_discover_device_t *result = result_list;
for (index = 0; index < count; index++) { struct hdhomerun_discover_device_t *result_end = result_list + result_count;
struct hdhomerun_discover_device_t *result = &result_list[index];
int valid_count = 0;
while (result < result_end) {
if (result->device_id == 0) {
result++;
continue;
}
printf("hdhomerun device %08X found at %u.%u.%u.%u\n", printf("hdhomerun device %08X found at %u.%u.%u.%u\n",
(unsigned int)result->device_id, (unsigned int)result->device_id,
(unsigned int)(result->ip_addr >> 24) & 0x0FF, (unsigned int)(result->ip_addr >> 16) & 0x0FF, (unsigned int)(result->ip_addr >> 24) & 0x0FF, (unsigned int)(result->ip_addr >> 16) & 0x0FF,
(unsigned int)(result->ip_addr >> 8) & 0x0FF, (unsigned int)(result->ip_addr >> 0) & 0x0FF (unsigned int)(result->ip_addr >> 8) & 0x0FF, (unsigned int)(result->ip_addr >> 0) & 0x0FF
); );
valid_count++;
result++;
} }
return count; if (valid_count == 0) {
printf("no devices found\n");
}
return valid_count;
} }
static int cmd_get(const char *item) static int cmd_get(const char *item)

View file

@ -168,34 +168,12 @@ static bool hdhomerun_discover_send_internal(struct hdhomerun_discover_t *ds, st
return hdhomerun_sock_sendto(dss->sock, target_ip, HDHOMERUN_DISCOVER_UDP_PORT, tx_pkt->start, tx_pkt->end - tx_pkt->start, 0); return hdhomerun_sock_sendto(dss->sock, target_ip, HDHOMERUN_DISCOVER_UDP_PORT, tx_pkt->start, tx_pkt->end - tx_pkt->start, 0);
} }
static bool hdhomerun_discover_send_wildcard_ip(struct hdhomerun_discover_t *ds, uint32_t device_type, uint32_t device_id) static bool hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
{ {
bool result = false; if (target_ip == 0x00000000) {
target_ip = 0xFFFFFFFF;
/*
* Send subnet broadcast using each local ip socket.
* This will work with multiple separate 169.254.x.x interfaces.
*/
unsigned int i;
for (i = 1; i < ds->sock_count; i++) {
struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
uint32_t target_ip = dss->local_ip | ~dss->subnet_mask;
result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id);
} }
/*
* If no local ip sockets then fall back to sending a global broadcast letting the OS choose the interface.
*/
if (!result) {
struct hdhomerun_discover_sock_t *dss = &ds->socks[0];
result = hdhomerun_discover_send_internal(ds, dss, 0xFFFFFFFF, device_type, device_id);
}
return result;
}
static bool hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
{
bool result = false; bool result = false;
/* /*
@ -205,11 +183,14 @@ static bool hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, u
unsigned int i; unsigned int i;
for (i = 1; i < ds->sock_count; i++) { for (i = 1; i < ds->sock_count; i++) {
struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
if (dss->subnet_mask == 0) {
continue; if (target_ip != 0xFFFFFFFF) {
} if (dss->subnet_mask == 0) {
if ((target_ip & dss->subnet_mask) != (dss->local_ip & dss->subnet_mask)) { continue;
continue; }
if ((target_ip & dss->subnet_mask) != (dss->local_ip & dss->subnet_mask)) {
continue;
}
} }
result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id); result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id);
@ -226,15 +207,6 @@ static bool hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, u
return result; return result;
} }
static bool hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
{
if (target_ip == 0) {
return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id);
} else {
return hdhomerun_discover_send_target_ip(ds, target_ip, device_type, device_id);
}
}
static bool hdhomerun_discover_is_legacy(uint32_t device_id) static bool hdhomerun_discover_is_legacy(uint32_t device_id)
{ {
switch (device_id >> 20) { switch (device_id >> 20) {

View file

@ -53,7 +53,7 @@ typedef struct {
#define LIBHDHOMERUN_API #define LIBHDHOMERUN_API
#if !defined(alignas) #if !defined(alignas) && !defined(__cplusplus)
#define alignas(n) __attribute__((aligned(n))) #define alignas(n) __attribute__((aligned(n)))
#endif #endif

View file

@ -1,7 +1,7 @@
/* /*
* hdhomerun_sock_posix.c * hdhomerun_sock_posix.c
* *
* Copyright © 2010-2016 Silicondust USA Inc. <www.silicondust.com>. * Copyright © 2010-2019 Silicondust USA Inc. <www.silicondust.com>.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -23,14 +23,6 @@
#include <net/if.h> #include <net/if.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#ifndef SIOCGIFCONF
#include <sys/sockio.h>
#endif
#ifndef _SIZEOF_ADDR_IFREQ
#define _SIZEOF_ADDR_IFREQ(x) sizeof(x)
#endif
#ifndef MSG_NOSIGNAL #ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0 #define MSG_NOSIGNAL 0
#endif #endif
@ -39,28 +31,79 @@ struct hdhomerun_sock_t {
int sock; int sock;
}; };
static bool hdhomerun_local_ip_info_add(struct hdhomerun_local_ip_info_t *ip_info, int sock, struct ifreq *ifr)
{
/* Flags. */
if (ioctl(sock, SIOCGIFFLAGS, ifr) != 0) {
return false;
}
if ((ifr->ifr_flags & IFF_UP) == 0) {
return false;
}
if ((ifr->ifr_flags & IFF_RUNNING) == 0) {
return false;
}
/* Local IP address. */
if (ioctl(sock, SIOCGIFADDR, ifr) != 0) {
return false;
}
struct sockaddr_in *ip_addr_in = (struct sockaddr_in *)&ifr->ifr_addr;
uint32_t ip_addr = ntohl(ip_addr_in->sin_addr.s_addr);
if (ip_addr == 0) {
return false;
}
/* Subnet mask. */
if (ioctl(sock, SIOCGIFNETMASK, ifr) != 0) {
return false;
}
struct sockaddr_in *subnet_mask_in = (struct sockaddr_in *)&ifr->ifr_addr;
uint32_t subnet_mask = ntohl(subnet_mask_in->sin_addr.s_addr);
/* Result. */
if (ip_info) {
ip_info->ip_addr = ip_addr;
ip_info->subnet_mask = subnet_mask;
}
return true;
}
#if defined(LIBHDHOMERUN_USE_LEGACY_SIOCGIFCONF)
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count) int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
{ {
int sock = socket(AF_INET, SOCK_DGRAM, 0); int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) { if (sock == -1) {
return -1; return -1;
} }
struct ifconf ifc; struct ifconf ifc;
size_t ifreq_buffer_size = 1024; size_t ifreq_buffer_size = 0;
void *ifreq_buffer = NULL;
while (1) { while (1) {
ifc.ifc_len = (int)ifreq_buffer_size; ifreq_buffer_size += 64 * sizeof(struct ifreq);
ifc.ifc_buf = (char *)malloc(ifreq_buffer_size);
if (!ifc.ifc_buf) { void *old_buffer = ifreq_buffer;
ifreq_buffer = realloc(old_buffer, ifreq_buffer_size);
if (!ifreq_buffer) {
if (old_buffer) {
free(old_buffer);
}
close(sock); close(sock);
return -1; return -1;
} }
memset(ifc.ifc_buf, 0, ifreq_buffer_size); ifc.ifc_len = (int)ifreq_buffer_size;
ifc.ifc_buf = (char *)ifreq_buffer;
memset(ifreq_buffer, 0, ifreq_buffer_size);
if (ioctl(sock, SIOCGIFCONF, &ifc) != 0) { if (ioctl(sock, SIOCGIFCONF, &ifc) != 0) {
free(ifc.ifc_buf); free(ifreq_buffer);
close(sock); close(sock);
return -1; return -1;
} }
@ -68,64 +111,85 @@ int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int
if (ifc.ifc_len < (int)ifreq_buffer_size) { if (ifc.ifc_len < (int)ifreq_buffer_size) {
break; break;
} }
free(ifc.ifc_buf);
ifreq_buffer_size += 1024;
} }
struct hdhomerun_local_ip_info_t *ip_info = (max_count > 0) ? ip_info_list : NULL;
char *ptr = ifc.ifc_buf; char *ptr = ifc.ifc_buf;
char *end = ifc.ifc_buf + ifc.ifc_len; char *end = ifc.ifc_buf + ifc.ifc_len;
int count = 0; int count = 0;
while (ptr < end) {
while (ptr + sizeof(struct ifreq) <= end) {
struct ifreq *ifr = (struct ifreq *)ptr; struct ifreq *ifr = (struct ifreq *)ptr;
ptr += _SIZEOF_ADDR_IFREQ(*ifr); ptr += sizeof(struct ifreq);
/* Flags. */ if (!hdhomerun_local_ip_info_add(ip_info, sock, ifr)) {
if (ioctl(sock, SIOCGIFFLAGS, ifr) != 0) {
continue; continue;
} }
if ((ifr->ifr_flags & IFF_UP) == 0) {
continue;
}
if ((ifr->ifr_flags & IFF_RUNNING) == 0) {
continue;
}
/* Local IP address. */
if (ioctl(sock, SIOCGIFADDR, ifr) != 0) {
continue;
}
struct sockaddr_in *ip_addr_in = (struct sockaddr_in *)&(ifr->ifr_addr);
uint32_t ip_addr = ntohl(ip_addr_in->sin_addr.s_addr);
if (ip_addr == 0) {
continue;
}
/* Subnet mask. */
if (ioctl(sock, SIOCGIFNETMASK, ifr) != 0) {
continue;
}
struct sockaddr_in *subnet_mask_in = (struct sockaddr_in *)&(ifr->ifr_addr);
uint32_t subnet_mask = ntohl(subnet_mask_in->sin_addr.s_addr);
/* Report. */
if (count < max_count) {
struct hdhomerun_local_ip_info_t *ip_info = &ip_info_list[count];
ip_info->ip_addr = ip_addr;
ip_info->subnet_mask = subnet_mask;
}
count++; count++;
if (count >= max_count) {
ip_info = NULL;
} else {
ip_info++;
}
} }
free(ifc.ifc_buf); free(ifreq_buffer);
close(sock); close(sock);
return count; return count;
} }
#else
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
{
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) {
return -1;
}
struct if_nameindex *ni = if_nameindex();
if (!ni) {
close(sock);
return -1;
}
struct hdhomerun_local_ip_info_t *ip_info = (max_count > 0) ? ip_info_list : NULL;
struct if_nameindex *iter = ni;
int count = 0;
while (1) {
if (!iter->if_name) {
if (iter->if_index == 0) {
break;
}
iter++;
continue;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, iter->if_name, IF_NAMESIZE);
iter++;
if (!hdhomerun_local_ip_info_add(ip_info, sock, &ifr)) {
continue;
}
count++;
if (count >= max_count) {
ip_info = NULL;
} else {
ip_info++;
}
}
if_freenameindex(ni);
close(sock);
return count;
}
#endif
static struct hdhomerun_sock_t *hdhomerun_sock_create_internal(int protocol) static struct hdhomerun_sock_t *hdhomerun_sock_create_internal(int protocol)
{ {