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
|
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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue