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"