mirror of
https://github.com/Silicondust/libhdhomerun
synced 2025-07-06 04:52:19 -07:00
release 20190607
This commit is contained in:
parent
9719cbc7a5
commit
a84eb45c43
5 changed files with 155 additions and 109 deletions
2
Makefile
2
Makefile
|
@ -32,7 +32,7 @@ else
|
|||
LDFLAGS += -lsocket
|
||||
endif
|
||||
ifeq ($(OS),Darwin)
|
||||
CFLAGS += -arch i386 -arch x86_64
|
||||
CFLAGS += -arch x86_64
|
||||
LIBEXT := .dylib
|
||||
SHARED := -dynamiclib -install_name libhdhomerun$(LIBEXT)
|
||||
endif
|
||||
|
|
|
@ -91,27 +91,37 @@ static int discover_print(char *target_ip_str)
|
|||
}
|
||||
|
||||
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);
|
||||
if (count < 0) {
|
||||
int result_count = hdhomerun_discover_find_devices_custom_v2(target_ip, HDHOMERUN_DEVICE_TYPE_WILDCARD, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64);
|
||||
if (result_count < 0) {
|
||||
fprintf(stderr, "error sending discover request\n");
|
||||
return -1;
|
||||
}
|
||||
if (count == 0) {
|
||||
printf("no devices found\n");
|
||||
return 0;
|
||||
|
||||
struct hdhomerun_discover_device_t *result = result_list;
|
||||
struct hdhomerun_discover_device_t *result_end = result_list + result_count;
|
||||
|
||||
int valid_count = 0;
|
||||
while (result < result_end) {
|
||||
if (result->device_id == 0) {
|
||||
result++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int index;
|
||||
for (index = 0; index < count; index++) {
|
||||
struct hdhomerun_discover_device_t *result = &result_list[index];
|
||||
printf("hdhomerun device %08X found at %u.%u.%u.%u\n",
|
||||
(unsigned int)result->device_id,
|
||||
(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
|
||||
);
|
||||
|
||||
valid_count++;
|
||||
result++;
|
||||
}
|
||||
|
||||
return count;
|
||||
if (valid_count == 0) {
|
||||
printf("no devices found\n");
|
||||
}
|
||||
|
||||
return valid_count;
|
||||
}
|
||||
|
||||
static int cmd_get(const char *item)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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 (target_ip == 0x00000000) {
|
||||
target_ip = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
|
@ -205,12 +183,15 @@ static bool hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, u
|
|||
unsigned int i;
|
||||
for (i = 1; i < ds->sock_count; i++) {
|
||||
struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
|
||||
|
||||
if (target_ip != 0xFFFFFFFF) {
|
||||
if (dss->subnet_mask == 0) {
|
||||
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);
|
||||
}
|
||||
|
@ -226,15 +207,6 @@ static bool hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, u
|
|||
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)
|
||||
{
|
||||
switch (device_id >> 20) {
|
||||
|
|
|
@ -53,7 +53,7 @@ typedef struct {
|
|||
|
||||
#define LIBHDHOMERUN_API
|
||||
|
||||
#if !defined(alignas)
|
||||
#if !defined(alignas) && !defined(__cplusplus)
|
||||
#define alignas(n) __attribute__((aligned(n)))
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -23,14 +23,6 @@
|
|||
#include <net/if.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
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
@ -39,28 +31,79 @@ struct hdhomerun_sock_t {
|
|||
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 sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sock == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ifconf ifc;
|
||||
size_t ifreq_buffer_size = 1024;
|
||||
size_t ifreq_buffer_size = 0;
|
||||
void *ifreq_buffer = NULL;
|
||||
|
||||
while (1) {
|
||||
ifc.ifc_len = (int)ifreq_buffer_size;
|
||||
ifc.ifc_buf = (char *)malloc(ifreq_buffer_size);
|
||||
if (!ifc.ifc_buf) {
|
||||
ifreq_buffer_size += 64 * sizeof(struct ifreq);
|
||||
|
||||
void *old_buffer = ifreq_buffer;
|
||||
ifreq_buffer = realloc(old_buffer, ifreq_buffer_size);
|
||||
if (!ifreq_buffer) {
|
||||
if (old_buffer) {
|
||||
free(old_buffer);
|
||||
}
|
||||
close(sock);
|
||||
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) {
|
||||
free(ifc.ifc_buf);
|
||||
free(ifreq_buffer);
|
||||
close(sock);
|
||||
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) {
|
||||
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 *end = ifc.ifc_buf + ifc.ifc_len;
|
||||
|
||||
int count = 0;
|
||||
while (ptr < end) {
|
||||
|
||||
while (ptr + sizeof(struct ifreq) <= end) {
|
||||
struct ifreq *ifr = (struct ifreq *)ptr;
|
||||
ptr += _SIZEOF_ADDR_IFREQ(*ifr);
|
||||
ptr += sizeof(struct ifreq);
|
||||
|
||||
/* Flags. */
|
||||
if (ioctl(sock, SIOCGIFFLAGS, ifr) != 0) {
|
||||
if (!hdhomerun_local_ip_info_add(ip_info, sock, ifr)) {
|
||||
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++;
|
||||
|
||||
if (count >= max_count) {
|
||||
ip_info = NULL;
|
||||
} else {
|
||||
ip_info++;
|
||||
}
|
||||
}
|
||||
|
||||
free(ifc.ifc_buf);
|
||||
free(ifreq_buffer);
|
||||
close(sock);
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue