/* *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 */ #include "avahidiscovery.h" #include const AvahiPoll * getAvahiPoll(void); #include 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(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"