2 Commits

Author SHA1 Message Date
d203025409 AvahiCore - house keeping 2022-10-02 21:34:16 -04:00
38d236dee1 Fix Android api 30 issue
Google disabled bind() to a netlink socket in api 30.  This change disables
the netlink socket used in avahi-core on Android which means there is no
async network interface info.  When the apps starts, a list of interfaces
is gotten with getifaddrs() and avahi uses this list to monitor.  Avahi
does not monitor while the app sleeps and deletes the monitor.
2022-10-02 21:34:16 -04:00
3 changed files with 186 additions and 40 deletions

View File

@ -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 <string.h>
#include <net/if.h>
#include <linux/if_addr.h>
#include <netinet/in.h>
#include <ifaddrs.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <avahi-common/malloc.h>
#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;
}

View File

@ -36,32 +36,25 @@
class QZeroConfPrivate
{
public:
QZeroConfPrivate(QZeroConf *parent)
QZeroConfPrivate(QZeroConf *parent) { pub = parent; }
void createOrDeleteServer()
{
qint32 error;
pub = parent;
group = NULL;
browser = NULL;
txt = NULL;
ready = 0;
registerWaiting = 0;
poll = avahi_qt_poll_get();
if (!poll) {
return;
}
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)
@ -69,10 +62,10 @@ public:
QZeroConfPrivate *ref = static_cast<QZeroConfPrivate *>(userdata);
switch (state) {
case AVAHI_SERVER_RUNNING:
ref->ready = 1;
if (ref->registerWaiting) {
ref->registerWaiting = 0;
ref->registerService(ref->name.toUtf8(), ref->type.toUtf8(), ref->domain.toUtf8(), ref->port);
ref->ready = true;
if (ref->registerWaiting) {
ref->registerWaiting = false;
ref->registerService(ref->name.toUtf8(), ref->type.toUtf8(), ref->domain.toUtf8(), ref->port);
}
break;
case AVAHI_SERVER_COLLISION:
@ -228,6 +221,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,20 +254,24 @@ public:
QZeroConf *pub;
const AvahiPoll *poll;
static AvahiServer *server;
static quint32 referenceCount;
AvahiServerConfig config;
AvahiSEntryGroup *group;
AvahiSServiceBrowser *browser;
static size_t serviceObjectCount;
static size_t browserObjectCount;
static AvahiServerConfig config;
AvahiSEntryGroup *group = nullptr;
AvahiSServiceBrowser *browser = nullptr;
AvahiProtocol aProtocol;
QMap <QString, AvahiSServiceResolver *> resolvers;
AvahiStringList *txt;
bool ready, registerWaiting;
AvahiStringList *txt = nullptr;
bool ready = false;
bool registerWaiting = false;
QString name, type, domain;
qint32 port;
};
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 +284,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,10 +294,14 @@ 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 {
pri->registerWaiting = 1;
pri->registerWaiting = true;
pri->name = name;
pri->type = type;
pri->domain = domain;
@ -312,6 +314,8 @@ void QZeroConf::stopServicePublish(void)
if (pri->group) {
avahi_s_entry_group_free(pri->group);
pri->group = NULL;
pri->serviceObjectCount--;
pri->createOrDeleteServer();
}
}
@ -348,6 +352,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;

View File

@ -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