diff --git a/avahi-core/iface-android-api-30.c b/avahi-core/iface-android-api-30.c new file mode 100644 index 0000000..8562627 --- /dev/null +++ b/avahi-core/iface-android-api-30.c @@ -0,0 +1,135 @@ +/*** + This file is part of avahi. + + avahi 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. + + avahi 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 avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "iface.h" +#include "addr-util.h" + +int avahi_interface_monitor_init_osdep(AvahiInterfaceMonitor *m) { + AvahiHwInterface *hw; + AvahiInterface *i; + AvahiAddress raddr; + AvahiInterfaceAddress *addr; + struct ifaddrs *addrs_list; + struct ifaddrs *ifa; + + getifaddrs(&addrs_list); + for (ifa = addrs_list; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr || (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)) + continue; + + unsigned int ifi_index = if_nametoindex(ifa->ifa_name); + if (!(hw = avahi_interface_monitor_get_hw_interface(m, ifi_index))) { + + /* No object found, so let's create a new + * one. avahi_hw_interface_new() will call + * avahi_interface_new() internally twice for IPv4 and + * IPv6, so there is no need for us to do that + * ourselves */ + if ((hw = avahi_hw_interface_new(m, (AvahiIfIndex) ifi_index))) { + hw->flags_ok = + (ifa->ifa_flags & IFF_UP) && + (!m->server->config.use_iff_running || (ifa->ifa_flags & IFF_RUNNING)) && + !(ifa->ifa_flags & IFF_LOOPBACK) && + (ifa->ifa_flags & IFF_MULTICAST) && + (m->server->config.allow_point_to_point || !(ifa->ifa_flags & IFF_POINTOPOINT)); + + avahi_free(hw->name); + hw->name = avahi_strndup(ifa->ifa_name, strlen(ifa->ifa_name)); + +// fixme - these mtu values are differnet from what ip addr reports +// struct ifreq ifr; +// memset(&ifr, 0, sizeof(ifr)); +// int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); +// strcpy(ifr.ifr_name, hw->name); +// if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { +// //perror("SIOCGIFFLAGS"); +// } +// close(sock); +// hw->mtu = ifr.ifr_mtu; + + /* Check whether this interface is now "relevant" for us. If + * it is Avahi will start to announce its records on this + * interface and send out queries for subscribed records on + * it */ + avahi_hw_interface_check_relevant(hw); + + /* Update any associated RRs of this interface. (i.e. the + * _workstation._tcp record containing the MAC address) */ + avahi_hw_interface_update_rrs(hw, 0); + } else { + goto out; + } + } + + /* Try to get a reference to our AvahiInterface object for the + * interface this address is assigned to. If ther is no object + * for this interface, we ignore this address. */ + if (!(i = avahi_interface_monitor_get_interface(m, (AvahiIfIndex) ifi_index, avahi_af_to_proto(ifa->ifa_addr->sa_family)))) + continue; + + avahi_address_from_sockaddr(ifa->ifa_addr, &raddr); + + /* This address is new or has been modified, so let's get an object for it */ + if (!(addr = avahi_interface_monitor_get_address(m, i, &raddr))) + + /* Mmm, no object existing yet, so let's create a new one */ + if (!(addr = avahi_interface_address_new(m, i, &raddr, 4))) + continue; /* OOM */ + + /* Update the scope field for the address */ + //addr->global_scope = 0;//ifaddrmsg->ifa_scope == RT_SCOPE_UNIVERSE || ifaddrmsg->ifa_scope == RT_SCOPE_SITE; + addr->deprecated = !!(ifa->ifa_flags & IFA_F_DEPRECATED); + + /* Avahi only considers interfaces with at least one address + * attached relevant. Since we migh have added or removed an + * address, let's have it check again whether the interface is + * now relevant */ + avahi_interface_check_relevant(i); + + /* Update any associated RRs, like A or AAAA for our new/removed address */ + avahi_interface_update_rrs(i, 0); + } + + m->list_complete = 1; + avahi_interface_monitor_check_relevant(m); + + /* And update all RRs attached to any interface */ + avahi_interface_monitor_update_rrs(m, 0); + +out: + freeifaddrs(addrs_list); + + return 0; +} + +void avahi_interface_monitor_free_osdep(AvahiInterfaceMonitor *m) { + (void) m; +} + +void avahi_interface_monitor_sync(AvahiInterfaceMonitor *m) { + (void) m; +} diff --git a/avahicore.cpp b/avahicore.cpp index b9dd1ca..f5e6fce 100644 --- a/avahicore.cpp +++ b/avahicore.cpp @@ -38,30 +38,31 @@ class QZeroConfPrivate public: QZeroConfPrivate(QZeroConf *parent) { - qint32 error; - pub = parent; group = NULL; browser = NULL; txt = NULL; ready = 0; registerWaiting = 0; + } - poll = avahi_qt_poll_get(); - if (!poll) { - return; - } + void createOrDeleteServer() + { + qint32 error; - avahi_server_config_init(&config); - config.publish_workstation = 0; - - if (!referenceCount) { + if (!serviceObjectCount && !browserObjectCount) { + avahi_server_free(server); + avahi_server_config_free(&config); + server = nullptr; + } else if (!server) { + poll = avahi_qt_poll_get(); + if (!poll) { + return; + } + avahi_server_config_init(&config); + config.publish_workstation = 0; server = avahi_server_new(poll, &config, serverCallback, this, &error); } - referenceCount++; - if (!server) { - return; - } } static void serverCallback(AvahiServer *, AvahiServerState state, AVAHI_GCC_UNUSED void * userdata) @@ -228,6 +229,9 @@ public: for (r = resolvers.begin(); r != resolvers.end(); r++) avahi_s_service_resolver_free(*r); resolvers.clear(); + + browserObjectCount--; + createOrDeleteServer(); } void registerService(const char *name, const char *type, const char *domain, quint16 port) @@ -258,8 +262,9 @@ public: QZeroConf *pub; const AvahiPoll *poll; static AvahiServer *server; - static quint32 referenceCount; - AvahiServerConfig config; + static size_t serviceObjectCount; + static size_t browserObjectCount; + static AvahiServerConfig config; AvahiSEntryGroup *group; AvahiSServiceBrowser *browser; AvahiProtocol aProtocol; @@ -271,7 +276,9 @@ public: }; AvahiServer* QZeroConfPrivate::server = nullptr; -quint32 QZeroConfPrivate::referenceCount = 0; +AvahiServerConfig QZeroConfPrivate::config; +size_t QZeroConfPrivate::serviceObjectCount = 0; +size_t QZeroConfPrivate::browserObjectCount = 0; QZeroConf::QZeroConf(QObject *parent) : QObject (parent) { @@ -284,9 +291,7 @@ QZeroConf::~QZeroConf() avahi_string_list_free(pri->txt); pri->broswerCleanUp(); avahi_server_config_free(&pri->config); - pri->referenceCount--; - if (!pri->referenceCount) - avahi_server_free(pri->server); + stopServicePublish(); delete pri; } @@ -296,6 +301,10 @@ void QZeroConf::startServicePublish(const char *name, const char *type, const ch emit error(QZeroConf::serviceRegistrationFailed); return; } + + pri->serviceObjectCount++; + pri->createOrDeleteServer(); + if (pri->ready) pri->registerService(name, type, domain, port); else { @@ -312,6 +321,8 @@ void QZeroConf::stopServicePublish(void) if (pri->group) { avahi_s_entry_group_free(pri->group); pri->group = NULL; + pri->serviceObjectCount--; + pri->createOrDeleteServer(); } } @@ -348,6 +359,9 @@ void QZeroConf::startBrowser(QString type, QAbstractSocket::NetworkLayerProtocol if (pri->browser) emit error(QZeroConf::browserFailed); + pri->browserObjectCount++; + pri->createOrDeleteServer(); + switch (protocol) { case QAbstractSocket::IPv4Protocol: pri->aProtocol = AVAHI_PROTO_INET; break; case QAbstractSocket::IPv6Protocol: pri->aProtocol = AVAHI_PROTO_INET6; break; diff --git a/qtzeroconf.pri b/qtzeroconf.pri index ab841b4..1d57236 100644 --- a/qtzeroconf.pri +++ b/qtzeroconf.pri @@ -69,7 +69,7 @@ ubports|android: { DEFINES+= HAVE_STRLCPY GETTEXT_PACKAGE } ubports: { - DEFINES+= _GNU_SOURCE GETTEXT_PACKAGE + DEFINES+= _GNU_SOURCE GETTEXT_PACKAGE HAVE_NETLINK } SOURCES+= $$ACM/address.c SOURCES+= $$ACM/alternative.c @@ -84,7 +84,6 @@ ubports|android: { SOURCES+= $$ACM/timeval.c SOURCES+= $$ACM/utf8.c # avahi-core - DEFINES+= HAVE_NETLINK SOURCES+= $$ACR/addr-util.c SOURCES+= $$ACR/announce.c SOURCES+= $$ACR/browse.c @@ -99,10 +98,15 @@ ubports|android: { SOURCES+= $$ACR/fdutil.c SOURCES+= $$ACR/hashmap.c SOURCES+= $$ACR/iface.c - SOURCES+= $$ACR/iface-linux.c + android: { + SOURCES+= $$ACR/iface-android-api-30.c + } + ubports: { + SOURCES+= $$ACR/iface-linux.c + SOURCES+= $$ACR/netlink.c + } SOURCES+= $$ACR/log.c SOURCES+= $$ACR/multicast-lookup.c - SOURCES+= $$ACR/netlink.c SOURCES+= $$ACR/prioq.c SOURCES+= $$ACR/probe-sched.c SOURCES+= $$ACR/querier.c