DNSSD
mdnsd-servicebrowser.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "mdnsd-servicebrowser_p.h"
00022 #include "domainbrowser.h"
00023 #include "servicebrowser.h"
00024 #include "mdnsd-responder.h"
00025 #include "remoteservice.h"
00026 #include "mdnsd-sdevent.h"
00027 #include <dns_sd.h>
00028 #include <QtCore/QStringList>
00029 #include <QtCore/QHash>
00030 #include <QtCore/QCoreApplication>
00031 #include <QtCore/QTimer>
00032
00033 #define TIMEOUT_WAN 2000
00034 #define TIMEOUT_LAN 200
00035
00036 namespace DNSSD
00037 {
00038 void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
00039 const char *serviceName, const char *regtype, const char *replyDomain, void *context);
00040
00041 ServiceBrowser::ServiceBrowser(const QString& type,bool autoResolve,const QString& domain, const QString& subtype)
00042 :d(new ServiceBrowserPrivate(this))
00043 {
00044 d->m_type=type;
00045 d->m_autoResolve=autoResolve;
00046 d->m_domain=domain;
00047 d->m_subtype=subtype;
00048 d->timeout.setSingleShot(true);
00049 connect(&d->timeout,SIGNAL(timeout()),d,SLOT(onTimeout()));
00050 }
00051
00052
00053 ServiceBrowser::State ServiceBrowser::isAvailable()
00054 {
00055
00056
00057
00058
00059 return Working;
00060 }
00061 ServiceBrowser::~ ServiceBrowser()
00062 {
00063 delete d;
00064 }
00065
00066 bool ServiceBrowser::isAutoResolving() const
00067 {
00068 return d->m_autoResolve;
00069 }
00070
00071
00072 void ServiceBrowserPrivate::serviceResolved(bool success)
00073 {
00074 QObject* sender_obj = const_cast<QObject*>(sender());
00075 RemoteService* svr = static_cast<RemoteService*>(sender_obj);
00076 disconnect(svr,SIGNAL(resolved(bool)),this,SLOT(serviceResolved(bool)));
00077 QList<RemoteService::Ptr>::Iterator it = m_duringResolve.begin();
00078 QList<RemoteService::Ptr>::Iterator itEnd = m_duringResolve.end();
00079 while ( it!= itEnd && svr!= (*it).data()) ++it;
00080 if (it != itEnd) {
00081 if (success) {
00082 m_services+=(*it);
00083 emit m_parent->serviceAdded(RemoteService::Ptr(svr));
00084 }
00085 m_duringResolve.erase(it);
00086 queryFinished();
00087 }
00088 }
00089
00090 void ServiceBrowser::startBrowse()
00091 {
00092 if (d->isRunning()) return;
00093 d->m_finished = false;
00094 DNSServiceRef ref;
00095 QString fullType=d->m_type;
00096 if (!d->m_subtype.isEmpty()) fullType=d->m_subtype+"._sub."+d->m_type;
00097 if (DNSServiceBrowse(&ref,0,0, fullType.toAscii().constData(),
00098 domainToDNS(d->m_domain),query_callback,reinterpret_cast<void*>(d))
00099 == kDNSServiceErr_NoError) d->setRef(ref);
00100 if (!d->isRunning()) emit finished();
00101 else d->timeout.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAN : TIMEOUT_WAN);
00102 }
00103
00104
00105 void ServiceBrowserPrivate::queryFinished()
00106 {
00107 if (!m_duringResolve.count() && m_finished) emit m_parent->finished();
00108 }
00109
00110
00111 QList<RemoteService::Ptr> ServiceBrowser::services() const
00112 {
00113 return d->m_services;
00114 }
00115
00116 void ServiceBrowser::virtual_hook(int, void*)
00117 {}
00118
00119 RemoteService::Ptr ServiceBrowserPrivate::find(RemoteService::Ptr s) const
00120 {
00121 Q_FOREACH (const RemoteService::Ptr& i, m_services) if (*s==*i) return i;
00122 Q_FOREACH (const RemoteService::Ptr& i, m_duringResolve) if (*s==*i) return i;
00123 return s;
00124 }
00125
00126
00127 void ServiceBrowserPrivate::customEvent(QEvent* event)
00128 {
00129 if (event->type()==QEvent::User+SD_ERROR) {
00130 stop();
00131 m_finished=false;
00132 queryFinished();
00133 }
00134 if (event->type()==QEvent::User+SD_ADDREMOVE) {
00135 AddRemoveEvent *aev = static_cast<AddRemoveEvent*>(event);
00136
00137 RemoteService::Ptr svr(new RemoteService(aev->m_name,aev->m_type.left(aev->m_type.length()-1),aev->m_domain));
00138 if (aev->m_op==AddRemoveEvent::Add) {
00139 if (m_autoResolve) {
00140 connect(svr.data(),SIGNAL(resolved(bool )),this,SLOT(serviceResolved(bool )));
00141 m_duringResolve+=svr;
00142 svr->resolveAsync();
00143 } else {
00144 m_services+=svr;
00145 emit m_parent->serviceAdded(svr);
00146 }
00147 }
00148 else {
00149 svr=find(svr);
00150 emit m_parent->serviceRemoved(svr);
00151 m_services.removeAll(svr);
00152 }
00153 m_finished = aev->m_last;
00154 if (m_finished) queryFinished();
00155 }
00156 }
00157
00158 void ServiceBrowserPrivate::onTimeout()
00159 {
00160 m_finished=true;
00161 queryFinished();
00162 }
00163
00164 void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
00165 const char *serviceName, const char *regtype, const char *replyDomain,
00166 void *context)
00167 {
00168 QObject *obj = reinterpret_cast<QObject*>(context);
00169 if (errorCode != kDNSServiceErr_NoError) {
00170 ErrorEvent err;
00171 QCoreApplication::sendEvent(obj, &err);
00172 } else {
00173 AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add :
00174 AddRemoveEvent::Remove, QString::fromUtf8(serviceName), regtype,
00175 DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing));
00176 QCoreApplication::sendEvent(obj, &arev);
00177 }
00178 }
00179
00180
00181 }
00182
00183 #include "servicebrowser.moc"
00184 #include "mdnsd-servicebrowser_p.moc"