151 lines
4.5 KiB
C++
151 lines
4.5 KiB
C++
/*
|
|
*Copyright (C) <2017> Alex B
|
|
*
|
|
*This program is free software: you can redistribute it and/or modify
|
|
*it under the terms of the GNU General Public License as published by
|
|
*the Free Software Foundation, either version 2 of the License, or
|
|
*(at your option) any later version.
|
|
*
|
|
*This program 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 General Public License for more details.
|
|
*
|
|
*You should have received a copy of the GNU General Public License
|
|
*along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
#include "avahidiscovery.h"
|
|
#include <avahi-common/error.h>
|
|
|
|
const AvahiPoll * getAvahiPoll(void);
|
|
|
|
#include <QDebug>
|
|
static bool debugIsEnabled=false;
|
|
#define DBUG if (debugIsEnabled) qWarning() << "Avahi" << __FUNCTION__
|
|
|
|
void AvahiDiscovery::enableDebug()
|
|
{
|
|
debugIsEnabled=true;
|
|
}
|
|
|
|
static AvahiDiscovery *ptr = nullptr;
|
|
|
|
static void resolverCallback(
|
|
AvahiServiceResolver *r,
|
|
AVAHI_GCC_UNUSED AvahiIfIndex interface,
|
|
AVAHI_GCC_UNUSED AvahiProtocol protocol,
|
|
AvahiResolverEvent event,
|
|
const char *name,
|
|
AVAHI_GCC_UNUSED const char *type,
|
|
AVAHI_GCC_UNUSED const char *domain,
|
|
AVAHI_GCC_UNUSED const char *hostName,
|
|
const AvahiAddress *address,
|
|
uint16_t port,
|
|
AVAHI_GCC_UNUSED AvahiStringList *txt,
|
|
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
|
|
void *userdata)
|
|
{
|
|
char a[AVAHI_ADDRESS_STR_MAX];
|
|
|
|
switch(event) {
|
|
case AVAHI_RESOLVER_FAILURE:
|
|
//avahi resolver not found
|
|
break;
|
|
case AVAHI_RESOLVER_FOUND:
|
|
avahi_address_snprint(a, sizeof(a), address);
|
|
break;
|
|
}
|
|
|
|
int eventType = *( static_cast<int*>(userdata) );
|
|
switch(eventType) {
|
|
case AVAHI_BROWSER_NEW:
|
|
emit ptr->mpdFound(name, a, port);
|
|
break;
|
|
case AVAHI_BROWSER_REMOVE:
|
|
emit ptr->mpdRemoved(name);
|
|
break;
|
|
}
|
|
|
|
avahi_service_resolver_free(r);
|
|
free(userdata);
|
|
}
|
|
|
|
static void browseCallback(
|
|
AvahiServiceBrowser *b,
|
|
AvahiIfIndex interface,
|
|
AvahiProtocol protocol,
|
|
AvahiBrowserEvent event,
|
|
const char *name,
|
|
const char *type,
|
|
const char *domain,
|
|
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
|
|
AVAHI_GCC_UNUSED void* userdata)
|
|
{
|
|
switch (event) {
|
|
case AVAHI_BROWSER_FAILURE:
|
|
DBUG << "(Browser) " << avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)));
|
|
break;
|
|
case AVAHI_BROWSER_NEW:
|
|
if (!(avahi_service_resolver_new (avahi_service_browser_get_client(b), interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_MULTICAST, resolverCallback, new int(AVAHI_BROWSER_NEW)))) {
|
|
DBUG << "Failed to resolve service " << name;
|
|
}
|
|
break;
|
|
case AVAHI_BROWSER_REMOVE:
|
|
if (!(avahi_service_resolver_new (avahi_service_browser_get_client(b), interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_MULTICAST, resolverCallback, new int(AVAHI_BROWSER_REMOVE)))) {
|
|
DBUG << "Failed to resolve service " << name;
|
|
}
|
|
break;
|
|
case AVAHI_BROWSER_ALL_FOR_NOW:
|
|
DBUG << "Service browser: ALL_FOR_NOW";
|
|
break;
|
|
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
|
DBUG << "Service browser: CACHE_EXHAUSTED";
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void clientCallback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void *userdata)
|
|
{
|
|
assert(c);
|
|
|
|
if (AVAHI_CLIENT_FAILURE == state) {
|
|
DBUG << "Server connection failure: " << avahi_strerror(avahi_client_errno(c));
|
|
}
|
|
}
|
|
|
|
|
|
AvahiDiscovery::AvahiDiscovery()
|
|
{
|
|
ptr = this;
|
|
|
|
/* create avahi client */
|
|
int error;
|
|
m_client = avahi_client_new(getAvahiPoll(), AVAHI_CLIENT_IGNORE_USER_CONFIG, clientCallback, nullptr, &error);
|
|
if (!m_client) {
|
|
DBUG << "Failed to create client: " << avahi_strerror(error);
|
|
return;
|
|
}
|
|
|
|
/* create avahi browser */
|
|
m_browser = avahi_service_browser_new(m_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, "_mpd._tcp", nullptr, AVAHI_LOOKUP_USE_MULTICAST, browseCallback, m_client);
|
|
if (!m_browser) {
|
|
DBUG << "Failed to create service browser: " << avahi_strerror(avahi_client_errno(m_client));
|
|
return;
|
|
}
|
|
}
|
|
|
|
AvahiDiscovery::~AvahiDiscovery()
|
|
{
|
|
if (m_browser) {
|
|
avahi_service_browser_free(m_browser);
|
|
}
|
|
|
|
if (m_client) {
|
|
avahi_client_free(m_client);
|
|
}
|
|
}
|
|
|
|
#include "moc_avahidiscovery.cpp"
|