File indexing completed on 2024-04-28 03:54:04
0001 /* 0002 This file is part of the KDE project 0003 0004 SPDX-FileCopyrightText: 2004 Jakub Stachowski <qbast@go2.pl> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef KDNSSDSERVICEBROWSER_H 0010 #define KDNSSDSERVICEBROWSER_H 0011 0012 #include "remoteservice.h" 0013 #include <QHostAddress> 0014 #include <QObject> 0015 0016 #include <memory> 0017 0018 namespace KDNSSD 0019 { 0020 class DomainBrowser; 0021 class ServiceBrowserPrivate; 0022 0023 /** 0024 * @class ServiceBrowser servicebrowser.h KDNSSD/ServiceBrowser 0025 * @short Browses for network services advertised over DNS-SD 0026 * 0027 * This is the central class in the KDNSSD library for applications 0028 * that want to discover services on network. 0029 * 0030 * Suppose that you need list of web servers running. Then you 0031 * might do something like 0032 * @code 0033 * KDNSSD::ServiceBrowser *browser = new KDNSSD::ServiceBrowser(QStringLiteral("_http._tcp")); 0034 * connect(browser, &KDNSSD::ServiceBrowser::serviceAdded, 0035 * this, [](KDNSSD::RemoteService::Ptr service) { 0036 * }); 0037 * connect(browser, &KDNSSD::ServiceBrowser::serviceRemoved, 0038 * this, [](KDNSSD::RemoteService::Ptr service) { 0039 * }); 0040 * browser->startBrowse(); 0041 * @endcode 0042 * 0043 * In above example addService() will be called for every web server 0044 * already running and for every web service that subsequently 0045 * appears on the network and delService() will be called when 0046 * a server previously advertised is stopped. 0047 * 0048 * Because no domain was passed to constructor, the default domain 0049 * will be searched. To find other domains to browse for services on, 0050 * use DomainBrowser. 0051 * 0052 * @author Jakub Stachowski 0053 */ 0054 class KDNSSD_EXPORT ServiceBrowser : public QObject 0055 { 0056 Q_OBJECT 0057 0058 public: 0059 /** 0060 * Availability of DNS-SD services 0061 */ 0062 enum State { 0063 /** the service is available */ 0064 Working, 0065 /** not available because mDnsd or Avahi daemon is not running */ 0066 Stopped, 0067 /** not available because KDE was compiled without DNS-SD support */ 0068 Unsupported, 0069 }; 0070 0071 /** 0072 * Create a ServiceBrowser for a particular service type 0073 * 0074 * DomainBrowser can be used to find other domains to browse on. 0075 * If no domain is given, the default domain is used. 0076 * 0077 * The service type is the high-level protocol type, followed by a dot, 0078 * followed by the transport protocol type (@c _tcp or @c _udp). 0079 * The <a href="http://www.dns-sd.org">DNS-SD website</a> maintains 0080 * <a href="http://www.dns-sd.org/ServiceTypes.html">a full list</a> 0081 * of service types. 0082 * 0083 * The @p subtype parameter allows you to do more fine-grained filtering 0084 * on the services you are interested in. So you might request only 0085 * FTP servers that allow anonymous access by passing "_ftp._tcp" as the 0086 * @p type and "_anon" as the @p subtype. Subtypes are particularly 0087 * important for types like _soap and _upnp, which are far too generic 0088 * for most applications. In these cases, the subtype can be used to 0089 * specify the particular SOAP or UPnP protocol they want. 0090 * 0091 * @warning 0092 * Enabling @p autoResolve will increase network usage by resolving 0093 * all services, so this feature should be used only when necessary. 0094 * 0095 * @param type service types to browse for (example: "_http._tcp") 0096 * @param autoResolve discovered services will be resolved before being 0097 * reported with the serviceAdded() signal 0098 * @param domain a domain to search on instead of the default one 0099 * @param subtype only browse for a specific subtype 0100 * 0101 * @see startBrowse() and isAvailable() 0102 */ 0103 explicit ServiceBrowser(const QString &type, bool autoResolve = false, const QString &domain = QString(), const QString &subtype = QString()); 0104 0105 ~ServiceBrowser() override; 0106 0107 /** 0108 * The currently known services of the specified type 0109 * 0110 * @returns a list of RemoteService pointers 0111 * 0112 * @see serviceAdded() and serviceRemoved() 0113 */ 0114 QList<RemoteService::Ptr> services() const; 0115 0116 /** 0117 * Starts browsing for services 0118 * 0119 * Only the first call to this function will have any effect. 0120 * 0121 * Browsing stops when the ServiceBrowser object is destroyed. 0122 * 0123 * @warning The serviceAdded() signal may be emitted before this 0124 * function returns. 0125 * 0126 * @see serviceAdded(), serviceRemoved() and finished() 0127 */ 0128 virtual void startBrowse(); 0129 0130 /** 0131 * Checks availability of DNS-SD services 0132 * 0133 * Although this method is part of ServiceBrowser, none of the classes 0134 * in this library will be able to perform their intended function 0135 * if this method does not return Working. 0136 * 0137 * If this method does not return Working, it is still safe to call 0138 * any of the methods in this library. However, no services will be 0139 * found or published and no domains will be found. 0140 * 0141 * If you use this function to report an error to the user, below 0142 * is a suggestion on how to word the errors when publishing a 0143 * service. The first line of each error message can also be 0144 * used for reporting errors when browsing for services. 0145 * 0146 * @code 0147 * switch(KDNSSD::ServiceBrowser::isAvailable()) { 0148 * case KDNSSD::ServiceBrowser::Working: 0149 * return ""; 0150 * case KDNSSD::ServiceBrowser::Stopped: 0151 * return i18n("<p>The Zeroconf daemon is not running. See the Service" 0152 * " Discovery Handbook for more information.<br/>" 0153 * "Other users will not see the services provided by this 0154 * " system when browsing the network via zeroconf, but " 0155 * " normal access will still work.</p>"); 0156 * case KDNSSD::ServiceBrowser::Unsupported: 0157 * return i18n("<p>Zeroconf support is not available in this version of KDE." 0158 * " See the Service Discovery Handbook for more information.<br/>" 0159 * "Other users will not see the services provided by this 0160 * " application when browsing the network via zeroconf, but " 0161 * " normal access will still work.</p>"); 0162 * default: 0163 * return i18n("<p>Unknown error with Zeroconf.<br/>" 0164 * "Other users will not see the services provided by this 0165 * " application when browsing the network via zeroconf, but " 0166 * " normal access will still work.</p>"); 0167 * } 0168 * @endcode 0169 * 0170 */ 0171 static State isAvailable(); 0172 0173 /** 0174 * Whether discovered services are resolved before being reported 0175 * 0176 * @return the value of the @p autoResolve parameter passed to the constructor 0177 * 0178 * @since 4.1 0179 */ 0180 bool isAutoResolving() const; 0181 0182 /** 0183 * Resolves an mDNS hostname into an IP address 0184 * 0185 * This function is very rarely useful, since a properly configured 0186 * system is able to resolve an mDNS-based host name using the system 0187 * resolver (ie: you can just pass the mDNS hostname to KIO or other 0188 * library). 0189 * 0190 * @param hostname the hostname to be resolved 0191 * @return a QHostAddress containing the IP address, or QHostAddress() if 0192 * resolution failed 0193 * @since 4.2 0194 */ 0195 static QHostAddress resolveHostName(const QString &hostname); 0196 0197 /** 0198 * The mDNS hostname of the local machine 0199 * 0200 * Usually this will return the same as QHostInfo::localHostName(), 0201 * but it may be changed to something different 0202 * in the Avahi configuration file (if using the Avahi backend). 0203 * 0204 * @return the hostname, or an empty string on failure 0205 * @since 4.2 0206 */ 0207 static QString getLocalHostName(); 0208 0209 Q_SIGNALS: 0210 /** 0211 * Emitted when new service is discovered 0212 * 0213 * If isAutoResolving() returns @c true, this will not be emitted 0214 * until the service has been resolved. 0215 * 0216 * @param service a RemoteService object describing the service 0217 * 0218 * @see serviceRemoved() and finished() 0219 */ 0220 void serviceAdded(KDNSSD::RemoteService::Ptr service); 0221 0222 /** 0223 * Emitted when a service is no longer published over DNS-SD 0224 * 0225 * The RemoteService object is removed from the services() list 0226 * and deleted immediately after this signal returns. 0227 * 0228 * @warning 0229 * Do @b not use a delayed connection with this signal 0230 * 0231 * @param service a RemoteService object describing the service 0232 * 0233 * @see serviceAdded() and finished() 0234 */ 0235 void serviceRemoved(KDNSSD::RemoteService::Ptr service); 0236 0237 /** 0238 * Emitted when the list of published services has settled 0239 * 0240 * This signal is emitted once after startBrowse() is called 0241 * when all the services of the requested type that are 0242 * currently published have been reported (even if none 0243 * are available or the DNS-SD service is not available). 0244 * It is emitted again when a new batch of services become 0245 * available or disappear. 0246 * 0247 * For example, if a new host is connected to network and 0248 * announces some services watched for by this ServiceBrowser, 0249 * they will be reported by one or more serviceAdded() signals 0250 * and the whole batch will be concluded by finished(). 0251 * 0252 * This signal can be used by applications that just want to 0253 * get a list of the currently available services 0254 * (similar to a directory listing) and do not care about 0255 * adding or removing services that appear or disappear later. 0256 * 0257 * @warning 0258 * There is no guarantee any RemoteService 0259 * pointers received by serviceAdded() will be valid 0260 * by the time this signal is emitted, so you should either 0261 * do all your work involving them in the slot receiving 0262 * the serviceAdded() signal, or you should listen to 0263 * serviceRemoved() as well. 0264 * 0265 * @see serviceAdded() and serviceRemoved() 0266 */ 0267 void finished(); 0268 0269 protected: 0270 virtual void virtual_hook(int, void *); 0271 0272 private: 0273 friend class ServiceBrowserPrivate; 0274 std::unique_ptr<ServiceBrowserPrivate> const d; 0275 Q_DECLARE_PRIVATE_D(d, ServiceBrowser) 0276 }; 0277 0278 } 0279 0280 #endif