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 | |
37 | namespace DNSSD |
38 | { |
39 | void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, |
40 | const char *serviceName, const char *regtype, const char *replyDomain, void *context); |
41 | |
42 | ServiceBrowser::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 | |
54 | ServiceBrowser::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 | } |
62 | ServiceBrowser::~ ServiceBrowser() |
63 | { |
64 | delete d; |
65 | } |
66 | |
67 | bool ServiceBrowser::isAutoResolving() const |
68 | { |
69 | return d->m_autoResolve; |
70 | } |
71 | |
72 | |
73 | void 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 | |
91 | void 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 | |
106 | void ServiceBrowserPrivate::queryFinished() |
107 | { |
108 | if (!m_duringResolve.count() && m_finished) emit m_parent->finished(); |
109 | } |
110 | |
111 | |
112 | QList<RemoteService::Ptr> ServiceBrowser::services() const |
113 | { |
114 | return d->m_services; |
115 | } |
116 | |
117 | void ServiceBrowser::virtual_hook(int, void*) |
118 | {} |
119 | |
120 | RemoteService::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 | |
127 | void 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 | |
165 | void ServiceBrowserPrivate::onTimeout() |
166 | { |
167 | m_finished=true; |
168 | queryFinished(); |
169 | } |
170 | |
171 | void 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) |
188 | QHostAddress ServiceBrowser::resolveHostName(const QString &hostname) |
189 | { |
190 | return QHostAddress(); |
191 | } |
192 | |
193 | QString 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.