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

Reply via email to