From 8d861a8f0b0b45cb10ac145468b916f112acaaa0 Mon Sep 17 00:00:00 2001 From: Nick Kelsey Date: Sat, 30 Jan 2016 11:51:36 -0800 Subject: [PATCH] libhdhomerun 20160130 --- README.md | 27 +-- hdhomerun_channels.c | 2 +- hdhomerun_channels.h | 36 +-- hdhomerun_channelscan.c | 2 +- hdhomerun_channelscan.h | 12 +- hdhomerun_config.c | 18 +- hdhomerun_control.c | 15 +- hdhomerun_control.h | 28 +-- hdhomerun_debug.c | 16 +- hdhomerun_debug.h | 24 +- hdhomerun_device.c | 2 +- hdhomerun_device.h | 132 +++++------ hdhomerun_device_selector.c | 10 +- hdhomerun_device_selector.h | 25 +- hdhomerun_discover.c | 7 +- hdhomerun_discover.h | 12 +- hdhomerun_os.h | 8 +- hdhomerun_os_posix.c | 99 ++++++-- hdhomerun_os_posix.h | 32 ++- hdhomerun_os_windows.c | 64 ++++-- hdhomerun_os_windows.h | 81 ++++--- hdhomerun_pkt.c | 2 +- hdhomerun_pkt.h | 35 +-- hdhomerun_sock.h | 43 ++-- hdhomerun_sock_posix.c | 443 ++++++++++++++++++++++-------------- hdhomerun_sock_windows.c | 426 ++++++++++++++++++---------------- hdhomerun_types.h | 2 +- hdhomerun_video.c | 16 +- hdhomerun_video.h | 22 +- 29 files changed, 916 insertions(+), 725 deletions(-) diff --git a/README.md b/README.md index 3c0bb57..1c24502 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,11 @@ -/* - * README - * - * Copyright © 2005-2009 Silicondust USA Inc. . - * - * 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. . -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 diff --git a/hdhomerun_channels.c b/hdhomerun_channels.c index 9beec5e..6746770 100644 --- a/hdhomerun_channels.c +++ b/hdhomerun_channels.c @@ -1,7 +1,7 @@ /* * hdhomerun_channels.c * - * Copyright © 2007-2008 Silicondust USA Inc. . + * Copyright © 2007-2014 Silicondust USA Inc. . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/hdhomerun_channels.h b/hdhomerun_channels.h index 73be727..6061e88 100644 --- a/hdhomerun_channels.h +++ b/hdhomerun_channels.h @@ -1,7 +1,7 @@ /* * hdhomerun_channels.h * - * Copyright © 2007-2008 Silicondust USA Inc. . + * Copyright © 2007-2015 Silicondust USA Inc. . * * 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 } diff --git a/hdhomerun_channelscan.c b/hdhomerun_channelscan.c index eef2a5f..a077b87 100644 --- a/hdhomerun_channelscan.c +++ b/hdhomerun_channelscan.c @@ -1,7 +1,7 @@ /* * hdhomerun_channelscan.c * - * Copyright © 2007-2010 Silicondust USA Inc. . + * Copyright © 2007-2015 Silicondust USA Inc. . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/hdhomerun_channelscan.h b/hdhomerun_channelscan.h index 1b2849d..9306230 100644 --- a/hdhomerun_channelscan.h +++ b/hdhomerun_channelscan.h @@ -1,7 +1,7 @@ /* * hdhomerun_channelscan.h * - * Copyright © 2007-2008 Silicondust USA Inc. . + * Copyright © 2007-2015 Silicondust USA Inc. . * * 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 } diff --git a/hdhomerun_config.c b/hdhomerun_config.c index debd946..1aa93d2 100644 --- a/hdhomerun_config.c +++ b/hdhomerun_config.c @@ -1,7 +1,7 @@ /* * hdhomerun_config.c * - * Copyright © 2006-2008 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * 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; diff --git a/hdhomerun_control.c b/hdhomerun_control.c index db57e93..be7ba67 100644 --- a/hdhomerun_control.c +++ b/hdhomerun_control.c @@ -1,7 +1,7 @@ /* * hdhomerun_control.c * - * Copyright © 2006-2010 Silicondust USA Inc. . + * Copyright © 2006-2016 Silicondust USA Inc. . * * 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; diff --git a/hdhomerun_control.h b/hdhomerun_control.h index 7e2512a..a598ce2 100644 --- a/hdhomerun_control.h +++ b/hdhomerun_control.h @@ -1,7 +1,7 @@ /* * hdhomerun_control.h * - * Copyright © 2006 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * 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 } diff --git a/hdhomerun_debug.c b/hdhomerun_debug.c index 5514603..9184479 100644 --- a/hdhomerun_debug.c +++ b/hdhomerun_debug.c @@ -1,7 +1,7 @@ /* * hdhomerun_debug.c * - * Copyright © 2006-2010 Silicondust USA Inc. . + * Copyright © 2007-2016 Silicondust USA Inc. . * * 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; } diff --git a/hdhomerun_debug.h b/hdhomerun_debug.h index fbc2da9..5f6a183 100644 --- a/hdhomerun_debug.h +++ b/hdhomerun_debug.h @@ -1,7 +1,7 @@ /* * hdhomerun_debug.h * - * Copyright © 2006 Silicondust USA Inc. . + * Copyright © 2007-2015 Silicondust USA Inc. . * * 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 } diff --git a/hdhomerun_device.c b/hdhomerun_device.c index fa4a508..68cf1af 100644 --- a/hdhomerun_device.c +++ b/hdhomerun_device.c @@ -1,7 +1,7 @@ /* * hdhomerun_device.c * - * Copyright © 2006-2010 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/hdhomerun_device.h b/hdhomerun_device.h index 3693943..6b54ec0 100644 --- a/hdhomerun_device.h +++ b/hdhomerun_device.h @@ -1,7 +1,7 @@ /* * hdhomerun_device.h * - * Copyright © 2006-2008 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * 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 */ -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 } diff --git a/hdhomerun_device_selector.c b/hdhomerun_device_selector.c index bc46c84..e75882c 100644 --- a/hdhomerun_device_selector.c +++ b/hdhomerun_device_selector.c @@ -1,7 +1,7 @@ /* * hdhomerun_device_selector.c * - * Copyright © 2009-2010 Silicondust USA Inc. . + * Copyright © 2009-2016 Silicondust USA Inc. . * * 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; } diff --git a/hdhomerun_device_selector.h b/hdhomerun_device_selector.h index 24fcd80..a66e058 100644 --- a/hdhomerun_device_selector.h +++ b/hdhomerun_device_selector.h @@ -1,7 +1,7 @@ /* * hdhomerun_device_selector.h * - * Copyright © 2009 Silicondust USA Inc. . + * Copyright © 2009-2015 Silicondust USA Inc. . * * 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 } diff --git a/hdhomerun_discover.c b/hdhomerun_discover.c index f60ab63..b48c457 100644 --- a/hdhomerun_discover.c +++ b/hdhomerun_discover.c @@ -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; } diff --git a/hdhomerun_discover.h b/hdhomerun_discover.h index 947aaa1..4626d55 100644 --- a/hdhomerun_discover.h +++ b/hdhomerun_discover.h @@ -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 } diff --git a/hdhomerun_os.h b/hdhomerun_os.h index 1976632..f7e1511 100644 --- a/hdhomerun_os.h +++ b/hdhomerun_os.h @@ -1,7 +1,7 @@ /* * hdhomerun_os.h * - * Copyright © 2006-2008 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * 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" diff --git a/hdhomerun_os_posix.c b/hdhomerun_os_posix.c index 5a38edf..06fd398 100644 --- a/hdhomerun_os_posix.c +++ b/hdhomerun_os_posix.c @@ -1,7 +1,7 @@ /* * hdhomerun_os_posix.c * - * Copyright © 2006-2010 Silicondust USA Inc. . + * Copyright © 2006-2016 Silicondust USA Inc. . * * 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 #include + +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) { diff --git a/hdhomerun_os_posix.h b/hdhomerun_os_posix.h index 006f026..e20ee61 100644 --- a/hdhomerun_os_posix.h +++ b/hdhomerun_os_posix.h @@ -1,7 +1,7 @@ /* * hdhomerun_os_posix.h * - * Copyright © 2006-2010 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * 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 #include -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 } diff --git a/hdhomerun_os_windows.c b/hdhomerun_os_windows.c index 1e5f9d8..1440316 100644 --- a/hdhomerun_os_windows.c +++ b/hdhomerun_os_windows.c @@ -1,7 +1,7 @@ /* * hdhomerun_os_windows.c * - * Copyright © 2006-2010 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * 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); -} diff --git a/hdhomerun_os_windows.h b/hdhomerun_os_windows.h index 8f7585a..ed8a6a2 100644 --- a/hdhomerun_os_windows.h +++ b/hdhomerun_os_windows.h @@ -1,7 +1,7 @@ /* * hdhomerun_os_windows.h * - * Copyright © 2006-2010 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * 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 +#ifdef _WINRT +#include +#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 +#include #include #include #include #include #include +#include #include #include #include #include #include -#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 } diff --git a/hdhomerun_pkt.c b/hdhomerun_pkt.c index 13ed8bd..d8071c6 100644 --- a/hdhomerun_pkt.c +++ b/hdhomerun_pkt.c @@ -1,7 +1,7 @@ /* * hdhomerun_pkt.c * - * Copyright © 2005-2006 Silicondust USA Inc. . + * Copyright © 2006-2014 Silicondust USA Inc. . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/hdhomerun_pkt.h b/hdhomerun_pkt.h index 008a96a..9821b91 100644 --- a/hdhomerun_pkt.h +++ b/hdhomerun_pkt.h @@ -1,7 +1,7 @@ /* * hdhomerun_pkt.h * - * Copyright © 2005-2006 Silicondust USA Inc. . + * Copyright © 2006-2015 Silicondust USA Inc. . * * 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 } diff --git a/hdhomerun_sock.h b/hdhomerun_sock.h index d14f6e4..0c252db 100644 --- a/hdhomerun_sock.h +++ b/hdhomerun_sock.h @@ -1,7 +1,7 @@ /* * hdhomerun_sock.h * - * Copyright © 2010 Silicondust USA Inc. . + * Copyright © 2010-2016 Silicondust USA Inc. . * * 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 } diff --git a/hdhomerun_sock_posix.c b/hdhomerun_sock_posix.c index 8846c5d..17fcd6f 100644 --- a/hdhomerun_sock_posix.c +++ b/hdhomerun_sock_posix.c @@ -1,7 +1,7 @@ /* * hdhomerun_sock_posix.c * - * Copyright © 2010 Silicondust USA Inc. . + * Copyright © 2010-2016 Silicondust USA Inc. . * * 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 @@ -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; - } - - /* Set non-blocking */ - if (fcntl(sock, F_SETFL, O_NONBLOCK) != 0) { - close(sock); - return HDHOMERUN_SOCK_INVALID; - } - - /* Success. */ - return sock; + return hdhomerun_sock_create_internal(SOCK_STREAM); } -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,14 @@ 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) -{ - uint64_t current_time = getcurrenttime(); - if (current_time >= stop_time) { - return FALSE; - } - - struct pollfd poll_event; - poll_event.fd = sock; - poll_event.events = event_type; - 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) { - 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_connect(struct hdhomerun_sock_t *sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout) { struct sockaddr_in sock_addr; memset(&sock_addr, 0, sizeof(sock_addr)); @@ -324,128 +321,224 @@ 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 (connect(sock->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); + 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; + } + + return TRUE; } -bool_t hdhomerun_sock_send(hdhomerun_sock_t sock, const void *data, size_t length, uint64_t timeout) +bool_t hdhomerun_sock_send(struct 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 = send(sock->sock, ptr, length, MSG_NOSIGNAL); + 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)) { - return FALSE; - } - if (!hdhomerun_sock_wait_for_event(sock, POLLOUT, stop_time)) { - return FALSE; - } - continue; - } - - if (ret < (int)length) { - ptr += ret; - length -= ret; - continue; - } - - return TRUE; + if ((ret < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) { + return FALSE; + } + + if (ret > 0) { + ptr += ret; + length -= ret; } -} -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)) { - return FALSE; - } - if (!hdhomerun_sock_wait_for_event(sock, POLLIN, stop_time)) { - return FALSE; - } - continue; - } + struct pollfd poll_event; + poll_event.fd = sock->sock; + poll_event.events = POLLOUT; + poll_event.revents = 0; - if (ret == 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)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = htonl(remote_addr); + sock_addr.sin_port = htons(remote_port); + + const uint8_t *ptr = (const uint8_t *)data; + int 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 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 = 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; - } + struct sockaddr_in sock_addr; + memset(&sock_addr, 0, sizeof(sock_addr)); + socklen_t sockaddr_size = sizeof(sock_addr); + 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; } diff --git a/hdhomerun_sock_windows.c b/hdhomerun_sock_windows.c index 3a80a5b..dd20fbb 100644 --- a/hdhomerun_sock_windows.c +++ b/hdhomerun_sock_windows.c @@ -1,7 +1,7 @@ /* * hdhomerun_sock_windows.c * - * Copyright © 2010 Silicondust USA Inc. . + * Copyright © 2010-2016 Silicondust USA Inc. . * * 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 #include +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; - } - - /* Set non-blocking */ - unsigned long mode = 1; - if (ioctlsocket(sock, FIONBIO, &mode) != 0) { - closesocket(sock); - return HDHOMERUN_SOCK_INVALID; - } - - /* Success. */ - return sock; + return hdhomerun_sock_create_internal(SOCK_STREAM); } -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) { - uint64_t current_time = getcurrenttime(); - if (current_time >= stop_time) { + if (!hdhomerun_sock_event_select(sock, FD_WRITE | FD_CLOSE)) { return FALSE; } - WSAEVENT wsa_event = WSACreateEvent(); - if (wsa_event == WSA_INVALID_EVENT) { - 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) -{ 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) { - return FALSE; - } - if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) { - return FALSE; - } - continue; + int ret = send(sock->sock, (char *)ptr, (int)length, 0); + if (ret >= (int)length) { + return TRUE; } - 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; - } - - 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, (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)) { - return FALSE; - } - continue; - } - - if (ret == 0) { + 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; + } + + if (WaitForSingleObjectEx(sock->event, (DWORD)(stop_time - current_time), FALSE) != WAIT_OBJECT_0) { + return FALSE; + } + } +} + +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) +{ + 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); + + 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; + } + if (WSAGetLastError() != WSAEWOULDBLOCK) { + return FALSE; + } + + if (WaitForSingleObjectEx(sock->event, (DWORD)timeout, FALSE) != WAIT_OBJECT_0) { + return FALSE; + } + + 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; - } + struct sockaddr_in sock_addr; + memset(&sock_addr, 0, sizeof(sock_addr)); + int sockaddr_size = sizeof(sock_addr); + 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; } diff --git a/hdhomerun_types.h b/hdhomerun_types.h index e2a888f..55992ea 100644 --- a/hdhomerun_types.h +++ b/hdhomerun_types.h @@ -1,7 +1,7 @@ /* * hdhomerun_types.h * - * Copyright © 2008-2009 Silicondust USA Inc. . + * Copyright © 2008-2015 Silicondust USA Inc. . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/hdhomerun_video.c b/hdhomerun_video.c index aaca66d..85c4dfd 100644 --- a/hdhomerun_video.c +++ b/hdhomerun_video.c @@ -1,7 +1,7 @@ /* * hdhomerun_video.c * - * Copyright © 2006-2010 Silicondust USA Inc. . + * Copyright © 2006-2016 Silicondust USA Inc. . * * 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) diff --git a/hdhomerun_video.h b/hdhomerun_video.h index d6485e1..25275a4 100644 --- a/hdhomerun_video.h +++ b/hdhomerun_video.h @@ -1,7 +1,7 @@ /* * hdhomerun_video.h * - * Copyright © 2006 Silicondust USA Inc. . + * Copyright © 2006-2016 Silicondust USA Inc. . * * 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 }