00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <signal.h>
00022 #include <errno.h>
00023 #include <tqstringlist.h>
00024 #include <tqfile.h>
00025 #include "domainbrowser.h"
00026 #include "responder.h"
00027 #include "query.h"
00028 #include "servicebrowser.h"
00029 #ifdef HAVE_DNSSD
00030 #include <avahi-client/client.h>
00031 #endif
00032 #include <config.h>
00033
00034 namespace DNSSD
00035 {
00036
00037 const TQString ServiceBrowser::AllServices = "_services._dns-sd._udp";
00038
00039 class ServiceBrowserPrivate
00040 {
00041 public:
00042 ServiceBrowserPrivate() : m_running(false)
00043 {}
00044 TQValueList<RemoteService::Ptr> m_services;
00045 TQValueList<RemoteService::Ptr> m_duringResolve;
00046 TQStringList m_types;
00047 DomainBrowser* m_domains;
00048 int m_flags;
00049 bool m_running;
00050 bool m_finished;
00051 TQDict<Query> resolvers;
00052 };
00053
00054 ServiceBrowser::ServiceBrowser(const TQString& type,DomainBrowser* domains,bool autoResolve)
00055 {
00056 if (domains) init(type,domains,autoResolve ? AutoResolve : 0);
00057 else init(type,new DomainBrowser(this),autoResolve ? AutoResolve|AutoDelete : AutoDelete);
00058 }
00059 ServiceBrowser::ServiceBrowser(const TQStringList& types,DomainBrowser* domains,int flags)
00060 {
00061 if (domains) init(types,domains,flags);
00062 else init(types,new DomainBrowser(this),flags|AutoDelete);
00063 }
00064
00065 void ServiceBrowser::init(const TQStringList& type,DomainBrowser* domains,int flags)
00066 {
00067 d = new ServiceBrowserPrivate();
00068 d->resolvers.setAutoDelete(true);
00069 d->m_types=type;
00070 d->m_flags=flags;
00071 d->m_domains = domains;
00072 connect(d->m_domains,TQT_SIGNAL(domainAdded(const TQString& )),this,TQT_SLOT(addDomain(const TQString& )));
00073 connect(d->m_domains,TQT_SIGNAL(domainRemoved(const TQString& )),this,
00074 TQT_SLOT(removeDomain(const TQString& )));
00075 }
00076 ServiceBrowser::ServiceBrowser(const TQString& type,const TQString& domain,bool autoResolve)
00077 {
00078 init(type,new DomainBrowser(domain,false,this),autoResolve ? AutoResolve|AutoDelete : AutoDelete);
00079 }
00080 ServiceBrowser::ServiceBrowser(const TQString& type,const TQString& domain,int flags)
00081 {
00082 init(type,new DomainBrowser(domain,false,this),flags | AutoDelete);
00083 }
00084
00085 const ServiceBrowser::State ServiceBrowser::isAvailable()
00086 {
00087 #ifdef HAVE_DNSSD
00088 AvahiClientState s = Responder::self().state();
00089 #ifdef AVAHI_API_0_6
00090 return (s==AVAHI_CLIENT_FAILURE) ? Stopped : Working;
00091 #else
00092 return (s==AVAHI_CLIENT_S_INVALID || s==AVAHI_CLIENT_DISCONNECTED) ? Stopped : Working;
00093 #endif
00094 #else
00095 return Unsupported;
00096 #endif
00097 }
00098 ServiceBrowser::~ ServiceBrowser()
00099 {
00100 if (d->m_flags & AutoDelete) delete d->m_domains;
00101 delete d;
00102 }
00103
00104 const DomainBrowser* ServiceBrowser::browsedDomains() const
00105 {
00106 return d->m_domains;
00107 }
00108
00109 void ServiceBrowser::serviceResolved(bool success)
00110 {
00111 TQObject* sender_obj = const_cast<TQObject*>(TQT_TQOBJECT_CONST(sender()));
00112 RemoteService* svr = static_cast<RemoteService*>(sender_obj);
00113 disconnect(svr,TQT_SIGNAL(resolved(bool)),this,TQT_SLOT(serviceResolved(bool)));
00114 TQValueList<RemoteService::Ptr>::Iterator it = d->m_duringResolve.begin();
00115 TQValueList<RemoteService::Ptr>::Iterator itEnd = d->m_duringResolve.end();
00116 while ( it!= itEnd && svr!= (*it)) ++it;
00117 if (it != itEnd) {
00118 if (success) {
00119 d->m_services+=(*it);
00120 emit serviceAdded(svr);
00121 }
00122 d->m_duringResolve.remove(it);
00123 queryFinished();
00124 }
00125 }
00126
00127 void ServiceBrowser::startBrowse()
00128 {
00129 if (d->m_running) return;
00130 d->m_running=true;
00131 if (isAvailable()!=Working) return;
00132 if (d->m_domains->isRunning()) {
00133 TQStringList::const_iterator itEnd = d->m_domains->domains().end();
00134 for ( TQStringList::const_iterator it = d->m_domains->domains().begin(); it != itEnd; ++it )
00135 addDomain(*it);
00136 } else d->m_domains->startBrowse();
00137 }
00138
00139 void ServiceBrowser::gotNewService(RemoteService::Ptr svr)
00140 {
00141 if (findDuplicate(svr)==(d->m_services.end())) {
00142 if (d->m_flags & AutoResolve) {
00143 connect(svr,TQT_SIGNAL(resolved(bool )),this,TQT_SLOT(serviceResolved(bool )));
00144 d->m_duringResolve+=svr;
00145 svr->resolveAsync();
00146 } else {
00147 d->m_services+=svr;
00148 emit serviceAdded(svr);
00149 }
00150 }
00151 }
00152
00153 void ServiceBrowser::gotRemoveService(RemoteService::Ptr svr)
00154 {
00155 TQValueList<RemoteService::Ptr>::Iterator it = findDuplicate(svr);
00156 if (it!=(d->m_services.end())) {
00157 emit serviceRemoved(*it);
00158 d->m_services.remove(it);
00159 }
00160 }
00161
00162
00163 void ServiceBrowser::removeDomain(const TQString& domain)
00164 {
00165 while (d->resolvers[domain]) d->resolvers.remove(domain);
00166 TQValueList<RemoteService::Ptr>::Iterator it = d->m_services.begin();
00167 while (it!=d->m_services.end())
00168
00169 if ((*it)->domain().section('.',0) == domain.section('.',0)) {
00170 emit serviceRemoved(*it);
00171 it = d->m_services.remove(it);
00172 } else ++it;
00173 }
00174
00175 void ServiceBrowser::addDomain(const TQString& domain)
00176 {
00177 if (!d->m_running) return;
00178 if (!(d->resolvers[domain])) {
00179 TQStringList::ConstIterator itEnd = d->m_types.end();
00180 for (TQStringList::ConstIterator it=d->m_types.begin(); it!=itEnd; ++it) {
00181 Query* b = new Query((*it),domain);
00182 connect(b,TQT_SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),this,
00183 TQT_SLOT(gotNewService(DNSSD::RemoteService::Ptr)));
00184 connect(b,TQT_SIGNAL(serviceRemoved(DNSSD::RemoteService::Ptr )),this,
00185 TQT_SLOT(gotRemoveService(DNSSD::RemoteService::Ptr)));
00186 connect(b,TQT_SIGNAL(finished()),this,TQT_SLOT(queryFinished()));
00187 b->startQuery();
00188 d->resolvers.insert(domain,b);
00189 }
00190 }
00191 }
00192
00193 void ServiceBrowser::queryFinished()
00194 {
00195 if (allFinished()) emit finished();
00196 }
00197
00198 bool ServiceBrowser::allFinished()
00199 {
00200 if (d->m_duringResolve.count()) return false;
00201 bool all = true;
00202 TQDictIterator<Query> it(d->resolvers);
00203 for ( ; it.current(); ++it) all&=(*it)->isFinished();
00204 return all;
00205 }
00206
00207 const TQValueList<RemoteService::Ptr>& ServiceBrowser::services() const
00208 {
00209 return d->m_services;
00210 }
00211
00212 void ServiceBrowser::virtual_hook(int, void*)
00213 {}
00214
00215 TQValueList<RemoteService::Ptr>::Iterator ServiceBrowser::findDuplicate(RemoteService::Ptr src)
00216 {
00217 TQValueList<RemoteService::Ptr>::Iterator itEnd = d->m_services.end();
00218 for (TQValueList<RemoteService::Ptr>::Iterator it = d->m_services.begin(); it!=itEnd; ++it)
00219 if ((src->type()==(*it)->type()) && (src->serviceName()==(*it)->serviceName()) &&
00220 (src->domain() == (*it)->domain())) return it;
00221 return itEnd;
00222 }
00223
00224
00225 }
00226
00227 #include "servicebrowser.moc"