OSDN Git Service

Merge remote-tracking branch 'origin/2.4'
[qt-creator-jp/qt-creator-jp.git] / src / libs / zeroconf / servicebrowser_p.h
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
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.
18 **
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.
22 **
23 ** Other Usage
24 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
30 **
31 **************************************************************************/
32
33 #ifndef SERVICEBROWSER_P_H
34 #define SERVICEBROWSER_P_H
35
36 #include "dns_sd_types.h"
37 #include "servicebrowser.h"
38
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>
47
48 class QHostInfo;
49
50 namespace ZeroConf {
51 namespace Internal {
52
53 // represents a zero conf library exposing the dns-sd interface
54 class ZConfLib {
55 public:
56     ZConfLib *fallbackLib;
57
58     ZConfLib(ZConfLib *fallBack);
59     virtual ~ZConfLib();
60
61     virtual QString name();
62
63     virtual bool tryStartDaemon();
64
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;
75
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;
81
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,
87                                        void *context) = 0;
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;
92     bool isOk();
93
94     static ZConfLib *createEmbeddedLib(const QString &daemonPath, ZConfLib *fallback=0);
95     static ZConfLib *createNativeLib(const QString &libName, ZConfLib *fallback=0);
96     static ZConfLib *defaultLib();
97 private:
98     bool m_isOk;
99 };
100
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 {
103 public:
104     QHash<QString, QString> txtRecord;
105     short                   port;
106     QString                 serviceName;
107     QString                 serviceType;
108     QString                 domain;
109     QString                 fullName;
110     QString                 hostName;
111     ServiceBrowserPrivate   *serviceBrowser;
112     QHostInfo               *host;
113     Service::Ptr             publishedService;
114     Service                 *currentService;
115
116     typedef QSharedPointer<ServiceGatherer> Ptr;
117
118     enum Status{
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
128     };
129
130     void enactServiceChange();
131     void retireService();
132     Ptr gatherer();
133
134     void stopResolve();
135     void stopTxt();
136     void stopHostResolution();
137     void restartResolve();
138     void restartTxt();
139     void restartHostResolution();
140
141     bool currentServiceCanBePublished();
142
143     ~ServiceGatherer();
144     static Ptr createGatherer(const QString &newService, const QString &newType, const QString &newDomain,
145                               const QString &fullName, uint32_t interfaceIndex, ServiceBrowserPrivate *serviceBrowser);
146
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);
151
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);
155
156     void addrReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
157                    DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address,
158                    uint32_t ttl);
159     void maybeRemove();
160     void stop();
161     void reload(qint32 interfaceIndex=0);
162     void remove();
163     void reconfirm();
164     ZConfLib *lib();
165 private:
166     ServiceGatherer(const QString &newService, const QString &newType, const QString &newDomain,
167                     const QString &fullName, uint32_t interfaceIndex, ServiceBrowserPrivate *serviceBrowser);
168
169     DNSServiceRef           resolveConnection;
170     DNSServiceRef           txtConnection;
171     DNSServiceRef           addrConnection;
172     uint32_t                interfaceIndex;
173
174     quint32 status;
175     QWeakPointer<ServiceGatherer> self;
176 };
177
178 //Q_DECLARE_METATYPE(Service::ConstPtr)
179
180 class ConnectionThread;
181
182 class MainConnection{
183 public:
184     enum RequestFlowStatus {
185         NormalRFS,
186         MoreComingRFS,
187         ForceUpdateRFS
188     };
189     RequestFlowStatus flowStatus;
190     enum {
191         // Note: the select() implementation on Windows (Winsock2) fails with any timeout much larger than this
192         LONG_TIME = 100000000
193     };
194     /// WARNING order matters in this enum, and status should only be changed with increaseStatusTo
195     enum Status {
196         Starting,
197         Started,
198         Running,
199         Stopping,
200         Stopped
201     };
202     ZConfLib *lib;
203
204     MainConnection();
205     ~MainConnection();
206     QMutex *lock();
207     void waitStartup();
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);
215     void gotoValidLib();
216     void abortLib();
217     void createConnection();
218     void destroyConnection();
219     bool handleEvent();
220     bool increaseStatusTo(int s);
221     void selectLoop();
222     void handleEvents();
223     DNSServiceRef mainRef();
224
225     QStringList errors();
226     void clearErrors();
227     void appendError(const QStringList &msgs,bool fullFailure);
228     bool isOk();
229 private:
230     mutable QMutex m_lock;
231     QList<ServiceBrowserPrivate *> m_browsers;
232     DNSServiceRef   m_mainRef;
233     volatile int m_timeOut;
234     bool m_failed;
235     ConnectionThread *m_thread;
236     QAtomicInt m_status;
237     int m_nErrs;
238     bool m_useSelect;
239     QStringList m_errors;
240 };
241
242 class ServiceBrowserPrivate {
243     friend class ServiceBrowser;
244 public:
245     ServiceBrowser *q;
246     QString         serviceType;
247     QString         domain;
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;
257     bool failed;
258     bool browsing;
259     bool autoResolveAddresses;
260     bool requireAddresses;
261
262     DNSServiceRef   mainRef();
263     void updateFlowStatusForCancel();
264     void updateFlowStatusForFlags(DNSServiceFlags flags);
265
266     void pendingGathererAdd(ServiceGatherer::Ptr gatherer);
267
268     ServiceBrowserPrivate(const QString &serviceType, const QString &domain, bool requireAddresses,
269                           MainConnectionPtr conn);
270     ~ServiceBrowserPrivate();
271
272     void insertGatherer(const QString &fullName);
273     void maybeUpdateLists();
274
275     bool startBrowsing(quint32 interfaceIndex);
276     void stopBrowsing();
277     void reconfirmService(Service::ConstPtr s);
278
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);
287 };
288
289 class ConnectionThread: public QThread{
290     MainConnection &connection;
291
292     void run();
293 public:
294     ConnectionThread(MainConnection &mc, QObject *parent=0);
295 };
296 } // namespace Internal
297 } // namespace Zeroconf
298
299 #endif // SERVICEBROWSER_P_H