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 | #ifndef DNSSDSERVICEBROWSER_H |
22 | #define DNSSDSERVICEBROWSER_H |
23 | |
24 | #include <QtCore/QObject> |
25 | #include <QtNetwork/QHostAddress> |
26 | |
27 | #include <dnssd/remoteservice.h> |
28 | |
29 | |
30 | namespace DNSSD |
31 | { |
32 | class DomainBrowser; |
33 | class ServiceBrowserPrivate; |
34 | |
35 | /** |
36 | * @class ServiceBrowser servicebrowser.h DNSSD/ServiceBrowser |
37 | * @short Browses for network services advertised over DNS-SD |
38 | * |
39 | * This is the central class in the DNSSD library for applications |
40 | * that want to discover services on network. |
41 | * |
42 | * Suppose that you need list of web servers running. Then you |
43 | * might do something like |
44 | * @code |
45 | * DNSSD::ServiceBrowser* browser = new DNSSD::ServiceBrowser("_http._tcp"); |
46 | * connect(browser, SIGNAL(serviceAdded(RemoteService::Ptr)), |
47 | * this, SLOT(addService(RemoteService::Ptr))); |
48 | * connect(browser, SIGNAL(serviceRemoved(RemoteService::Ptr)), |
49 | * this, SLOT(delService(RemoteService::Ptr))); |
50 | * browser->startBrowse(); |
51 | * @endcode |
52 | * |
53 | * In above example addService() will be called for every web server |
54 | * already running and for every web service that subsequently |
55 | * appears on the network and delService() will be called when |
56 | * a server previously advertised is stopped. |
57 | * |
58 | * Because no domain was passed to constructor, the default domain |
59 | * will be searched. To find other domains to browse for services on, |
60 | * use DomainBrowser. |
61 | * |
62 | * @author Jakub Stachowski |
63 | */ |
64 | class KDNSSD_EXPORT ServiceBrowser : public QObject |
65 | { |
66 | Q_OBJECT |
67 | |
68 | public: |
69 | /** |
70 | * Availability of DNS-SD services |
71 | */ |
72 | enum State { |
73 | /** the service is available */ |
74 | Working, |
75 | /** not available because mDnsd or Avahi daemon is not running */ |
76 | Stopped, |
77 | /** not available because KDE was compiled without DNS-SD support */ |
78 | Unsupported |
79 | }; |
80 | |
81 | /** |
82 | * Create a ServiceBrowser for a particular service type |
83 | * |
84 | * DomainBrowser can be used to find other domains to browse on. |
85 | * If no domain is given, the default domain is used. |
86 | * |
87 | * The service type is the high-level protocol type, followed by a dot, |
88 | * followed by the transport protocol type (@c _tcp or @c _udp). |
89 | * The <a href="http://www.dns-sd.org">DNS-SD website</a> maintains |
90 | * <a href="http://www.dns-sd.org/ServiceTypes.html">a full list</a> |
91 | * of service types. |
92 | * |
93 | * The @p subtype parameter allows you to do more fine-grained filtering |
94 | * on the services you are interested in. So you might request only |
95 | * FTP servers that allow anonymous access by passing "_ftp._tcp" as the |
96 | * @p type and "_anon" as the @p subtype. Subtypes are particularly |
97 | * important for types like _soap and _upnp, which are far too generic |
98 | * for most applications. In these cases, the subtype can be used to |
99 | * specify the particular SOAP or UPnP protocol they want. |
100 | * |
101 | * @warning |
102 | * Enabling @p autoResolve will increase network usage by resolving |
103 | * all services, so this feature should be used only when necessary. |
104 | * |
105 | * @param type service types to browse for (example: "_http._tcp") |
106 | * @param autoResolve discovered services will be resolved before being |
107 | * reported with the serviceAdded() signal |
108 | * @param domain a domain to search on instead of the default one |
109 | * @param subtype only browse for a specific subtype |
110 | * |
111 | * @see startBrowse() and isAvailable() |
112 | */ |
113 | explicit ServiceBrowser(const QString& type, |
114 | bool autoResolve = false, |
115 | const QString& domain = QString(), |
116 | const QString& subtype = QString()); |
117 | |
118 | ~ServiceBrowser(); |
119 | |
120 | /** |
121 | * The currently known services of the specified type |
122 | * |
123 | * @returns a list of RemoteService pointers |
124 | * |
125 | * @see serviceAdded() and serviceRemoved() |
126 | */ |
127 | QList<RemoteService::Ptr> services() const; |
128 | |
129 | /** |
130 | * Starts browsing for services |
131 | * |
132 | * Only the first call to this function will have any effect. |
133 | * |
134 | * Browsing stops when the ServiceBrowser object is destroyed. |
135 | * |
136 | * @warning The serviceAdded() signal may be emitted before this |
137 | * function returns. |
138 | * |
139 | * @see serviceAdded(), serviceRemoved() and finished() |
140 | */ |
141 | virtual void startBrowse(); |
142 | |
143 | /** |
144 | * Checks availability of DNS-SD services |
145 | * |
146 | * Although this method is part of ServiceBrowser, none of the classes |
147 | * in this library will be able to perform their intended function |
148 | * if this method does not return Working. |
149 | * |
150 | * If this method does not return Working, it is still safe to call |
151 | * any of the methods in this library. However, no services will be |
152 | * found or published and no domains will be found. |
153 | * |
154 | * If you use this function to report an error to the user, below |
155 | * is a suggestion on how to word the errors when publishing a |
156 | * service. The first line of each error message can also be |
157 | * used for reporting errors when browsing for services. |
158 | * |
159 | * @code |
160 | * switch(DNSSD::ServiceBrowser::isAvailable()) { |
161 | * case DNSSD::ServiceBrowser::Working: |
162 | * return ""; |
163 | * case DNSSD::ServiceBrowser::Stopped: |
164 | * return i18n("<p>The Zeroconf daemon is not running. See the Service" |
165 | * " Discovery Handbook for more information.<br/>" |
166 | * "Other users will not see the services provided by this |
167 | * " system when browsing the network via zeroconf, but " |
168 | * " normal access will still work.</p>"); |
169 | * case DNSSD::ServiceBrowser::Unsupported: |
170 | * return i18n("<p>Zeroconf support is not available in this version of KDE." |
171 | * " See the Service Discovery Handbook for more information.<br/>" |
172 | * "Other users will not see the services provided by this |
173 | * " application when browsing the network via zeroconf, but " |
174 | * " normal access will still work.</p>"); |
175 | * default: |
176 | * return i18n("<p>Unknown error with Zeroconf.<br/>" |
177 | * "Other users will not see the services provided by this |
178 | * " application when browsing the network via zeroconf, but " |
179 | * " normal access will still work.</p>"); |
180 | * } |
181 | * @endcode |
182 | * |
183 | */ |
184 | static State isAvailable(); |
185 | |
186 | /** |
187 | * Whether discovered services are resolved before being reported |
188 | * |
189 | * @return the value of the @p autoResolve parameter passed to the constructor |
190 | * |
191 | * @since 4.1 |
192 | */ |
193 | bool isAutoResolving() const; |
194 | |
195 | /** |
196 | * Resolves an mDNS hostname into an IP address |
197 | * |
198 | * This function is very rarely useful, since a properly configured |
199 | * system is able to resolve an mDNS-based host name using the system |
200 | * resolver (ie: you can just pass the mDNS hostname to KIO or other |
201 | * library). |
202 | * |
203 | * @param hostname the hostname to be resolved |
204 | * @return a QHostAddress containing the IP address, or QHostAddress() if |
205 | * resolution failed |
206 | * @since 4.2 |
207 | */ |
208 | static QHostAddress resolveHostName(const QString& hostname); |
209 | |
210 | /** |
211 | * The mDNS hostname of the local machine |
212 | * |
213 | * Usually this will return the same as QHostInfo::localHostName(), |
214 | * but it may be changed to something different |
215 | * in the Avahi configuration file (if using the Avahi backend). |
216 | * |
217 | * @return the hostname, or an empty string on failure |
218 | * @since 4.2 |
219 | */ |
220 | static QString getLocalHostName(); |
221 | |
222 | Q_SIGNALS: |
223 | /** |
224 | * Emitted when new service is discovered |
225 | * |
226 | * If isAutoResolving() returns @c true, this will not be emitted |
227 | * until the service has been resolved. |
228 | * |
229 | * @param service a RemoteService object describing the service |
230 | * |
231 | * @see serviceRemoved() and finished() |
232 | */ |
233 | void serviceAdded(DNSSD::RemoteService::Ptr service); |
234 | |
235 | /** |
236 | * Emitted when a service is no longer published over DNS-SD |
237 | * |
238 | * The RemoteService object is removed from the services() list |
239 | * and deleted immediately after this signal returns. |
240 | * |
241 | * @warning |
242 | * Do @b not use a delayed connection with this signal |
243 | * |
244 | * @param service a RemoteService object describing the service |
245 | * |
246 | * @see serviceAdded() and finished() |
247 | */ |
248 | void serviceRemoved(DNSSD::RemoteService::Ptr service); |
249 | |
250 | /** |
251 | * Emitted when the list of published services has settled |
252 | * |
253 | * This signal is emitted once after startBrowse() is called |
254 | * when all the services of the requested type that are |
255 | * currently published have been reported (even if none |
256 | * are available or the DNS-SD service is not available). |
257 | * It is emitted again when a new batch of services become |
258 | * available or disappear. |
259 | * |
260 | * For example, if a new host is connected to network and |
261 | * announces some services watched for by this ServiceBrowser, |
262 | * they will be reported by one or more serviceAdded() signals |
263 | * and the whole batch will be concluded by finished(). |
264 | * |
265 | * This signal can be used by applications that just want to |
266 | * get a list of the currently available services |
267 | * (similar to a directory listing) and do not care about |
268 | * adding or removing services that appear or disappear later. |
269 | * |
270 | * @warning |
271 | * There is no guarantee any RemoteService |
272 | * pointers received by serviceAdded() will be valid |
273 | * by the time this signal is emitted, so you should either |
274 | * do all your work involving them in the slot receiving |
275 | * the serviceAdded() signal, or you should listen to |
276 | * serviceRemoved() as well. |
277 | * |
278 | * @see serviceAdded() and serviceRemoved() |
279 | */ |
280 | void finished(); |
281 | |
282 | protected: |
283 | virtual void virtual_hook(int, void*); |
284 | |
285 | private: |
286 | friend class ServiceBrowserPrivate; |
287 | ServiceBrowserPrivate* const d; |
288 | |
289 | }; |
290 | |
291 | } |
292 | |
293 | #endif |
294 | |