Warning: That file was not part of the compilation database. It may have many parsing errors.

1/* This file is part of the KDE project
2 *
3 * Copyright (C) 2004 Jakub Stachowski <qbast@go2.pl>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "mdnsd-servicebrowser_p.h"
22#include "domainbrowser.h"
23#include "servicebrowser.h"
24#include "mdnsd-responder.h"
25#include "remoteservice.h"
26#include "mdnsd-sdevent.h"
27#include <dns_sd.h>
28#include <QtCore/QStringList>
29#include <QtCore/QHash>
30#include <QtCore/QCoreApplication>
31#include <QtCore/QTimer>
32#include <QtNetwork/QHostInfo>
33
34#define TIMEOUT_WAN 2000
35#define TIMEOUT_LAN 200
36
37namespace DNSSD
38{
39void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
40 const char *serviceName, const char *regtype, const char *replyDomain, void *context);
41
42ServiceBrowser::ServiceBrowser(const QString& type,bool autoResolve,const QString& domain, const QString& subtype)
43 :d(new ServiceBrowserPrivate(this))
44{
45 d->m_type=type;
46 d->m_autoResolve=autoResolve;
47 d->m_domain=domain;
48 d->m_subtype=subtype;
49 d->timeout.setSingleShot(true);
50 connect(&d->timeout,SIGNAL(timeout()),d,SLOT(onTimeout()));
51}
52
53
54ServiceBrowser::State ServiceBrowser::isAvailable()
55{
56// DNSServiceRef ref;
57// bool ok (DNSServiceCreateConnection(&ref)==kDNSServiceErr_NoError);
58// if (ok) DNSServiceRefDeallocate(ref);
59// return (ok) ? Working : Stopped;
60 return Working;
61}
62ServiceBrowser::~ ServiceBrowser()
63{
64 delete d;
65}
66
67bool ServiceBrowser::isAutoResolving() const
68{
69 return d->m_autoResolve;
70}
71
72
73void ServiceBrowserPrivate::serviceResolved(bool success)
74{
75 QObject* sender_obj = const_cast<QObject*>(sender());
76 RemoteService* svr = static_cast<RemoteService*>(sender_obj);
77 disconnect(svr,SIGNAL(resolved(bool)),this,SLOT(serviceResolved(bool)));
78 QList<RemoteService::Ptr>::Iterator it = m_duringResolve.begin();
79 QList<RemoteService::Ptr>::Iterator itEnd = m_duringResolve.end();
80 while ( it!= itEnd && svr!= (*it).data()) ++it;
81 if (it != itEnd) {
82 if (success) {
83 m_services+=(*it);
84 emit m_parent->serviceAdded(RemoteService::Ptr(svr));
85 }
86 m_duringResolve.erase(it);
87 queryFinished();
88 }
89}
90
91void ServiceBrowser::startBrowse()
92{
93 if (d->isRunning()) return;
94 d->m_finished = false;
95 DNSServiceRef ref;
96 QString fullType=d->m_type;
97 if (!d->m_subtype.isEmpty()) fullType=d->m_subtype+"._sub."+d->m_type;
98 if (DNSServiceBrowse(&ref,0,0, fullType.toLatin1().constData(),
99 domainToDNS(d->m_domain),query_callback,reinterpret_cast<void*>(d))
100 == kDNSServiceErr_NoError) d->setRef(ref);
101 if (!d->isRunning()) emit finished();
102 else d->timeout.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAN : TIMEOUT_WAN);
103}
104
105
106void ServiceBrowserPrivate::queryFinished()
107{
108 if (!m_duringResolve.count() && m_finished) emit m_parent->finished();
109}
110
111
112QList<RemoteService::Ptr> ServiceBrowser::services() const
113{
114 return d->m_services;
115}
116
117void ServiceBrowser::virtual_hook(int, void*)
118{}
119
120RemoteService::Ptr ServiceBrowserPrivate::find(RemoteService::Ptr s, const QList<RemoteService::Ptr>& where) const
121{
122 Q_FOREACH (const RemoteService::Ptr& i, where) if (*s==*i) return i;
123 return RemoteService::Ptr();
124}
125
126
127void ServiceBrowserPrivate::customEvent(QEvent* event)
128{
129 if (event->type()==QEvent::User+SD_ERROR) {
130 stop();
131 m_finished=false;
132 queryFinished();
133 }
134 if (event->type()==QEvent::User+SD_ADDREMOVE) {
135 AddRemoveEvent *aev = static_cast<AddRemoveEvent*>(event);
136 // m_type has useless trailing dot
137 RemoteService::Ptr svr(new RemoteService(aev->m_name,aev->m_type.left(aev->m_type.length()-1),aev->m_domain));
138 if (aev->m_op==AddRemoveEvent::Add) {
139 if (m_autoResolve) {
140 connect(svr.data(),SIGNAL(resolved(bool)),this,SLOT(serviceResolved(bool)));
141 m_duringResolve+=svr;
142 svr->resolveAsync();
143 } else {
144 m_services+=svr;
145 emit m_parent->serviceAdded(svr);
146 }
147 }
148 else {
149
150 RemoteService::Ptr found=find(svr, m_duringResolve);
151 if (!found.isNull()) m_duringResolve.removeAll(found);
152 else {
153 found=find(svr, m_services);
154 if (!found.isNull()) {
155 emit m_parent->serviceRemoved(found);
156 m_services.removeAll(found);
157 }
158 }
159 }
160 m_finished = aev->m_last;
161 if (m_finished) queryFinished();
162 }
163}
164
165void ServiceBrowserPrivate::onTimeout()
166{
167 m_finished=true;
168 queryFinished();
169}
170
171void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
172 const char *serviceName, const char *regtype, const char *replyDomain,
173 void *context)
174{
175 QObject *obj = reinterpret_cast<QObject*>(context);
176 if (errorCode != kDNSServiceErr_NoError) {
177 ErrorEvent err;
178 QCoreApplication::sendEvent(obj, &err);
179 } else {
180 AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add :
181 AddRemoveEvent::Remove, QString::fromUtf8(serviceName), regtype,
182 DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing));
183 QCoreApplication::sendEvent(obj, &arev);
184 }
185}
186
187// TODO: Please Implement Me - Using a KResolver (if not natively)
188QHostAddress ServiceBrowser::resolveHostName(const QString &hostname)
189{
190 return QHostAddress();
191}
192
193QString ServiceBrowser::getLocalHostName()
194{
195 return QHostInfo::localHostName();
196}
197
198}
199
200#include "servicebrowser.moc"
201#include "mdnsd-servicebrowser_p.moc"
202

Warning: That file was not part of the compilation database. It may have many parsing errors.