1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
31 **************************************************************************/
33 #ifndef SERVICEBROWSER_P_H
34 #define SERVICEBROWSER_P_H
36 #include "dns_sd_types.h"
37 #include "servicebrowser.h"
39 #include <QtCore/QAtomicInt>
40 #include <QtCore/QHash>
41 #include <QtCore/QList>
42 #include <QtCore/QMap>
43 #include <QtCore/QMutex>
44 #include <QtCore/QSharedPointer>
45 #include <QtCore/QStringList>
46 #include <QtCore/QThread>
53 // represents a zero conf library exposing the dns-sd interface
56 ZConfLib *fallbackLib;
58 ZConfLib(ZConfLib *fallBack);
61 virtual QString name();
63 virtual bool tryStartDaemon();
65 virtual void refDeallocate(DNSServiceRef sdRef) = 0;
66 virtual DNSServiceErrorType resolve(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
67 const char *name, const char *regtype, const char *domain,
68 DNSServiceResolveReply callBack, void *context) = 0;
69 virtual DNSServiceErrorType queryRecord(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
70 const char *fullname, uint16_t rrtype, uint16_t rrclass,
71 DNSServiceQueryRecordReply callBack, void *context) = 0;
72 virtual DNSServiceErrorType getAddrInfo(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
73 DNSServiceProtocol protocol, const char *hostname,
74 DNSServiceGetAddrInfoReply callBack, void *context) = 0;
76 // remove txt functions from lib and always embed?
77 virtual uint16_t txtRecordGetCount(uint16_t txtLen, const void *txtRecord) = 0;
78 virtual DNSServiceErrorType txtRecordGetItemAtIndex(uint16_t txtLen, const void *txtRecord,
79 uint16_t itemIndex, uint16_t keyBufLen, char *key,
80 uint8_t *valueLen, const void **value) = 0;
82 virtual DNSServiceErrorType reconfirmRecord(DNSServiceFlags flags, uint32_t interfaceIndex,
83 const char *fullname, uint16_t rrtype, uint16_t rrclass,
84 uint16_t rdlen, const void *rdata) = 0; // opt
85 virtual DNSServiceErrorType browse(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
86 const char *regtype, const char *domain, DNSServiceBrowseReply callBack,
88 virtual DNSServiceErrorType getProperty(const char *property, void *result, uint32_t *size) = 0;
89 virtual DNSServiceErrorType processResult(DNSServiceRef sdRef) = 0;
90 virtual DNSServiceErrorType createConnection(DNSServiceRef *sdRef) = 0;
91 virtual int refSockFD(DNSServiceRef sdRef) = 0;
94 static ZConfLib *createEmbeddedLib(const QString &daemonPath, ZConfLib *fallback=0);
95 static ZConfLib *createNativeLib(const QString &libName, ZConfLib *fallback=0);
96 static ZConfLib *defaultLib();
101 /// class that gathers all needed info on a service, all its methods (creation included) are supposed to be called by the listener/reaction thread
102 class ServiceGatherer {
104 QHash<QString, QString> txtRecord;
111 ServiceBrowserPrivate *serviceBrowser;
113 Service::Ptr publishedService;
114 Service *currentService;
116 typedef QSharedPointer<ServiceGatherer> Ptr;
119 ResolveConnectionFailed = 1 << 0,
120 ResolveConnectionActive = 1 << 1,
121 ResolveConnectionSuccess = 1 << 2,
122 TxtConnectionFailed = 1 << 3,
123 TxtConnectionActive = 1 << 4,
124 TxtConnectionSuccess = 1 << 5,
125 AddrConnectionFailed = 1 << 6,
126 AddrConnectionActive = 1 << 7,
127 AddrConnectionSuccess = 1 << 8
130 void enactServiceChange();
131 void retireService();
136 void stopHostResolution();
137 void restartResolve();
139 void restartHostResolution();
141 bool currentServiceCanBePublished();
144 static Ptr createGatherer(const QString &newService, const QString &newType, const QString &newDomain,
145 const QString &fullName, uint32_t interfaceIndex, ServiceBrowserPrivate *serviceBrowser);
147 void serviceResolveReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
148 DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget,
149 uint16_t port /* In network byte order */, uint16_t txtLen,
150 const unsigned char *rawTxtRecord);
152 void txtRecordReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
153 DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype,
154 uint16_t rrclass, uint16_t txtLen, const void *rawTxtRecord, uint32_t ttl);
156 void addrReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
157 DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address,
161 void reload(qint32 interfaceIndex=0);
166 ServiceGatherer(const QString &newService, const QString &newType, const QString &newDomain,
167 const QString &fullName, uint32_t interfaceIndex, ServiceBrowserPrivate *serviceBrowser);
169 DNSServiceRef resolveConnection;
170 DNSServiceRef txtConnection;
171 DNSServiceRef addrConnection;
172 uint32_t interfaceIndex;
175 QWeakPointer<ServiceGatherer> self;
178 //Q_DECLARE_METATYPE(Service::ConstPtr)
180 class ConnectionThread;
182 class MainConnection{
184 enum RequestFlowStatus {
189 RequestFlowStatus flowStatus;
191 // Note: the select() implementation on Windows (Winsock2) fails with any timeout much larger than this
192 LONG_TIME = 100000000
194 /// WARNING order matters in this enum, and status should only be changed with increaseStatusTo
208 void stop(bool wait=true);
209 void addBrowser(ServiceBrowserPrivate *browser);
210 void removeBrowser(ServiceBrowserPrivate *browser);
211 void updateFlowStatusForCancel();
212 void updateFlowStatusForFlags(DNSServiceFlags flags);
213 void maybeUpdateLists();
214 QString tr(const char *s);
217 void createConnection();
218 void destroyConnection();
220 bool increaseStatusTo(int s);
223 DNSServiceRef mainRef();
225 QStringList errors();
227 void appendError(const QStringList &msgs,bool fullFailure);
230 mutable QMutex m_lock;
231 QList<ServiceBrowserPrivate *> m_browsers;
232 DNSServiceRef m_mainRef;
233 volatile int m_timeOut;
235 ConnectionThread *m_thread;
239 QStringList m_errors;
242 class ServiceBrowserPrivate {
243 friend class ServiceBrowser;
248 MainConnectionPtr mainConnection;
249 DNSServiceRef serviceConnection;
250 DNSServiceFlags flags;
251 uint32_t interfaceIndex;
252 QList<QString> knownServices;
253 QMap<QString, ServiceGatherer::Ptr> gatherers;
254 QList<Service::ConstPtr> activeServices;
255 QList<Service::ConstPtr> nextActiveServices;
256 QList<ServiceGatherer::Ptr> pendingGatherers;
259 bool autoResolveAddresses;
260 bool requireAddresses;
262 DNSServiceRef mainRef();
263 void updateFlowStatusForCancel();
264 void updateFlowStatusForFlags(DNSServiceFlags flags);
266 void pendingGathererAdd(ServiceGatherer::Ptr gatherer);
268 ServiceBrowserPrivate(const QString &serviceType, const QString &domain, bool requireAddresses,
269 MainConnectionPtr conn);
270 ~ServiceBrowserPrivate();
272 void insertGatherer(const QString &fullName);
273 void maybeUpdateLists();
275 bool startBrowsing(quint32 interfaceIndex);
277 void reconfirmService(Service::ConstPtr s);
279 void browseReply(DNSServiceRef sdRef, DNSServiceFlags flags,
280 uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName,
281 const char *regtype, const char *replyDomain);
282 void serviceChanged(const Service::ConstPtr &oldService, const Service::ConstPtr &newService, ServiceBrowser *browser);
283 void serviceAdded(const Service::ConstPtr &service, ServiceBrowser *browser);
284 void serviceRemoved(const Service::ConstPtr &service, ServiceBrowser *browser);
285 void servicesUpdated(ServiceBrowser *browser);
286 void hadError(QStringList errorMsgs, bool completeFailure);
289 class ConnectionThread: public QThread{
290 MainConnection &connection;
294 ConnectionThread(MainConnection &mc, QObject *parent=0);
296 } // namespace Internal
297 } // namespace Zeroconf
299 #endif // SERVICEBROWSER_P_H