servicebrowser_p.h 12.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#ifndef SERVICEBROWSER_P_H
#define SERVICEBROWSER_P_H

#include "dns_sd_types.h"
#include "servicebrowser.h"

39
#include <QtCore/QCoreApplication>
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <QtCore/QAtomicInt>
#include <QtCore/QHash>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QMutex>
#include <QtCore/QSharedPointer>
#include <QtCore/QStringList>
#include <QtCore/QThread>

class QHostInfo;

namespace ZeroConf {
namespace Internal {

54
55
56
class ServiceGatherer;
class ServiceBrowserPrivate;

57
58
// represents a zero conf library exposing the dns-sd interface
class ZConfLib {
59
    Q_DECLARE_TR_FUNCTIONS(ZeroConf)
60
public:
61
    typedef QSharedPointer<ZConfLib> Ptr;
62
63
64
65
66
67
68
69
    typedef void *ConnectionRef;
    typedef void *BrowserRef;
    enum ProcessStatus {
        ProcessedOk,
        ProcessedQuit,
        ProcessedError,
        ProcessedFailure
    };
70
    Ptr fallbackLib;
71

72
    ZConfLib(Ptr fallBack);
73
74
75
76
77
78
79
    virtual ~ZConfLib();

    virtual QString name();

    virtual bool tryStartDaemon();

    virtual void refDeallocate(DNSServiceRef sdRef) = 0;
80
    virtual void browserDeallocate(BrowserRef *sdRef) = 0;
Fawzi Mohamed's avatar
Fawzi Mohamed committed
81
82
83
    virtual DNSServiceErrorType resolve(ConnectionRef cRef, DNSServiceRef *sdRef,
                                        uint32_t interfaceIndex, const char *name,
                                        const char *regtype, const char *domain,
84
                                        ServiceGatherer *gatherer) = 0;
Fawzi Mohamed's avatar
Fawzi Mohamed committed
85
86
    virtual DNSServiceErrorType queryRecord(ConnectionRef cRef, DNSServiceRef *sdRef,
                                            uint32_t interfaceIndex, const char *fullname,
87
                                            ServiceGatherer *gatherer) = 0;
Fawzi Mohamed's avatar
Fawzi Mohamed committed
88
89
90
    virtual DNSServiceErrorType getAddrInfo(ConnectionRef cRef, DNSServiceRef *sdRef,
                                            uint32_t interfaceIndex, DNSServiceProtocol protocol,
                                            const char *hostname, ServiceGatherer *gatherer) = 0;
91
92

    virtual DNSServiceErrorType reconfirmRecord(ConnectionRef cRef, uint32_t interfaceIndex,
Fawzi Mohamed's avatar
Fawzi Mohamed committed
93
94
95
96
97
98
                                                const char *name, const char *type,
                                                const char *domain, const char *fullname) = 0;
    virtual DNSServiceErrorType browse(ConnectionRef cRef, BrowserRef *sdRef,
                                       uint32_t interfaceIndex,
                                       const char *regtype, const char *domain,
                                       ServiceBrowserPrivate *browser) = 0;
99
    virtual DNSServiceErrorType getProperty(const char *property, void *result, uint32_t *size) = 0;
100
101
102
103
    virtual ProcessStatus processResult(ConnectionRef sdRef) = 0;
    virtual DNSServiceErrorType createConnection(ConnectionRef *sdRef) = 0;
    virtual void stopConnection(ConnectionRef cRef) = 0;
    virtual void destroyConnection(ConnectionRef *sdRef) = 0;
104
    bool isOk();
105
106
    QString errorMsg();
    void setError(bool failure, const QString &eMsg);
107

108
109
110
    static Ptr createEmbeddedLib(const QString &daemonPath, Ptr fallback = Ptr(0));
    static Ptr createDnsSdLib(const QString &libName, Ptr fallback = Ptr(0));
    static Ptr createAvahiLib(const QString &libName, Ptr fallback = Ptr(0));
111
protected:
112
    bool m_isOk;
113
    QString m_errorMsg;
114
115
};

Fawzi Mohamed's avatar
Fawzi Mohamed committed
116
117
/// class that gathers all needed info on a service, all its methods (creation included) are
/// supposed to be called by the listener/reaction thread
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
class ServiceGatherer {
public:
    QString                 hostName;
    ServiceBrowserPrivate   *serviceBrowser;
    QHostInfo               *host;
    Service::Ptr             publishedService;
    Service                 *currentService;

    typedef QSharedPointer<ServiceGatherer> Ptr;

    enum Status{
        ResolveConnectionFailed  = 1 << 0,
        ResolveConnectionActive  = 1 << 1,
        ResolveConnectionSuccess = 1 << 2,
        TxtConnectionFailed      = 1 << 3,
        TxtConnectionActive      = 1 << 4,
        TxtConnectionSuccess     = 1 << 5,
        AddrConnectionFailed     = 1 << 6,
        AddrConnectionActive     = 1 << 7,
        AddrConnectionSuccess    = 1 << 8
    };

140
    QString fullName();
141
142
143
144
145
146
147
148
149
150
151
152
153
154
    void enactServiceChange();
    void retireService();
    Ptr gatherer();

    void stopResolve();
    void stopTxt();
    void stopHostResolution();
    void restartResolve();
    void restartTxt();
    void restartHostResolution();

    bool currentServiceCanBePublished();

    ~ServiceGatherer();
Fawzi Mohamed's avatar
Fawzi Mohamed committed
155
156
157
    static Ptr createGatherer(const QString &newService, const QString &newType,
                              const QString &newDomain, const QString &fullName,
                              uint32_t interfaceIndex, ServiceBrowserPrivate *serviceBrowser);
158

159
160
161
    void serviceResolveReply(DNSServiceFlags flags, uint32_t interfaceIndex,
                             DNSServiceErrorType errorCode, const char *hosttarget,
                             const QString &port, uint16_t txtLen,
162
163
                             const unsigned char *rawTxtRecord);

164
165
    void txtRecordReply(DNSServiceFlags flags, DNSServiceErrorType errorCode,
                        uint16_t txtLen, const void *rawTxtRecord, uint32_t ttl);
166
167
    void txtFieldReply(DNSServiceFlags flags, DNSServiceErrorType errorCode,
                        uint16_t txtLen, const void *rawTxtRecord, uint32_t ttl);
168

Fawzi Mohamed's avatar
Fawzi Mohamed committed
169
170
    void addrReply(DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *hostname,
                   const struct sockaddr *address, uint32_t ttl);
171
172
    void maybeRemove();
    void stop();
Fawzi Mohamed's avatar
Fawzi Mohamed committed
173
    void reload(qint32 interfaceIndex = 0);
174
175
    void remove();
    void reconfirm();
176
    ZConfLib::Ptr lib();
177
178
private:
    ServiceGatherer(const QString &newService, const QString &newType, const QString &newDomain,
Fawzi Mohamed's avatar
Fawzi Mohamed committed
179
180
                    const QString &fullName, uint32_t interfaceIndex,
                    ServiceBrowserPrivate *serviceBrowser);
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

    DNSServiceRef           resolveConnection;
    DNSServiceRef           txtConnection;
    DNSServiceRef           addrConnection;
    uint32_t                interfaceIndex;

    quint32 status;
    QWeakPointer<ServiceGatherer> self;
};

//Q_DECLARE_METATYPE(Service::ConstPtr)

class ConnectionThread;

class MainConnection{
196
    Q_DECLARE_TR_FUNCTIONS(ZeroConf)
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
public:
    enum RequestFlowStatus {
        NormalRFS,
        MoreComingRFS,
        ForceUpdateRFS
    };
    RequestFlowStatus flowStatus;
    /// WARNING order matters in this enum, and status should only be changed with increaseStatusTo
    enum Status {
        Starting,
        Started,
        Running,
        Stopping,
        Stopped
    };
212
    ZConfLib::Ptr lib;
213
214
215
216
217

    MainConnection();
    ~MainConnection();
    QMutex *lock();
    void waitStartup();
Fawzi Mohamed's avatar
Fawzi Mohamed committed
218
    void stop(bool wait = true);
219
220
221
222
223
224
225
226
227
    void addBrowser(ServiceBrowserPrivate *browser);
    void removeBrowser(ServiceBrowserPrivate *browser);
    void updateFlowStatusForCancel();
    void updateFlowStatusForFlags(DNSServiceFlags flags);
    void maybeUpdateLists();
    void gotoValidLib();
    void abortLib();
    void createConnection();
    void destroyConnection();
228
    ZConfLib::ProcessStatus handleEvent();
229
230
    bool increaseStatusTo(int s);
    void handleEvents();
231
    ZConfLib::ConnectionRef mainRef();
232
233
234

    QStringList errors();
    void clearErrors();
Fawzi Mohamed's avatar
Fawzi Mohamed committed
235
    void appendError(const QStringList &msgs, bool fullFailure);
236
237
238
239
    bool isOk();
private:
    mutable QMutex m_lock;
    QList<ServiceBrowserPrivate *> m_browsers;
240
    ZConfLib::ConnectionRef m_mainRef;
241
242
243
244
245
246
247
248
249
250
251
252
253
    bool m_failed;
    ConnectionThread *m_thread;
    QAtomicInt m_status;
    int m_nErrs;
    QStringList m_errors;
};

class ServiceBrowserPrivate {
    friend class ServiceBrowser;
public:
    ServiceBrowser *q;
    QString         serviceType;
    QString         domain;
254
255
    MainConnectionPtr    mainConnection;
    ZConfLib::BrowserRef serviceConnection;
256
257
258
259
260
261
262
263
264
265
266
267
    DNSServiceFlags flags;
    uint32_t        interfaceIndex;
    QList<QString>  knownServices;
    QMap<QString, ServiceGatherer::Ptr> gatherers;
    QList<Service::ConstPtr> activeServices;
    QList<Service::ConstPtr> nextActiveServices;
    QList<ServiceGatherer::Ptr> pendingGatherers;
    bool failed;
    bool browsing;
    bool autoResolveAddresses;
    bool requireAddresses;

268
    ZConfLib::ConnectionRef mainRef();
269
270
271
272
273
274
275
276
277
278
279
280
    void updateFlowStatusForCancel();
    void updateFlowStatusForFlags(DNSServiceFlags flags);

    void pendingGathererAdd(ServiceGatherer::Ptr gatherer);

    ServiceBrowserPrivate(const QString &serviceType, const QString &domain, bool requireAddresses,
                          MainConnectionPtr conn);
    ~ServiceBrowserPrivate();

    void insertGatherer(const QString &fullName);
    void maybeUpdateLists();

Fawzi Mohamed's avatar
Fawzi Mohamed committed
281
282
    void startBrowsing(quint32 interfaceIndex);
    bool internalStartBrowsing();
283
284
285
    void stopBrowsing();
    void reconfirmService(Service::ConstPtr s);

286
    void browseReply(DNSServiceFlags flags,
Fawzi Mohamed's avatar
Fawzi Mohamed committed
287
288
289
290
                     uint32_t interfaceIndex, DNSServiceErrorType errorCode,
                     const char *serviceName, const char *regtype, const char *replyDomain);
    void serviceChanged(const Service::ConstPtr &oldService, const Service::ConstPtr &newService,
                        ServiceBrowser *browser);
291
292
293
294
295
296
297
298
299
300
301
    void serviceAdded(const Service::ConstPtr &service, ServiceBrowser *browser);
    void serviceRemoved(const Service::ConstPtr &service, ServiceBrowser *browser);
    void servicesUpdated(ServiceBrowser *browser);
    void hadError(QStringList errorMsgs, bool completeFailure);
};

class ConnectionThread: public QThread{
    MainConnection &connection;

    void run();
public:
Fawzi Mohamed's avatar
Fawzi Mohamed committed
302
    ConnectionThread(MainConnection &mc, QObject *parent = 0);
303
};
304

Fawzi Mohamed's avatar
Fawzi Mohamed committed
305
306
307
308
309
310
311
312
313
314
extern "C" void DNSSD_API cServiceResolveReply(
        DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
        DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port,
        uint16_t txtLen, const unsigned char *txtRecord, void *context);
extern "C" void DNSSD_API cTxtRecordReply(DNSServiceRef sdRef, DNSServiceFlags flags,
                                          uint32_t interfaceIndex, DNSServiceErrorType errorCode,
                                          const char *fullname, uint16_t rrtype, uint16_t rrclass,
                                          uint16_t rdlen, const void *rdata, uint32_t ttl,
                                          void *context);
extern "C" void DNSSD_API cAddrReply(DNSServiceRef sdRef, DNSServiceFlags flags,
315
                                     uint32_t interfaceIndex, DNSServiceErrorType errorCode,
Fawzi Mohamed's avatar
Fawzi Mohamed committed
316
317
318
319
320
321
                                     const char *hostname, const struct sockaddr *address,
                                     uint32_t ttl, void *context);
extern "C" void DNSSD_API cBrowseReply(DNSServiceRef sdRef, DNSServiceFlags flags,
                                       uint32_t interfaceIndex, DNSServiceErrorType errorCode,
                                       const char *serviceName, const char *regtype,
                                       const char *replyDomain, void *context);
322
323
324
325
} // namespace Internal
} // namespace Zeroconf

#endif // SERVICEBROWSER_P_H