libhdhomerun 20160130

This commit is contained in:
Nick Kelsey 2016-01-30 11:51:36 -08:00
parent a2475b9991
commit 8d861a8f0b
29 changed files with 916 additions and 725 deletions

View file

@ -1,28 +1,11 @@
/*
* README
*
* Copyright © 2005-2009 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
Copyright © 2005-2016 Silicondust USA Inc. <www.silicondust.com>.
Top level include file: hdhomerun.h
This library implements the libhdhomerun protocol for use with Silicondust HDHomeRun TV tuners.
Top level API: hdhomerun_device. See hdhomerun_device.h for documentation.
To compile simply "make" - this will compile both the library and the hdhomerun_config command line
utility suitable for sending commands or scripting control of a HDHomeRun.
The hdhomerun_device API should be used rather than the low level control and video APIs required with previous versions.
The top level API is hdhomerun_device - see hdhomerun_device.h for documentation.
Additional libraries required:
- pthread

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_channels.c
*
* Copyright © 2007-2008 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2007-2014 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

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_channels.h
*
* Copyright © 2007-2008 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2007-2015 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
@ -25,27 +25,27 @@ extern "C" {
struct hdhomerun_channel_entry_t;
struct hdhomerun_channel_list_t;
extern LIBTYPE const char *hdhomerun_channelmap_get_channelmap_from_country_source(const char *countrycode, const char *source, const char *supported);
extern LIBTYPE const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap);
extern LIBHDHOMERUN_API const char *hdhomerun_channelmap_get_channelmap_from_country_source(const char *countrycode, const char *source, const char *supported);
extern LIBHDHOMERUN_API const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap);
extern LIBTYPE uint16_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry);
extern LIBTYPE uint32_t hdhomerun_channel_entry_frequency(struct hdhomerun_channel_entry_t *entry);
extern LIBTYPE const char *hdhomerun_channel_entry_name(struct hdhomerun_channel_entry_t *entry);
extern LIBHDHOMERUN_API uint16_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry);
extern LIBHDHOMERUN_API uint32_t hdhomerun_channel_entry_frequency(struct hdhomerun_channel_entry_t *entry);
extern LIBHDHOMERUN_API const char *hdhomerun_channel_entry_name(struct hdhomerun_channel_entry_t *entry);
extern LIBTYPE struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap);
extern LIBTYPE void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list);
extern LIBHDHOMERUN_API struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap);
extern LIBHDHOMERUN_API void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list);
extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list);
extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list);
extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry);
extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry);
extern LIBTYPE uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list);
extern LIBTYPE uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list);
extern LIBHDHOMERUN_API struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list);
extern LIBHDHOMERUN_API struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list);
extern LIBHDHOMERUN_API struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry);
extern LIBHDHOMERUN_API struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry);
extern LIBHDHOMERUN_API uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list);
extern LIBHDHOMERUN_API uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list);
extern LIBTYPE uint32_t hdhomerun_channel_frequency_round(uint32_t frequency, uint32_t resolution);
extern LIBTYPE uint32_t hdhomerun_channel_frequency_round_normal(uint32_t frequency);
extern LIBTYPE uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint16_t channel_number);
extern LIBTYPE uint16_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency);
extern LIBHDHOMERUN_API uint32_t hdhomerun_channel_frequency_round(uint32_t frequency, uint32_t resolution);
extern LIBHDHOMERUN_API uint32_t hdhomerun_channel_frequency_round_normal(uint32_t frequency);
extern LIBHDHOMERUN_API uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint16_t channel_number);
extern LIBHDHOMERUN_API uint16_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_channelscan.c
*
* Copyright © 2007-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2007-2015 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

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_channelscan.h
*
* Copyright © 2007-2008 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2007-2015 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
@ -29,12 +29,12 @@ extern "C" {
struct hdhomerun_channelscan_t;
extern LIBTYPE struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, const char *channelmap);
extern LIBTYPE void channelscan_destroy(struct hdhomerun_channelscan_t *scan);
extern LIBHDHOMERUN_API struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, const char *channelmap);
extern LIBHDHOMERUN_API void channelscan_destroy(struct hdhomerun_channelscan_t *scan);
extern LIBTYPE int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
extern LIBTYPE int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
extern LIBTYPE uint8_t channelscan_get_progress(struct hdhomerun_channelscan_t *scan);
extern LIBHDHOMERUN_API int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
extern LIBHDHOMERUN_API int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
extern LIBHDHOMERUN_API uint8_t channelscan_get_progress(struct hdhomerun_channelscan_t *scan);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_config.c
*
* Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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
@ -20,16 +20,6 @@
#include "hdhomerun.h"
/*
* The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
* Attempting to restore on exit fails to restore if the program is terminated by the user.
* Solution - set the output format each printf.
*/
#if defined(__WINDOWS__)
#define printf console_printf
#define vprintf console_vprintf
#endif
static const char *appname;
struct hdhomerun_device_t *hd;
@ -413,7 +403,7 @@ static int cmd_save(const char *tuner_str, const char *filename)
}
/* Windows - indicate activity to suppress auto sleep mode. */
#if defined(__WINDOWS__)
#if defined(_WIN32)
SetThreadExecutionState(ES_SYSTEM_REQUIRED);
#endif
@ -625,7 +615,9 @@ static int main_cmd(int argc, char *argv[])
static int main_internal(int argc, char *argv[])
{
#if defined(__WINDOWS__)
#if defined(_WIN32)
/* Configure console for UTF-8. */
SetConsoleOutputCP(CP_UTF8);
/* Initialize network socket support. */
WORD wVersionRequested = MAKEWORD(2, 0);
WSADATA wsaData;

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_control.c
*
* Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2016 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
@ -30,7 +30,7 @@ struct hdhomerun_control_sock_t {
uint32_t desired_device_ip;
uint32_t actual_device_id;
uint32_t actual_device_ip;
hdhomerun_sock_t sock;
struct hdhomerun_sock_t *sock;
struct hdhomerun_debug_t *dbg;
struct hdhomerun_pkt_t tx_pkt;
struct hdhomerun_pkt_t rx_pkt;
@ -38,12 +38,12 @@ struct hdhomerun_control_sock_t {
static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs)
{
if (cs->sock == HDHOMERUN_SOCK_INVALID) {
if (!cs->sock) {
return;
}
hdhomerun_sock_destroy(cs->sock);
cs->sock = HDHOMERUN_SOCK_INVALID;
cs->sock = NULL;
}
void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip)
@ -65,7 +65,6 @@ struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, ui
}
cs->dbg = dbg;
cs->sock = HDHOMERUN_SOCK_INVALID;
hdhomerun_control_set_device(cs, device_id, device_ip);
return cs;
@ -79,7 +78,7 @@ void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs)
static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs)
{
if (cs->sock != HDHOMERUN_SOCK_INVALID) {
if (cs->sock) {
return TRUE;
}
@ -103,7 +102,7 @@ static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs
/* Create socket. */
cs->sock = hdhomerun_sock_create_tcp();
if (cs->sock == HDHOMERUN_SOCK_INVALID) {
if (!cs->sock) {
hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to create socket (%d)\n", hdhomerun_sock_getlasterror());
return FALSE;
}
@ -216,7 +215,7 @@ static int hdhomerun_control_send_recv_internal(struct hdhomerun_control_sock_t
int i;
for (i = 0; i < 2; i++) {
if (cs->sock == HDHOMERUN_SOCK_INVALID) {
if (!cs->sock) {
if (!hdhomerun_control_connect_sock(cs)) {
hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: connect failed\n");
return -1;

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_control.h
*
* Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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
@ -37,20 +37,20 @@ struct hdhomerun_control_sock_t;
*
* When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy.
*/
extern LIBTYPE struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip, struct hdhomerun_debug_t *dbg);
extern LIBTYPE void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs);
extern LIBHDHOMERUN_API struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip, struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs);
/*
* Get the actual device id or ip of the device.
*
* Returns 0 if the device id cannot be determined.
*/
extern LIBTYPE uint32_t hdhomerun_control_get_device_id(struct hdhomerun_control_sock_t *cs);
extern LIBTYPE uint32_t hdhomerun_control_get_device_ip(struct hdhomerun_control_sock_t *cs);
extern LIBTYPE uint32_t hdhomerun_control_get_device_id_requested(struct hdhomerun_control_sock_t *cs);
extern LIBTYPE uint32_t hdhomerun_control_get_device_ip_requested(struct hdhomerun_control_sock_t *cs);
extern LIBHDHOMERUN_API uint32_t hdhomerun_control_get_device_id(struct hdhomerun_control_sock_t *cs);
extern LIBHDHOMERUN_API uint32_t hdhomerun_control_get_device_ip(struct hdhomerun_control_sock_t *cs);
extern LIBHDHOMERUN_API uint32_t hdhomerun_control_get_device_id_requested(struct hdhomerun_control_sock_t *cs);
extern LIBHDHOMERUN_API uint32_t hdhomerun_control_get_device_ip_requested(struct hdhomerun_control_sock_t *cs);
extern LIBTYPE void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip);
extern LIBHDHOMERUN_API void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip);
/*
* Get the local machine IP address used when communicating with the device.
@ -59,12 +59,12 @@ extern LIBTYPE void hdhomerun_control_set_device(struct hdhomerun_control_sock_t
*
* Returns 32-bit IP address with native endianness, or 0 on error.
*/
extern LIBTYPE uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs);
extern LIBHDHOMERUN_API uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs);
/*
* Low-level communication.
*/
extern LIBTYPE int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type);
extern LIBHDHOMERUN_API int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type);
/*
* Get/set a control variable on the device.
@ -83,9 +83,9 @@ extern LIBTYPE int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *
* Returns 0 if the operation was rejected (pvalue NULL, perror set).
* Returns -1 if a communication error occurs.
*/
extern LIBTYPE int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror);
extern LIBTYPE int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror);
extern LIBTYPE int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror);
extern LIBHDHOMERUN_API int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror);
extern LIBHDHOMERUN_API int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror);
extern LIBHDHOMERUN_API int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror);
/*
* Upload new firmware to the device.
@ -96,7 +96,7 @@ extern LIBTYPE int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_s
* Returns 0 if the upload was rejected.
* Returns -1 if an error occurs.
*/
extern LIBTYPE int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file);
extern LIBHDHOMERUN_API int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_debug.c
*
* Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2007-2016 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
@ -65,7 +65,7 @@ struct hdhomerun_debug_t
char *file_name;
FILE *file_fp;
hdhomerun_sock_t sock;
struct hdhomerun_sock_t *sock;
};
static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg);
@ -77,8 +77,6 @@ struct hdhomerun_debug_t *hdhomerun_debug_create(void)
return NULL;
}
dbg->sock = HDHOMERUN_SOCK_INVALID;
pthread_mutex_init(&dbg->print_lock, NULL);
pthread_mutex_init(&dbg->queue_lock, NULL);
pthread_mutex_init(&dbg->send_lock, NULL);
@ -109,7 +107,7 @@ void hdhomerun_debug_destroy(struct hdhomerun_debug_t *dbg)
if (dbg->file_fp) {
fclose(dbg->file_fp);
}
if (dbg->sock != HDHOMERUN_SOCK_INVALID) {
if (dbg->sock) {
hdhomerun_sock_destroy(dbg->sock);
}
@ -124,9 +122,9 @@ static void hdhomerun_debug_close_internal(struct hdhomerun_debug_t *dbg)
dbg->file_fp = NULL;
}
if (dbg->sock != HDHOMERUN_SOCK_INVALID) {
if (dbg->sock) {
hdhomerun_sock_destroy(dbg->sock);
dbg->sock = HDHOMERUN_SOCK_INVALID;
dbg->sock = NULL;
}
}
@ -350,7 +348,7 @@ static bool_t hdhomerun_debug_output_message_file(struct hdhomerun_debug_t *dbg,
/* Send lock held by caller */
static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
{
if (dbg->sock == HDHOMERUN_SOCK_INVALID) {
if (!dbg->sock) {
uint64_t current_time = getcurrenttime();
if (current_time < dbg->connect_delay) {
return FALSE;
@ -358,7 +356,7 @@ static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg,
dbg->connect_delay = current_time + HDHOMERUN_DEBUG_CONNECT_RETRY_TIME;
dbg->sock = hdhomerun_sock_create_tcp();
if (dbg->sock == HDHOMERUN_SOCK_INVALID) {
if (!dbg->sock) {
return FALSE;
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_debug.h
*
* Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2007-2015 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
@ -32,20 +32,20 @@ extern "C" {
struct hdhomerun_debug_t;
extern LIBTYPE struct hdhomerun_debug_t *hdhomerun_debug_create(void);
extern LIBTYPE void hdhomerun_debug_destroy(struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API struct hdhomerun_debug_t *hdhomerun_debug_create(void);
extern LIBHDHOMERUN_API void hdhomerun_debug_destroy(struct hdhomerun_debug_t *dbg);
extern LIBTYPE void hdhomerun_debug_set_prefix(struct hdhomerun_debug_t *dbg, const char *prefix);
extern LIBTYPE void hdhomerun_debug_set_filename(struct hdhomerun_debug_t *dbg, const char *filename);
extern LIBTYPE void hdhomerun_debug_enable(struct hdhomerun_debug_t *dbg);
extern LIBTYPE void hdhomerun_debug_disable(struct hdhomerun_debug_t *dbg);
extern LIBTYPE bool_t hdhomerun_debug_enabled(struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API void hdhomerun_debug_set_prefix(struct hdhomerun_debug_t *dbg, const char *prefix);
extern LIBHDHOMERUN_API void hdhomerun_debug_set_filename(struct hdhomerun_debug_t *dbg, const char *filename);
extern LIBHDHOMERUN_API void hdhomerun_debug_enable(struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API void hdhomerun_debug_disable(struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API bool_t hdhomerun_debug_enabled(struct hdhomerun_debug_t *dbg);
extern LIBTYPE void hdhomerun_debug_flush(struct hdhomerun_debug_t *dbg, uint64_t timeout);
extern LIBTYPE void hdhomerun_debug_close(struct hdhomerun_debug_t *dbg, uint64_t timeout);
extern LIBHDHOMERUN_API void hdhomerun_debug_flush(struct hdhomerun_debug_t *dbg, uint64_t timeout);
extern LIBHDHOMERUN_API void hdhomerun_debug_close(struct hdhomerun_debug_t *dbg, uint64_t timeout);
extern LIBTYPE void hdhomerun_debug_printf(struct hdhomerun_debug_t *dbg, const char *fmt, ...);
extern LIBTYPE void hdhomerun_debug_vprintf(struct hdhomerun_debug_t *dbg, const char *fmt, va_list args);
extern LIBHDHOMERUN_API void hdhomerun_debug_printf(struct hdhomerun_debug_t *dbg, const char *fmt, ...);
extern LIBHDHOMERUN_API void hdhomerun_debug_vprintf(struct hdhomerun_debug_t *dbg, const char *fmt, va_list args);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_device.c
*
* Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_device.h
*
* Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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
@ -63,25 +63,25 @@ extern "C" {
* <tuner index>
* /tuner<tuner index>
*/
extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg);
extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create_multicast(uint32_t multicast_ip, uint16_t multicast_port, struct hdhomerun_debug_t *dbg);
extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str, struct hdhomerun_debug_t *dbg);
extern LIBTYPE void hdhomerun_device_destroy(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API struct hdhomerun_device_t *hdhomerun_device_create_multicast(uint32_t multicast_ip, uint16_t multicast_port, struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str, struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API void hdhomerun_device_destroy(struct hdhomerun_device_t *hd);
/*
* Get the device id, ip, or tuner of the device instance.
*/
extern LIBTYPE const char *hdhomerun_device_get_name(struct hdhomerun_device_t *hd);
extern LIBTYPE uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd);
extern LIBTYPE uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd);
extern LIBTYPE uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd);
extern LIBTYPE uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd);
extern LIBTYPE unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API const char *hdhomerun_device_get_name(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd);
extern LIBTYPE int hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip);
extern LIBTYPE int hdhomerun_device_set_multicast(struct hdhomerun_device_t *hd, uint32_t multicast_ip, uint16_t multicast_port);
extern LIBTYPE int hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);
extern LIBTYPE int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str);
extern LIBHDHOMERUN_API int hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip);
extern LIBHDHOMERUN_API int hdhomerun_device_set_multicast(struct hdhomerun_device_t *hd, uint32_t multicast_ip, uint16_t multicast_port);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str);
/*
* Get the local machine IP address used when communicating with the device.
@ -90,7 +90,7 @@ extern LIBTYPE int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t
*
* Returns 32-bit IP address with native endianness, or 0 on error.
*/
extern LIBTYPE uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd);
/*
* Get operations.
@ -103,29 +103,29 @@ extern LIBTYPE uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun
* Returns 0 if the operation was rejected.
* Returns -1 if a communication error occurred.
*/
extern LIBTYPE int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status);
extern LIBTYPE int hdhomerun_device_get_tuner_vstatus(struct hdhomerun_device_t *hd, char **pvstatus_str, struct hdhomerun_tuner_vstatus_t *vstatus);
extern LIBTYPE int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo);
extern LIBTYPE int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel);
extern LIBTYPE int hdhomerun_device_get_tuner_vchannel(struct hdhomerun_device_t *hd, char **pvchannel);
extern LIBTYPE int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap);
extern LIBTYPE int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter);
extern LIBTYPE int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram);
extern LIBTYPE int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget);
extern LIBTYPE int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount);
extern LIBTYPE int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner);
extern LIBTYPE int hdhomerun_device_get_oob_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status);
extern LIBTYPE int hdhomerun_device_get_oob_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount);
extern LIBTYPE int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget);
extern LIBTYPE int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num);
extern LIBTYPE int hdhomerun_device_get_supported(struct hdhomerun_device_t *hd, char *prefix, char **pstr);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_vstatus(struct hdhomerun_device_t *hd, char **pvstatus_str, struct hdhomerun_tuner_vstatus_t *vstatus);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_vchannel(struct hdhomerun_device_t *hd, char **pvchannel);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount);
extern LIBHDHOMERUN_API int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner);
extern LIBHDHOMERUN_API int hdhomerun_device_get_oob_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status);
extern LIBHDHOMERUN_API int hdhomerun_device_get_oob_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount);
extern LIBHDHOMERUN_API int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget);
extern LIBHDHOMERUN_API int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num);
extern LIBHDHOMERUN_API int hdhomerun_device_get_supported(struct hdhomerun_device_t *hd, char *prefix, char **pstr);
extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status);
extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status);
extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status);
extern LIBHDHOMERUN_API uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status);
extern LIBHDHOMERUN_API uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status);
extern LIBHDHOMERUN_API uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status);
extern LIBTYPE const char *hdhomerun_device_get_hw_model_str(struct hdhomerun_device_t *hd);
extern LIBTYPE const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API const char *hdhomerun_device_get_hw_model_str(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd);
/*
* Set operations.
@ -136,15 +136,15 @@ extern LIBTYPE const char *hdhomerun_device_get_model_str(struct hdhomerun_devic
* Returns 0 if the operation was rejected.
* Returns -1 if a communication error occurred.
*/
extern LIBTYPE int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel);
extern LIBTYPE int hdhomerun_device_set_tuner_vchannel(struct hdhomerun_device_t *hd, const char *vchannel);
extern LIBTYPE int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap);
extern LIBTYPE int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter);
extern LIBTYPE int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]);
extern LIBTYPE int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program);
extern LIBTYPE int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target);
extern LIBTYPE int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target);
extern LIBTYPE int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_device_t *hd, const char *modulation_list);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner_vchannel(struct hdhomerun_device_t *hd, const char *vchannel);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program);
extern LIBHDHOMERUN_API int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target);
extern LIBHDHOMERUN_API int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target);
extern LIBHDHOMERUN_API int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_device_t *hd, const char *modulation_list);
/*
* Get/set a named control variable on the device.
@ -163,8 +163,8 @@ extern LIBTYPE int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_dev
* Returns 0 if the operation was rejected (pvalue NULL, perror set).
* Returns -1 if a communication error occurs.
*/
extern LIBTYPE int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror);
extern LIBTYPE int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror);
extern LIBHDHOMERUN_API int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror);
extern LIBHDHOMERUN_API int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror);
/*
* Tuner locking.
@ -179,14 +179,14 @@ extern LIBTYPE int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const
* previously held lock. If locking is used then this function must be called
* before destroying the hdhomerun_device object.
*/
extern LIBTYPE int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror);
extern LIBTYPE int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd);
extern LIBTYPE int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror);
extern LIBHDHOMERUN_API int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd);
/*
* Intended only for non persistent connections; eg, hdhomerun_config.
*/
extern LIBTYPE void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey);
extern LIBHDHOMERUN_API void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey);
/*
* Wait for tuner lock after channel change.
@ -198,7 +198,7 @@ extern LIBTYPE void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_de
* It will return quickly if there is no signal detected.
* Worst case it will time out after 1.5 seconds - the case where there is signal but no lock.
*/
extern LIBTYPE int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status);
extern LIBHDHOMERUN_API int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status);
/*
* Stream a filtered program or the unfiltered stream.
@ -216,18 +216,18 @@ extern LIBTYPE int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd,
*
* The hdhomerun_device_stream_stop function tells the device to stop streaming data.
*/
extern LIBTYPE int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd);
extern LIBTYPE uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size);
extern LIBTYPE void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd);
extern LIBTYPE void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size);
extern LIBHDHOMERUN_API void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd);
/*
* Channel scan API.
*/
extern LIBTYPE int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap);
extern LIBTYPE int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
extern LIBTYPE int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap);
extern LIBHDHOMERUN_API int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
extern LIBHDHOMERUN_API int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
extern LIBHDHOMERUN_API uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd);
/*
* Upload new firmware to the device.
@ -238,19 +238,19 @@ extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomeru
* Returns 0 if the upload was rejected.
* Returns -1 if an error occurs.
*/
extern LIBTYPE int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file);
extern LIBHDHOMERUN_API int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file);
/*
* Low level accessor functions.
*/
extern LIBTYPE struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd);
extern LIBTYPE struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd);
/*
* Debug print internal stats.
*/
extern LIBTYPE void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd);
extern LIBTYPE void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats);
extern LIBHDHOMERUN_API void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_device_selector.c
*
* Copyright © 2009-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2009-2016 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
@ -56,7 +56,7 @@ void hdhomerun_device_selector_destroy(struct hdhomerun_device_selector_t *hds,
free(hds);
}
LIBTYPE int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds)
int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds)
{
return (int)hds->hd_count;
}
@ -263,7 +263,7 @@ int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t
return count;
}
#if defined(__WINDOWS__)
#if defined(_WIN32) && !defined(_WINRT)
int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource)
{
HKEY tuners_key;
@ -374,8 +374,8 @@ static bool_t hdhomerun_device_selector_choose_test(struct hdhomerun_device_sele
/*
* Test local port.
*/
hdhomerun_sock_t test_sock = hdhomerun_sock_create_udp();
if (test_sock == HDHOMERUN_SOCK_INVALID) {
struct hdhomerun_sock_t *test_sock = hdhomerun_sock_create_udp();
if (!test_sock) {
hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_choose_test: device %s in use, failed to create test sock\n", name);
return FALSE;
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_device_selector.h
*
* Copyright © 2009 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2009-2015 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
@ -27,34 +27,35 @@ extern "C" {
* All tuners registered with a specific device selector instance must have the same signal source.
* The dbg parameter may be null.
*/
extern LIBTYPE struct hdhomerun_device_selector_t *hdhomerun_device_selector_create(struct hdhomerun_debug_t *dbg);
extern LIBTYPE void hdhomerun_device_selector_destroy(struct hdhomerun_device_selector_t *hds, bool_t destroy_devices);
extern LIBHDHOMERUN_API struct hdhomerun_device_selector_t *hdhomerun_device_selector_create(struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API void hdhomerun_device_selector_destroy(struct hdhomerun_device_selector_t *hds, bool_t destroy_devices);
/*
* Get the number of devices in the list.
*/
extern LIBTYPE int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds);
extern LIBHDHOMERUN_API int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds);
/*
* Populate device selector with devices from given source.
* Returns the number of devices populated.
*/
extern LIBTYPE int hdhomerun_device_selector_load_from_str(struct hdhomerun_device_selector_t *hds, char *device_str);
extern LIBTYPE int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename);
#if defined(__WINDOWS__)
extern LIBTYPE int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource);
extern LIBHDHOMERUN_API int hdhomerun_device_selector_load_from_str(struct hdhomerun_device_selector_t *hds, char *device_str);
extern LIBHDHOMERUN_API int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename);
#if defined(_WIN32) && !defined(_WINRT)
extern LIBHDHOMERUN_API int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource);
#endif
/*
* Add/remove a device from the selector list.
*/
extern LIBTYPE void hdhomerun_device_selector_add_device(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *hd);
extern LIBTYPE void hdhomerun_device_selector_remove_device(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API void hdhomerun_device_selector_add_device(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *hd);
extern LIBHDHOMERUN_API void hdhomerun_device_selector_remove_device(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *hd);
/*
* Find a device in the selector list.
*/
extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_selector_find_device(struct hdhomerun_device_selector_t *hds, uint32_t device_id, unsigned int tuner_index);
extern LIBHDHOMERUN_API struct hdhomerun_device_t *hdhomerun_device_selector_find_device(struct hdhomerun_device_selector_t *hds, uint32_t device_id, unsigned int tuner_index);
/*
* Select and lock an available device.
@ -79,7 +80,7 @@ extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_selector_find_device(
* to refresh the lock. If this function succeeds then the same device can be used. If this fucntion fails
* then call hdhomerun_device_selector_choose_and_lock() to choose and lock an available tuner.
*/
extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_selector_choose_and_lock(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *prefered);
extern LIBHDHOMERUN_API struct hdhomerun_device_t *hdhomerun_device_selector_choose_and_lock(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *prefered);
#ifdef __cplusplus
}

View file

@ -23,7 +23,7 @@
#define HDHOMERUN_DISOCVER_MAX_SOCK_COUNT 16
struct hdhomerun_discover_sock_t {
hdhomerun_sock_t sock;
struct hdhomerun_sock_t *sock;
bool_t detected;
uint32_t local_ip;
uint32_t subnet_mask;
@ -54,8 +54,9 @@ static bool_t hdhomerun_discover_sock_add(struct hdhomerun_discover_t *ds, uint3
}
/* Create socket. */
hdhomerun_sock_t sock = hdhomerun_sock_create_udp();
if (sock == HDHOMERUN_SOCK_INVALID) {
struct hdhomerun_sock_t *sock = hdhomerun_sock_create_udp();
if (!sock) {
hdhomerun_debug_printf(ds->dbg, "discover: failed to allocate socket (%d)\n", hdhomerun_sock_getlasterror());
return FALSE;
}

View file

@ -45,14 +45,14 @@ struct hdhomerun_discover_device_t {
* Returns the number of devices found.
* Retruns -1 on error.
*/
extern LIBTYPE int hdhomerun_discover_find_devices_custom_v2(uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count);
extern LIBHDHOMERUN_API int hdhomerun_discover_find_devices_custom_v2(uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count);
/*
* Optional: persistent discover instance available for discover polling use.
*/
extern LIBTYPE struct hdhomerun_discover_t *hdhomerun_discover_create(struct hdhomerun_debug_t *dbg);
extern LIBTYPE void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds);
extern LIBTYPE int hdhomerun_discover_find_devices_v2(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count);
extern LIBHDHOMERUN_API struct hdhomerun_discover_t *hdhomerun_discover_create(struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds);
extern LIBHDHOMERUN_API int hdhomerun_discover_find_devices_v2(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count);
/*
* Verify that the device ID given is valid.
@ -63,7 +63,7 @@ extern LIBTYPE int hdhomerun_discover_find_devices_v2(struct hdhomerun_discover_
* Returns TRUE if valid.
* Returns FALSE if not valid.
*/
extern LIBTYPE bool_t hdhomerun_discover_validate_device_id(uint32_t device_id);
extern LIBHDHOMERUN_API bool_t hdhomerun_discover_validate_device_id(uint32_t device_id);
/*
* Detect if an IP address is multicast.
@ -71,7 +71,7 @@ extern LIBTYPE bool_t hdhomerun_discover_validate_device_id(uint32_t device_id);
* Returns TRUE if multicast.
* Returns FALSE if zero, unicast, expermental, or broadcast.
*/
extern LIBTYPE bool_t hdhomerun_discover_is_ip_multicast(uint32_t ip_addr);
extern LIBHDHOMERUN_API bool_t hdhomerun_discover_is_ip_multicast(uint32_t ip_addr);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_os.h
*
* Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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
@ -18,11 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if defined(_WIN32) || defined(_WIN64)
#define __WINDOWS__
#endif
#if defined(__WINDOWS__)
#if defined(_WIN32)
#include "hdhomerun_os_windows.h"
#else
#include "hdhomerun_os_posix.h"

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_os_posix.c
*
* Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2016 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
@ -21,8 +21,48 @@
#include "hdhomerun_os.h"
#if defined(__APPLE__)
#include <mach/clock.h>
#include <mach/mach.h>
static pthread_once_t clock_monotonic_once = PTHREAD_ONCE_INIT;
static clock_serv_t clock_monotonic_clock_serv;
static void clock_monotonic_init(void)
{
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clock_monotonic_clock_serv);
}
static inline void clock_monotonic_timespec(struct timespec *ts)
{
pthread_once(&clock_monotonic_once, clock_monotonic_init);
struct mach_timespec mt;
clock_get_time(clock_monotonic_clock_serv, &mt);
ts->tv_nsec = mt.tv_nsec;
ts->tv_sec = mt.tv_sec;
}
static inline void clock_realtime_timespec(struct timespec *ts)
{
struct timeval tv;
gettimeofday(&tv, NULL);
ts->tv_nsec = tv.tv_usec * 1000;
ts->tv_sec = tv.tv_sec;
}
#else
static inline void clock_monotonic_timespec(struct timespec *ts)
{
clock_gettime(CLOCK_MONOTONIC, ts);
}
static inline void clock_realtime_timespec(struct timespec *ts)
{
clock_gettime(CLOCK_REALTIME, ts);
}
#endif
static pthread_once_t random_get32_once = PTHREAD_ONCE_INIT;
@ -51,22 +91,9 @@ uint32_t random_get32(void)
uint64_t getcurrenttime(void)
{
#if defined(CLOCK_MONOTONIC)
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return ((uint64_t)t.tv_sec * 1000) + (t.tv_nsec / 1000000);
#elif defined(__APPLE__)
clock_serv_t clock_serv;
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clock_serv);
struct mach_timespec t;
clock_get_time(clock_serv, &t);
mach_port_deallocate(mach_task_self(), clock_serv);
return ((uint64_t)t.tv_sec * 1000) + (t.tv_nsec / 1000000);
#else
#error no clock source for getcurrenttime()
#endif
struct timespec ts;
clock_monotonic_timespec(&ts);
return ((uint64_t)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
}
void msleep_approx(uint64_t ms)
@ -97,6 +124,44 @@ void msleep_minimum(uint64_t ms)
}
}
void thread_cond_init(thread_cond_t *cond)
{
pthread_mutex_init(&cond->lock, NULL);
pthread_cond_init(&cond->cond, NULL);
}
void thread_cond_dispose(thread_cond_t *cond)
{
}
void thread_cond_signal(thread_cond_t *cond)
{
pthread_mutex_lock(&cond->lock);
pthread_cond_signal(&cond->cond);
pthread_mutex_unlock(&cond->lock);
}
void thread_cond_wait(thread_cond_t *cond)
{
pthread_mutex_lock(&cond->lock);
pthread_cond_wait(&cond->cond, &cond->lock);
pthread_mutex_unlock(&cond->lock);
}
void thread_cond_wait_with_timeout(thread_cond_t *cond, uint64_t max_wait_time)
{
struct timespec ts;
clock_realtime_timespec(&ts);
uint64_t tv_nsec = (uint64_t)ts.tv_nsec + (max_wait_time * 1000000);
ts.tv_nsec = (long)(tv_nsec % 1000000000);
ts.tv_sec += (time_t)(tv_nsec / 1000000000);
pthread_mutex_lock(&cond->lock);
pthread_cond_timedwait(&cond->cond, &cond->lock, &ts);
pthread_mutex_unlock(&cond->lock);
}
bool_t hdhomerun_vsprintf(char *buffer, char *end, const char *fmt, va_list ap)
{
if (buffer >= end) {

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_os_posix.h
*
* Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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
@ -38,25 +38,35 @@
#include <netdb.h>
#include <pthread.h>
typedef int bool_t;
typedef uint8_t bool_t;
typedef void (*sig_t)(int);
#define LIBTYPE
#define console_vprintf vprintf
#define console_printf printf
typedef struct {
pthread_mutex_t lock;
pthread_cond_t cond;
} thread_cond_t;
#define LIBHDHOMERUN_API
#define THREAD_FUNC_PREFIX void *
#define THREAD_FUNC_RESULT NULL
#ifdef __cplusplus
extern "C" {
#endif
extern LIBTYPE uint32_t random_get32(void);
extern LIBTYPE uint64_t getcurrenttime(void);
extern LIBTYPE void msleep_approx(uint64_t ms);
extern LIBTYPE void msleep_minimum(uint64_t ms);
extern LIBHDHOMERUN_API uint32_t random_get32(void);
extern LIBHDHOMERUN_API uint64_t getcurrenttime(void);
extern LIBHDHOMERUN_API void msleep_approx(uint64_t ms);
extern LIBHDHOMERUN_API void msleep_minimum(uint64_t ms);
extern LIBTYPE bool_t hdhomerun_vsprintf(char *buffer, char *end, const char *fmt, va_list ap);
extern LIBTYPE bool_t hdhomerun_sprintf(char *buffer, char *end, const char *fmt, ...);
extern LIBHDHOMERUN_API void thread_cond_init(thread_cond_t *cond);
extern LIBHDHOMERUN_API void thread_cond_dispose(thread_cond_t *cond);
extern LIBHDHOMERUN_API void thread_cond_signal(thread_cond_t *cond);
extern LIBHDHOMERUN_API void thread_cond_wait(thread_cond_t *cond);
extern LIBHDHOMERUN_API void thread_cond_wait_with_timeout(thread_cond_t *cond, uint64_t max_wait_time);
extern LIBHDHOMERUN_API bool_t hdhomerun_vsprintf(char *buffer, char *end, const char *fmt, va_list ap);
extern LIBHDHOMERUN_API bool_t hdhomerun_sprintf(char *buffer, char *end, const char *fmt, ...);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_os_windows.c
*
* Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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
@ -18,12 +18,21 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "hdhomerun_os.h"
static DWORD random_get32_context_tls = TlsAlloc();
#include "hdhomerun.h"
#if defined(_WINRT)
uint32_t random_get32(void)
{
return (uint32_t)getcurrenttime();
}
#else
uint32_t random_get32(void)
{
static DWORD random_get32_context_tls = 0xFFFFFFFF;
if (random_get32_context_tls == 0xFFFFFFFF) {
random_get32_context_tls = TlsAlloc();
}
HCRYPTPROV *phProv = (HCRYPTPROV *)TlsGetValue(random_get32_context_tls);
if (!phProv) {
phProv = (HCRYPTPROV *)calloc(1, sizeof(HCRYPTPROV));
@ -38,6 +47,7 @@ uint32_t random_get32(void)
return Result;
}
#endif
uint64_t getcurrenttime(void)
{
@ -100,6 +110,31 @@ void pthread_mutex_unlock(pthread_mutex_t *mutex)
ReleaseMutex(*mutex);
}
void thread_cond_init(thread_cond_t *cond)
{
*cond = CreateEvent(NULL, FALSE, FALSE, NULL);
}
void thread_cond_dispose(thread_cond_t *cond)
{
CloseHandle(*cond);
}
void thread_cond_signal(thread_cond_t *cond)
{
SetEvent(*cond);
}
void thread_cond_wait(thread_cond_t *cond)
{
WaitForSingleObject(*cond, INFINITE);
}
void thread_cond_wait_with_timeout(thread_cond_t *cond, uint64_t max_wait_time)
{
WaitForSingleObject(*cond, (DWORD)max_wait_time);
}
bool_t hdhomerun_vsprintf(char *buffer, char *end, const char *fmt, va_list ap)
{
if (buffer >= end) {
@ -129,24 +164,3 @@ bool_t hdhomerun_sprintf(char *buffer, char *end, const char *fmt, ...)
va_end(ap);
return result;
}
/*
* The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
* Attempting to restore on exit fails to restore if the program is terminated by the user.
* Solution - set the output format each printf.
*/
void console_vprintf(const char *fmt, va_list ap)
{
UINT cp = GetConsoleOutputCP();
SetConsoleOutputCP(CP_UTF8);
vprintf(fmt, ap);
SetConsoleOutputCP(cp);
}
void console_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
console_vprintf(fmt, ap);
va_end(ap);
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_os_windows.h
*
* Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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
@ -18,40 +18,49 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define _WINSOCKAPI_
#include <windows.h>
#ifdef _WINRT
#include <SDKDDKVer.h>
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#if defined(DLL_IMPORT)
#define LIBTYPE __declspec( dllexport )
#elif defined(DLL_EXPORT)
#define LIBTYPE __declspec( dllimport )
#else
#define LIBTYPE
#ifdef LIBHDHOMERUN_DLLEXPORT
#define LIBHDHOMERUN_API __declspec(dllexport)
#endif
#ifdef LIBHDHOMERUN_DLLIMPORT
#define LIBHDHOMERUN_API __declspec(dllimport)
#endif
#ifndef LIBHDHOMERUN_API
#define LIBHDHOMERUN_API
#endif
typedef int bool_t;
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef signed __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef uint8_t bool_t;
typedef void (*sig_t)(int);
typedef HANDLE pthread_t;
typedef HANDLE pthread_mutex_t;
typedef HANDLE thread_cond_t;
#if !defined(va_copy)
#define va_copy(x, y) x = y
@ -60,35 +69,35 @@ typedef HANDLE pthread_mutex_t;
#define atoll _atoi64
#define strdup _strdup
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define fseeko _fseeki64
#define ftello _ftelli64
#define THREAD_FUNC_PREFIX DWORD WINAPI
#define THREAD_FUNC_RESULT 0
#ifdef __cplusplus
extern "C" {
#endif
extern LIBTYPE uint32_t random_get32(void);
extern LIBTYPE uint64_t getcurrenttime(void);
extern LIBTYPE void msleep_approx(uint64_t ms);
extern LIBTYPE void msleep_minimum(uint64_t ms);
extern LIBHDHOMERUN_API uint32_t random_get32(void);
extern LIBHDHOMERUN_API uint64_t getcurrenttime(void);
extern LIBHDHOMERUN_API void msleep_approx(uint64_t ms);
extern LIBHDHOMERUN_API void msleep_minimum(uint64_t ms);
extern LIBTYPE int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg);
extern LIBTYPE int pthread_join(pthread_t tid, void **value_ptr);
extern LIBTYPE void pthread_mutex_init(pthread_mutex_t *mutex, void *attr);
extern LIBTYPE void pthread_mutex_lock(pthread_mutex_t *mutex);
extern LIBTYPE void pthread_mutex_unlock(pthread_mutex_t *mutex);
extern LIBHDHOMERUN_API int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg);
extern LIBHDHOMERUN_API int pthread_join(pthread_t tid, void **value_ptr);
extern LIBHDHOMERUN_API void pthread_mutex_init(pthread_mutex_t *mutex, void *attr);
extern LIBHDHOMERUN_API void pthread_mutex_lock(pthread_mutex_t *mutex);
extern LIBHDHOMERUN_API void pthread_mutex_unlock(pthread_mutex_t *mutex);
extern LIBTYPE bool_t hdhomerun_vsprintf(char *buffer, char *end, const char *fmt, va_list ap);
extern LIBTYPE bool_t hdhomerun_sprintf(char *buffer, char *end, const char *fmt, ...);
extern LIBHDHOMERUN_API void thread_cond_init(thread_cond_t *cond);
extern LIBHDHOMERUN_API void thread_cond_dispose(thread_cond_t *cond);
extern LIBHDHOMERUN_API void thread_cond_signal(thread_cond_t *cond);
extern LIBHDHOMERUN_API void thread_cond_wait(thread_cond_t *cond);
extern LIBHDHOMERUN_API void thread_cond_wait_with_timeout(thread_cond_t *cond, uint64_t max_wait_time);
/*
* The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
* Attempting to restore on exit fails to restore if the program is terminated by the user.
* Solution - set the output format each printf.
*/
extern LIBTYPE void console_vprintf(const char *fmt, va_list ap);
extern LIBTYPE void console_printf(const char *fmt, ...);
extern LIBHDHOMERUN_API bool_t hdhomerun_vsprintf(char *buffer, char *end, const char *fmt, va_list ap);
extern LIBHDHOMERUN_API bool_t hdhomerun_sprintf(char *buffer, char *end, const char *fmt, ...);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_pkt.c
*
* Copyright © 2005-2006 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2014 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

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_pkt.h
*
* Copyright © 2005-2006 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2015 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
@ -133,6 +133,7 @@ extern "C" {
#define HDHOMERUN_DEVICE_TYPE_WILDCARD 0xFFFFFFFF
#define HDHOMERUN_DEVICE_TYPE_TUNER 0x00000001
#define HDHOMERUN_DEVICE_TYPE_STORAGE 0x00000005
#define HDHOMERUN_DEVICE_ID_WILDCARD 0xFFFFFFFF
#define HDHOMERUN_MIN_PEEK_LENGTH 4
@ -145,25 +146,25 @@ struct hdhomerun_pkt_t {
uint8_t buffer[3074];
};
extern LIBTYPE struct hdhomerun_pkt_t *hdhomerun_pkt_create(void);
extern LIBTYPE void hdhomerun_pkt_destroy(struct hdhomerun_pkt_t *pkt);
extern LIBTYPE void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt);
extern LIBHDHOMERUN_API struct hdhomerun_pkt_t *hdhomerun_pkt_create(void);
extern LIBHDHOMERUN_API void hdhomerun_pkt_destroy(struct hdhomerun_pkt_t *pkt);
extern LIBHDHOMERUN_API void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt);
extern LIBTYPE uint8_t hdhomerun_pkt_read_u8(struct hdhomerun_pkt_t *pkt);
extern LIBTYPE uint16_t hdhomerun_pkt_read_u16(struct hdhomerun_pkt_t *pkt);
extern LIBTYPE uint32_t hdhomerun_pkt_read_u32(struct hdhomerun_pkt_t *pkt);
extern LIBTYPE size_t hdhomerun_pkt_read_var_length(struct hdhomerun_pkt_t *pkt);
extern LIBTYPE uint8_t *hdhomerun_pkt_read_tlv(struct hdhomerun_pkt_t *pkt, uint8_t *ptag, size_t *plength);
extern LIBTYPE void hdhomerun_pkt_read_mem(struct hdhomerun_pkt_t *pkt, void *mem, size_t length);
extern LIBHDHOMERUN_API uint8_t hdhomerun_pkt_read_u8(struct hdhomerun_pkt_t *pkt);
extern LIBHDHOMERUN_API uint16_t hdhomerun_pkt_read_u16(struct hdhomerun_pkt_t *pkt);
extern LIBHDHOMERUN_API uint32_t hdhomerun_pkt_read_u32(struct hdhomerun_pkt_t *pkt);
extern LIBHDHOMERUN_API size_t hdhomerun_pkt_read_var_length(struct hdhomerun_pkt_t *pkt);
extern LIBHDHOMERUN_API uint8_t *hdhomerun_pkt_read_tlv(struct hdhomerun_pkt_t *pkt, uint8_t *ptag, size_t *plength);
extern LIBHDHOMERUN_API void hdhomerun_pkt_read_mem(struct hdhomerun_pkt_t *pkt, void *mem, size_t length);
extern LIBTYPE void hdhomerun_pkt_write_u8(struct hdhomerun_pkt_t *pkt, uint8_t v);
extern LIBTYPE void hdhomerun_pkt_write_u16(struct hdhomerun_pkt_t *pkt, uint16_t v);
extern LIBTYPE void hdhomerun_pkt_write_u32(struct hdhomerun_pkt_t *pkt, uint32_t v);
extern LIBTYPE void hdhomerun_pkt_write_var_length(struct hdhomerun_pkt_t *pkt, size_t v);
extern LIBTYPE void hdhomerun_pkt_write_mem(struct hdhomerun_pkt_t *pkt, const void *mem, size_t length);
extern LIBHDHOMERUN_API void hdhomerun_pkt_write_u8(struct hdhomerun_pkt_t *pkt, uint8_t v);
extern LIBHDHOMERUN_API void hdhomerun_pkt_write_u16(struct hdhomerun_pkt_t *pkt, uint16_t v);
extern LIBHDHOMERUN_API void hdhomerun_pkt_write_u32(struct hdhomerun_pkt_t *pkt, uint32_t v);
extern LIBHDHOMERUN_API void hdhomerun_pkt_write_var_length(struct hdhomerun_pkt_t *pkt, size_t v);
extern LIBHDHOMERUN_API void hdhomerun_pkt_write_mem(struct hdhomerun_pkt_t *pkt, const void *mem, size_t length);
extern LIBTYPE bool_t hdhomerun_pkt_open_frame(struct hdhomerun_pkt_t *pkt, uint16_t *ptype);
extern LIBTYPE void hdhomerun_pkt_seal_frame(struct hdhomerun_pkt_t *pkt, uint16_t frame_type);
extern LIBHDHOMERUN_API int hdhomerun_pkt_open_frame(struct hdhomerun_pkt_t *pkt, uint16_t *ptype);
extern LIBHDHOMERUN_API void hdhomerun_pkt_seal_frame(struct hdhomerun_pkt_t *pkt, uint16_t frame_type);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_sock.h
*
* Copyright © 2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2010-2016 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
@ -26,33 +26,36 @@ struct hdhomerun_local_ip_info_t {
uint32_t subnet_mask;
};
extern LIBTYPE int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count);
extern LIBHDHOMERUN_API int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count);
#define HDHOMERUN_SOCK_INVALID -1
struct hdhomerun_sock_t;
typedef int hdhomerun_sock_t;
extern LIBHDHOMERUN_API struct hdhomerun_sock_t *hdhomerun_sock_create_udp(void);
extern LIBHDHOMERUN_API struct hdhomerun_sock_t *hdhomerun_sock_create_tcp(void);
extern LIBHDHOMERUN_API void hdhomerun_sock_stop(struct hdhomerun_sock_t *sock);
extern LIBHDHOMERUN_API void hdhomerun_sock_destroy(struct hdhomerun_sock_t *sock);
extern LIBTYPE hdhomerun_sock_t hdhomerun_sock_create_udp(void);
extern LIBTYPE hdhomerun_sock_t hdhomerun_sock_create_tcp(void);
extern LIBTYPE void hdhomerun_sock_destroy(hdhomerun_sock_t sock);
extern LIBHDHOMERUN_API void hdhomerun_sock_set_send_buffer_size(struct hdhomerun_sock_t *sock, size_t size);
extern LIBHDHOMERUN_API void hdhomerun_sock_set_recv_buffer_size(struct hdhomerun_sock_t *sock, size_t size);
extern LIBHDHOMERUN_API void hdhomerun_sock_set_allow_reuse(struct hdhomerun_sock_t *sock);
extern LIBTYPE int hdhomerun_sock_getlasterror(void);
extern LIBTYPE uint32_t hdhomerun_sock_getsockname_addr(hdhomerun_sock_t sock);
extern LIBTYPE uint16_t hdhomerun_sock_getsockname_port(hdhomerun_sock_t sock);
extern LIBTYPE uint32_t hdhomerun_sock_getpeername_addr(hdhomerun_sock_t sock);
extern LIBTYPE uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name);
extern LIBHDHOMERUN_API int hdhomerun_sock_getlasterror(void);
extern LIBHDHOMERUN_API uint32_t hdhomerun_sock_getsockname_addr(struct hdhomerun_sock_t *sock);
extern LIBHDHOMERUN_API uint16_t hdhomerun_sock_getsockname_port(struct hdhomerun_sock_t *sock);
extern LIBHDHOMERUN_API uint32_t hdhomerun_sock_getpeername_addr(struct hdhomerun_sock_t *sock);
extern LIBHDHOMERUN_API uint32_t hdhomerun_sock_getaddrinfo_addr(struct hdhomerun_sock_t *sock, const char *name);
extern LIBTYPE bool_t hdhomerun_sock_join_multicast_group(hdhomerun_sock_t sock, uint32_t multicast_ip, uint32_t local_ip);
extern LIBTYPE bool_t hdhomerun_sock_leave_multicast_group(hdhomerun_sock_t sock, uint32_t multicast_ip, uint32_t local_ip);
extern LIBHDHOMERUN_API bool_t hdhomerun_sock_join_multicast_group(struct hdhomerun_sock_t *sock, uint32_t multicast_ip, uint32_t local_ip);
extern LIBHDHOMERUN_API bool_t hdhomerun_sock_leave_multicast_group(struct hdhomerun_sock_t *sock, uint32_t multicast_ip, uint32_t local_ip);
extern LIBTYPE bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t local_port, bool_t allow_reuse);
extern LIBTYPE bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout);
extern LIBHDHOMERUN_API bool_t hdhomerun_sock_bind(struct hdhomerun_sock_t *sock, uint32_t local_addr, uint16_t local_port, bool_t allow_reuse);
extern LIBHDHOMERUN_API bool_t hdhomerun_sock_connect(struct hdhomerun_sock_t *sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout);
extern LIBTYPE bool_t hdhomerun_sock_send(hdhomerun_sock_t sock, const void *data, size_t length, uint64_t timeout);
extern LIBTYPE bool_t hdhomerun_sock_sendto(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout);
extern LIBHDHOMERUN_API bool_t hdhomerun_sock_send(struct hdhomerun_sock_t *sock, const void *data, size_t length, uint64_t timeout);
extern LIBHDHOMERUN_API bool_t hdhomerun_sock_sendto(struct hdhomerun_sock_t *sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout);
extern LIBTYPE bool_t hdhomerun_sock_recv(hdhomerun_sock_t sock, void *data, size_t *length, uint64_t timeout);
extern LIBTYPE bool_t hdhomerun_sock_recvfrom(hdhomerun_sock_t sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout);
extern LIBHDHOMERUN_API bool_t hdhomerun_sock_recv(struct hdhomerun_sock_t *sock, void *data, size_t *length, uint64_t timeout);
extern LIBHDHOMERUN_API bool_t hdhomerun_sock_recvfrom(struct hdhomerun_sock_t *sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout);
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_sock_posix.c
*
* Copyright © 2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2010-2016 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
@ -18,22 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Implementation notes:
*
* API specifies timeout for each operation (or zero for non-blocking).
*
* It is not possible to rely on the OS socket timeout as this will fail to
* detect the command-response situation where data is sent successfully and
* the other end chooses not to send a response (other than the TCP ack).
*
* The select() cannot be used with high socket numbers (typically max 1024)
* so the code works as follows:
* - Use non-blocking sockets to allow operation without select.
* - Use select where safe (low socket numbers).
* - Poll with short sleep when select cannot be used safely.
*/
#include "hdhomerun.h"
#include <net/if.h>
@ -51,10 +35,14 @@
#define MSG_NOSIGNAL 0
#endif
struct hdhomerun_sock_t {
int sock;
};
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);
if (sock == HDHOMERUN_SOCK_INVALID) {
if (sock == -1) {
return -1;
}
@ -77,7 +65,7 @@ int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int
return -1;
}
if (ifc.ifc_len < ifreq_buffer_size) {
if (ifc.ifc_len < (int)ifreq_buffer_size) {
break;
}
@ -139,49 +127,83 @@ int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int
return count;
}
hdhomerun_sock_t hdhomerun_sock_create_udp(void)
static struct hdhomerun_sock_t *hdhomerun_sock_create_internal(int protocol)
{
struct hdhomerun_sock_t *sock = (struct hdhomerun_sock_t *)calloc(1, sizeof(struct hdhomerun_sock_t));
if (!sock) {
return NULL;
}
/* Create socket. */
hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
return HDHOMERUN_SOCK_INVALID;
sock->sock = socket(AF_INET, protocol, 0);
if (sock->sock == -1) {
free(sock);
return NULL;
}
/* Set non-blocking */
if (fcntl(sock, F_SETFL, O_NONBLOCK) != 0) {
close(sock);
return HDHOMERUN_SOCK_INVALID;
if (fcntl(sock->sock, F_SETFL, O_NONBLOCK) != 0) {
hdhomerun_sock_destroy(sock);
return NULL;
}
/* Configure socket not to generate pipe-error signal (BSD/OSX). */
#if defined(SO_NOSIGPIPE)
int set = 1;
setsockopt(sock->sock, SOL_SOCKET, SO_NOSIGPIPE, (char *)&set, sizeof(set));
#endif
/* Success. */
return sock;
}
struct hdhomerun_sock_t *hdhomerun_sock_create_udp(void)
{
struct hdhomerun_sock_t *sock = hdhomerun_sock_create_internal(SOCK_DGRAM);
if (!sock) {
return NULL;
}
/* Allow broadcast. */
int sock_opt = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock->sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
/* Success. */
return sock;
}
hdhomerun_sock_t hdhomerun_sock_create_tcp(void)
struct hdhomerun_sock_t *hdhomerun_sock_create_tcp(void)
{
/* Create socket. */
hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
return HDHOMERUN_SOCK_INVALID;
return hdhomerun_sock_create_internal(SOCK_STREAM);
}
/* Set non-blocking */
if (fcntl(sock, F_SETFL, O_NONBLOCK) != 0) {
close(sock);
return HDHOMERUN_SOCK_INVALID;
}
/* Success. */
return sock;
}
void hdhomerun_sock_destroy(hdhomerun_sock_t sock)
void hdhomerun_sock_destroy(struct hdhomerun_sock_t *sock)
{
close(sock);
close(sock->sock);
free(sock);
}
void hdhomerun_sock_stop(struct hdhomerun_sock_t *sock)
{
shutdown(sock->sock, SHUT_RDWR);
}
void hdhomerun_sock_set_send_buffer_size(struct hdhomerun_sock_t *sock, size_t size)
{
int size_opt = (int)size;
setsockopt(sock->sock, SOL_SOCKET, SO_SNDBUF, (char *)&size_opt, sizeof(size_opt));
}
void hdhomerun_sock_set_recv_buffer_size(struct hdhomerun_sock_t *sock, size_t size)
{
int size_opt = (int)size;
setsockopt(sock->sock, SOL_SOCKET, SO_RCVBUF, (char *)&size_opt, sizeof(size_opt));
}
void hdhomerun_sock_set_allow_reuse(struct hdhomerun_sock_t *sock)
{
int sock_opt = 1;
setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt));
}
int hdhomerun_sock_getlasterror(void)
@ -189,43 +211,43 @@ int hdhomerun_sock_getlasterror(void)
return errno;
}
uint32_t hdhomerun_sock_getsockname_addr(hdhomerun_sock_t sock)
uint32_t hdhomerun_sock_getsockname_addr(struct hdhomerun_sock_t *sock)
{
struct sockaddr_in sock_addr;
socklen_t sockaddr_size = sizeof(sock_addr);
if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
if (getsockname(sock->sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
return 0;
}
return ntohl(sock_addr.sin_addr.s_addr);
}
uint16_t hdhomerun_sock_getsockname_port(hdhomerun_sock_t sock)
uint16_t hdhomerun_sock_getsockname_port(struct hdhomerun_sock_t *sock)
{
struct sockaddr_in sock_addr;
socklen_t sockaddr_size = sizeof(sock_addr);
if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
if (getsockname(sock->sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
return 0;
}
return ntohs(sock_addr.sin_port);
}
uint32_t hdhomerun_sock_getpeername_addr(hdhomerun_sock_t sock)
uint32_t hdhomerun_sock_getpeername_addr(struct hdhomerun_sock_t *sock)
{
struct sockaddr_in sock_addr;
socklen_t sockaddr_size = sizeof(sock_addr);
if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
if (getpeername(sock->sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
return 0;
}
return ntohl(sock_addr.sin_addr.s_addr);
}
uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name)
uint32_t hdhomerun_sock_getaddrinfo_addr(struct hdhomerun_sock_t *sock, const char *name)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@ -245,38 +267,38 @@ uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name
return addr;
}
bool_t hdhomerun_sock_join_multicast_group(hdhomerun_sock_t sock, uint32_t multicast_ip, uint32_t local_ip)
bool_t hdhomerun_sock_join_multicast_group(struct hdhomerun_sock_t *sock, uint32_t multicast_ip, uint32_t local_ip)
{
struct ip_mreq imr;
memset(&imr, 0, sizeof(imr));
imr.imr_multiaddr.s_addr = htonl(multicast_ip);
imr.imr_interface.s_addr = htonl(local_ip);
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
if (setsockopt(sock->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
return FALSE;
}
return TRUE;
}
bool_t hdhomerun_sock_leave_multicast_group(hdhomerun_sock_t sock, uint32_t multicast_ip, uint32_t local_ip)
bool_t hdhomerun_sock_leave_multicast_group(struct hdhomerun_sock_t *sock, uint32_t multicast_ip, uint32_t local_ip)
{
struct ip_mreq imr;
memset(&imr, 0, sizeof(imr));
imr.imr_multiaddr.s_addr = htonl(multicast_ip);
imr.imr_interface.s_addr = htonl(local_ip);
if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
if (setsockopt(sock->sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
return FALSE;
}
return TRUE;
}
bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t local_port, bool_t allow_reuse)
bool_t hdhomerun_sock_bind(struct hdhomerun_sock_t *sock, uint32_t local_addr, uint16_t local_port, bool_t allow_reuse)
{
int sock_opt = allow_reuse;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt));
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
@ -284,39 +306,100 @@ bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t
sock_addr.sin_addr.s_addr = htonl(local_addr);
sock_addr.sin_port = htons(local_port);
if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
if (bind(sock->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
return FALSE;
}
return TRUE;
}
static bool_t hdhomerun_sock_wait_for_event(hdhomerun_sock_t sock, short event_type, uint64_t stop_time)
bool_t hdhomerun_sock_connect(struct hdhomerun_sock_t *sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout)
{
uint64_t current_time = getcurrenttime();
if (current_time >= stop_time) {
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = htonl(remote_addr);
sock_addr.sin_port = htons(remote_port);
if (connect(sock->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
}
struct pollfd poll_event;
poll_event.fd = sock;
poll_event.events = event_type;
poll_event.fd = sock->sock;
poll_event.events = POLLOUT;
poll_event.revents = 0;
uint64_t timeout = stop_time - current_time;
if (poll(&poll_event, 1, (int)timeout) <= 0) {
return FALSE;
}
if ((poll_event.revents & event_type) == 0) {
if ((poll_event.revents & POLLOUT) == 0) {
return FALSE;
}
return TRUE;
}
bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout)
bool_t hdhomerun_sock_send(struct hdhomerun_sock_t *sock, const void *data, size_t length, uint64_t timeout)
{
const uint8_t *ptr = (const uint8_t *)data;
int ret = send(sock->sock, ptr, length, MSG_NOSIGNAL);
if (ret >= length) {
return TRUE;
}
if ((ret < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
if (ret > 0) {
ptr += ret;
length -= ret;
}
uint64_t stop_time = getcurrenttime() + timeout;
while (1) {
struct pollfd poll_event;
poll_event.fd = sock->sock;
poll_event.events = POLLOUT;
poll_event.revents = 0;
if (poll(&poll_event, 1, (int)timeout) <= 0) {
return FALSE;
}
if ((poll_event.revents & POLLOUT) == 0) {
return FALSE;
}
ret = send(sock->sock, ptr, length, MSG_NOSIGNAL);
if (ret >= length) {
return TRUE;
}
if ((ret < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
if (ret > 0) {
ptr += ret;
length -= ret;
}
uint64_t current_time = getcurrenttime();
if (current_time >= stop_time) {
return FALSE;
}
timeout = stop_time - current_time;
}
}
bool_t hdhomerun_sock_sendto(struct hdhomerun_sock_t *sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout)
{
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
@ -324,128 +407,138 @@ bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint1
sock_addr.sin_addr.s_addr = htonl(remote_addr);
sock_addr.sin_port = htons(remote_port);
if (connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
}
uint64_t stop_time = getcurrenttime() + timeout;
return hdhomerun_sock_wait_for_event(sock, POLLOUT, stop_time);
}
bool_t hdhomerun_sock_send(hdhomerun_sock_t sock, const void *data, size_t length, uint64_t timeout)
{
uint64_t stop_time = getcurrenttime() + timeout;
const uint8_t *ptr = (const uint8_t *)data;
while (1) {
int ret = send(sock, ptr, length, MSG_NOSIGNAL);
if (ret <= 0) {
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
if (!hdhomerun_sock_wait_for_event(sock, POLLOUT, stop_time)) {
return FALSE;
}
continue;
}
if (ret < (int)length) {
ptr += ret;
length -= ret;
continue;
}
int ret = sendto(sock->sock, ptr, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
if (ret >= length) {
return TRUE;
}
}
bool_t hdhomerun_sock_sendto(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout)
{
uint64_t stop_time = getcurrenttime() + timeout;
const uint8_t *ptr = (const uint8_t *)data;
while (1) {
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = htonl(remote_addr);
sock_addr.sin_port = htons(remote_port);
int ret = sendto(sock, ptr, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
if (ret <= 0) {
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
if ((ret < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
if (!hdhomerun_sock_wait_for_event(sock, POLLOUT, stop_time)) {
return FALSE;
}
continue;
}
if (ret < (int)length) {
if (ret > 0) {
ptr += ret;
length -= ret;
continue;
}
return TRUE;
}
}
bool_t hdhomerun_sock_recv(hdhomerun_sock_t sock, void *data, size_t *length, uint64_t timeout)
{
uint64_t stop_time = getcurrenttime() + timeout;
while (1) {
int ret = recv(sock, data, *length, 0);
if (ret < 0) {
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
struct pollfd poll_event;
poll_event.fd = sock->sock;
poll_event.events = POLLOUT;
poll_event.revents = 0;
if (poll(&poll_event, 1, (int)timeout) <= 0) {
return FALSE;
}
if (!hdhomerun_sock_wait_for_event(sock, POLLIN, stop_time)) {
if ((poll_event.revents & POLLOUT) == 0) {
return FALSE;
}
continue;
ret = sendto(sock->sock, ptr, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
if (ret >= length) {
return TRUE;
}
if ((ret < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
if (ret > 0) {
ptr += ret;
length -= ret;
}
uint64_t current_time = getcurrenttime();
if (current_time >= stop_time) {
return FALSE;
}
timeout = stop_time - current_time;
}
}
bool_t hdhomerun_sock_recv(struct hdhomerun_sock_t *sock, void *data, size_t *length, uint64_t timeout)
{
int ret = recv(sock->sock, data, *length, 0);
if (ret > 0) {
*length = ret;
return TRUE;
}
if (ret == 0) {
return FALSE;
}
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
struct pollfd poll_event;
poll_event.fd = sock->sock;
poll_event.events = POLLIN;
poll_event.revents = 0;
if (poll(&poll_event, 1, (int)timeout) <= 0) {
return FALSE;
}
if ((poll_event.revents & POLLIN) == 0) {
return FALSE;
}
ret = recv(sock->sock, data, *length, 0);
if (ret > 0) {
*length = ret;
return TRUE;
}
return FALSE;
}
bool_t hdhomerun_sock_recvfrom(hdhomerun_sock_t sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout)
bool_t hdhomerun_sock_recvfrom(struct hdhomerun_sock_t *sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout)
{
uint64_t stop_time = getcurrenttime() + timeout;
while (1) {
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
socklen_t sockaddr_size = sizeof(sock_addr);
int ret = recvfrom(sock, data, *length, 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
if (ret < 0) {
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
if (!hdhomerun_sock_wait_for_event(sock, POLLIN, stop_time)) {
return FALSE;
}
continue;
}
if (ret == 0) {
return FALSE;
}
int ret = recvfrom(sock->sock, data, *length, 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
if (ret > 0) {
*remote_addr = ntohl(sock_addr.sin_addr.s_addr);
*remote_port = ntohs(sock_addr.sin_port);
*length = ret;
return TRUE;
}
if (ret == 0) {
return FALSE;
}
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
return FALSE;
}
struct pollfd poll_event;
poll_event.fd = sock->sock;
poll_event.events = POLLIN;
poll_event.revents = 0;
if (poll(&poll_event, 1, (int)timeout) <= 0) {
return FALSE;
}
if ((poll_event.revents & POLLIN) == 0) {
return FALSE;
}
ret = recvfrom(sock->sock, data, *length, 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
if (ret > 0) {
*remote_addr = ntohl(sock_addr.sin_addr.s_addr);
*remote_port = ntohs(sock_addr.sin_port);
*length = ret;
return TRUE;
}
return FALSE;
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_sock_windows.c
*
* Copyright © 2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2010-2016 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
@ -18,25 +18,16 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Implementation notes:
*
* API specifies timeout for each operation (or zero for non-blocking).
*
* It is not possible to rely on the OS socket timeout as this will fail to
* detect the command-response situation where data is sent successfully and
* the other end chooses not to send a response (other than the TCP ack).
*
* Windows supports select() however native WSA events are used to:
* - avoid problems with socket numbers above 1024.
* - wait without allowing other events handlers to run (important for use
* with win7 WMC).
*/
#include "hdhomerun.h"
#include <windows.h>
#include <iphlpapi.h>
struct hdhomerun_sock_t {
SOCKET sock;
HANDLE event;
long events_selected;
};
#if !defined(_WINRT)
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
{
PIP_ADAPTER_INFO AdapterInfo;
@ -99,52 +90,91 @@ int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int
free(AdapterInfo);
return count;
}
#endif
hdhomerun_sock_t hdhomerun_sock_create_udp(void)
static struct hdhomerun_sock_t *hdhomerun_sock_create_internal(int protocol)
{
struct hdhomerun_sock_t *sock = (struct hdhomerun_sock_t *)calloc(1, sizeof(struct hdhomerun_sock_t));
if (!sock) {
return NULL;
}
/* Create socket. */
hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
return HDHOMERUN_SOCK_INVALID;
sock->sock = socket(AF_INET, protocol, 0);
if (sock->sock == INVALID_SOCKET) {
free(sock);
return NULL;
}
/* Set non-blocking */
unsigned long mode = 1;
if (ioctlsocket(sock, FIONBIO, &mode) != 0) {
closesocket(sock);
return HDHOMERUN_SOCK_INVALID;
if (ioctlsocket(sock->sock, FIONBIO, &mode) != 0) {
hdhomerun_sock_destroy(sock);
return NULL;
}
/* Event */
sock->event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!sock->event) {
hdhomerun_sock_destroy(sock);
return NULL;
}
/* Success. */
return sock;
}
struct hdhomerun_sock_t *hdhomerun_sock_create_udp(void)
{
struct hdhomerun_sock_t *sock = hdhomerun_sock_create_internal(SOCK_DGRAM);
if (!sock) {
return NULL;
}
/* Allow broadcast. */
int sock_opt = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock->sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
/* Success. */
return sock;
}
hdhomerun_sock_t hdhomerun_sock_create_tcp(void)
struct hdhomerun_sock_t *hdhomerun_sock_create_tcp(void)
{
/* Create socket. */
hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
return HDHOMERUN_SOCK_INVALID;
return hdhomerun_sock_create_internal(SOCK_STREAM);
}
/* Set non-blocking */
unsigned long mode = 1;
if (ioctlsocket(sock, FIONBIO, &mode) != 0) {
closesocket(sock);
return HDHOMERUN_SOCK_INVALID;
}
/* Success. */
return sock;
}
void hdhomerun_sock_destroy(hdhomerun_sock_t sock)
void hdhomerun_sock_destroy(struct hdhomerun_sock_t *sock)
{
closesocket(sock);
if (sock->event) {
CloseHandle(sock->event);
}
closesocket(sock->sock);
free(sock);
}
void hdhomerun_sock_stop(struct hdhomerun_sock_t *sock)
{
shutdown(sock->sock, SD_BOTH);
}
void hdhomerun_sock_set_send_buffer_size(struct hdhomerun_sock_t *sock, size_t size)
{
int size_opt = (int)size;
setsockopt(sock->sock, SOL_SOCKET, SO_SNDBUF, (char *)&size_opt, sizeof(size_opt));
}
void hdhomerun_sock_set_recv_buffer_size(struct hdhomerun_sock_t *sock, size_t size)
{
int size_opt = (int)size;
setsockopt(sock->sock, SOL_SOCKET, SO_RCVBUF, (char *)&size_opt, sizeof(size_opt));
}
void hdhomerun_sock_set_allow_reuse(struct hdhomerun_sock_t *sock)
{
int sock_opt = 1;
setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt));
}
int hdhomerun_sock_getlasterror(void)
@ -152,43 +182,43 @@ int hdhomerun_sock_getlasterror(void)
return WSAGetLastError();
}
uint32_t hdhomerun_sock_getsockname_addr(hdhomerun_sock_t sock)
uint32_t hdhomerun_sock_getsockname_addr(struct hdhomerun_sock_t *sock)
{
struct sockaddr_in sock_addr;
int sockaddr_size = sizeof(sock_addr);
if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
if (getsockname(sock->sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
return 0;
}
return ntohl(sock_addr.sin_addr.s_addr);
}
uint16_t hdhomerun_sock_getsockname_port(hdhomerun_sock_t sock)
uint16_t hdhomerun_sock_getsockname_port(struct hdhomerun_sock_t *sock)
{
struct sockaddr_in sock_addr;
int sockaddr_size = sizeof(sock_addr);
if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
if (getsockname(sock->sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
return 0;
}
return ntohs(sock_addr.sin_port);
}
uint32_t hdhomerun_sock_getpeername_addr(hdhomerun_sock_t sock)
uint32_t hdhomerun_sock_getpeername_addr(struct hdhomerun_sock_t *sock)
{
struct sockaddr_in sock_addr;
int sockaddr_size = sizeof(sock_addr);
if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
if (getpeername(sock->sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
return 0;
}
return ntohl(sock_addr.sin_addr.s_addr);
}
uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name)
uint32_t hdhomerun_sock_getaddrinfo_addr(struct hdhomerun_sock_t *sock, const char *name)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@ -208,38 +238,38 @@ uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name
return addr;
}
bool_t hdhomerun_sock_join_multicast_group(hdhomerun_sock_t sock, uint32_t multicast_ip, uint32_t local_ip)
bool_t hdhomerun_sock_join_multicast_group(struct hdhomerun_sock_t *sock, uint32_t multicast_ip, uint32_t local_ip)
{
struct ip_mreq imr;
memset(&imr, 0, sizeof(imr));
imr.imr_multiaddr.s_addr = htonl(multicast_ip);
imr.imr_interface.s_addr = htonl(local_ip);
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
if (setsockopt(sock->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
return FALSE;
}
return TRUE;
}
bool_t hdhomerun_sock_leave_multicast_group(hdhomerun_sock_t sock, uint32_t multicast_ip, uint32_t local_ip)
bool_t hdhomerun_sock_leave_multicast_group(struct hdhomerun_sock_t *sock, uint32_t multicast_ip, uint32_t local_ip)
{
struct ip_mreq imr;
memset(&imr, 0, sizeof(imr));
imr.imr_multiaddr.s_addr = htonl(multicast_ip);
imr.imr_interface.s_addr = htonl(local_ip);
if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
if (setsockopt(sock->sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
return FALSE;
}
return TRUE;
}
bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t local_port, bool_t allow_reuse)
bool_t hdhomerun_sock_bind(struct hdhomerun_sock_t *sock, uint32_t local_addr, uint16_t local_port, bool_t allow_reuse)
{
int sock_opt = allow_reuse;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt));
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
@ -247,204 +277,202 @@ bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t
sock_addr.sin_addr.s_addr = htonl(local_addr);
sock_addr.sin_port = htons(local_port);
if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
if (bind(sock->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
return FALSE;
}
return TRUE;
}
bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout)
bool_t hdhomerun_sock_event_select(struct hdhomerun_sock_t *sock, long events)
{
/* Connect (non-blocking). */
if (sock->events_selected != events) {
if (WSAEventSelect(sock->sock, sock->event, events) == SOCKET_ERROR) {
return FALSE;
}
sock->events_selected = events;
}
ResetEvent(sock->event);
return TRUE;
}
bool_t hdhomerun_sock_connect(struct hdhomerun_sock_t *sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout)
{
if (!hdhomerun_sock_event_select(sock, FD_WRITE | FD_CLOSE)) {
return FALSE;
}
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = htonl(remote_addr);
sock_addr.sin_port = htons(remote_port);
if (connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
if (connect(sock->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
return FALSE;
}
}
/* Wait for connect to complete (both success and failure will signal). */
WSAEVENT wsa_event = WSACreateEvent();
if (wsa_event == WSA_INVALID_EVENT) {
DWORD wait_ret = WaitForSingleObjectEx(sock->event, (DWORD)timeout, FALSE);
if (wait_ret != WAIT_OBJECT_0) {
return FALSE;
}
if (WSAEventSelect(sock, wsa_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR) {
WSACloseEvent(wsa_event);
WSANETWORKEVENTS network_events;
if (WSAEnumNetworkEvents(sock->sock, sock->event, &network_events) == SOCKET_ERROR) {
return FALSE;
}
DWORD ret = WaitForSingleObjectEx(wsa_event, (DWORD)timeout, FALSE);
WSACloseEvent(wsa_event);
if (ret != WAIT_OBJECT_0) {
if ((network_events.lNetworkEvents & FD_WRITE) == 0) {
return FALSE;
}
/* Detect success/failure. */
wsa_event = WSACreateEvent();
if (wsa_event == WSA_INVALID_EVENT) {
return FALSE;
}
if (WSAEventSelect(sock, wsa_event, FD_CLOSE) == SOCKET_ERROR) {
WSACloseEvent(wsa_event);
return FALSE;
}
ret = WaitForSingleObjectEx(wsa_event, 0, FALSE);
WSACloseEvent(wsa_event);
if (ret == WAIT_OBJECT_0) {
if (network_events.lNetworkEvents & FD_CLOSE) {
return FALSE;
}
return TRUE;
}
static bool_t hdhomerun_sock_wait_for_event(hdhomerun_sock_t sock, long event_type, uint64_t stop_time)
bool_t hdhomerun_sock_send(struct hdhomerun_sock_t *sock, const void *data, size_t length, uint64_t timeout)
{
if (!hdhomerun_sock_event_select(sock, FD_WRITE | FD_CLOSE)) {
return FALSE;
}
uint64_t stop_time = getcurrenttime() + timeout;
const uint8_t *ptr = (uint8_t *)data;
while (1) {
int ret = send(sock->sock, (char *)ptr, (int)length, 0);
if (ret >= (int)length) {
return TRUE;
}
if ((ret == SOCKET_ERROR) && (WSAGetLastError() != WSAEWOULDBLOCK)) {
return FALSE;
}
if (ret > 0) {
ptr += ret;
length -= ret;
}
uint64_t current_time = getcurrenttime();
if (current_time >= stop_time) {
return FALSE;
}
WSAEVENT wsa_event = WSACreateEvent();
if (wsa_event == WSA_INVALID_EVENT) {
if (WaitForSingleObjectEx(sock->event, (DWORD)(stop_time - current_time), FALSE) != WAIT_OBJECT_0) {
return FALSE;
}
if (WSAEventSelect(sock, wsa_event, event_type) == SOCKET_ERROR) {
WSACloseEvent(wsa_event);
return FALSE;
}
}
DWORD ret = WaitForSingleObjectEx(wsa_event, (DWORD)(stop_time - current_time), FALSE);
WSACloseEvent(wsa_event);
if (ret != WAIT_OBJECT_0) {
return FALSE;
}
return TRUE;
}
bool_t hdhomerun_sock_send(hdhomerun_sock_t sock, const void *data, size_t length, uint64_t timeout)
bool_t hdhomerun_sock_sendto(struct hdhomerun_sock_t *sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout)
{
uint64_t stop_time = getcurrenttime() + timeout;
const uint8_t *ptr = (uint8_t *)data;
while (1) {
int ret = send(sock, (char *)ptr, (int)length, 0);
if (ret <= 0) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
if (!hdhomerun_sock_event_select(sock, FD_WRITE | FD_CLOSE)) {
return FALSE;
}
if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
return FALSE;
}
continue;
}
if (ret < (int)length) {
ptr += ret;
length -= ret;
continue;
}
return TRUE;
}
}
bool_t hdhomerun_sock_sendto(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout)
{
uint64_t stop_time = getcurrenttime() + timeout;
const uint8_t *ptr = (uint8_t *)data;
while (1) {
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = htonl(remote_addr);
sock_addr.sin_port = htons(remote_port);
int ret = sendto(sock, (char *)ptr, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
if (ret <= 0) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
return FALSE;
}
if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
return FALSE;
}
continue;
}
if (ret < (int)length) {
ptr += ret;
length -= ret;
continue;
}
int ret = sendto(sock->sock, (char *)data, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
if (ret >= (int)length) {
return TRUE;
}
if (ret >= 0) {
return FALSE;
}
bool_t hdhomerun_sock_recv(hdhomerun_sock_t sock, void *data, size_t *length, uint64_t timeout)
{
uint64_t stop_time = getcurrenttime() + timeout;
while (1) {
int ret = recv(sock, (char *)data, (int)(*length), 0);
if (ret < 0) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
return FALSE;
}
if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
if (WaitForSingleObjectEx(sock->event, (DWORD)timeout, FALSE) != WAIT_OBJECT_0) {
return FALSE;
}
continue;
ret = sendto(sock->sock, (char *)data, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
if (ret >= (int)length) {
return TRUE;
}
return FALSE;
}
bool_t hdhomerun_sock_recv(struct hdhomerun_sock_t *sock, void *data, size_t *length, uint64_t timeout)
{
if (!hdhomerun_sock_event_select(sock, FD_READ | FD_CLOSE)) {
return FALSE;
}
int ret = recv(sock->sock, (char *)data, (int)(*length), 0);
if (ret > 0) {
*length = ret;
return TRUE;
}
if (ret == 0) {
return FALSE;
}
if (WSAGetLastError() != WSAEWOULDBLOCK) {
return FALSE;
}
if (WaitForSingleObjectEx(sock->event, (DWORD)timeout, FALSE) != WAIT_OBJECT_0) {
return FALSE;
}
ret = recv(sock->sock, (char *)data, (int)(*length), 0);
if (ret > 0) {
*length = ret;
return TRUE;
}
return FALSE;
}
bool_t hdhomerun_sock_recvfrom(hdhomerun_sock_t sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout)
bool_t hdhomerun_sock_recvfrom(struct hdhomerun_sock_t *sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout)
{
uint64_t stop_time = getcurrenttime() + timeout;
if (!hdhomerun_sock_event_select(sock, FD_READ | FD_CLOSE)) {
return FALSE;
}
while (1) {
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
int sockaddr_size = sizeof(sock_addr);
int ret = recvfrom(sock, (char *)data, (int)(*length), 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
if (ret < 0) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
return FALSE;
}
if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
return FALSE;
}
continue;
}
if (ret == 0) {
return FALSE;
}
int ret = recvfrom(sock->sock, (char *)data, (int)(*length), 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
if (ret > 0) {
*remote_addr = ntohl(sock_addr.sin_addr.s_addr);
*remote_port = ntohs(sock_addr.sin_port);
*length = ret;
return TRUE;
}
if (ret == 0) {
return FALSE;
}
if (WSAGetLastError() != WSAEWOULDBLOCK) {
return FALSE;
}
if (WaitForSingleObjectEx(sock->event, (DWORD)timeout, FALSE) != WAIT_OBJECT_0) {
return FALSE;
}
ret = recvfrom(sock->sock, (char *)data, (int)(*length), 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
if (ret > 0) {
*remote_addr = ntohl(sock_addr.sin_addr.s_addr);
*remote_port = ntohs(sock_addr.sin_port);
*length = ret;
return TRUE;
}
return FALSE;
}

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_types.h
*
* Copyright © 2008-2009 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2008-2015 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

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_video.c
*
* Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2016 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,7 +23,7 @@
struct hdhomerun_video_sock_t {
pthread_mutex_t lock;
struct hdhomerun_debug_t *dbg;
hdhomerun_sock_t sock;
struct hdhomerun_sock_t *sock;
volatile size_t head;
volatile size_t tail;
@ -56,7 +56,6 @@ struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, bool
}
vs->dbg = dbg;
vs->sock = HDHOMERUN_SOCK_INVALID;
pthread_mutex_init(&vs->lock, NULL);
/* Reset sequence tracking. */
@ -79,14 +78,13 @@ struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, bool
/* Create socket. */
vs->sock = hdhomerun_sock_create_udp();
if (vs->sock == HDHOMERUN_SOCK_INVALID) {
if (!vs->sock) {
hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate socket\n");
goto error;
}
/* Expand socket buffer size. */
int rx_size = 1024 * 1024;
setsockopt(vs->sock, SOL_SOCKET, SO_RCVBUF, (char *)&rx_size, sizeof(rx_size));
hdhomerun_sock_set_recv_buffer_size(vs->sock, 1024 * 1024);
/* Bind socket. */
if (!hdhomerun_sock_bind(vs->sock, INADDR_ANY, listen_port, allow_port_reuse)) {
@ -104,7 +102,7 @@ struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, bool
return vs;
error:
if (vs->sock != HDHOMERUN_SOCK_INVALID) {
if (vs->sock) {
hdhomerun_sock_destroy(vs->sock);
}
if (vs->buffer) {
@ -125,7 +123,7 @@ void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs)
free(vs);
}
hdhomerun_sock_t hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs)
struct hdhomerun_sock_t *hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs)
{
return vs->sock;
}
@ -281,7 +279,7 @@ static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg)
pthread_mutex_unlock(&vs->lock);
}
return NULL;
return THREAD_FUNC_RESULT;
}
uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size)

View file

@ -1,7 +1,7 @@
/*
* hdhomerun_video.h
*
* Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>.
* Copyright © 2006-2016 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
@ -48,21 +48,21 @@ struct hdhomerun_video_stats_t {
*
* When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy.
*/
extern LIBTYPE struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, bool_t allow_port_reuse, size_t buffer_size, struct hdhomerun_debug_t *dbg);
extern LIBTYPE void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs);
extern LIBHDHOMERUN_API struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, bool_t allow_port_reuse, size_t buffer_size, struct hdhomerun_debug_t *dbg);
extern LIBHDHOMERUN_API void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs);
/*
* Get the port the socket is listening on.
*
* Returns 16-bit port with native endianness, or 0 on error.
*/
extern LIBTYPE uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs);
extern LIBHDHOMERUN_API uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs);
/*
* Join/leave multicast group.
*/
extern LIBTYPE int hdhomerun_video_join_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip);
extern LIBTYPE void hdhomerun_video_leave_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip);
extern LIBHDHOMERUN_API int hdhomerun_video_join_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip);
extern LIBHDHOMERUN_API void hdhomerun_video_leave_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip);
/*
* Read data from buffer.
@ -81,23 +81,23 @@ extern LIBTYPE void hdhomerun_video_leave_multicast_group(struct hdhomerun_video
* The buffer is implemented as a ring buffer. It is possible for this function to return a small
* amount of data when more is available due to the wrap-around case.
*/
extern LIBTYPE uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size);
extern LIBHDHOMERUN_API uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size);
/*
* Flush the buffer.
*/
extern LIBTYPE void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs);
extern LIBHDHOMERUN_API void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs);
/*
* Debug print internal stats.
*/
extern LIBTYPE void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs);
extern LIBTYPE void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats);
extern LIBHDHOMERUN_API void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs);
extern LIBHDHOMERUN_API void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats);
/*
* Internal use only.
*/
extern LIBTYPE hdhomerun_sock_t hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs);
extern LIBHDHOMERUN_API struct hdhomerun_sock_t *hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs);
#ifdef __cplusplus
}