dnssd Library API Documentation

servicebrowser.cpp

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., 59 Temple Place - Suite 330,
00018  * Boston, MA 02111-1307, USA.
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 //  DNSServiceRef ref;
00076 //  bool ok (DNSServiceCreateConnection(&ref)==kDNSServiceErr_NoError); 
00077 //  if (ok) DNSServiceRefDeallocate(ref);
00078 //  return (ok) ? Working : Stopped;
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         // use section to skip possible trailing dot
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"
KDE Logo
This file is part of the documentation for dnssd Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 16 07:02:14 2005 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003