On 9 March 2007 22:58, Michael Nottebrock wrote:
> On Friday, 9. March 2007 05:25, Dima Panov wrote:
> > On 8 March 2007 05:40, Michael Nottebrock wrote:
> > > mDNSResponder and libthai are small leaf dependencies which provide
> > > important features to kdelibs to those who need them and which cannot
> > > be added by a binary plugin later. We deem the small overhead (2 mb
> > > source code for mDNSResponder and libthai combined or 1 mb for the
> > > mDNSResponder + libthai binary packages combined) acceptable for
> > > everyone and not worth adding additional complexity to the port.
> >
> > Is it possible to use Avahi instead of mDNSResponder with fresh KDE?
> > mDNSResponder is not ready to IPv6, which is used in our neighborhood,
> > and running avahi-daemon and mDNSd at same machine lead to duplicate
> > names.
>
> You can deinstall mDNSResponder and install avahi with the libdns_sd
> compatibility turned on (the avahi port has an option for that) and things
> should just work, but if you're going to recompile kdelibs afterwards, you
> will additionally need to add the avahi include dirs to CXXFLAGS so kdelibs
> will find the mDNSResponder compatibility header and enable the feature.
Simple replace mDNSResponder with avahi-libs does't work :(
After searching in KDE's mailing lista, I've found libkdnssd-avahi replacement
for kdelibs 3.5.x . Can you review this patch?
> We couldn't depend on avahi in kdelibs in the past in order to maintain
> FreeBSD 4.x compatibility, which isn't an issue anymore, so we might switch
> the dependency over to avahi properly at some point.
It coul'd be great!
--
Дмитрий А. Панов
Академия Экономики и Права
Хабаровск, Россия
diff -urN dnssd/Makefile.in dnssd/Makefile.in
--- dnssd/Makefile.in.orig Tue Feb 20 14:32:29 2007
+++ dnssd/Makefile.in Tue Feb 20 14:48:02 2007
@@ -518,7 +520,7 @@
xdg_menudir = @xdg_menudir@
# set the include path for X, qt and KDE
-INCLUDES = -I$(top_srcdir) $(all_includes)
+INCLUDES = -I$(top_srcdir) $(all_includes) $(AVAHI_CFLAGS)
# these are the headers for your project
noinst_HEADERS = sdevent.h
@@ -536,7 +538,7 @@
dnssdinclude_HEADERS = domainbrowser.h query.h remoteservice.h \
publicservice.h servicebase.h servicebrowser.h settings.h
-libkdnssd_la_LIBADD = ../kdecore/libkdecore.la $(LIB_DNSSD)
+libkdnssd_la_LIBADD = ../kdecore/libkdecore.la $(LIB_DNSSD) $(AVAHI_LIBS)
libkdnssd_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -version-info 1:0
#>- all: all-am
#>+ 1
diff -urN dnssd/domainbrowser.cpp dnssd/domainbrowser.cpp
--- dnssd/domainbrowser.cpp Wed Nov 9 08:39:39 2005
+++ dnssd/domainbrowser.cpp Tue Feb 20 14:19:21 2007
@@ -27,46 +27,56 @@
#include "query.h"
#include "servicebrowser.h"
#include <kapplication.h>
+#ifdef AVAHI_API_0_6
+#include <avahi-client/lookup.h>
+#endif
namespace DNSSD
{
-#ifdef HAVE_DNSSD
-void domain_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
- const char *replyDomain, void *context);
+#ifdef AVAHI_API_0_6
+void domains_callback(AvahiDomainBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+ AvahiLookupResultFlags, void* context);
+#else
+void domains_callback(AvahiDomainBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+ void* context);
#endif
-class DomainBrowserPrivate : public Responder
+
+class DomainBrowserPrivate
{
public:
- DomainBrowserPrivate(DomainBrowser* owner) : Responder(), m_browseLAN(false), m_started(false), m_owner(owner) {}
+ DomainBrowserPrivate(DomainBrowser* owner) : m_browseLAN(false), m_started(false),
+ m_browser(0), m_owner(owner) {}
+ ~DomainBrowserPrivate() { if (m_browser) avahi_domain_browser_free(m_browser); }
QStringList m_domains;
virtual void customEvent(QCustomEvent* event);
bool m_browseLAN;
bool m_started;
+ AvahiDomainBrowser* m_browser;
DomainBrowser* m_owner;
};
void DomainBrowserPrivate::customEvent(QCustomEvent* event)
{
- if (event->type()==QEvent::User+SD_ERROR) stop();
if (event->type()==QEvent::User+SD_ADDREMOVE) {
AddRemoveEvent *aev = static_cast<AddRemoveEvent*>(event);
if (aev->m_op==AddRemoveEvent::Add) m_owner->gotNewDomain(aev->m_domain);
else m_owner->gotRemoveDomain(aev->m_domain);
}
}
+
DomainBrowser::DomainBrowser(QObject *parent) : QObject(parent)
{
d = new DomainBrowserPrivate(this);
- d->m_domains = Configuration::domainList();
+ d->m_domains = Configuration::domainList();
if (Configuration::browseLocal()) {
d->m_domains+="local.";
d->m_browseLAN=true;
}
- connect(KApplication::kApplication(),SIGNAL(kipcMessage(int,int)),this,
- SLOT(domainListChanged(int,int)));
+ connect(KApplication::kApplication(),SIGNAL(kipcMessage(int,int)),this,
+ SLOT(domainListChanged(int,int)));
}
DomainBrowser::DomainBrowser(const QStringList& domains, bool recursive, QObject *parent) : QObject(parent)
@@ -88,14 +98,15 @@
if (d->m_started) return;
d->m_started=true;
if (ServiceBrowser::isAvailable()!=ServiceBrowser::Working) return;
- QStringList::const_iterator itEnd = d->m_domains.end();
+ QStringList::const_iterator itEnd = d->m_domains.end();
for (QStringList::const_iterator it=d->m_domains.begin(); it!=itEnd; ++it ) emit domainAdded(*it);
-#ifdef HAVE_DNSSD
- if (d->m_browseLAN) {
- DNSServiceRef ref;
- if (DNSServiceEnumerateDomains(&ref,kDNSServiceFlagsBrowseDomains,0,domain_callback,
- reinterpret_cast<void*>(d))==kDNSServiceErr_NoError) d->setRef(ref);
- }
+ if (d->m_browseLAN)
+#ifdef AVAHI_API_0_6
+ d->m_browser = avahi_domain_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ "local.", AVAHI_DOMAIN_BROWSER_BROWSE, (AvahiLookupFlags)0, domains_callback, this);
+#else
+ d->m_browser = avahi_domain_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ "local.", AVAHI_DOMAIN_BROWSER_BROWSE, domains_callback, this);
#endif
}
@@ -115,9 +126,14 @@
void DomainBrowser::domainListChanged(int message,int)
{
if (message!=KIPCDomainsChanged) return;
+
bool was_started = d->m_started;
- if (d->isRunning()) d->stop(); // LAN query
+ if (d->m_browser) {
+ avahi_domain_browser_free(d->m_browser); // LAN query
+ d->m_browser=0;
+ }
d->m_started = false;
+
// remove all domains and resolvers
if (was_started) {
QStringList::const_iterator itEnd = d->m_domains.end();
@@ -129,7 +145,7 @@
Configuration::self()->readConfig();
d->m_browseLAN = Configuration::browseLocal();
d->m_domains = Configuration::domainList();
- if (Configuration::browseLocal()) d->m_domains+="local.";
+ if (Configuration::browseLocal()) d->m_domains+="local";
// this will emit domainAdded() for every domain if necessary
if (was_started) startBrowse();
}
@@ -147,22 +163,21 @@
void DomainBrowser::virtual_hook(int, void*)
{}
-#ifdef HAVE_DNSSD
-void domain_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
- const char *replyDomain, void *context)
+#ifdef AVAHI_API_0_6
+void domains_callback(AvahiDomainBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+ AvahiLookupResultFlags,void* context)
+#else
+void domains_callback(AvahiDomainBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+ void* context)
+#endif
{
QObject *obj = reinterpret_cast<QObject*>(context);
- if (errorCode != kDNSServiceErr_NoError) {
- ErrorEvent err;
- QApplication::sendEvent(obj, &err);
- } else {
- AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add :
+ AddRemoveEvent* arev=new AddRemoveEvent((event==AVAHI_BROWSER_NEW) ? AddRemoveEvent::Add :
AddRemoveEvent::Remove, QString::null, QString::null,
- DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing));
- QApplication::sendEvent(obj, &arev);
- }
+ DNSToDomain(replyDomain));
+ QApplication::postEvent(obj, arev);
}
-#endif
+
}
#include "domainbrowser.moc"
diff -urN dnssd/publicservice.cpp dnssd/publicservice.cpp
--- dnssd/publicservice.cpp Tue Oct 11 02:06:42 2005
+++ dnssd/publicservice.cpp Tue Feb 20 14:19:21 2007
@@ -27,9 +27,15 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include <qapplication.h>
-#include <network/ksocketaddress.h>
+#include <ksocketaddress.h>
#include <kurl.h>
#include <unistd.h>
+#include <avahi-client/client.h>
+#ifdef AVAHI_API_0_6
+#include <avahi-client/publish.h>
+#endif
+#include <avahi-common/alternative.h>
+#include <avahi-common/strlst.h>
#include "sdevent.h"
#include "responder.h"
#include "servicebrowser.h"
@@ -38,16 +44,23 @@
namespace DNSSD
{
static unsigned long publicIP();
-#ifdef HAVE_DNSSD
-void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
- const char*, const char*, void *context);
-#endif
-class PublicServicePrivate : public Responder
+
+void publish_callback (AvahiEntryGroup*, AvahiEntryGroupState s, void *context);
+
+class PublicServicePrivate
{
public:
- PublicServicePrivate() : m_published(false)
+ PublicServicePrivate() : m_published(false), m_running(false), m_collision(false)
{}
bool m_published;
+ bool m_running;
+ bool m_collision;
+ AvahiEntryGroup* m_group;
+ void commit()
+ {
+ if (!m_collision) avahi_entry_group_commit(m_group);
+ }
+
};
PublicService::PublicService(const QString& name, const QString& type, unsigned int port,
@@ -55,6 +68,9 @@
: QObject(), ServiceBase(name, type, QString::null, domain, port)
{
d = new PublicServicePrivate;
+ if (Responder::self().client()) d->m_group = avahi_entry_group_new(Responder::self().client(),
+ publish_callback,this);
+ connect(&Responder::self(),SIGNAL(stateChanged(AvahiClientState)),this,SLOT(clientState(AvahiClientState)));
if (domain.isNull())
if (Configuration::publishType()==Configuration::EnumPublishType::LAN) m_domain="local.";
else m_domain=Configuration::publishDomain();
@@ -63,114 +79,148 @@
PublicService::~PublicService()
{
- stop();
+ if (d->m_group) avahi_entry_group_free(d->m_group);
delete d;
}
+void PublicService::tryApply()
+{
+ if (fillEntryGroup()) d->commit();
+ else {
+ stop();
+ emit published(false);
+ }
+}
+
void PublicService::setServiceName(const QString& serviceName)
{
m_serviceName = serviceName;
- if (d->isRunning()) {
- stop();
- publishAsync();
- }
+ if (d->m_running) {
+ avahi_entry_group_reset(d->m_group);
+ tryApply();
+ }
}
void PublicService::setDomain(const QString& domain)
{
m_domain = domain;
- if (d->isRunning()) {
- stop();
- publishAsync();
- }
+ if (d->m_running) {
+ avahi_entry_group_reset(d->m_group);
+ tryApply();
+ }
}
void PublicService::setType(const QString& type)
{
m_type = type;
- if (d->isRunning()) {
- stop();
- publishAsync();
- }
+ if (d->m_running) {
+ avahi_entry_group_reset(d->m_group);
+ tryApply();
+ }
}
void PublicService::setPort(unsigned short port)
{
m_port = port;
- if (d->isRunning()) {
- stop();
- publishAsync();
- }
+ if (d->m_running) {
+ avahi_entry_group_reset(d->m_group);
+ tryApply();
+ }
}
-bool PublicService::isPublished() const
+void PublicService::setTextData(const QMap<QString,QString>& textData)
{
- return d->m_published;
+ m_textData = textData;
+ if (d->m_running) {
+ avahi_entry_group_reset(d->m_group);
+ tryApply();
+ }
}
-void PublicService::setTextData(const QMap<QString,QString>& textData)
+bool PublicService::isPublished() const
{
- m_textData = textData;
- if (d->isRunning()) {
- stop();
- publishAsync();
- }
+ return d->m_published;
}
bool PublicService::publish()
{
publishAsync();
- while (d->isRunning() && !d->m_published) d->process();
+ while (d->m_running && !d->m_published) Responder::self().process();
return d->m_published;
}
void PublicService::stop()
{
- d->stop();
- d->m_published = false;
+ if (d->m_group) avahi_entry_group_reset(d->m_group);
+ d->m_published = false;
+}
+bool PublicService::fillEntryGroup()
+{
+ AvahiStringList *s=0;
+ QMap<QString,QString>::ConstIterator itEnd = m_textData.end();
+ for (QMap<QString,QString>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it)
+ s = avahi_string_list_add_pair(s, it.key().utf8(),it.data().utf8());
+#ifdef AVAHI_API_0_6
+ bool res = (!avahi_entry_group_add_service_strlst(d->m_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, (AvahiPublishFlags)0,
+ m_serviceName.isNull() ? avahi_client_get_host_name(Responder::self().client()) : m_serviceName.utf8().data(),
+ m_type.ascii(),domainToDNS(m_domain),m_hostName.utf8(),m_port,s));
+#else
+ bool res = (!avahi_entry_group_add_service_strlst(d->m_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ m_serviceName.isNull() ? avahi_client_get_host_name(Responder::self().client()) : m_serviceName.utf8().data(),
+ m_type.ascii(),m_domain.utf8(),m_hostName.utf8(),m_port,s));
+#endif
+ avahi_string_list_free(s);
+ return res;
}
-void PublicService::publishAsync()
+void PublicService::clientState(AvahiClientState s)
{
- if (d->isRunning()) stop();
-#ifdef HAVE_DNSSD
- if (ServiceBrowser::isAvailable()==ServiceBrowser::Working) {
- TXTRecordRef txt;
- TXTRecordCreate(&txt,0,0);
- QMap<QString,QString>::ConstIterator itEnd = m_textData.end();
- for (QMap<QString,QString>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it) {
- QCString value = it.data().utf8();
- if (TXTRecordSetValue(&txt,it.key().utf8(),value.length(),value)!=kDNSServiceErr_NoError) {
- TXTRecordDeallocate(&txt);
- emit published(false);
- return;
- }
- }
- DNSServiceRef ref;
- if (DNSServiceRegister(&ref,0,0,m_serviceName.utf8(),m_type.ascii(),domainToDNS(m_domain),NULL,
- htons(m_port),TXTRecordGetLength(&txt),TXTRecordGetBytesPtr(&txt),publish_callback,
- reinterpret_cast<void*>(this)) == kDNSServiceErr_NoError) d->setRef(ref);
- TXTRecordDeallocate(&txt);
- }
+ if (!d->m_running) return;
+ switch (s) {
+#ifdef AVAHI_API_0_6
+ case AVAHI_CLIENT_FAILURE:
+#else
+ case AVAHI_CLIENT_S_INVALID:
+ case AVAHI_CLIENT_DISCONNECTED:
#endif
- if (!d->isRunning()) emit published(false);
+ stop();
+ emit published(false);
+ break;
+ case AVAHI_CLIENT_S_REGISTERING:
+ case AVAHI_CLIENT_S_COLLISION:
+ avahi_entry_group_reset(d->m_group);
+ d->m_collision=true;
+ break;
+ case AVAHI_CLIENT_S_RUNNING:
+ if (d->m_collision) {
+ d->m_collision=false;
+ tryApply();
+ }
+ }
+}
+
+void PublicService::publishAsync()
+{
+ if (d->m_running) stop();
+
+ if (!d->m_group) {
+ emit published(false);
+ return;
+ }
+ AvahiClientState s=avahi_client_get_state(Responder::self().client());
+ d->m_running=true;
+ d->m_collision=true; // make it look like server is getting out of collision to force registering
+ clientState(s);
}
-#ifdef HAVE_DNSSD
-void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
- const char*, const char*, void *context)
+void publish_callback (AvahiEntryGroup*, AvahiEntryGroupState s, void *context)
{
QObject *obj = reinterpret_cast<QObject*>(context);
- if (errorCode != kDNSServiceErr_NoError) {
- ErrorEvent err;
- QApplication::sendEvent(obj, &err);
- } else {
- PublishEvent pev(QString::fromUtf8(name));
- QApplication::sendEvent(obj, &pev);
- }
+ if (s!=AVAHI_ENTRY_GROUP_ESTABLISHED && s!=AVAHI_ENTRY_GROUP_COLLISION) return;
+ PublishEvent* pev=new PublishEvent(s==AVAHI_ENTRY_GROUP_ESTABLISHED);
+ QApplication::postEvent(obj, pev);
}
-#endif
const KURL PublicService::toInvitation(const QString& host)
{
@@ -194,14 +244,13 @@
void PublicService::customEvent(QCustomEvent* event)
{
- if (event->type()==QEvent::User+SD_ERROR) {
- stop();
- emit published(false);
- }
if (event->type()==QEvent::User+SD_PUBLISH) {
+ if (!static_cast<PublishEvent*>(event)->m_ok) {
+ setServiceName(QString::fromUtf8(avahi_alternative_service_name(m_serviceName.utf8())));
+ return;
+ }
d->m_published=true;
emit published(true);
- m_serviceName = static_cast<PublishEvent*>(event)->m_name;
}
}
diff -urN dnssd/publicservice.h dnssd/publicservice.h
--- dnssd/publicservice.h Tue Oct 11 02:06:42 2005
+++ dnssd/publicservice.h Tue Feb 20 14:19:21 2007
@@ -23,6 +23,7 @@
#include <qobject.h>
#include <dnssd/servicebase.h>
+#include <avahi-client/client.h>
class KURL;
namespace DNSSD
@@ -137,6 +138,10 @@
void published(bool);
private:
PublicServicePrivate *d;
+ bool fillEntryGroup();
+ void tryApply();
+private slots:
+ void clientState(AvahiClientState);
protected:
virtual void customEvent(QCustomEvent* event);
diff -urN dnssd/query.cpp dnssd/query.cpp
--- dnssd/query.cpp Wed Nov 9 08:39:39 2005
+++ dnssd/query.cpp Tue Feb 20 14:19:21 2007
@@ -22,26 +22,46 @@
#include "responder.h"
#include "remoteservice.h"
#include "sdevent.h"
-#include <kdebug.h>
+#include <qdatetime.h>
#include <qapplication.h>
#include <qtimer.h>
-#define TIMEOUT_WAN 2000
+#include <avahi-client/client.h>
+#ifdef AVAHI_API_0_6
+#include <avahi-client/lookup.h>
+#endif
+
#define TIMEOUT_LAN 200
namespace DNSSD
{
-#ifdef HAVE_DNSSD
-void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
- const char *serviceName, const char *regtype, const char *replyDomain, void *context);
+#ifdef AVAHI_API_0_6
+
+void services_callback(AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* name,
+ const char* regtype, const char* domain, AvahiLookupResultFlags, void* context);
+void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
+ const char* replyDomain, AvahiLookupResultFlags, void* context);
+#else
+void services_callback(AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* name,
+ const char* regtype, const char* domain, void* context);
+void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
+ const char* replyDomain, void* context);
+void domains_callback(AvahiDomainBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+ void* context);
#endif
-class QueryPrivate : public Responder
+
+enum BrowserType { Types, Services };
+
+class QueryPrivate
{
public:
- QueryPrivate(const QString& type, const QString& domain) : Responder(), m_finished(false),
- m_domain(domain), m_type(type)
- {};
+ QueryPrivate(const QString& type, const QString& domain) : m_finished(false), m_browser(0),
+ m_running(false), m_domain(domain), m_type(type) {}
+
bool m_finished;
+ BrowserType m_browserType;
+ void* m_browser;
+ bool m_running;
QString m_domain;
QTimer timeout;
QString m_type;
@@ -56,12 +76,18 @@
Query::~Query()
{
+ if (d->m_browser) {
+ switch (d->m_browserType) {
+ case Services: avahi_service_browser_free((AvahiServiceBrowser*)d->m_browser); break;
+ case Types: avahi_service_type_browser_free((AvahiServiceTypeBrowser*)d->m_browser); break;
+ }
+ }
delete d;
}
bool Query::isRunning() const
{
- return d->isRunning();
+ return d->m_running;
}
bool Query::isFinished() const
@@ -76,16 +102,31 @@
void Query::startQuery()
{
- if (d->isRunning()) return;
+ if (d->m_running) return;
d->m_finished = false;
-#ifdef HAVE_DNSSD
- DNSServiceRef ref;
- if (DNSServiceBrowse(&ref,0,0, d->m_type.ascii(),
- domainToDNS(d->m_domain),query_callback,reinterpret_cast<void*>(this))
- == kDNSServiceErr_NoError) d->setRef(ref);
+ if (d->m_type=="_services._dns-sd._udp") {
+ d->m_browserType = Types;
+#ifdef AVAHI_API_0_6
+ d->m_browser = avahi_service_type_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ domainToDNS(d->m_domain), (AvahiLookupFlags)0, types_callback, this);
+#else
+ d->m_browser = avahi_service_type_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ d->m_domain.utf8(), types_callback, this);
#endif
- if (!d->isRunning()) emit finished();
- else d->timeout.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAN : TIMEOUT_WAN,true);
+ } else {
+ d->m_browserType = Services;
+#ifdef AVAHI_API_0_6
+ d->m_browser = avahi_service_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ d->m_type.ascii(),domainToDNS(d->m_domain), (AvahiLookupFlags)0, services_callback,this);
+#else
+ d->m_browser = avahi_service_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ d->m_type.ascii(),d->m_domain.utf8(),services_callback,this);
+#endif
+ }
+ if (d->m_browser) {
+ d->m_running=true;
+ d->timeout.start(TIMEOUT_LAN,true);
+ } else emit finished();
}
void Query::virtual_hook(int, void*)
{
@@ -93,24 +134,15 @@
void Query::customEvent(QCustomEvent* event)
{
- if (event->type()==QEvent::User+SD_ERROR) {
- d->stop();
- d->m_finished=false;
- emit finished();
- }
if (event->type()==QEvent::User+SD_ADDREMOVE) {
- RemoteService* svr;
+ d->timeout.start(TIMEOUT_LAN,true);
+ d->m_finished=false;
AddRemoveEvent *aev = static_cast<AddRemoveEvent*>(event);
// m_type has useless trailing dot
- QString type=aev->m_type.left(aev->m_type.length()-1);
- // label is badly splitted here - _http _tcp.local. . - rely on decode()
- if (d->m_type=="_services._dns-sd._udp") svr = new RemoteService(aev->m_name+"."+
- type+"."+aev->m_domain);
- else svr = new RemoteService(aev->m_name, type, aev->m_domain);
+ RemoteService* svr = new RemoteService(aev->m_name,
+ aev->m_type,aev->m_domain);
if (aev->m_op==AddRemoveEvent::Add) emit serviceAdded(svr);
else emit serviceRemoved(svr);
- d->m_finished = aev->m_last;
- if (d->m_finished) emit finished();
}
}
@@ -119,22 +151,36 @@
d->m_finished=true;
emit finished();
}
-#ifdef HAVE_DNSSD
-void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
- const char *serviceName, const char *regtype, const char *replyDomain,
- void *context)
+
+#ifdef AVAHI_API_0_6
+void services_callback (AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event,
+ const char* serviceName, const char* regtype, const char* replyDomain, AvahiLookupResultFlags, void* context)
+#else
+void services_callback (AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event,
+ const char* serviceName, const char* regtype, const char* replyDomain, void* context)
+#endif
{
QObject *obj = reinterpret_cast<QObject*>(context);
- if (errorCode != kDNSServiceErr_NoError) {
- ErrorEvent err;
- QApplication::sendEvent(obj, &err);
- } else {
- AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add :
+ AddRemoveEvent* arev = new AddRemoveEvent((event==AVAHI_BROWSER_NEW) ? AddRemoveEvent::Add :
AddRemoveEvent::Remove, QString::fromUtf8(serviceName), regtype,
- DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing));
- QApplication::sendEvent(obj, &arev);
- }
+ DNSToDomain(replyDomain));
+ QApplication::postEvent(obj, arev);
}
+
+#ifdef AVAHI_API_0_6
+void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
+ const char* replyDomain, AvahiLookupResultFlags, void* context)
+#else
+void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
+ const char* replyDomain, void* context)
#endif
+{
+ QObject *obj = reinterpret_cast<QObject*>(context);
+ AddRemoveEvent* arev = new AddRemoveEvent((event==AVAHI_BROWSER_NEW) ? AddRemoveEvent::Add :
+ AddRemoveEvent::Remove, QString::null, regtype,
+ DNSToDomain(replyDomain));
+ QApplication::postEvent(obj, arev);
+}
+
}
#include "query.moc"
diff -urN dnssd/remoteservice.cpp dnssd/remoteservice.cpp
--- dnssd/remoteservice.cpp Fri Jan 20 03:07:20 2006
+++ dnssd/remoteservice.cpp Tue Feb 20 14:19:21 2007
@@ -27,33 +27,39 @@
#include <sys/types.h>
#endif
#include <netinet/in.h>
+#include <avahi-client/client.h>
+#include <avahi-common/strlst.h>
+#ifdef AVAHI_API_0_6
+#include <avahi-client/lookup.h>
+#endif
#include "remoteservice.h"
#include "responder.h"
#include "sdevent.h"
-#include <kdebug.h>
namespace DNSSD
{
-#ifdef HAVE_DNSSD
-void resolve_callback ( DNSServiceRef,
- DNSServiceFlags,
- uint32_t,
- DNSServiceErrorType errorCode,
- const char*,
- const char *hosttarget,
- uint16_t port,
- uint16_t txtLen,
- const char *txtRecord,
- void *context
- );
-
+#ifdef AVAHI_API_0_6
+void resolve_callback(AvahiServiceResolver*, AvahiIfIndex, AvahiProtocol proto, AvahiResolverEvent e,
+ const char* name, const char* type, const char* domain, const char* hostname, const AvahiAddress* a,
+ uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags, void* context);
+#else
+void resolve_callback(AvahiServiceResolver*, AvahiIfIndex, AvahiProtocol proto, AvahiResolverEvent e,
+ const char* name, const char* type, const char* domain, const char* hostname, const AvahiAddress* a,
+ uint16_t port, AvahiStringList* txt, void* context);
#endif
+
class RemoteServicePrivate : public Responder
{
public:
- RemoteServicePrivate() : Responder(), m_resolved(false)
- {};
+ RemoteServicePrivate() : m_resolved(false), m_running(false), m_resolver(0) {}
bool m_resolved;
+ bool m_running;
+ AvahiServiceResolver* m_resolver;
+ void stop() {
+ m_running = false;
+ if (m_resolver) avahi_service_resolver_free(m_resolver);
+ m_resolver=0;
+ }
};
RemoteService::RemoteService(const QString& label)
@@ -83,29 +89,33 @@
RemoteService::~RemoteService()
{
+ if (d->m_resolver) avahi_service_resolver_free(d->m_resolver);
delete d;
}
bool RemoteService::resolve()
{
resolveAsync();
- while (d->isRunning() && !d->m_resolved) d->process();
+ while (d->m_running && !d->m_resolved) Responder::self().process();
d->stop();
return d->m_resolved;
}
void RemoteService::resolveAsync()
{
- if (d->isRunning()) return;
+ if (d->m_running) return;
d->m_resolved = false;
- kdDebug() << this << ":Starting resolve of : " << m_serviceName << " " << m_type << " " << m_domain << "\n";
-#ifdef HAVE_DNSSD
- DNSServiceRef ref;
- if (DNSServiceResolve(&ref,0,0,m_serviceName.utf8(), m_type.ascii(),
- domainToDNS(m_domain),resolve_callback,reinterpret_cast<void*>(this))
- == kDNSServiceErr_NoError) d->setRef(ref);
+ // FIXME: first protocol should be set?
+#ifdef AVAHI_API_0_6
+ d->m_resolver = avahi_service_resolver_new(Responder::self().client(),AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ m_serviceName.utf8(), m_type.ascii(), domainToDNS(m_domain), AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_NO_ADDRESS,
+ resolve_callback, this);
+#else
+ d->m_resolver = avahi_service_resolver_new(Responder::self().client(),AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ m_serviceName.utf8(), m_type.ascii(), m_domain.utf8(), AVAHI_PROTO_UNSPEC, resolve_callback, this);
#endif
- if (!d->isRunning()) emit resolved(false);
+ if (d->m_resolver) d->m_running=true;
+ else emit resolved(false);
}
bool RemoteService::isResolved() const
@@ -154,42 +164,33 @@
return s;
}
-
-#ifdef HAVE_DNSSD
-void resolve_callback ( DNSServiceRef,
- DNSServiceFlags,
- uint32_t,
- DNSServiceErrorType errorCode,
- const char*,
- const char *hosttarget,
- uint16_t port,
- uint16_t txtLen,
- const char *txtRecord,
- void *context
- )
+#ifdef AVAHI_API_0_6
+void resolve_callback(AvahiServiceResolver*, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent e,
+ const char*, const char*, const char*, const char* hostname, const AvahiAddress*,
+ uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags, void* context)
+#else
+void resolve_callback(AvahiServiceResolver*, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent e,
+ const char*, const char*, const char*, const char* hostname, const AvahiAddress*,
+ uint16_t port, AvahiStringList* txt, void* context)
+#endif
{
QObject *obj = reinterpret_cast<QObject*>(context);
- if (errorCode != kDNSServiceErr_NoError) {
+ if (e != AVAHI_RESOLVER_FOUND) {
ErrorEvent err;
QApplication::sendEvent(obj, &err);
return;
}
- char key[256];
- int index=0;
- unsigned char valueLen;
- kdDebug() << "Resolve callback\n";
QMap<QString,QString> map;
- const void *voidValue = 0;
- while (TXTRecordGetItemAtIndex(txtLen,txtRecord,index++,256,key,&valueLen,
- &voidValue) == kDNSServiceErr_NoError)
- {
- if (voidValue) map[QString::fromUtf8(key)]=QString::fromUtf8((const char*)voidValue,valueLen);
- else map[QString::fromUtf8(key)]=QString::null;
- }
- ResolveEvent rev(DNSToDomain(hosttarget),ntohs(port),map);
+ while (txt) {
+ char *key, *value;
+ size_t size;
+ if (avahi_string_list_get_pair(txt,&key,&value,&size)) break;
+ map[QString::fromUtf8(key)]=(value) ? QString::fromUtf8(value) : QString::null;
+ txt = txt->next;
+ }
+ ResolveEvent rev(DNSToDomain(hostname),port,map);
QApplication::sendEvent(obj, &rev);
}
-#endif
}
diff -urN dnssd/responder.cpp dnssd/responder.cpp
--- dnssd/responder.cpp Tue Oct 11 02:06:42 2005
+++ dnssd/responder.cpp Tue Feb 20 14:19:21 2007
@@ -20,62 +20,61 @@
#include "responder.h"
#include <qapplication.h>
+#include <qeventloop.h>
+#include <kstaticdeleter.h>
#include <kidna.h>
+#include <kdebug.h>
+#include <avahi-qt3/qt-watch.h>
-// dns_sd.h API should care about proper encoding of non-latin1 characters
-// but for now it does not
-#define IDN_BROKEN_IN_MDNSRESPONDER
namespace DNSSD
{
-Responder::Responder(DNSServiceRef ref,QObject *parent, const char *name)
- : QObject(parent, name), m_ref(0), m_socket(0)
+static KStaticDeleter<Responder> responder_sd;
+Responder* Responder::m_self = 0;
+
+void client_callback(AvahiClient *, AvahiClientState s, void* u)
{
- setRef(ref);
+ Responder *r = reinterpret_cast<Responder*>(u);
+ emit (r->stateChanged(s));
}
-
-void Responder::setRef(DNSServiceRef ref)
+
+
+Responder::Responder()
{
- if (m_socket || m_ref) stop();
- m_running = false;
- m_ref = ref;
- if (m_ref == 0 ) return;
-#ifdef HAVE_DNSSD
- int fd = DNSServiceRefSockFD(ref);
- if (fd == -1) return;
- m_socket = new QSocketNotifier(fd,QSocketNotifier::Read,this);
- connect(m_socket,SIGNAL(activated(int)),this,SLOT(process()));
- m_running = true;
+ int error;
+ const AvahiPoll* poll = avahi_qt_poll_get();
+#ifdef AVAHI_API_0_6
+ m_client = avahi_client_new(poll, AVAHI_CLIENT_IGNORE_USER_CONFIG,client_callback, this, &error);
+#else
+ m_client = avahi_client_new(poll, client_callback, this, &error);
#endif
+ if (!m_client) kdWarning() << "Failed to create avahi client" << endl;
}
+
Responder::~Responder()
{
- stop();
+ if (m_client) avahi_client_free(m_client);
}
-void Responder::stop()
+Responder& Responder::self()
{
- if (m_socket) delete m_socket;
- m_socket = 0;
-#ifdef HAVE_DNSSD
- if (m_ref) DNSServiceRefDeallocate(m_ref);
-#endif
- m_ref = 0;
- m_running = false;
-}
-
+ if (!m_self) responder_sd.setObject(m_self, new Responder);
+ return *m_self;
+}
void Responder::process()
{
-#ifdef HAVE_DNSSD
- if ( DNSServiceProcessResult(m_ref) != kDNSServiceErr_NoError) stop();
-#endif
+ qApp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
}
-bool Responder::isRunning() const
+AvahiClientState Responder::state() const
{
- return m_running;
+#ifdef AVAHI_API_0_6
+ return (m_client) ? (avahi_client_get_state(m_client)) : AVAHI_CLIENT_FAILURE;
+#else
+ return (m_client) ? (avahi_client_get_state(m_client)) : AVAHI_CLIENT_DISCONNECTED;
+#endif
}
bool domainIsLocal(const QString& domain)
@@ -85,22 +84,14 @@
QCString domainToDNS(const QString &domain)
{
-#ifdef IDN_BROKEN_IN_MDNSRESPONDER
if (domainIsLocal(domain)) return domain.utf8();
else return KIDNA::toAsciiCString(domain);
-#else
- return domain.utf8();
-#endif
}
QString DNSToDomain(const char* domain)
{
-#ifdef IDN_BROKEN_IN_MDNSRESPONDER
if (domainIsLocal(domain)) return QString::fromUtf8(domain);
else return KIDNA::toUnicode(domain);
-#else
- return QString::fromUtf8(domain);
-#endif
}
diff -urN dnssd/responder.h dnssd/responder.h
--- dnssd/responder.h Tue Oct 11 02:06:42 2005
+++ dnssd/responder.h Tue Feb 20 14:19:21 2007
@@ -25,12 +25,7 @@
#include <qsocketnotifier.h>
#include <qsignal.h>
#include <config.h>
-#ifdef HAVE_DNSSD
-#include <dns_sd.h>
-#else
-#define DNSServiceRef void*
-#endif
-
+#include <avahi-client/client.h>
namespace DNSSD
{
@@ -38,30 +33,28 @@
This class should not be used directly.
@author Jakub Stachowski
[EMAIL PROTECTED] Internal class wrapping dns_sd.h interface
[EMAIL PROTECTED] Internal class wrapping avahi client
*/
class Responder : public QObject
{
Q_OBJECT
public:
- Responder(DNSServiceRef ref=0,QObject *parent = 0, const char *name = 0);
+ Responder();
~Responder();
- /**
- Returns true if it is possible to use mDNS service publishing and discovery.
- It needs mDNSResponder running.
- */
- bool isRunning() const;
- void setRef(DNSServiceRef ref);
- void stop();
-public slots:
+ static Responder& self();
+ AvahiClientState state() const;
+ AvahiClient* client() const { return m_client; }
void process();
-protected:
- DNSServiceRef m_ref;
- bool m_running;
- QSocketNotifier *m_socket;
+signals:
+ void stateChanged(AvahiClientState);
+private:
+ AvahiClient* m_client;
+ static Responder* m_self;
+ friend void client_callback(AvahiClient*, AvahiClientState, void*);
+
};
/* Utils functions */
@@ -70,6 +63,7 @@
// Encodes domain name using utf8() or IDN
QCString domainToDNS(const QString &domain);
QString DNSToDomain(const char* domain);
+
}
diff -urN dnssd/sdevent.h dnssd/sdevent.h
--- dnssd/sdevent.h Tue Oct 11 02:06:42 2005
+++ dnssd/sdevent.h Tue Feb 20 14:19:21 2007
@@ -41,24 +41,23 @@
public:
enum Operation { Add, Remove };
AddRemoveEvent(Operation op,const QString& name,const QString& type,
- const QString& domain, bool last) : QCustomEvent(QEvent::User+SD_ADDREMOVE),
- m_op(op), m_name(name), m_type(type), m_domain(domain), m_last(last)
+ const QString& domain) : QCustomEvent(QEvent::User+SD_ADDREMOVE),
+ m_op(op), m_name(name), m_type(type), m_domain(domain)
{}
const Operation m_op;
const QString m_name;
const QString m_type;
const QString m_domain;
- const bool m_last;
};
class PublishEvent : public QCustomEvent
{
public:
- PublishEvent(const QString& name) : QCustomEvent(QEvent::User+SD_PUBLISH), m_name(name)
+ PublishEvent(bool ok) : QCustomEvent(QEvent::User+SD_PUBLISH), m_ok(ok)
{}
- const QString m_name;
+ bool m_ok;
};
class ResolveEvent : public QCustomEvent
diff -urN dnssd/servicebase.cpp dnssd/servicebase.cpp
--- dnssd/servicebase.cpp Wed Nov 9 08:39:39 2005
+++ dnssd/servicebase.cpp Tue Feb 20 14:19:21 2007
@@ -34,7 +34,7 @@
QString ServiceBase::encode()
{
- return m_serviceName.replace("\\","\\\\").replace(".","\\.") + QString(".") + m_type +
+ return m_serviceName.replace(".","\\.").replace("\\","\\\\") + QString(".") + m_type +
QString(".") + m_domain;
}
diff -urN dnssd/servicebrowser.cpp dnssd/servicebrowser.cpp
--- dnssd/servicebrowser.cpp Tue Oct 11 02:06:42 2005
+++ dnssd/servicebrowser.cpp Tue Feb 20 14:19:21 2007
@@ -23,14 +23,11 @@
#include <qstringlist.h>
#include <qfile.h>
#include "domainbrowser.h"
+#include "responder.h"
#include "query.h"
#include "servicebrowser.h"
+#include <avahi-client/client.h>
#include <config.h>
-#ifdef HAVE_DNSSD
-#include <dns_sd.h>
-#endif
-
-#define MDNSD_PID "/var/run/mdnsd.pid"
namespace DNSSD
{
@@ -85,20 +82,12 @@
const ServiceBrowser::State ServiceBrowser::isAvailable()
{
-#ifdef HAVE_DNSSD
- QFile f(MDNSD_PID);
- if (!f.open(IO_ReadOnly)) return Stopped; // no pidfile
- QString line;
- if (f.readLine(line,16)<1) return Stopped;
- unsigned int pid = line.toUInt();
- if (pid==0) return Stopped; // not a pid
- return (kill(pid,0)==0 || errno==EPERM) ? Working : Stopped;
- // signal 0 only checks if process is running, mdnsd is probably owned by 'nobody' so we will
- // get EPERM, if mdnsd is not running error will be ESRCH
-
+ AvahiClientState s = Responder::self().state();
+#ifdef AVAHI_API_0_6
+ return (s==AVAHI_CLIENT_FAILURE) ? Stopped : Working;
#else
- return Unsupported;
-#endif
+ return (s==AVAHI_CLIENT_S_INVALID || s==AVAHI_CLIENT_DISCONNECTED) ? Stopped : Working;
+#endif
}
ServiceBrowser::~ ServiceBrowser()
{
Index: Makefile
===================================================================
RCS file: /home/ncvs/ports/x11/kdelibs3/Makefile,v
retrieving revision 1.210
diff -u -r1.210 Makefile
--- Makefile 6 Mar 2007 13:37:12 -0000 1.210
+++ Makefile 7 Mar 2007 00:57:18 -0000
@@ -23,7 +23,6 @@
art_lgpl_2.5:${PORTSDIR}/graphics/libart_lgpl \
artsc.0:${PORTSDIR}/audio/arts \
aspell:${PORTSDIR}/textproc/aspell \
- dns_sd:${PORTSDIR}/net/mDNSResponder \
idn:${PORTSDIR}/dns/libidn \
jasper:${PORTSDIR}/graphics/jasper \
pcre:${PORTSDIR}/devel/pcre \
@@ -82,6 +81,15 @@
LIB_DEPENDS+= bz2.1:${PORTSDIR}/archivers/bzip2
.endif # !exists(/usr/bin/bzip2)
+.if exists(${LOCALBASE}/include/avahi-compat-libdns_sd/dns_sd.h) || defined(WITH_LIBDNS)
+LIB_DEPENDS+= dns_sd:${PORTSDIR}/net/avahi
+AVAHI_CFLAGS= -DAVAHI_API_0_6 -D_REENTRANT -D_THREAD_SAFE -I${LOCALBASE}/include
+AVAHI_LIBS= -lavahi-qt3 -lavahi-common -lavahi-client -lavahi-core -lavahi-glib -pthread -L${LOCALBASE}/lib
+MAKE_ENV+= AVAHI_CFLAGS="${AVAHI_CFLAGS}" AVAHI_LIBS="${AVAHI_LIBS}"
+.else
+LIB_DEPENDS+= dns_sd:${PORTSDIR}/net/mDNSResponder
+.endif
+
pre-configure:
${REINPLACE_CMD} "s,%%LOCALBASE%%,${LOCALBASE},g" ${WRKSRC}/kdeprint/cups/kmcupsmanager.cpp
${REINPLACE_CMD} -e "s,ac_cups_share_test=.*,ac_cups_share_test=\`\$$kde_cups_config --datadir\`,g" \
_______________________________________________
kde-freebsd mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/kde-freebsd