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 <kdebug.h> 00026 #include <qapplication.h> 00027 #include <qtimer.h> 00028 00029 #define TIMEOUT_WAN 2000 00030 #define TIMEOUT_LAN 200 00031 00032 namespace DNSSD 00033 { 00034 #ifdef HAVE_DNSSD 00035 void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, 00036 const char *serviceName, const char *regtype, const char *replyDomain, void *context); 00037 #endif 00038 class QueryPrivate : public Responder 00039 { 00040 public: 00041 QueryPrivate(const QString& type, const QString& domain) : Responder(), m_finished(false), 00042 m_domain(domain), m_type(type) 00043 {}; 00044 bool m_finished; 00045 QString m_domain; 00046 QTimer timeout; 00047 QString m_type; 00048 }; 00049 00050 Query::Query(const QString& type, const QString& domain) 00051 { 00052 d = new QueryPrivate(type,domain); 00053 connect(&d->timeout,SIGNAL(timeout()),this,SLOT(timeout())); 00054 } 00055 00056 00057 Query::~Query() 00058 { 00059 delete d; 00060 } 00061 00062 bool Query::isRunning() const 00063 { 00064 return d->isRunning(); 00065 } 00066 00067 bool Query::isFinished() const 00068 { 00069 return d->m_finished; 00070 } 00071 00072 const QString& Query::domain() const 00073 { 00074 return d->m_domain; 00075 } 00076 00077 void Query::startQuery() 00078 { 00079 if (d->isRunning()) return; 00080 d->m_finished = false; 00081 #ifdef HAVE_DNSSD 00082 DNSServiceRef ref; 00083 if (DNSServiceBrowse(&ref,0,0, d->m_type.ascii(), 00084 domainToDNS(d->m_domain),query_callback,reinterpret_cast<void*>(this)) 00085 == kDNSServiceErr_NoError) d->setRef(ref); 00086 #endif 00087 if (!d->isRunning()) emit finished(); 00088 else d->timeout.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAN : TIMEOUT_WAN,true); 00089 } 00090 void Query::virtual_hook(int, void*) 00091 { 00092 } 00093 00094 void Query::customEvent(QCustomEvent* event) 00095 { 00096 if (event->type()==QEvent::User+SD_ERROR) { 00097 d->stop(); 00098 d->m_finished=false; 00099 emit finished(); 00100 } 00101 if (event->type()==QEvent::User+SD_ADDREMOVE) { 00102 RemoteService* svr; 00103 AddRemoveEvent *aev = static_cast<AddRemoveEvent*>(event); 00104 // m_type has useless trailing dot 00105 QString type=aev->m_type.left(aev->m_type.length()-1); 00106 // label is badly splitted here - _http _tcp.local. . - rely on decode() 00107 if (d->m_type=="_services._dns-sd._udp") svr = new RemoteService(aev->m_name+"."+ 00108 type+"."+aev->m_domain); 00109 else svr = new RemoteService(aev->m_name, type, aev->m_domain); 00110 if (aev->m_op==AddRemoveEvent::Add) emit serviceAdded(svr); 00111 else emit serviceRemoved(svr); 00112 d->m_finished = aev->m_last; 00113 if (d->m_finished) emit finished(); 00114 } 00115 } 00116 00117 void Query::timeout() 00118 { 00119 d->m_finished=true; 00120 emit finished(); 00121 } 00122 #ifdef HAVE_DNSSD 00123 void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, 00124 const char *serviceName, const char *regtype, const char *replyDomain, 00125 void *context) 00126 { 00127 QObject *obj = reinterpret_cast<QObject*>(context); 00128 if (errorCode != kDNSServiceErr_NoError) { 00129 ErrorEvent err; 00130 QApplication::sendEvent(obj, &err); 00131 } else { 00132 AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add : 00133 AddRemoveEvent::Remove, QString::fromUtf8(serviceName), regtype, 00134 DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing)); 00135 QApplication::sendEvent(obj, &arev); 00136 } 00137 } 00138 #endif 00139 } 00140 #include "query.moc"