query.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., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "query.h" 
00022 #include "responder.h"
00023 #include "remoteservice.h"
00024 #include "sdevent.h"
00025 #include <qdatetime.h>
00026 #include <qapplication.h>
00027 #include <qtimer.h>
00028 
00029 #include <avahi-client/client.h>
00030 #ifdef AVAHI_API_0_6
00031 #include <avahi-client/lookup.h>
00032 #endif
00033 
00034 #define TIMEOUT_LAN 200
00035 
00036 namespace DNSSD
00037 {
00038 #ifdef AVAHI_API_0_6
00039 
00040 void services_callback(AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* name,
00041     const char* regtype, const char* domain, AvahiLookupResultFlags, void* context);
00042 void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
00043     const char* replyDomain, AvahiLookupResultFlags, void* context);
00044 #else
00045 void services_callback(AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* name,
00046     const char* regtype, const char* domain, void* context);
00047 void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
00048     const char* replyDomain, void* context);
00049 void domains_callback(AvahiDomainBrowser*,  AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
00050      void* context);
00051 #endif
00052 
00053 enum BrowserType { Types, Services };
00054 
00055 class QueryPrivate 
00056 {
00057 public:
00058     QueryPrivate(const QString& type, const QString& domain) : m_finished(false), m_browser(0),
00059     m_running(false), m_domain(domain), m_type(type) {}
00060 
00061     bool m_finished;
00062     BrowserType m_browserType;
00063     void* m_browser;
00064     bool m_running;
00065     QString m_domain;
00066     QTimer timeout;
00067     QString m_type;
00068 };
00069 
00070 Query::Query(const QString& type, const QString& domain)
00071 {
00072     d = new QueryPrivate(type,domain);
00073     connect(&d->timeout,SIGNAL(timeout()),this,SLOT(timeout()));
00074 }
00075 
00076 
00077 Query::~Query()
00078 {
00079     if (d->m_browser) {
00080         switch (d->m_browserType) {
00081         case Services: avahi_service_browser_free((AvahiServiceBrowser*)d->m_browser); break;
00082         case Types: avahi_service_type_browser_free((AvahiServiceTypeBrowser*)d->m_browser); break;
00083         }
00084     }           
00085     delete d;
00086 }
00087 
00088 bool Query::isRunning() const
00089 {
00090     return d->m_running;
00091 }
00092 
00093 bool Query::isFinished() const
00094 {
00095     return d->m_finished;
00096 }
00097 
00098 const QString& Query::domain() const
00099 {
00100     return d->m_domain;
00101 }
00102 
00103 void Query::startQuery()
00104 {
00105     if (d->m_running) return;
00106     d->m_finished = false;
00107     if (d->m_type=="_services._dns-sd._udp") {
00108         d->m_browserType = Types;
00109 #ifdef AVAHI_API_0_6
00110         d->m_browser = avahi_service_type_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
00111         domainToDNS(d->m_domain), (AvahiLookupFlags)0, types_callback, this);
00112 #else
00113         d->m_browser = avahi_service_type_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
00114         d->m_domain.utf8(), types_callback, this);
00115 #endif
00116     } else {
00117         d->m_browserType = Services;
00118 #ifdef AVAHI_API_0_6
00119         d->m_browser = avahi_service_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
00120         d->m_type.ascii(),domainToDNS(d->m_domain),  (AvahiLookupFlags)0, services_callback,this);
00121 #else
00122         d->m_browser = avahi_service_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
00123         d->m_type.ascii(),d->m_domain.utf8(),services_callback,this);
00124 #endif
00125     }
00126     if (d->m_browser) {
00127         d->m_running=true;
00128         d->timeout.start(TIMEOUT_LAN,true);
00129     } else emit finished();
00130 }
00131 void Query::virtual_hook(int, void*)
00132 {
00133 }
00134 
00135 void Query::customEvent(QCustomEvent* event)
00136 {
00137     if (event->type()==QEvent::User+SD_ADDREMOVE) {
00138         d->timeout.start(TIMEOUT_LAN,true);
00139         d->m_finished=false;
00140         AddRemoveEvent *aev = static_cast<AddRemoveEvent*>(event);
00141         // m_type has useless trailing dot
00142         RemoteService*  svr = new RemoteService(aev->m_name,
00143                 aev->m_type,aev->m_domain);
00144         if (aev->m_op==AddRemoveEvent::Add) emit serviceAdded(svr);
00145             else emit serviceRemoved(svr);
00146     }
00147 }
00148 
00149 void Query::timeout()
00150 {
00151     d->m_finished=true;
00152     emit finished();
00153 }
00154 
00155 #ifdef AVAHI_API_0_6
00156 void services_callback (AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, 
00157     const char* serviceName, const char* regtype, const char* replyDomain, AvahiLookupResultFlags, void* context)
00158 #else
00159 void services_callback (AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, 
00160     const char* serviceName, const char* regtype, const char* replyDomain, void* context)
00161 #endif
00162 {
00163     QObject *obj = reinterpret_cast<QObject*>(context);
00164     AddRemoveEvent* arev = new AddRemoveEvent((event==AVAHI_BROWSER_NEW) ? AddRemoveEvent::Add :
00165             AddRemoveEvent::Remove, QString::fromUtf8(serviceName), regtype, 
00166             DNSToDomain(replyDomain));
00167         QApplication::postEvent(obj, arev);
00168 }
00169 
00170 #ifdef AVAHI_API_0_6
00171 void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
00172     const char* replyDomain, AvahiLookupResultFlags, void* context)
00173 #else
00174 void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
00175     const char* replyDomain, void* context)
00176 #endif
00177 {
00178     QObject *obj = reinterpret_cast<QObject*>(context);
00179     AddRemoveEvent* arev = new AddRemoveEvent((event==AVAHI_BROWSER_NEW) ? AddRemoveEvent::Add :
00180             AddRemoveEvent::Remove, QString::null, regtype, 
00181             DNSToDomain(replyDomain));
00182         QApplication::postEvent(obj, arev);
00183 }
00184 
00185 }
00186 #include "query.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys