[gssdp] Port get_host_ip() to Android/Bionic



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]