--- a/meson.build Tue Oct 25 20:35:39 2022 -0500
+++ b/meson.build Mon Nov 07 22:00:16 2022 -0600
@@ -1,8 +1,8 @@
project('libtraversity', 'C',
- license : 'LGPL-2.0-or-later',
- meson_version : '>=0.63.0',
- default_options : ['c_std=c99', 'warning_level=2'])
+ license : 'LGPL-2.0-or-later', + meson_version : '>=0.63.0', + default_options : ['c_std=c99', 'warning_level=2']) ###############################################################################
@@ -11,9 +11,9 @@
parts = meson.project_version().split('-')
- traversity_extra_version = parts[1]
+ traversity_extra_version = parts[1] - traversity_extra_version = ''
+ traversity_extra_version = '' parts = parts[0].split('.')
@@ -25,6 +25,12 @@
traversity_minor_version,
traversity_micro_version)
+conf = configuration_data() +conf.set_quoted('PACKAGE', meson.project_name()) +conf.set_quoted('PACKAGE_NAME', meson.project_name()) +conf.set_quoted('VERSION', meson.project_version()) +conf.set_quoted('DISPLAY_VERSION', meson.project_version()) version_conf = configuration_data()
version_conf.set('TRAVERSITY_MAJOR_VERSION', traversity_major_version)
version_conf.set('TRAVERSITY_MINOR_VERSION', traversity_minor_version)
@@ -49,9 +55,11 @@
###############################################################################
GLIB = dependency('glib-2.0', version : '>=2.70.0')
- '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_70',
- '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_70',
+ '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_70', + '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_70', GOBJECT = dependency('gobject-2.0', version : '>=2.70.0')
@@ -59,16 +67,24 @@
TEMPLATE_GLIB = dependency('template-glib-1.0', version : '>=3.30.0')
###############################################################################
+############################################################################### +cc = meson.get_compiler('c') +conf.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs')) +conf.set('HAVE_INET_NTOP', cc.has_function('inet_ntop')) +############################################################################### ###############################################################################
if get_option('doc') and not get_option('introspection')
- error('Documentation requires GObject Introspection.')
+ error('Documentation requires GObject Introspection.') gidocgen_dep = dependency(
- 'gi-docgen', version: '>= 2021.1',
- fallback: ['gi-docgen', 'dummy_dep'],
- required: get_option('doc')
+ 'gi-docgen', version: '>= 2021.1', + fallback: ['gi-docgen', 'dummy_dep'], + required: get_option('doc') gidocgen = find_program('gi-docgen', required : get_option('doc'))
@@ -79,3 +95,6 @@
###############################################################################
subdir('traversity-test')
+# Output our configuration file. +configure_file(output : 'config.h', configuration : conf) --- a/traversity-test/traversity-test.c Tue Oct 25 20:35:39 2022 -0500
+++ b/traversity-test/traversity-test.c Mon Nov 07 22:00:16 2022 -0600
@@ -66,10 +66,29 @@
main(G_GNUC_UNUSED gint argc, G_GNUC_UNUSED gchar *argv[]) {
TraversityDiscoverer *discoverer = NULL;
loop = g_main_loop_new(NULL, FALSE);
+ g_message("local ip addresses:"); + ips = traversity_core_get_all_local_ips(&error); + g_message(" - error: %s", error->message); + char *ip = (char *)ips->data; + g_message(" - %s", ip); + ips = g_list_delete_link(ips, ips); discoverer = g_object_new(TRAVERSITY_TYPE_UPNP_DISCOVERER, NULL);
g_signal_connect(discoverer, "notify::status",
G_CALLBACK(traversity_test_notify_status_cb), loop);
--- a/traversity/meson.build Tue Oct 25 20:35:39 2022 -0500
+++ b/traversity/meson.build Mon Nov 07 22:00:16 2022 -0600
@@ -17,6 +17,17 @@
TRAVERSITY_BUILT_SOURCES = []
TRAVERSITY_BUILT_HEADERS = []
+TRAVERSITY_DEPENDENCIES = [GLIB, GOBJECT, TEMPLATE_GLIB] +if host_machine.system() == 'windows' + TRAVERSITY_SOURCES += 'traversitycoreunix.c' +if host_machine.system() == 'haiku' + TRAVERSITY_DEPENDENCIES += cc.find_library('network') traversity_filebase = 'traversity-1'
traversity_include_base = traversity_filebase / 'traversity'
@@ -61,7 +72,7 @@
libtraversity = library('traversity',
- dependencies : [GLIB, GOBJECT, TEMPLATE_GLIB],
+ dependencies : TRAVERSITY_DEPENDENCIES, c_args : TRAVERSITY_CFLAGS,
version : LIBTRAVERSITY_VERSION,
include_directories : [toplevel_inc, traversity_inc],
@@ -72,7 +83,7 @@
sources : TRAVERSITY_BUILT_HEADERS,
include_directories : [toplevel_inc, traversity_inc],
link_with : libtraversity,
- dependencies : [GLIB, GOBJECT, TEMPLATE_GLIB])
+ dependencies : TRAVERSITY_DEPENDENCIES) meson.override_dependency(traversity_filebase, traversity_dep)
--- a/traversity/traversitycore.h Tue Oct 25 20:35:39 2022 -0500
+++ b/traversity/traversitycore.h Mon Nov 07 22:00:16 2022 -0600
@@ -49,6 +49,19 @@
void traversity_core_uninit(void);
+ * traversity_core_get_all_local_ips: + * @error: (nullable) (optional): A return address for a [type@GLib.GError]. + * Gets a list of all of the local ip addresses. + * Returns: (transfer full) (element-type utf8): The list of all local IP +GList *traversity_core_get_all_local_ips(GError **error); #endif /* TRAVERSITY_CORE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/traversity/traversitycoreunix.c Mon Nov 07 22:00:16 2022 -0600
@@ -0,0 +1,285 @@
+#endif /* HAVE_CONFIG_H */ +/* This is used to test the ioctl method and should never be defined in a +/* #define FORCE_IOCTL */ +# warning Forcing use of SIOCGIFCONF ioctl to list local ip addresses! +#endif /* FORCE_IOCTL */ +#if defined(HAVE_GETIFADDRS) && defined(HAVE_INET_NTOP) && !defined(FORCE_IOCTL) +# include <netinet/in.h> +#else /* defined(HAVE_GETIFADDRS) && defined(HAVE_INET_NTOP) && !defined(FORCE_IOCTL) */ +# include <arpa/nameser.h> +# include <netinet/in.h> +# include <sys/socket.h> +#endif /* defined(HAVE_GETIFADDRS) && defined(HAVE_INET_NTOP) && !defined(FORCE_IOCTL) */ +# include <sys/sockio.h> +/* Calling sizeof(struct ifreq) isn't always correct on Mac OS X (and maybe + * others). This originated from gaim. +#ifdef _SIZEOF_ADDR_IFREQ +# define HX_SIZE_OF_IFREQ(a) _SIZEOF_ADDR_IFREQ(a) +# define HX_SIZE_OF_IFREQ(a) sizeof(a) +#include "traversitycore.h" +/****************************************************************************** + *****************************************************************************/ +#if defined(HAVE_GETIFADDRS) && defined(HAVE_INET_NTOP) && !defined(FORCE_IOCTL) +traversity_core_get_all_local_ips(GError **error) { + struct ifaddrs *first = NULL; + struct ifaddrs *ifa = NULL; + ret = getifaddrs(&first); + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to get network interfaces: %s", g_strerror(errno)); + for(ifa = first; ifa != NULL; ifa = ifa->ifa_next) { + const char *tmp = NULL; + int family = AF_UNSPEC; + if(ifa->ifa_addr == NULL) { + family = ifa->ifa_addr->sa_family; + /* If the interface doesn't support IPv4 or IPv6 skip it. */ + if(family != AF_INET && family != AF_INET6) { + /* If this is a loopback device skip it. */ + if(ifa->ifa_flags & IFF_LOOPBACK) { + if(family == AF_INET) { + /* If this is a non-null IPv4 address add it to our list. */ + struct sockaddr_in *in = (struct sockaddr_in *)ifa->ifa_addr; + tmp = inet_ntop(family, &in->sin_addr, host, sizeof(host)); + struct sockaddr_in6 *in = (struct sockaddr_in6 *)ifa->ifa_addr; + /* Peer-peer link-local communication is a big TODO. I am not sure + * how communicating link-local addresses is supposed to work, and + * it seems like it would require attempting the cartesian product + * of the local and remote interfaces to see if any match (eww). + if(!IN6_IS_ADDR_LINKLOCAL(&in->sin6_addr)) { + tmp = inet_ntop(family, &in->sin6_addr, host, sizeof(host)); + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to parse IP address: %s", + g_list_free_full(ips, g_free); + ips = g_list_prepend(ips, g_strdup(tmp)); + return g_list_reverse(ips); +#else /* defined(HAVE_GETIFADDRS) && defined(HAVE_INET_NTOP) */ +/* Note: This version does not work on macOS or Haiku. */ +traversity_core_get_all_local_ips(GError **error) { + struct ifreq *ifreq = NULL; + /* Create a socket to use in the ioctl call. */ + if((source = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to create socket: %s", g_strerror(errno)); + /* Call the ioctl to get the size of the buffer for all interfaces. + * Note: SIOCGIFCONF only supports IPv4. + if((ret = ioctl(source, SIOCGIFCONF, &ifc)) < 0) { + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to query network interfaces: %s", + /* ifc_len was set to the total size needed in the above call. */ + ifc.ifc_req = g_malloc(ifc.ifc_len); + if((ret = ioctl(source, SIOCGIFCONF, &ifc)) < 0) { + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to query network interfaces: %s", + /* Close the socket as we no longer need it. */ + /* Walk through each interface in our list. Item sizes can vary, so we + * add the size as one of the last steps in the body. + for(int i = 0; i < ifc.ifc_len;) { + len = HX_SIZE_OF_IFREQ(*ifreq); + if(ifreq->ifr_addr.sa_family == AF_INET) { + struct sockaddr_in *sinptr = (struct sockaddr_in *)&ifreq->ifr_addr; + const char *tmp = NULL; + tmp = inet_ntop(AF_INET, &sinptr->sin_addr, dst, sizeof(dst)); + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to parse IP address: %s", + g_list_free_full(ips, g_free); + if(g_strcmp0(dst, "127.0.0.1") != 0) { + ips = g_list_append(ips, g_strdup(dst)); + ifreq=(struct ifreq *)((char *)ifreq + len); +traversity_core_get_all_local_ips(GError **error) { + struct ifreq *ifr = NULL; + /* Create a socket to use in the ioctl call. */ + if((source = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to create socket: %s", g_strerror(errno)); + /* Setup our output buffer. */ + ifc.ifc_len = sizeof(buffer); + ifc.ifc_req = (struct ifreq *)buffer; + /* Call the ioctl to get all of the interfaces. + * Note: SIOCGIFCONF only supports IPv4. + if((ret = ioctl(source, SIOCGIFCONF, &ifc)) < 0) { + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to query network interfaces: %s", + /* Close the socket as we no longer need it. */ + /* Walk through each interface in our list. */ + while(tmp < buffer + ifc.ifc_len) { + /* Update ifr to point to the index of our buffer. */ + ifr = (struct ifreq *)tmp; + /* Move in the index in the buffer to the next record. */ + tmp += HX_SIZE_OF_IFREQ(*ifr); + if(ifr->ifr_addr.sa_family == AF_INET) { + const char *ret = NULL; + struct sockaddr_in *sinptr = (struct sockaddr_in *)&ifr->ifr_addr; + ret = inet_ntop(AF_INET, &sinptr->sin_addr, dst, sizeof(dst)); + g_set_error(error, TRAVERSITY_DOMAIN, 0, + "failed to convert IP address: %s", + g_list_free_full(ips, g_free); + if(g_strcmp0(dst, "127.0.0.1") != 0) { + ips = g_list_append(ips, g_strdup(dst)); +#endif /* defined(HAVE_GETIFADDRS) && defined(HAVE_INET_NTOP) */