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