[gssdp] Port get_host_ip() to Android/Bionic
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gssdp] Port get_host_ip() to Android/Bionic
- Date: Mon, 2 Sep 2013 18:37:11 +0000 (UTC)
commit 99dc6b5ed0b8a0d8388ef16d4265a186172133fc
Author: Reynaldo H. Verdejo Pinochet <reynaldo collabora com>
Date: Tue Apr 16 11:48:02 2013 -0400
Port get_host_ip() to Android/Bionic
Add Bionic netlink code for network configuration
discovery.
https://bugzilla.gnome.org/show_bug.cgi?id=707161
configure.ac | 17 ++++
libgssdp/Makefile.am | 4 +
libgssdp/gssdp-client.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 221 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index dd8fc2b..e5bec47 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,9 @@ GNOME_COMPILE_WARNINGS
AM_SILENT_RULES([yes])
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
AC_SEARCH_LIBS([strerror],[cposix])
AC_PROG_CC
AC_HEADER_STDC
@@ -114,6 +117,20 @@ esac
AC_MSG_RESULT([$os_win32])
AM_CONDITIONAL(OS_WIN32, [test $os_win32 = yes])
+dnl Check for Android
+AC_MSG_CHECKING([for Android as target OS])
+target_android=no
+case "$target_os" in
+ linux-android*)
+ target_android=yes
+ ;;
+ *)
+ target_android=no
+ ;;
+esac
+AC_MSG_RESULT([$target_android])
+AM_CONDITIONAL(TARGET_ANDROID, [test $target_android = yes])
+
GTK_DOC_CHECK([1.0])
AC_CONFIG_FILES([
diff --git a/libgssdp/Makefile.am b/libgssdp/Makefile.am
index f8d4dc2..c250f64 100644
--- a/libgssdp/Makefile.am
+++ b/libgssdp/Makefile.am
@@ -56,6 +56,10 @@ libgssdp_1_0_la_LIBADD += -lws2_32 -liphlpapi
libgssdp_1_0_la_LDFLAGS += -no-undefined
endif
+if TARGET_ANDROID
+libgssdp_1_0_la_LIBADD += -llog
+endif
+
EXTRA_DIST = gssdp-marshal.list
CLEANFILES = $(BUILT_SOURCES)
diff --git a/libgssdp/gssdp-client.c b/libgssdp/gssdp-client.c
index 876246c..baec893 100644
--- a/libgssdp/gssdp-client.c
+++ b/libgssdp/gssdp-client.c
@@ -54,7 +54,13 @@ typedef unsigned long in_addr_t;
#ifndef G_OS_WIN32
#include <arpa/inet.h>
#include <net/if.h>
+#ifndef __BIONIC__
#include <ifaddrs.h>
+#else
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <stdlib.h>
+#endif
#endif
#include <libsoup/soup-headers.h>
@@ -69,6 +75,10 @@ typedef unsigned long in_addr_t;
#define INET6_ADDRSTRLEN 46
#endif
+#ifdef __BIONIC__
+#include <android/log.h>
+#endif
+
/* Size of the buffer used for reading from the socket */
#define BUF_SIZE 65536
@@ -1240,6 +1250,196 @@ get_host_ip (GSSDPNetworkDevice *device)
g_free (adapters_addresses);
return TRUE;
+#elif __BIONIC__
+ struct ifreq *ifaces = NULL;
+ struct ifreq *iface = NULL;
+ struct ifreq tmp_iface;
+ struct ifconf ifconfigs;
+ struct sockaddr_in *address, *netmask;
+ struct in_addr net_address;
+ uint32_t ip;
+ int if_buf_size, sock, i, if_num;
+ GList *if_ptr, *if_list = NULL;
+
+ if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
+ __android_log_write (ANDROID_LOG_WARN,
+ "gssdp",
+ "Couldn't create socket");
+ return FALSE;
+ }
+
+ /* Fill ifaces with the available interfaces
+ * we incrementally proceed in chunks of 4
+ * till getting the full list
+ */
+
+ if_buf_size = 0;
+ do {
+ if_buf_size += 4 * sizeof (struct ifreq);
+ ifaces = g_realloc (ifaces, if_buf_size);
+ ifconfigs.ifc_len = if_buf_size;
+ ifconfigs.ifc_buf = (char *) ifaces;
+
+ /* FIXME: IPv4 only. This ioctl only deals with AF_INET */
+ if (ioctl (sock, SIOCGIFCONF, &ifconfigs) == -1) {
+ __android_log_print (ANDROID_LOG_WARN, "gssdp",
+ "Couldn't get list of devices. Asked for: %d",
+ if_buf_size / sizeof (struct ifreq));
+
+ goto fail;
+ }
+
+ } while (ifconfigs.ifc_len >= if_buf_size);
+
+ if_num = ifconfigs.ifc_len / sizeof (struct ifreq);
+
+ if (!device->iface_name) {
+ __android_log_print (ANDROID_LOG_DEBUG, "gssdp",
+ "Got list of %d interfaces. Looking for a suitable one",
+ if_num);
+ } else {
+ __android_log_print (ANDROID_LOG_DEBUG, "gssdp",
+ "List of %d interfaces ready. Now finding %s",
+ if_num, device->iface_name);
+ }
+
+ /* Buildup prioritized interface list
+ */
+
+ for (i = 0; i < if_num; i++) {
+
+ address = (struct sockaddr_in *) &(ifaces[i].ifr_addr);
+
+ __android_log_print (ANDROID_LOG_DEBUG,
+ "gssdp",
+ "Trying interface: %s",
+ ifaces[i].ifr_name);
+
+ if (!address->sin_addr.s_addr) {
+ __android_log_write (ANDROID_LOG_DEBUG, "gssdp",
+ "No configured address. Discarding");
+ continue;
+ }
+
+ memcpy (&tmp_iface, &ifaces[i], sizeof (struct ifreq));
+
+ if (ioctl (sock, SIOCGIFFLAGS, &tmp_iface) == -1) {
+ __android_log_write (ANDROID_LOG_DEBUG, "gssdp",
+ "Couldn't get flags. Discarding");
+ continue;
+ }
+
+ /* If an specific interface query was passed over.. */
+ if (device->iface_name &&
+ g_strcmp0 (device->iface_name, tmp_iface.ifr_name)) {
+ continue;
+ } else if (!(tmp_iface.ifr_flags & IFF_UP) ||
+ tmp_iface.ifr_flags & IFF_POINTOPOINT) {
+ continue;
+ }
+
+ /* Prefer non loopback */
+ if (ifaces[i].ifr_flags & IFF_LOOPBACK)
+ if_list = g_list_append (if_list, ifaces + i);
+ else
+ if_list = g_list_prepend (if_list, ifaces + i);
+
+ if (device->iface_name)
+ break;
+ }
+
+ if (!g_list_length (if_list)) {
+ __android_log_write (ANDROID_LOG_DEBUG,
+ "gssdp",
+ "No usable interfaces found");
+ goto fail;
+ }
+
+ /* Fill device with data from the first interface
+ * we can get complete config info for and return
+ */
+
+ for (if_ptr = if_list; if_ptr != NULL;
+ if_ptr = g_list_next (if_ptr)) {
+
+ iface = (struct ifreq *) if_ptr->data;
+ address = (struct sockaddr_in *) &(iface->ifr_addr);
+ netmask = (struct sockaddr_in *) &(iface->ifr_netmask);
+
+ device->host_ip = g_malloc0 (INET_ADDRSTRLEN);
+
+ if (inet_ntop (AF_INET, &(address->sin_addr),
+ device->host_ip, INET_ADDRSTRLEN) == NULL) {
+
+ __android_log_print (ANDROID_LOG_INFO,
+ "gssdp",
+ "Failed to get ip for: %s, %s",
+ iface->ifr_name,
+ strerror (errno));
+
+ g_free (device->host_ip);
+ device->host_ip = NULL;
+ continue;
+ }
+
+ ip = address->sin_addr.s_addr;
+
+ if (ioctl (sock, SIOCGIFNETMASK, iface) == -1) {
+ __android_log_write (ANDROID_LOG_DEBUG, "gssdp",
+ "Couldn't get netmask. Discarding");
+ g_free (device->host_ip);
+ device->host_ip = NULL;
+ continue;
+ }
+
+ memcpy (&device->mask, netmask, sizeof (struct sockaddr_in));
+
+ if (device->network == NULL) {
+ device->network = g_malloc0 (INET_ADDRSTRLEN);
+
+ net_address.s_addr = ip & netmask->sin_addr.s_addr;
+
+ if (inet_ntop (AF_INET, &net_address,
+ device->network, INET_ADDRSTRLEN) == NULL) {
+
+ __android_log_print (ANDROID_LOG_WARN, "gssdp",
+ "Failed to get nw for: %s, %s",
+ iface->ifr_name, strerror (errno));
+
+ g_free (device->host_ip);
+ device->host_ip = NULL;
+ g_free (device->network);
+ device->network = NULL;
+ continue;
+ }
+ }
+
+ if (!device->iface_name)
+ device->iface_name = g_strdup (iface->ifr_name);
+
+ goto success;
+
+ }
+
+ __android_log_write (ANDROID_LOG_WARN, "gssdp",
+ "Traversed whole list without finding a configured device");
+
+fail:
+ __android_log_write (ANDROID_LOG_WARN,
+ "gssdp",
+ "Failed to get configuration for device");
+ g_free (ifaces);
+ g_list_free (if_list);
+ close (sock);
+ return FALSE;
+success:
+ __android_log_print (ANDROID_LOG_DEBUG, "gssdp",
+ "Returned config params for device: %s ip: %s network: %s",
+ device->iface_name, device->host_ip, device->network);
+ g_free (ifaces);
+ g_list_free (if_list);
+ close (sock);
+ return TRUE;
#else
struct ifaddrs *ifa_list, *ifa;
GList *up_ifaces, *ifaceptr;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]