• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

DNSSD

servicebrowser.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  *
00003  * Copyright (C) 2004 Jakub Stachowski <qbast@go2.pl>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include <signal.h>
00022 #include <errno.h>
00023 #include <qstringlist.h>
00024 #include <qfile.h>
00025 #include "domainbrowser.h"
00026 #include "query.h"
00027 #include "servicebrowser.h"
00028 #include <config.h>
00029 #ifdef HAVE_DNSSD
00030 #include <dns_sd.h>
00031 #endif
00032 
00033 #define MDNSD_PID "/var/run/mdnsd.pid"
00034 
00035 namespace DNSSD
00036 {
00037 
00038 const QString ServiceBrowser::AllServices = "_services._dns-sd._udp";
00039 
00040 class ServiceBrowserPrivate 
00041 {
00042 public: 
00043     ServiceBrowserPrivate() : m_running(false) 
00044     {}
00045     QValueList<RemoteService::Ptr> m_services;
00046     QValueList<RemoteService::Ptr> m_duringResolve;
00047     QStringList m_types;
00048     DomainBrowser* m_domains;
00049     int m_flags;
00050     bool m_running;
00051     bool m_finished;
00052     QDict<Query> resolvers;
00053 };
00054 
00055 ServiceBrowser::ServiceBrowser(const QString& type,DomainBrowser* domains,bool autoResolve)
00056 {
00057     if (domains) init(type,domains,autoResolve ? AutoResolve : 0);
00058         else init(type,new DomainBrowser(this),autoResolve ?  AutoResolve|AutoDelete : AutoDelete);
00059 }
00060 ServiceBrowser::ServiceBrowser(const QStringList& types,DomainBrowser* domains,int flags)
00061 {
00062     if (domains) init(types,domains,flags);
00063         else init(types,new DomainBrowser(this),flags|AutoDelete);
00064 }
00065 
00066 void ServiceBrowser::init(const QStringList& type,DomainBrowser* domains,int flags)
00067 {
00068     d = new ServiceBrowserPrivate();
00069     d->resolvers.setAutoDelete(true);
00070     d->m_types=type;
00071     d->m_flags=flags;
00072     d->m_domains = domains;
00073     connect(d->m_domains,SIGNAL(domainAdded(const QString& )),this,SLOT(addDomain(const QString& )));
00074     connect(d->m_domains,SIGNAL(domainRemoved(const QString& )),this,
00075         SLOT(removeDomain(const QString& )));
00076 }
00077 ServiceBrowser::ServiceBrowser(const QString& type,const QString& domain,bool autoResolve)
00078 {
00079     init(type,new DomainBrowser(domain,false,this),autoResolve ? AutoResolve|AutoDelete : AutoDelete);
00080 }
00081 ServiceBrowser::ServiceBrowser(const QString& type,const QString& domain,int flags)
00082 {
00083     init(type,new DomainBrowser(domain,false,this),flags | AutoDelete);
00084 }
00085 
00086 const ServiceBrowser::State ServiceBrowser::isAvailable()
00087 {
00088 #ifdef HAVE_DNSSD
00089     QFile f(MDNSD_PID);
00090     if (!f.open(IO_ReadOnly)) return Stopped; // no pidfile
00091     QString line;
00092     if (f.readLine(line,16)<1) return Stopped;
00093     unsigned int pid = line.toUInt();
00094     if (pid==0) return Stopped;           // not a pid
00095     return (kill(pid,0)==0 || errno==EPERM) ? Working : Stopped; 
00096     // signal 0 only checks if process is running, mdnsd is probably owned by 'nobody' so we will
00097     // get EPERM, if mdnsd is not running error will be ESRCH
00098     
00099 #else
00100     return Unsupported;
00101 #endif
00102 }
00103 ServiceBrowser::~ ServiceBrowser()
00104 {
00105     if (d->m_flags & AutoDelete) delete d->m_domains;
00106     delete d;
00107 }
00108 
00109 const DomainBrowser* ServiceBrowser::browsedDomains() const
00110 {
00111     return d->m_domains;
00112 }
00113 
00114 void ServiceBrowser::serviceResolved(bool success)
00115 {
00116     QObject* sender_obj = const_cast<QObject*>(sender());
00117     RemoteService* svr = static_cast<RemoteService*>(sender_obj);
00118     disconnect(svr,SIGNAL(resolved(bool)),this,SLOT(serviceResolved(bool)));
00119     QValueList<RemoteService::Ptr>::Iterator it = d->m_duringResolve.begin();
00120     QValueList<RemoteService::Ptr>::Iterator itEnd = d->m_duringResolve.end();
00121     while ( it!= itEnd && svr!= (*it)) ++it;
00122     if (it != itEnd) {
00123         if (success) {
00124             d->m_services+=(*it);
00125             emit serviceAdded(svr);
00126         }
00127         d->m_duringResolve.remove(it);
00128         queryFinished();
00129     }
00130 }
00131 
00132 void ServiceBrowser::startBrowse()
00133 {
00134     if (d->m_running) return;
00135     d->m_running=true;
00136     if (isAvailable()!=Working) return;
00137     if (d->m_domains->isRunning()) {
00138         QStringList::const_iterator itEnd  = d->m_domains->domains().end();
00139         for ( QStringList::const_iterator it = d->m_domains->domains().begin(); it != itEnd; ++it )
00140             addDomain(*it);
00141     } else d->m_domains->startBrowse();
00142 }
00143 
00144 void ServiceBrowser::gotNewService(RemoteService::Ptr svr)
00145 {
00146     if (findDuplicate(svr)==(d->m_services.end()))  {
00147         if (d->m_flags & AutoResolve) {
00148             connect(svr,SIGNAL(resolved(bool )),this,SLOT(serviceResolved(bool )));
00149             d->m_duringResolve+=svr;
00150             svr->resolveAsync();
00151         } else  {
00152             d->m_services+=svr;
00153             emit serviceAdded(svr);
00154         }
00155     }
00156 }
00157 
00158 void ServiceBrowser::gotRemoveService(RemoteService::Ptr svr)
00159 {
00160     QValueList<RemoteService::Ptr>::Iterator it = findDuplicate(svr);
00161     if (it!=(d->m_services.end())) {
00162         emit serviceRemoved(*it);
00163         d->m_services.remove(it);
00164     }
00165 }
00166 
00167 
00168 void ServiceBrowser::removeDomain(const QString& domain)
00169 {
00170     while (d->resolvers[domain]) d->resolvers.remove(domain);
00171     QValueList<RemoteService::Ptr>::Iterator it = d->m_services.begin();
00172     while (it!=d->m_services.end()) 
00173         // use section to skip possible trailing dot
00174         if ((*it)->domain().section('.',0) == domain.section('.',0)) {
00175             emit serviceRemoved(*it);
00176             it = d->m_services.remove(it);
00177         } else ++it;
00178 }
00179 
00180 void ServiceBrowser::addDomain(const QString& domain)
00181 {
00182     if (!d->m_running) return;
00183     if (!(d->resolvers[domain])) {
00184         QStringList::ConstIterator itEnd = d->m_types.end();
00185         for (QStringList::ConstIterator it=d->m_types.begin(); it!=itEnd; ++it) {
00186             Query* b = new Query((*it),domain);
00187             connect(b,SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),this,
00188                 SLOT(gotNewService(DNSSD::RemoteService::Ptr)));
00189             connect(b,SIGNAL(serviceRemoved(DNSSD::RemoteService::Ptr )),this,
00190                 SLOT(gotRemoveService(DNSSD::RemoteService::Ptr)));
00191             connect(b,SIGNAL(finished()),this,SLOT(queryFinished()));
00192             b->startQuery();
00193             d->resolvers.insert(domain,b);
00194         }
00195     }
00196 }
00197 
00198 void ServiceBrowser::queryFinished()
00199 {
00200     if (allFinished()) emit finished();
00201 }
00202 
00203 bool ServiceBrowser::allFinished()
00204 {
00205     if  (d->m_duringResolve.count()) return false;
00206     bool all = true;
00207     QDictIterator<Query> it(d->resolvers);
00208     for ( ; it.current(); ++it) all&=(*it)->isFinished();
00209     return all;
00210 }
00211 
00212 const QValueList<RemoteService::Ptr>& ServiceBrowser::services() const
00213 {
00214     return d->m_services;
00215 }
00216 
00217 void ServiceBrowser::virtual_hook(int, void*)
00218 {}
00219 
00220 QValueList<RemoteService::Ptr>::Iterator ServiceBrowser::findDuplicate(RemoteService::Ptr src)
00221 {
00222     QValueList<RemoteService::Ptr>::Iterator itEnd = d->m_services.end();
00223     for (QValueList<RemoteService::Ptr>::Iterator it = d->m_services.begin(); it!=itEnd; ++it) 
00224         if ((src->type()==(*it)->type()) && (src->serviceName()==(*it)->serviceName()) &&
00225                    (src->domain() == (*it)->domain())) return it;
00226     return itEnd;
00227 }
00228 
00229 
00230 }
00231 
00232 #include "servicebrowser.moc"

DNSSD

Skip menu "DNSSD"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal